diff --git a/ldb-2.0.8/ABI/ldb-0.9.10.sigs b/ldb-2.0.8/ABI/ldb-0.9.10.sigs new file mode 100644 index 0000000..012ac65 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.10.sigs @@ -0,0 +1,218 @@ +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 *(void *, 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 *(void *, const char *, int) +ldb_binary_decode: struct ldb_val (void *, const char *) +ldb_binary_encode: char *(void *, struct ldb_val) +ldb_binary_encode_string: char *(void *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, const char *, size_t) +ldb_casefold_default: char *(void *, void *, const char *, size_t) +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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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 *(void *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(void *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(void *, struct ldb_dn *) +ldb_dn_canonical_string: char *(void *, 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 *(void *, struct ldb_dn *) +ldb_dn_escape_value: char *(void *, 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 *(void *, 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_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(void *, struct ldb_dn *, int) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(void *, 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_new: struct ldb_dn *(void *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(void *, 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_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_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 *(void *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +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_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, void *, 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 *(void *) +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_parse_control_strings: struct ldb_control **(struct ldb_context *, void *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(void *, 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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_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_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_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +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_val_dup: struct ldb_val (void *, 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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.12.sigs b/ldb-2.0.8/ABI/ldb-0.9.12.sigs new file mode 100644 index 0000000..2206e79 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.12.sigs @@ -0,0 +1,219 @@ +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 *(void *, 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 *(void *, const char *, int) +ldb_binary_decode: struct ldb_val (void *, const char *) +ldb_binary_encode: char *(void *, struct ldb_val) +ldb_binary_encode_string: char *(void *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, const char *, size_t) +ldb_casefold_default: char *(void *, void *, const char *, size_t) +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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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 *(void *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(void *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(void *, struct ldb_dn *) +ldb_dn_canonical_string: char *(void *, 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 *(void *, struct ldb_dn *) +ldb_dn_escape_value: char *(void *, 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 *(void *, 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_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(void *, struct ldb_dn *, int) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(void *, 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_new: struct ldb_dn *(void *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(void *, 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_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_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 *(void *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +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_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, void *, 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 *(void *) +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_parse_control_strings: struct ldb_control **(struct ldb_context *, void *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(void *, 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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_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_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_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +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_val_dup: struct ldb_val (void *, 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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.15.sigs b/ldb-2.0.8/ABI/ldb-0.9.15.sigs new file mode 100644 index 0000000..39d2f3e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.15.sigs @@ -0,0 +1,226 @@ +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_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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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_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_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_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_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 *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_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_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_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_location: const char *(struct ldb_request *) +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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.16.sigs b/ldb-2.0.8/ABI/ldb-0.9.16.sigs new file mode 100644 index 0000000..610a0a4 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.16.sigs @@ -0,0 +1,228 @@ +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_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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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_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_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_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_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 *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_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_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_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_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.17.sigs b/ldb-2.0.8/ABI/ldb-0.9.17.sigs new file mode 100644 index 0000000..d0f5699 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.17.sigs @@ -0,0 +1,229 @@ +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_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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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_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_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_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_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 *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_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_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_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_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.18.sigs b/ldb-2.0.8/ABI/ldb-0.9.18.sigs new file mode 100644 index 0000000..15913c9 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.18.sigs @@ -0,0 +1,240 @@ +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_asq_init: int (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_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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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_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_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_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_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 *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_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_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_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_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_paged_results_init: int (const char *) +ldb_paged_searches_init: int (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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_rdn_name_init: int (const char *) +ldb_register_backend: int (const char *, ldb_connect_fn, bool) +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_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +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_sample_init: int (const char *) +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_server_sort_init: int (const char *) +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_skel_init: int (const char *) +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_tdb_init: int (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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.19.sigs b/ldb-2.0.8/ABI/ldb-0.9.19.sigs new file mode 100644 index 0000000..6273870 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.19.sigs @@ -0,0 +1,245 @@ +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_asq_init: int (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_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_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_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_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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +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_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_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_paged_results_init: int (const char *) +ldb_paged_searches_init: int (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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_rdn_name_init: int (const char *) +ldb_register_backend: int (const char *, ldb_connect_fn, bool) +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_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +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_sample_init: int (const char *) +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_server_sort_init: int (const char *) +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_skel_init: int (const char *) +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_tdb_init: int (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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.20.sigs b/ldb-2.0.8/ABI/ldb-0.9.20.sigs new file mode 100644 index 0000000..6273870 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.20.sigs @@ -0,0 +1,245 @@ +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_asq_init: int (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_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_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_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_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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +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_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_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_paged_results_init: int (const char *) +ldb_paged_searches_init: int (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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_rdn_name_init: int (const char *) +ldb_register_backend: int (const char *, ldb_connect_fn, bool) +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_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +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_sample_init: int (const char *) +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_server_sort_init: int (const char *) +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_skel_init: int (const char *) +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_tdb_init: int (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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.22.sigs b/ldb-2.0.8/ABI/ldb-0.9.22.sigs new file mode 100644 index 0000000..b5a69c1 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.22.sigs @@ -0,0 +1,245 @@ +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_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_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_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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_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_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_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_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_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_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.23.sigs b/ldb-2.0.8/ABI/ldb-0.9.23.sigs new file mode 100644 index 0000000..73e5caa --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.23.sigs @@ -0,0 +1,247 @@ +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_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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_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_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_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_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_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_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-0.9.24.sigs b/ldb-2.0.8/ABI/ldb-0.9.24.sigs new file mode 100644 index 0000000..5cb32f7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-0.9.24.sigs @@ -0,0 +1,248 @@ +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_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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_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_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_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_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_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_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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.0.0.sigs b/ldb-2.0.8/ABI/ldb-1.0.0.sigs new file mode 100644 index 0000000..5cb32f7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.0.0.sigs @@ -0,0 +1,248 @@ +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_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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_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_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_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_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_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_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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.0.1.sigs b/ldb-2.0.8/ABI/ldb-1.0.1.sigs new file mode 100644 index 0000000..5cb32f7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.0.1.sigs @@ -0,0 +1,248 @@ +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_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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_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_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_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_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_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_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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.0.2.sigs b/ldb-2.0.8/ABI/ldb-1.0.2.sigs new file mode 100644 index 0000000..c13ac87 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.0.2.sigs @@ -0,0 +1,250 @@ +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_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_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_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +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_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_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_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_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_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_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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.0.sigs b/ldb-2.0.8/ABI/ldb-1.1.0.sigs new file mode 100644 index 0000000..149d4bc --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.0.sigs @@ -0,0 +1,253 @@ +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_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_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_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_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_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_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_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_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_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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.1.sigs b/ldb-2.0.8/ABI/ldb-1.1.1.sigs new file mode 100644 index 0000000..2fe215c --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.1.sigs @@ -0,0 +1,254 @@ +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_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_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_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_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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.10.sigs b/ldb-2.0.8/ABI/ldb-1.1.10.sigs new file mode 100644 index 0000000..de5026e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.10.sigs @@ -0,0 +1,259 @@ +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_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_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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.11.sigs b/ldb-2.0.8/ABI/ldb-1.1.11.sigs new file mode 100644 index 0000000..de5026e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.11.sigs @@ -0,0 +1,259 @@ +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_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_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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.12.sigs b/ldb-2.0.8/ABI/ldb-1.1.12.sigs new file mode 100644 index 0000000..c8ccd25 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.12.sigs @@ -0,0 +1,260 @@ +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_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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.13.sigs b/ldb-2.0.8/ABI/ldb-1.1.13.sigs new file mode 100644 index 0000000..c8ccd25 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.13.sigs @@ -0,0 +1,260 @@ +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_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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.14.sigs b/ldb-2.0.8/ABI/ldb-1.1.14.sigs new file mode 100644 index 0000000..eac5194 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.14.sigs @@ -0,0 +1,262 @@ +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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.15.sigs b/ldb-2.0.8/ABI/ldb-1.1.15.sigs new file mode 100644 index 0000000..eac5194 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.15.sigs @@ -0,0 +1,262 @@ +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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.16.sigs b/ldb-2.0.8/ABI/ldb-1.1.16.sigs new file mode 100644 index 0000000..eac5194 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.16.sigs @@ -0,0 +1,262 @@ +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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.17.sigs b/ldb-2.0.8/ABI/ldb-1.1.17.sigs new file mode 100644 index 0000000..eac5194 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.17.sigs @@ -0,0 +1,262 @@ +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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.18.sigs b/ldb-2.0.8/ABI/ldb-1.1.18.sigs new file mode 100644 index 0000000..eac5194 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.18.sigs @@ -0,0 +1,262 @@ +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_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_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_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/ldb-2.0.8/ABI/ldb-1.1.19.sigs b/ldb-2.0.8/ABI/ldb-1.1.19.sigs new file mode 100644 index 0000000..b46c5c7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.19.sigs @@ -0,0 +1,263 @@ +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_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_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/ldb-2.0.8/ABI/ldb-1.1.2.sigs b/ldb-2.0.8/ABI/ldb-1.1.2.sigs new file mode 100644 index 0000000..d0df756 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.2.sigs @@ -0,0 +1,256 @@ +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_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_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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.20.sigs b/ldb-2.0.8/ABI/ldb-1.1.20.sigs new file mode 100644 index 0000000..b46c5c7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.20.sigs @@ -0,0 +1,263 @@ +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_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_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/ldb-2.0.8/ABI/ldb-1.1.21.sigs b/ldb-2.0.8/ABI/ldb-1.1.21.sigs new file mode 100644 index 0000000..b46c5c7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.21.sigs @@ -0,0 +1,263 @@ +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_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_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/ldb-2.0.8/ABI/ldb-1.1.22.sigs b/ldb-2.0.8/ABI/ldb-1.1.22.sigs new file mode 100644 index 0000000..6d9767b --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.22.sigs @@ -0,0 +1,264 @@ +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_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/ldb-2.0.8/ABI/ldb-1.1.23.sigs b/ldb-2.0.8/ABI/ldb-1.1.23.sigs new file mode 100644 index 0000000..6d9767b --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.23.sigs @@ -0,0 +1,264 @@ +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_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/ldb-2.0.8/ABI/ldb-1.1.24.sigs b/ldb-2.0.8/ABI/ldb-1.1.24.sigs new file mode 100644 index 0000000..6d9767b --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.24.sigs @@ -0,0 +1,264 @@ +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_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/ldb-2.0.8/ABI/ldb-1.1.25.sigs b/ldb-2.0.8/ABI/ldb-1.1.25.sigs new file mode 100644 index 0000000..3f33df9 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.25.sigs @@ -0,0 +1,265 @@ +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_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/ldb-2.0.8/ABI/ldb-1.1.26.sigs b/ldb-2.0.8/ABI/ldb-1.1.26.sigs new file mode 100644 index 0000000..3f33df9 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.26.sigs @@ -0,0 +1,265 @@ +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_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/ldb-2.0.8/ABI/ldb-1.1.27.sigs b/ldb-2.0.8/ABI/ldb-1.1.27.sigs new file mode 100644 index 0000000..4fa30d8 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/ABI/ldb-1.1.28.sigs b/ldb-2.0.8/ABI/ldb-1.1.28.sigs new file mode 100644 index 0000000..4fa30d8 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/ABI/ldb-1.1.29.sigs b/ldb-2.0.8/ABI/ldb-1.1.29.sigs new file mode 100644 index 0000000..0ea968d --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/ABI/ldb-1.1.3.sigs b/ldb-2.0.8/ABI/ldb-1.1.3.sigs new file mode 100644 index 0000000..d0df756 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.3.sigs @@ -0,0 +1,256 @@ +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_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_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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.30.sigs b/ldb-2.0.8/ABI/ldb-1.1.30.sigs new file mode 100644 index 0000000..ef9c53e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.30.sigs @@ -0,0 +1,272 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.1.31.sigs b/ldb-2.0.8/ABI/ldb-1.1.31.sigs new file mode 100644 index 0000000..d183708 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.31.sigs @@ -0,0 +1,274 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.1.4.sigs b/ldb-2.0.8/ABI/ldb-1.1.4.sigs new file mode 100644 index 0000000..d0df756 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.4.sigs @@ -0,0 +1,256 @@ +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_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_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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.5.sigs b/ldb-2.0.8/ABI/ldb-1.1.5.sigs new file mode 100644 index 0000000..cc0f859 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.5.sigs @@ -0,0 +1,257 @@ +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_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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.6.sigs b/ldb-2.0.8/ABI/ldb-1.1.6.sigs new file mode 100644 index 0000000..f90fa13 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.6.sigs @@ -0,0 +1,258 @@ +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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.7.sigs b/ldb-2.0.8/ABI/ldb-1.1.7.sigs new file mode 100644 index 0000000..f90fa13 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.7.sigs @@ -0,0 +1,258 @@ +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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.8.sigs b/ldb-2.0.8/ABI/ldb-1.1.8.sigs new file mode 100644 index 0000000..f90fa13 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.8.sigs @@ -0,0 +1,258 @@ +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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.1.9.sigs b/ldb-2.0.8/ABI/ldb-1.1.9.sigs new file mode 100644 index 0000000..f90fa13 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.1.9.sigs @@ -0,0 +1,258 @@ +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_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_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_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_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_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_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/ldb-2.0.8/ABI/ldb-1.2.0.sigs b/ldb-2.0.8/ABI/ldb-1.2.0.sigs new file mode 100644 index 0000000..1be2ae7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.2.0.sigs @@ -0,0 +1,276 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.2.1.sigs b/ldb-2.0.8/ABI/ldb-1.2.1.sigs new file mode 100644 index 0000000..1be2ae7 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.2.1.sigs @@ -0,0 +1,276 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.2.2.sigs b/ldb-2.0.8/ABI/ldb-1.2.2.sigs new file mode 100644 index 0000000..9dc61cd --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.2.2.sigs @@ -0,0 +1,277 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.2.3.sigs b/ldb-2.0.8/ABI/ldb-1.2.3.sigs new file mode 100644 index 0000000..9dc61cd --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.2.3.sigs @@ -0,0 +1,277 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.3.0.sigs b/ldb-2.0.8/ABI/ldb-1.3.0.sigs new file mode 100644 index 0000000..a31b84e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.3.0.sigs @@ -0,0 +1,279 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.3.1.sigs b/ldb-2.0.8/ABI/ldb-1.3.1.sigs new file mode 100644 index 0000000..a31b84e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.3.1.sigs @@ -0,0 +1,279 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.3.2.sigs b/ldb-2.0.8/ABI/ldb-1.3.2.sigs new file mode 100644 index 0000000..a31b84e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.3.2.sigs @@ -0,0 +1,279 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.4.0.sigs b/ldb-2.0.8/ABI/ldb-1.4.0.sigs new file mode 100644 index 0000000..a31b84e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.4.0.sigs @@ -0,0 +1,279 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.4.1.sigs b/ldb-2.0.8/ABI/ldb-1.4.1.sigs new file mode 100644 index 0000000..a31b84e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.4.1.sigs @@ -0,0 +1,279 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.5.0.sigs b/ldb-2.0.8/ABI/ldb-1.5.0.sigs new file mode 100644 index 0000000..a31b84e --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.5.0.sigs @@ -0,0 +1,279 @@ +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.5.1.sigs b/ldb-2.0.8/ABI/ldb-1.5.1.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.5.1.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.5.2.sigs b/ldb-2.0.8/ABI/ldb-1.5.2.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.5.2.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.5.3.sigs b/ldb-2.0.8/ABI/ldb-1.5.3.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.5.3.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.6.0.sigs b/ldb-2.0.8/ABI/ldb-1.6.0.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.6.0.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.6.1.sigs b/ldb-2.0.8/ABI/ldb-1.6.1.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.6.1.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.6.2.sigs b/ldb-2.0.8/ABI/ldb-1.6.2.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.6.2.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-1.6.3.sigs b/ldb-2.0.8/ABI/ldb-1.6.3.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-1.6.3.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-2.0.0.sigs b/ldb-2.0.8/ABI/ldb-2.0.0.sigs new file mode 100644 index 0000000..0c1234f --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.0.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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/ldb-2.0.8/ABI/ldb-2.0.1.sigs b/ldb-2.0.8/ABI/ldb-2.0.1.sigs new file mode 100644 index 0000000..f782d73 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.1.sigs @@ -0,0 +1,280 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, 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/ldb-2.0.8/ABI/ldb-2.0.2.sigs b/ldb-2.0.8/ABI/ldb-2.0.2.sigs new file mode 100644 index 0000000..5fc5560 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.2.sigs @@ -0,0 +1,281 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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 *, uint32_t) +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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +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/ldb-2.0.8/ABI/ldb-2.0.3.sigs b/ldb-2.0.8/ABI/ldb-2.0.3.sigs new file mode 100644 index 0000000..5fc5560 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.3.sigs @@ -0,0 +1,281 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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 *, uint32_t) +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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +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/ldb-2.0.8/ABI/ldb-2.0.4.sigs b/ldb-2.0.8/ABI/ldb-2.0.4.sigs new file mode 100644 index 0000000..446804b --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.4.sigs @@ -0,0 +1,282 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_copy: const char **(TALLOC_CTX *, const char **) +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 *, uint32_t) +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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +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/ldb-2.0.8/ABI/ldb-2.0.5.sigs b/ldb-2.0.8/ABI/ldb-2.0.5.sigs new file mode 100644 index 0000000..5049dc6 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.5.sigs @@ -0,0 +1,283 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +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/ldb-2.0.8/ABI/ldb-2.0.6.sigs b/ldb-2.0.8/ABI/ldb-2.0.6.sigs new file mode 100644 index 0000000..5049dc6 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.6.sigs @@ -0,0 +1,283 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +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/ldb-2.0.8/ABI/ldb-2.0.7.sigs b/ldb-2.0.8/ABI/ldb-2.0.7.sigs new file mode 100644 index 0000000..5049dc6 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.7.sigs @@ -0,0 +1,283 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +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/ldb-2.0.8/ABI/ldb-2.0.8.sigs b/ldb-2.0.8/ABI/ldb-2.0.8.sigs new file mode 100644 index 0000000..5049dc6 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-2.0.8.sigs @@ -0,0 +1,283 @@ +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_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +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_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +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_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +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_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +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_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_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_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: 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_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +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_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +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_require_private_event_context: void (struct ldb_context *) +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_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +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/ldb-2.0.8/ABI/ldb-ildap-0.9.12.sigs b/ldb-2.0.8/ABI/ldb-ildap-0.9.12.sigs new file mode 100644 index 0000000..4639220 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-ildap-0.9.12.sigs @@ -0,0 +1,224 @@ +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 *(void *, 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 *(void *, const char *, int) +ldb_binary_decode: struct ldb_val (void *, const char *) +ldb_binary_encode: char *(void *, struct ldb_val) +ldb_binary_encode_string: char *(void *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, const char *, size_t) +ldb_casefold_default: char *(void *, void *, const char *, size_t) +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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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 *(void *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(void *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(void *, struct ldb_dn *) +ldb_dn_canonical_string: char *(void *, 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 *(void *, struct ldb_dn *) +ldb_dn_escape_value: char *(void *, 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 *(void *, 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_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(void *, struct ldb_dn *, int) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(void *, 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_new: struct ldb_dn *(void *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(void *, 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_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_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 *(void *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +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_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, void *, 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 *(void *) +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_parse_control_strings: struct ldb_control **(struct ldb_context *, void *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(void *, 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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_fn) +ldb_register_module: int (const struct ldb_module_ops *) +ldb_register_samba_handlers: int (struct ldb_context *) +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_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_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +ldb_samba_syntax_by_lDAPDisplayName: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +ldb_samba_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +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_val_dup: struct ldb_val (void *, 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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) +ldb_wrap_connect: struct ldb_context *(TALLOC_CTX *, struct tevent_context *, struct loadparm_context *, const char *, struct auth_session_info *, struct cli_credentials *, unsigned int) +ldb_wrap_fork_hook: void (void) diff --git a/ldb-2.0.8/ABI/ldb-samba4-0.9.10.sigs b/ldb-2.0.8/ABI/ldb-samba4-0.9.10.sigs new file mode 100644 index 0000000..7f9dbb5 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-samba4-0.9.10.sigs @@ -0,0 +1,223 @@ +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 *(void *, 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 *(void *, const char *, int) +ldb_binary_decode: struct ldb_val (void *, const char *) +ldb_binary_encode: char *(void *, struct ldb_val) +ldb_binary_encode_string: char *(void *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, const char *, size_t) +ldb_casefold_default: char *(void *, void *, const char *, size_t) +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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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 *(void *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(void *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(void *, struct ldb_dn *) +ldb_dn_canonical_string: char *(void *, 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 *(void *, struct ldb_dn *) +ldb_dn_escape_value: char *(void *, 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 *(void *, 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_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(void *, struct ldb_dn *, int) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(void *, 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_new: struct ldb_dn *(void *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(void *, 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_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_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 *(void *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +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_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, void *, 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 *(void *) +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_parse_control_strings: struct ldb_control **(struct ldb_context *, void *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(void *, 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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_fn) +ldb_register_module: int (const struct ldb_module_ops *) +ldb_register_samba_handlers: int (struct ldb_context *) +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_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_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +ldb_samba_syntax_by_lDAPDisplayName: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +ldb_samba_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +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_val_dup: struct ldb_val (void *, 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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) +ldb_wrap_connect: struct ldb_context *(TALLOC_CTX *, struct tevent_context *, struct loadparm_context *, const char *, struct auth_session_info *, struct cli_credentials *, unsigned int) +ldb_wrap_fork_hook: void (void) diff --git a/ldb-2.0.8/ABI/ldb-samba4-0.9.11.sigs b/ldb-2.0.8/ABI/ldb-samba4-0.9.11.sigs new file mode 100644 index 0000000..4639220 --- /dev/null +++ b/ldb-2.0.8/ABI/ldb-samba4-0.9.11.sigs @@ -0,0 +1,224 @@ +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 *(void *, 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 *(void *, const char *, int) +ldb_binary_decode: struct ldb_val (void *, const char *) +ldb_binary_encode: char *(void *, struct ldb_val) +ldb_binary_encode_string: char *(void *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, 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 *, void *, const char *, size_t) +ldb_casefold_default: char *(void *, void *, const char *, size_t) +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_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +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 *(void *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(void *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(void *, struct ldb_dn *) +ldb_dn_canonical_string: char *(void *, 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 *(void *, struct ldb_dn *) +ldb_dn_escape_value: char *(void *, 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 *(void *, 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_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(void *, struct ldb_dn *, int) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(void *, 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_new: struct ldb_dn *(void *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(void *, 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_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_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 *(void *, 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_init_module_chain: int (struct ldb_context *, struct ldb_module *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +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_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_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_load_modules_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +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_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +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_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +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_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +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_private: void (struct ldb_module *, void *) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, 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_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_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, void *, 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 *(void *) +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_parse_control_strings: struct ldb_control **(struct ldb_context *, void *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(void *, 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_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_fn) +ldb_register_module: int (const struct ldb_module_ops *) +ldb_register_samba_handlers: int (struct ldb_context *) +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_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_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +ldb_samba_syntax_by_lDAPDisplayName: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +ldb_samba_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +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_val_dup: struct ldb_val (void *, 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_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) +ldb_wrap_connect: struct ldb_context *(TALLOC_CTX *, struct tevent_context *, struct loadparm_context *, const char *, struct auth_session_info *, struct cli_credentials *, unsigned int) +ldb_wrap_fork_hook: void (void) diff --git a/ldb-2.0.8/ABI/pyldb-util-1.1.10.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.10.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.10.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/ldb-2.0.8/ABI/pyldb-util-1.1.11.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.11.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.11.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/ldb-2.0.8/ABI/pyldb-util-1.1.12.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.12.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.12.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/ldb-2.0.8/ABI/pyldb-util-1.1.13.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.13.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.13.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/ldb-2.0.8/ABI/pyldb-util-1.1.14.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.14.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.14.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/ldb-2.0.8/ABI/pyldb-util-1.1.15.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.15.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.15.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/ldb-2.0.8/ABI/pyldb-util-1.1.16.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.16.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.16.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/ldb-2.0.8/ABI/pyldb-util-1.1.17.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.17.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.17.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/ldb-2.0.8/ABI/pyldb-util-1.1.18.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.18.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.18.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/ldb-2.0.8/ABI/pyldb-util-1.1.19.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.19.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.19.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/ldb-2.0.8/ABI/pyldb-util-1.1.2.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.2.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.2.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/ldb-2.0.8/ABI/pyldb-util-1.1.20.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.20.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.20.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/ldb-2.0.8/ABI/pyldb-util-1.1.21.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.21.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.21.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/ldb-2.0.8/ABI/pyldb-util-1.1.22.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.22.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.22.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/ldb-2.0.8/ABI/pyldb-util-1.1.23.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.23.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.23.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/ldb-2.0.8/ABI/pyldb-util-1.1.24.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.24.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.24.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/ldb-2.0.8/ABI/pyldb-util-1.1.25.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.25.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.25.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/ldb-2.0.8/ABI/pyldb-util-1.1.26.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.26.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.26.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/ldb-2.0.8/ABI/pyldb-util-1.1.27.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.27.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/ABI/pyldb-util-1.1.28.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.28.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/ABI/pyldb-util-1.1.29.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.29.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/ABI/pyldb-util-1.1.3.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.3.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.3.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/ldb-2.0.8/ABI/pyldb-util-1.1.30.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.30.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.30.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/ldb-2.0.8/ABI/pyldb-util-1.1.31.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.31.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.31.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/ldb-2.0.8/ABI/pyldb-util-1.1.4.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.4.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.4.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/ldb-2.0.8/ABI/pyldb-util-1.1.5.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.5.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.5.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/ldb-2.0.8/ABI/pyldb-util-1.1.6.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.6.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.6.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/ldb-2.0.8/ABI/pyldb-util-1.1.7.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.7.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.7.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/ldb-2.0.8/ABI/pyldb-util-1.1.8.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.8.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.8.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/ldb-2.0.8/ABI/pyldb-util-1.1.9.sigs b/ldb-2.0.8/ABI/pyldb-util-1.1.9.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.1.9.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/ldb-2.0.8/ABI/pyldb-util-1.2.0.sigs b/ldb-2.0.8/ABI/pyldb-util-1.2.0.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.2.0.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/ldb-2.0.8/ABI/pyldb-util-1.2.1.sigs b/ldb-2.0.8/ABI/pyldb-util-1.2.1.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.2.1.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/ldb-2.0.8/ABI/pyldb-util-1.2.2.sigs b/ldb-2.0.8/ABI/pyldb-util-1.2.2.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.2.2.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/ldb-2.0.8/ABI/pyldb-util-1.2.3.sigs b/ldb-2.0.8/ABI/pyldb-util-1.2.3.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.2.3.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/ldb-2.0.8/ABI/pyldb-util-1.3.0.sigs b/ldb-2.0.8/ABI/pyldb-util-1.3.0.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.3.0.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/ldb-2.0.8/ABI/pyldb-util-1.3.1.sigs b/ldb-2.0.8/ABI/pyldb-util-1.3.1.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.3.1.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/ldb-2.0.8/ABI/pyldb-util-1.3.2.sigs b/ldb-2.0.8/ABI/pyldb-util-1.3.2.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.3.2.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/ldb-2.0.8/ABI/pyldb-util-1.4.0.sigs b/ldb-2.0.8/ABI/pyldb-util-1.4.0.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.4.0.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/ldb-2.0.8/ABI/pyldb-util-1.4.1.sigs b/ldb-2.0.8/ABI/pyldb-util-1.4.1.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.4.1.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/ldb-2.0.8/ABI/pyldb-util-1.5.0.sigs b/ldb-2.0.8/ABI/pyldb-util-1.5.0.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.5.0.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/ldb-2.0.8/ABI/pyldb-util-1.5.1.sigs b/ldb-2.0.8/ABI/pyldb-util-1.5.1.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.5.1.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/ldb-2.0.8/ABI/pyldb-util-1.5.2.sigs b/ldb-2.0.8/ABI/pyldb-util-1.5.2.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.5.2.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/ldb-2.0.8/ABI/pyldb-util-1.5.3.sigs b/ldb-2.0.8/ABI/pyldb-util-1.5.3.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.5.3.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/ldb-2.0.8/ABI/pyldb-util-1.6.0.sigs b/ldb-2.0.8/ABI/pyldb-util-1.6.0.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.6.0.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/ldb-2.0.8/ABI/pyldb-util-1.6.1.sigs b/ldb-2.0.8/ABI/pyldb-util-1.6.1.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.6.1.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/ldb-2.0.8/ABI/pyldb-util-1.6.2.sigs b/ldb-2.0.8/ABI/pyldb-util-1.6.2.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.6.2.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/ldb-2.0.8/ABI/pyldb-util-1.6.3.sigs b/ldb-2.0.8/ABI/pyldb-util-1.6.3.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-1.6.3.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/ldb-2.0.8/ABI/pyldb-util-2.0.0.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.0.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.0.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/ldb-2.0.8/ABI/pyldb-util-2.0.1.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.1.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.1.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/ldb-2.0.8/ABI/pyldb-util-2.0.2.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.2.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.2.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/ldb-2.0.8/ABI/pyldb-util-2.0.3.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.3.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.3.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/ldb-2.0.8/ABI/pyldb-util-2.0.4.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.4.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.4.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/ldb-2.0.8/ABI/pyldb-util-2.0.5.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.5.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.5.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/ldb-2.0.8/ABI/pyldb-util-2.0.6.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.6.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.6.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/ldb-2.0.8/ABI/pyldb-util-2.0.7.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.7.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.7.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/ldb-2.0.8/ABI/pyldb-util-2.0.8.sigs b/ldb-2.0.8/ABI/pyldb-util-2.0.8.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util-2.0.8.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/ldb-2.0.8/ABI/pyldb-util.py3-2.0.0.sigs b/ldb-2.0.8/ABI/pyldb-util.py3-2.0.0.sigs new file mode 100644 index 0000000..74d6719 --- /dev/null +++ b/ldb-2.0.8/ABI/pyldb-util.py3-2.0.0.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/ldb-2.0.8/Doxyfile b/ldb-2.0.8/Doxyfile new file mode 100644 index 0000000..07b12b5 --- /dev/null +++ b/ldb-2.0.8/Doxyfile @@ -0,0 +1,26 @@ +PROJECT_NAME = LDB +OUTPUT_DIRECTORY = apidocs +REPEAT_BRIEF = YES +OPTIMIZE_OUTPUT_FOR_C = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +GENERATE_TODOLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +SHOW_USED_FILES = NO +SHOW_DIRECTORIES = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +INPUT = include . +FILE_PATTERNS = *.h *.dox +EXCLUDE = include/config.h include/dlinklist.h \ + include/includes.h +EXAMPLE_PATH = examples +GENERATE_HTML = YES +HTML_OUTPUT = html +GENERATE_MAN = YES +ALWAYS_DETAILED_SEC = YES +JAVADOC_AUTOBRIEF = YES diff --git a/ldb-2.0.8/Makefile b/ldb-2.0.8/Makefile new file mode 100644 index 0000000..b82723f --- /dev/null +++ b/ldb-2.0.8/Makefile @@ -0,0 +1,53 @@ +# simple makefile wrapper to run waf + +WAF_BIN=`PATH=buildtools/bin:../../buildtools/bin:$$PATH which waf` +WAF_BINARY=$(PYTHON) $(WAF_BIN) +WAF=PYTHONHASHSEED=1 WAF_MAKE=1 $(WAF_BINARY) + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: + $(WAF) test $(TEST_OPTIONS) + +dist: + touch .tmplock + WAFLOCK=.tmplock $(WAF) dist + +distcheck: + touch .tmplock + WAFLOCK=.tmplock $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags diff --git a/ldb-2.0.8/README_gcov.txt b/ldb-2.0.8/README_gcov.txt new file mode 100644 index 0000000..2abd937 --- /dev/null +++ b/ldb-2.0.8/README_gcov.txt @@ -0,0 +1,29 @@ +Here is how to use gcov to test code coverage in ldb. + +Step 1: build ldb with gcov enabled + + make clean all WITH_GCOV=1 + +Step 3: run the test suite + make test-tdb + +Step 4: produce the gcov report + make gcov + +Step 5: read the summary reports + less *.report.gcov + +Step 6: examine the per-file reports + less ldb_tdb\#ldb_tdb.c.gcov + +You can also combine steps 2 to 4 like this: + + make clean all test-tdb gcov WITH_GCOV=1 + +Note that you should not expect 100% coverage, as some error paths +(such as memory allocation failures) are very hard to trigger. There +are ways of working around this, but they are quite tricky (they +involve allocation wrappers that "fork and fail on malloc"). + +The lines to look for in the per-file reports are the ones starting +with "#####". Those are lines that are never executed. diff --git a/ldb-2.0.8/_ldb_text.py b/ldb-2.0.8/_ldb_text.py new file mode 100644 index 0000000..e0505e1 --- /dev/null +++ b/ldb-2.0.8/_ldb_text.py @@ -0,0 +1,146 @@ +# Text wrapper for ldb bindings +# +# Copyright (C) 2015 Petr Viktorin +# Published under the GNU LGPLv3 or later + +import ldb + + +def _recursive_encode(obj): + if isinstance(obj, bytes): + return obj + elif isinstance(obj, str): + return obj.encode('utf-8') + else: + return [_recursive_encode(o) for o in obj] + + +class _WrapBase(object): + + @classmethod + def _wrap(cls, wrapped): + self = cls.__new__(cls) + self._wrapped = wrapped + return self + + def __len__(self): + return len(self._wrapped) + + def __eq__(self, other): + if hasattr(other, '_wrapped'): + return self._wrapped == other._wrapped + else: + return self._wrapped == other + + def __ne__(self, other): + if hasattr(other, '_wrapped'): + return self._wrapped != other._wrapped + else: + return self._wrapped != other + + def __lt__(self, other): + if hasattr(other, '_wrapped'): + return self._wrapped < other._wrapped + else: + return self._wrapped < other + + def __le__(self, other): + if hasattr(other, '_wrapped'): + return self._wrapped >= other._wrapped + else: + return self._wrapped >= other + + def __gt__(self, other): + if hasattr(other, '_wrapped'): + return self._wrapped > other._wrapped + else: + return self._wrapped > other + + def __ge__(self, other): + if hasattr(other, '_wrapped'): + return self._wrapped >= other._wrapped + else: + return self._wrapped >= other + + def __repr__(self): + return '%s.text' % repr(self._wrapped) + + +class MessageElementTextWrapper(_WrapBase): + + """Text interface for a LDB message element""" + + def __iter__(self): + for item in self._wrapped: + yield item.decode('utf-8') + + def __getitem__(self, key): + result = self._wrapped[key] + if result is None: + return None + else: + return result.decode('utf-8') + + @property + def flags(self): + return self._wrapped.flags + + @property + def set_flags(self): + return self._wrapped.set_flags + + +_wrap_element = MessageElementTextWrapper._wrap + + +class MessageTextWrapper(_WrapBase): + + """Text interface for a LDB message""" + + def __getitem__(self, key): + result = self._wrapped[key] + if result is None: + return None + else: + return _wrap_element(result) + + def get(self, *args, **kwargs): + result = self._wrapped.get(*args, **kwargs) + if isinstance(result, ldb.MessageElement): + return _wrap_element(result) + elif isinstance(result, bytes): + return result.decode('utf-8') + else: + return result + + def __setitem__(self, key, item): + self._wrapped[key] = _recursive_encode(item) + + def __delitem__(self, key): + del self._wrapped[key] + + def elements(self): + return [_wrap_element(el) for el in self._wrapped.elements()] + + def items(self): + return [(attr, _wrap_element(el)) for attr, el in self._wrapped.items()] + + @property + def keys(self): + return self._wrapped.keys + + @property + def remove(self): + return self._wrapped.remove + + @property + def add(self): + return self._wrapped.add + + @property + def dn(self): + return self._wrapped.dn + + @dn.setter + def dn(self, new_value): + self._wrapped.dn = new_value diff --git a/ldb-2.0.8/buildtools/README b/ldb-2.0.8/buildtools/README new file mode 100644 index 0000000..eab0382 --- /dev/null +++ b/ldb-2.0.8/buildtools/README @@ -0,0 +1,12 @@ +See http://code.google.com/p/waf/ for more information on waf + +You can get a svn copy of the upstream source with: + + svn checkout http://waf.googlecode.com/svn/trunk/ waf-read-only + +Samba currently uses waf 1.5, which can be found at: + + http://waf.googlecode.com/svn/branches/waf-1.5 + +To update the current copy of waf, use the update-waf.sh script in this +directory. diff --git a/ldb-2.0.8/buildtools/bin/waf b/ldb-2.0.8/buildtools/bin/waf new file mode 100755 index 0000000..11ce8e7 --- /dev/null +++ b/ldb-2.0.8/buildtools/bin/waf @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# encoding: latin-1 +# Thomas Nagy, 2005-2018 +# +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +import os, sys, inspect + +VERSION="2.0.18" +REVISION="x" +GIT="x" +INSTALL="x" +C1='x' +C2='x' +C3='x' +cwd = os.getcwd() +join = os.path.join + +if sys.hexversion<0x206000f: + raise ImportError('Python >= 2.6 is required to create the waf file') + +WAF='waf' +def b(x): + return x +if sys.hexversion>0x300000f: + WAF='waf3' + def b(x): + return x.encode() + +def err(m): + print(('\033[91mError: %s\033[0m' % m)) + sys.exit(1) + +def unpack_wafdir(dir, src): + f = open(src,'rb') + c = 'corrupt archive (%d)' + while 1: + line = f.readline() + if not line: err('run waf-light from a folder containing waflib') + if line == b('#==>\n'): + txt = f.readline() + if not txt: err(c % 1) + if f.readline() != b('#<==\n'): err(c % 2) + break + if not txt: err(c % 3) + txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: + for x in ('Tools', 'extras'): + os.makedirs(join(dir, 'waflib', x)) + except OSError: + err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) + + os.chdir(dir) + tmp = 't.bz2' + t = open(tmp,'wb') + try: t.write(txt) + finally: t.close() + + try: + t = tarfile.open(tmp) + except: + try: + os.system('bunzip2 t.bz2') + t = tarfile.open('t') + tmp = 't' + except: + os.chdir(cwd) + try: shutil.rmtree(dir) + except OSError: pass + err("Waf cannot be unpacked, check that bzip2 support is present") + + try: + for x in t: t.extract(x) + finally: + t.close() + + for x in ('Tools', 'extras'): + os.chmod(join('waflib',x), 493) + + if sys.hexversion<0x300000f: + sys.path = [join(dir, 'waflib')] + sys.path + import fixpy2 + fixpy2.fixdir(dir) + + os.remove(tmp) + os.chdir(cwd) + + try: dir = unicode(dir, 'mbcs') + except: pass + try: + from ctypes import windll + windll.kernel32.SetFileAttributesW(dir, 2) + except: + pass + +def test(dir): + try: + os.stat(join(dir, 'waflib')) + return os.path.abspath(dir) + except OSError: + pass + +def find_lib(): + path = '../../third_party/waf' + paths = [path, path+'/waflib'] + return [os.path.abspath(os.path.join(os.path.dirname(__file__), x)) for x in paths] + +wafdir = find_lib() +for p in wafdir: + sys.path.insert(0, p) + +if __name__ == '__main__': + #import extras.compat15#PRELUDE + import sys + + from waflib.Tools import ccroot, c, ar, compiler_c, gcc + sys.modules['cc'] = c + sys.modules['ccroot'] = ccroot + sys.modules['ar'] = ar + sys.modules['compiler_cc'] = compiler_c + sys.modules['gcc'] = gcc + + from waflib import Options + Options.lockfile = os.environ.get('WAFLOCK', '.lock-wscript') + if os.path.isfile(Options.lockfile) and os.stat(Options.lockfile).st_size == 0: + os.environ['NOCLIMB'] = "1" + # there is a single top-level, but libraries must build independently + os.environ['NO_LOCK_IN_TOP'] = "1" + + from waflib import Task + class o(object): + display = None + Task.classes['cc_link'] = o + + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir[0]) + diff --git a/ldb-2.0.8/buildtools/compare_config_h4.sh b/ldb-2.0.8/buildtools/compare_config_h4.sh new file mode 100755 index 0000000..b78b36f --- /dev/null +++ b/ldb-2.0.8/buildtools/compare_config_h4.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# compare the generated config.h from a waf build with existing samba +# build + +grep "^.define" bin/default/source4/include/config.h | sort > waf-config.h +grep "^.define" $HOME/samba_old/source4/include/config.h | sort > old-config.h + +comm -23 old-config.h waf-config.h + +#echo +#diff -u old-config.h waf-config.h diff --git a/ldb-2.0.8/buildtools/compare_generated.sh b/ldb-2.0.8/buildtools/compare_generated.sh new file mode 100755 index 0000000..ebef8a9 --- /dev/null +++ b/ldb-2.0.8/buildtools/compare_generated.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# compare the generated files from a waf + +old_build=$HOME/samba_old + +gen_files=$(cd bin/default && find . -type f -name '*.[ch]') + +2>&1 + +strip_file() +{ + in_file=$1 + out_file=$2 + cat $in_file | + grep -v 'The following definitions come from' | + grep -v 'Automatically generated at' | + grep -v 'Generated from' | + sed 's|/home/tnagy/samba/source4||g' | + sed 's|/home/tnagy/samba/|../|g' | + sed 's|bin/default/source4/||g' | + sed 's|bin/default/|../|g' | + sed 's/define _____/define ___/g' | + sed 's/define __*/define _/g' | + sed 's/define _DEFAULT_/define _/g' | + sed 's/define _SOURCE4_/define ___/g' | + sed 's/define ___/define _/g' | + sed 's/ifndef ___/ifndef _/g' | + sed 's|endif /* ____|endif /* __|g' | + sed s/__DEFAULT_SOURCE4/__/ | + sed s/__DEFAULT_SOURCE4/__/ | + sed s/__DEFAULT/____/ > $out_file +} + +compare_file() +{ + f=$f + bname=$(basename $f) + t1=/tmp/$bname.old.$$ + t2=/tmp/$bname.new.$$ + strip_file $old_build/$f $t1 + strip_file bin/default/$f $t2 + diff -u -b $t1 $t2 2>&1 + rm -f $t1 $t2 +} + +for f in $gen_files; do + compare_file $f +done + diff --git a/ldb-2.0.8/buildtools/compare_install.sh b/ldb-2.0.8/buildtools/compare_install.sh new file mode 100755 index 0000000..b964117 --- /dev/null +++ b/ldb-2.0.8/buildtools/compare_install.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +prefix1="$1" +prefix2="$2" + +(cd $prefix1 && find . ) | sort > p1.txt +(cd $prefix2 && find . ) | sort > p2.txt +diff -u p[12].txt diff --git a/ldb-2.0.8/buildtools/examples/run_on_target.py b/ldb-2.0.8/buildtools/examples/run_on_target.py new file mode 100755 index 0000000..79c5730 --- /dev/null +++ b/ldb-2.0.8/buildtools/examples/run_on_target.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 + +# +# Sample run-on-target script +# This is a script that can be used as cross-execute parameter to samba +# configuration process, running the command on a remote target for which +# the cross-compiled configure test was compiled. +# +# To use: +# ./configure \ +# --cross-compile \ +# '--cross-execute=./buildtools/example/run_on_target.py --host=' +# +# A more elaborate example: +# ./configure \ +# --cross-compile \ +# '--cross-execute=./buildtools/example/run_on_target.py --host= --user= "--ssh=ssh -i " --destdir=/path/to/dir' +# +# Typically this is to be used also with --cross-answers, so that the +# cross answers file gets built and further builds can be made without +# the help of a remote target. +# +# The following assumptions are made: +# 1. rsync is available on build machine and target machine +# 2. A running ssh service on target machine with password-less shell login +# 3. A directory writable by the password-less login user +# 4. The tests on the target can run and provide reliable results +# from the login account's home directory. This is significant +# for example in locking tests which +# create files in the current directory. As a workaround to this +# assumption, the TESTDIR environment variable can be set on the target +# (using ssh command line or server config) and the tests shall +# chdir to that directory. +# + +import sys +import os +import subprocess +from optparse import OptionParser + +# those are defaults, but can be overidden using command line +SSH = 'ssh' +USER = None +HOST = 'localhost' + + +def xfer_files(ssh, srcdir, host, user, targ_destdir): + """Transfer executable files to target + + Use rsync to copy the directory containing program to run + INTO a destination directory on the target. An exact copy + of the source directory is created on the target machine, + possibly deleting files on the target machine which do not + exist on the source directory. + + The idea is that the test may include files in addition to + the compiled binary, and all of those files reside alongside + the binary in a source directory. + + For example, if the test to run is /foo/bar/test and the + destination directory on the target is /tbaz, then /tbaz/bar + on the target shall be an exact copy of /foo/bar on the source, + including deletion of files inside /tbaz/bar which do not exist + on the source. + """ + + userhost = host + if user: + userhost = '%s@%s' % (user, host) + + cmd = 'rsync --verbose -rl --ignore-times --delete -e "%s" %s %s:%s/' % \ + (ssh, srcdir, userhost, targ_destdir) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = p.communicate() + if p.returncode != 0: + raise Exception('failed syncing files\n stdout:\n%s\nstderr:%s\n' + % (out, err)) + + +def exec_remote(ssh, host, user, destdir, targdir, prog, args): + """Run a test on the target + + Using password-less ssh, run the compiled binary on the target. + + An assumption is that there's no need to cd into the target dir, + same as there's no need to do it on a native build. + """ + userhost = host + if user: + userhost = '%s@%s' % (user, host) + + cmd = '%s %s %s/%s/%s' % (ssh, userhost, destdir, targdir, prog) + if args: + cmd = cmd + ' ' + ' '.join(args) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = p.communicate() + return (p.returncode, out) + + +def main(argv): + usage = "usage: %prog [options] [args]" + parser = OptionParser(usage) + + parser.add_option('--ssh', help="SSH client and additional flags", + default=SSH) + parser.add_option('--host', help="target host name or IP address", + default=HOST) + parser.add_option('--user', help="login user on target", + default=USER) + parser.add_option('--destdir', help="work directory on target", + default='~') + + (options, args) = parser.parse_args(argv) + if len(args) < 1: + parser.error("please supply test program to run") + + progpath = args[0] + + # assume that a test that was not compiled fails (e.g. getconf) + if progpath[0] != '/': + return (1, "") + + progdir = os.path.dirname(progpath) + prog = os.path.basename(progpath) + targ_progdir = os.path.basename(progdir) + + xfer_files( + options.ssh, + progdir, + options.host, + options.user, + options.destdir) + + (rc, out) = exec_remote(options.ssh, + options.host, + options.user, + options.destdir, + targ_progdir, + prog, args[1:]) + return (rc, out) + + +if __name__ == '__main__': + (rc, out) = main(sys.argv[1:]) + sys.stdout.write(out) + sys.exit(rc) diff --git a/ldb-2.0.8/buildtools/scripts/Makefile.waf b/ldb-2.0.8/buildtools/scripts/Makefile.waf new file mode 100644 index 0000000..5fc939c --- /dev/null +++ b/ldb-2.0.8/buildtools/scripts/Makefile.waf @@ -0,0 +1,72 @@ +# simple makefile wrapper to run waf + +WAF_BINARY=BUILDTOOLS/bin/waf +WAF=WAF_MAKE=1 $(WAF_BINARY) + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: + $(WAF) test $(TEST_OPTIONS) + +help: + @echo NOTE: to run extended waf options use $(WAF_BINARY) or modify your PATH + $(WAF) --help + +testenv: + $(WAF) test --testenv $(TEST_OPTIONS) + +quicktest: + $(WAF) test --quick $(TEST_OPTIONS) + +dist: + $(WAF) dist + +distcheck: + $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +torture: all + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags + +bin/%:: FORCE + $(WAF) --targets=$@ +FORCE: + +configure: autogen-waf.sh BUILDTOOLS/scripts/configure.waf + ./autogen-waf.sh + +Makefile: autogen-waf.sh configure BUILDTOOLS/scripts/Makefile.waf + ./autogen-waf.sh diff --git a/ldb-2.0.8/buildtools/scripts/abi_gen.sh b/ldb-2.0.8/buildtools/scripts/abi_gen.sh new file mode 100755 index 0000000..6dd6d32 --- /dev/null +++ b/ldb-2.0.8/buildtools/scripts/abi_gen.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# generate a set of ABI signatures from a shared library + +SHAREDLIB="$1" + +GDBSCRIPT="gdb_syms.$$" + +( +cat < $GDBSCRIPT + +# forcing the terminal avoids a problem on Fedora12 +TERM=none gdb -n -batch -x $GDBSCRIPT "$SHAREDLIB" < /dev/null +rm -f $GDBSCRIPT diff --git a/ldb-2.0.8/buildtools/scripts/autogen-waf.sh b/ldb-2.0.8/buildtools/scripts/autogen-waf.sh new file mode 100755 index 0000000..7a6e94c --- /dev/null +++ b/ldb-2.0.8/buildtools/scripts/autogen-waf.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +p=`dirname $0` + +echo "Setting up for waf build" + +echo "Looking for the buildtools directory" + +d="buildtools" +while test \! -d "$p/$d"; do d="../$d"; done + +echo "Found buildtools in $p/$d" + +echo "Setting up configure" +rm -f $p/configure $p/include/config*.h* +sed "s|BUILDTOOLS|$d|g;s|BUILDPATH|$p|g" < "$p/$d/scripts/configure.waf" > $p/configure +chmod +x $p/configure + +echo "Setting up Makefile" +rm -f $p/makefile $p/Makefile +sed "s|BUILDTOOLS|$d|g" < "$p/$d/scripts/Makefile.waf" > $p/Makefile + +echo "done. Now run $p/configure or $p/configure.developer then make." +if [ $p != "." ]; then + echo "Notice: The build invoke path is not 'source4'! Use make with the parameter" + echo "-C <'source4' path>. Example: make -C source4 all" +fi diff --git a/ldb-2.0.8/buildtools/scripts/configure.waf b/ldb-2.0.8/buildtools/scripts/configure.waf new file mode 100755 index 0000000..a7d8d1d --- /dev/null +++ b/ldb-2.0.8/buildtools/scripts/configure.waf @@ -0,0 +1,14 @@ +#!/bin/sh + +PREVPATH=`dirname $0` + +WAF=BUILDTOOLS/bin/waf + +# using JOBS=1 gives maximum compatibility with +# systems like AIX which have broken threading in python +JOBS=1 +export JOBS + +cd BUILDPATH || exit 1 +$WAF configure "$@" || exit 1 +cd $PREVPATH diff --git a/ldb-2.0.8/buildtools/testwaf.sh b/ldb-2.0.8/buildtools/testwaf.sh new file mode 100755 index 0000000..127e525 --- /dev/null +++ b/ldb-2.0.8/buildtools/testwaf.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -e +set -x + +d=$(dirname $0) + +cd $d/.. +PREFIX=$HOME/testprefix + +if [ $# -gt 0 ]; then + tests="$*" +else + tests="lib/replace lib/talloc lib/tevent lib/tdb lib/ldb" +fi + +echo "testing in dirs $tests" + +for d in $tests; do + echo "`date`: testing $d" + pushd $d + rm -rf bin + type waf + waf dist + ./configure -C --enable-developer --prefix=$PREFIX + time make + make install + make distcheck + case $d in + "lib/ldb") + ldd bin/ldbadd + ;; + "lib/replace") + ldd bin/replace_testsuite + ;; + "lib/talloc") + ldd bin/talloc_testsuite + ;; + "lib/tdb") + ldd bin/tdbtool + ;; + esac + popd +done + +echo "testing python portability" +pushd lib/talloc +versions="python2.4 python2.5 python2.6 python3.0 python3.1" +for p in $versions; do + ret=$(which $p || echo "failed") + if [ $ret = "failed" ]; then + echo "$p not found, skipping" + continue + fi + echo "Testing $p" + $p ../../buildtools/bin/waf configure -C --enable-developer --prefix=$PREFIX + $p ../../buildtools/bin/waf build install +done +popd + +echo "testing cross compiling" +pushd lib/talloc +ret=$(which arm-linux-gnueabi-gcc || echo "failed") +if [ $ret != "failed" ]; then + CC=arm-linux-gnueabi-gcc ./configure -C --prefix=$PREFIX --cross-compile --cross-execute='runarm' + make && make install +else + echo "Cross-compiler not installed, skipping test" +fi +popd diff --git a/ldb-2.0.8/buildtools/wafsamba/README b/ldb-2.0.8/buildtools/wafsamba/README new file mode 100644 index 0000000..1968b55 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/README @@ -0,0 +1,8 @@ +This is a set of waf 'tools' to help make building the Samba +components easier, by having common functions in one place. This gives +us a more consistent build, and ensures that our project rules are +obeyed + + +TODO: + see http://wiki.samba.org/index.php/Waf diff --git a/ldb-2.0.8/buildtools/wafsamba/__init__.py b/ldb-2.0.8/buildtools/wafsamba/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ldb-2.0.8/buildtools/wafsamba/configure_file.py b/ldb-2.0.8/buildtools/wafsamba/configure_file.py new file mode 100644 index 0000000..6ad4354 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/configure_file.py @@ -0,0 +1,41 @@ +# handle substitution of variables in .in files + +import sys +import re +import os +from waflib import Build, Logs +from samba_utils import SUBST_VARS_RECURSIVE + +def subst_at_vars(task): + '''substiture @VAR@ style variables in a file''' + + env = task.env + s = task.inputs[0].read() + + # split on the vars + a = re.split('(@\w+@)', s) + out = [] + for v in a: + if re.match('@\w+@', v): + vname = v[1:-1] + if not vname in task.env and vname.upper() in task.env: + vname = vname.upper() + if not vname in task.env: + Logs.error("Unknown substitution %s in %s" % (v, task.name)) + sys.exit(1) + v = SUBST_VARS_RECURSIVE(task.env[vname], task.env) + out.append(v) + contents = ''.join(out) + task.outputs[0].write(contents) + return 0 + +def CONFIGURE_FILE(bld, in_file, **kwargs): + '''configure file''' + + base=os.path.basename(in_file) + t = bld.SAMBA_GENERATOR('INFILE_%s' % base, + rule = subst_at_vars, + source = in_file + '.in', + target = in_file, + vars = kwargs) +Build.BuildContext.CONFIGURE_FILE = CONFIGURE_FILE diff --git a/ldb-2.0.8/buildtools/wafsamba/generic_cc.py b/ldb-2.0.8/buildtools/wafsamba/generic_cc.py new file mode 100644 index 0000000..1352c54 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/generic_cc.py @@ -0,0 +1,70 @@ + +# compiler definition for a generic C compiler +# based on suncc.py from waf + +import os, optparse +from waflib import Errors +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +# +# Let waflib provide useful defaults, but +# provide generic_cc as last resort fallback on +# all platforms +# +from waflib.Tools.compiler_c import c_compiler +for key in c_compiler.keys(): + c_compiler[key].append('generic_cc') + +@conf +def find_generic_cc(conf): + v = conf.env + cc = None + if v.CC: + cc = v.CC + elif 'CC' in conf.environ: + cc = conf.environ['CC'] + if not cc: + cc = conf.find_program('cc', var='CC') + if not cc: + conf.fatal('generic_cc was not found') + + try: + conf.cmd_and_log(cc + ['--version']) + except Errors.WafError: + conf.fatal('%r --version could not be executed' % cc) + + v.CC = cc + v.CC_NAME = 'generic_cc' + +@conf +def generic_cc_common_flags(conf): + v = conf.env + + v.CC_SRC_F = '' + v.CC_TGT_F = ['-c', '-o'] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + if not v.LINK_CC: + v.LINK_CC = v.CC + + v.CCLNK_SRC_F = '' + v.CCLNK_TGT_F = ['-o'] + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + + v.cprogram_PATTERN = '%s' + v.cshlib_PATTERN = 'lib%s.so' + v.cstlib_PATTERN = 'lib%s.a' + +def configure(conf): + conf.find_generic_cc() + conf.find_ar() + conf.generic_cc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/buildtools/wafsamba/pkgconfig.py b/ldb-2.0.8/buildtools/wafsamba/pkgconfig.py new file mode 100644 index 0000000..b83d5f3 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/pkgconfig.py @@ -0,0 +1,68 @@ +# handle substitution of variables in pc files + +import os, re, sys +from waflib import Build, Logs +from samba_utils import SUBST_VARS_RECURSIVE, TO_LIST + +def subst_at_vars(task): + '''substiture @VAR@ style variables in a file''' + + s = task.inputs[0].read() + # split on the vars + a = re.split('(@\w+@)', s) + out = [] + done_var = {} + back_sub = [ ('PREFIX', '${prefix}'), ('EXEC_PREFIX', '${exec_prefix}')] + for v in a: + if re.match('@\w+@', v): + vname = v[1:-1] + if not vname in task.env and vname.upper() in task.env: + vname = vname.upper() + if not vname in task.env: + Logs.error("Unknown substitution %s in %s" % (v, task.name)) + sys.exit(1) + v = SUBST_VARS_RECURSIVE(task.env[vname], task.env) + # now we back substitute the allowed pc vars + for (b, m) in back_sub: + s = task.env[b] + if s == v[0:len(s)]: + if not b in done_var: + # we don't want to substitute the first usage + done_var[b] = True + else: + v = m + v[len(s):] + break + out.append(v) + contents = ''.join(out) + task.outputs[0].write(contents) + return 0 + + +def PKG_CONFIG_FILES(bld, pc_files, vnum=None, extra_name=None): + '''install some pkg_config pc files''' + dest = '${PKGCONFIGDIR}' + dest = bld.EXPAND_VARIABLES(dest) + for f in TO_LIST(pc_files): + if extra_name: + target = f.split('.pc')[0] + extra_name + ".pc" + else: + target = f + base=os.path.basename(target) + t = bld.SAMBA_GENERATOR('PKGCONFIG_%s' % base, + rule=subst_at_vars, + source=f+'.in', + target=target) + bld.add_manual_dependency(bld.path.find_or_declare(f), bld.env['PREFIX'].encode('utf8')) + t.vars = [] + if t.env.RPATH_ON_INSTALL: + t.env.LIB_RPATH = t.env.RPATH_ST % t.env.LIBDIR + else: + t.env.LIB_RPATH = '' + if vnum: + t.env.PACKAGE_VERSION = vnum + for v in [ 'PREFIX', 'EXEC_PREFIX', 'LIB_RPATH' ]: + t.vars.append(t.env[v]) + bld.INSTALL_FILES(dest, target, flat=True, destname=base) +Build.BuildContext.PKG_CONFIG_FILES = PKG_CONFIG_FILES + + diff --git a/ldb-2.0.8/buildtools/wafsamba/samba3.py b/ldb-2.0.8/buildtools/wafsamba/samba3.py new file mode 100644 index 0000000..5aab250 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba3.py @@ -0,0 +1,105 @@ +# a waf tool to add autoconf-like macros to the configure section +# and for SAMBA_ macros for building libraries, binaries etc + +import os +from waflib import Build +from samba_utils import os_path_relpath, TO_LIST +from samba_autoconf import library_flags + +def SAMBA3_IS_STATIC_MODULE(bld, module): + '''Check whether module is in static list''' + if module in bld.env['static_modules']: + return True + return False +Build.BuildContext.SAMBA3_IS_STATIC_MODULE = SAMBA3_IS_STATIC_MODULE + +def SAMBA3_IS_SHARED_MODULE(bld, module): + '''Check whether module is in shared list''' + if module in bld.env['shared_modules']: + return True + return False +Build.BuildContext.SAMBA3_IS_SHARED_MODULE = SAMBA3_IS_SHARED_MODULE + +def SAMBA3_IS_ENABLED_MODULE(bld, module): + '''Check whether module is in either shared or static list ''' + return SAMBA3_IS_STATIC_MODULE(bld, module) or SAMBA3_IS_SHARED_MODULE(bld, module) +Build.BuildContext.SAMBA3_IS_ENABLED_MODULE = SAMBA3_IS_ENABLED_MODULE + + + +def s3_fix_kwargs(bld, kwargs): + '''fix the build arguments for s3 build rules to include the + necessary includes, subdir and cflags options ''' + s3dir = os.path.join(bld.env.srcdir, 'source3') + s3reldir = os_path_relpath(s3dir, bld.path.abspath()) + + # the extra_includes list is relative to the source3 directory + extra_includes = [ '.', 'include', 'lib' ] + # local heimdal paths only included when USING_SYSTEM_KRB5 is not set + if not bld.CONFIG_SET("USING_SYSTEM_KRB5"): + extra_includes += [ '../source4/heimdal/lib/com_err', + '../source4/heimdal/lib/krb5', + '../source4/heimdal/lib/gssapi', + '../source4/heimdal_build', + '../bin/default/source4/heimdal/lib/asn1' ] + + if bld.CONFIG_SET('USING_SYSTEM_TDB'): + (tdb_includes, tdb_ldflags, tdb_cpppath) = library_flags(bld, 'tdb') + extra_includes += tdb_cpppath + else: + extra_includes += [ '../lib/tdb/include' ] + + if bld.CONFIG_SET('USING_SYSTEM_TEVENT'): + (tevent_includes, tevent_ldflags, tevent_cpppath) = library_flags(bld, 'tevent') + extra_includes += tevent_cpppath + else: + extra_includes += [ '../lib/tevent' ] + + if bld.CONFIG_SET('USING_SYSTEM_TALLOC'): + (talloc_includes, talloc_ldflags, talloc_cpppath) = library_flags(bld, 'talloc') + extra_includes += talloc_cpppath + else: + extra_includes += [ '../lib/talloc' ] + + if bld.CONFIG_SET('USING_SYSTEM_POPT'): + (popt_includes, popt_ldflags, popt_cpppath) = library_flags(bld, 'popt') + extra_includes += popt_cpppath + else: + extra_includes += [ '../lib/popt' ] + + # s3 builds assume that they will have a bunch of extra include paths + includes = [] + for d in extra_includes: + includes += [ os.path.join(s3reldir, d) ] + + # the rule may already have some includes listed + if 'includes' in kwargs: + includes += TO_LIST(kwargs['includes']) + kwargs['includes'] = includes + +# these wrappers allow for mixing of S3 and S4 build rules in the one build + +def SAMBA3_LIBRARY(bld, name, *args, **kwargs): + s3_fix_kwargs(bld, kwargs) + return bld.SAMBA_LIBRARY(name, *args, **kwargs) +Build.BuildContext.SAMBA3_LIBRARY = SAMBA3_LIBRARY + +def SAMBA3_MODULE(bld, name, *args, **kwargs): + s3_fix_kwargs(bld, kwargs) + return bld.SAMBA_MODULE(name, *args, **kwargs) +Build.BuildContext.SAMBA3_MODULE = SAMBA3_MODULE + +def SAMBA3_SUBSYSTEM(bld, name, *args, **kwargs): + s3_fix_kwargs(bld, kwargs) + return bld.SAMBA_SUBSYSTEM(name, *args, **kwargs) +Build.BuildContext.SAMBA3_SUBSYSTEM = SAMBA3_SUBSYSTEM + +def SAMBA3_BINARY(bld, name, *args, **kwargs): + s3_fix_kwargs(bld, kwargs) + return bld.SAMBA_BINARY(name, *args, **kwargs) +Build.BuildContext.SAMBA3_BINARY = SAMBA3_BINARY + +def SAMBA3_PYTHON(bld, name, *args, **kwargs): + s3_fix_kwargs(bld, kwargs) + return bld.SAMBA_PYTHON(name, *args, **kwargs) +Build.BuildContext.SAMBA3_PYTHON = SAMBA3_PYTHON diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_abi.py b/ldb-2.0.8/buildtools/wafsamba/samba_abi.py new file mode 100644 index 0000000..5e7686d --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_abi.py @@ -0,0 +1,261 @@ +# functions for handling ABI checking of libraries + +import os +import sys +import re +import fnmatch + +from waflib import Options, Utils, Logs, Task, Build, Errors +from waflib.TaskGen import feature, before, after +from wafsamba import samba_utils + +# these type maps cope with platform specific names for common types +# please add new type mappings into the list below +abi_type_maps = { + '_Bool' : 'bool', + 'struct __va_list_tag *' : 'va_list' + } + +version_key = lambda x: list(map(int, x.split("."))) + +def normalise_signature(sig): + '''normalise a signature from gdb''' + sig = sig.strip() + sig = re.sub('^\$[0-9]+\s=\s\{(.+)\}$', r'\1', sig) + sig = re.sub('^\$[0-9]+\s=\s\{(.+)\}(\s0x[0-9a-f]+\s<\w+>)+$', r'\1', sig) + sig = re.sub('^\$[0-9]+\s=\s(0x[0-9a-f]+)\s?(<\w+>)?$', r'\1', sig) + sig = re.sub('0x[0-9a-f]+', '0xXXXX', sig) + sig = re.sub('", ', r'\1"', sig) + + for t in abi_type_maps: + # we need to cope with non-word characters in mapped types + m = t + m = m.replace('*', '\*') + if m[-1].isalnum() or m[-1] == '_': + m += '\\b' + if m[0].isalnum() or m[0] == '_': + m = '\\b' + m + sig = re.sub(m, abi_type_maps[t], sig) + return sig + + +def normalise_varargs(sig): + '''cope with older versions of gdb''' + sig = re.sub(',\s\.\.\.', '', sig) + return sig + + +def parse_sigs(sigs, abi_match): + '''parse ABI signatures file''' + abi_match = samba_utils.TO_LIST(abi_match) + ret = {} + a = sigs.split('\n') + for s in a: + if s.find(':') == -1: + continue + sa = s.split(':') + if abi_match: + matched = False + negative = False + for p in abi_match: + if p[0] == '!' and fnmatch.fnmatch(sa[0], p[1:]): + negative = True + break + elif fnmatch.fnmatch(sa[0], p): + matched = True + break + if (not matched) and negative: + continue + Logs.debug("%s -> %s" % (sa[1], normalise_signature(sa[1]))) + ret[sa[0]] = normalise_signature(sa[1]) + return ret + +def save_sigs(sig_file, parsed_sigs): + '''save ABI signatures to a file''' + sigs = '' + for s in sorted(parsed_sigs.keys()): + sigs += '%s: %s\n' % (s, parsed_sigs[s]) + return samba_utils.save_file(sig_file, sigs, create_dir=True) + + +def abi_check_task(self): + '''check if the ABI has changed''' + abi_gen = self.ABI_GEN + + libpath = self.inputs[0].abspath(self.env) + libname = os.path.basename(libpath) + + sigs = samba_utils.get_string(Utils.cmd_output([abi_gen, libpath])) + parsed_sigs = parse_sigs(sigs, self.ABI_MATCH) + + sig_file = self.ABI_FILE + + old_sigs = samba_utils.load_file(sig_file) + if old_sigs is None or Options.options.ABI_UPDATE: + if not save_sigs(sig_file, parsed_sigs): + raise Errors.WafError('Failed to save ABI file "%s"' % sig_file) + Logs.warn('Generated ABI signatures %s' % sig_file) + return + + parsed_old_sigs = parse_sigs(old_sigs, self.ABI_MATCH) + + # check all old sigs + got_error = False + for s in parsed_old_sigs: + if not s in parsed_sigs: + Logs.error('%s: symbol %s has been removed - please update major version\n\tsignature: %s' % ( + libname, s, parsed_old_sigs[s])) + got_error = True + elif normalise_varargs(parsed_old_sigs[s]) != normalise_varargs(parsed_sigs[s]): + Logs.error('%s: symbol %s has changed - please update major version\n\told_signature: %s\n\tnew_signature: %s' % ( + libname, s, parsed_old_sigs[s], parsed_sigs[s])) + got_error = True + + for s in parsed_sigs: + if not s in parsed_old_sigs: + Logs.error('%s: symbol %s has been added - please mark it _PRIVATE_ or update minor version\n\tsignature: %s' % ( + libname, s, parsed_sigs[s])) + got_error = True + + if got_error: + raise Errors.WafError('ABI for %s has changed - please fix library version then build with --abi-update\nSee http://wiki.samba.org/index.php/Waf#ABI_Checking for more information\nIf you have not changed any ABI, and your platform always gives this error, please configure with --abi-check-disable to skip this check' % libname) + + +t = Task.task_factory('abi_check', abi_check_task, color='BLUE', ext_in='.bin') +t.quiet = True +# allow "waf --abi-check" to force re-checking the ABI +if '--abi-check' in sys.argv: + t.always_run = True + +@after('apply_link') +@feature('abi_check') +def abi_check(self): + '''check that ABI matches saved signatures''' + env = self.bld.env + if not env.ABI_CHECK or self.abi_directory is None: + return + + # if the platform doesn't support -fvisibility=hidden then the ABI + # checks become fairly meaningless + if not env.HAVE_VISIBILITY_ATTR: + return + + topsrc = self.bld.srcnode.abspath() + abi_gen = os.path.join(topsrc, 'buildtools/scripts/abi_gen.sh') + + abi_file = "%s/%s-%s.sigs" % (self.abi_directory, self.version_libname, + self.vnum) + + tsk = self.create_task('abi_check', self.link_task.outputs[0]) + tsk.ABI_FILE = abi_file + tsk.ABI_MATCH = self.abi_match + tsk.ABI_GEN = abi_gen + + +def abi_process_file(fname, version, symmap): + '''process one ABI file, adding new symbols to the symmap''' + for line in Utils.readf(fname).splitlines(): + symname = line.split(":")[0] + if not symname in symmap: + symmap[symname] = version + + +def abi_write_vscript(f, libname, current_version, versions, symmap, abi_match): + """Write a vscript file for a library in --version-script format. + + :param f: File-like object to write to + :param libname: Name of the library, uppercased + :param current_version: Current version + :param versions: Versions to consider + :param symmap: Dictionary mapping symbols -> version + :param abi_match: List of symbols considered to be public in the current + version + """ + + invmap = {} + for s in symmap: + invmap.setdefault(symmap[s], []).append(s) + + last_key = "" + versions = sorted(versions, key=version_key) + for k in versions: + symver = "%s_%s" % (libname, k) + if symver == current_version: + break + f.write("%s {\n" % symver) + if k in sorted(invmap.keys()): + f.write("\tglobal:\n") + for s in invmap.get(k, []): + f.write("\t\t%s;\n" % s); + f.write("}%s;\n\n" % last_key) + last_key = " %s" % symver + f.write("%s {\n" % current_version) + local_abi = list(filter(lambda x: x[0] == '!', abi_match)) + global_abi = list(filter(lambda x: x[0] != '!', abi_match)) + f.write("\tglobal:\n") + if len(global_abi) > 0: + for x in global_abi: + f.write("\t\t%s;\n" % x) + else: + f.write("\t\t*;\n") + # Always hide symbols that must be local if exist + local_abi.extend(["!_end", "!__bss_start", "!_edata"]) + f.write("\tlocal:\n") + for x in local_abi: + f.write("\t\t%s;\n" % x[1:]) + if global_abi != ["*"]: + if len(global_abi) > 0: + f.write("\t\t*;\n") + f.write("};\n") + + +def abi_build_vscript(task): + '''generate a vscript file for our public libraries''' + + tgt = task.outputs[0].bldpath(task.env) + + symmap = {} + versions = [] + for f in task.inputs: + fname = f.abspath(task.env) + basename = os.path.basename(fname) + version = basename[len(task.env.LIBNAME)+1:-len(".sigs")] + versions.append(version) + abi_process_file(fname, version, symmap) + f = open(tgt, mode='w') + try: + abi_write_vscript(f, task.env.LIBNAME, task.env.VERSION, versions, + symmap, task.env.ABI_MATCH) + finally: + f.close() + + +def ABI_VSCRIPT(bld, libname, abi_directory, version, vscript, abi_match=None): + '''generate a vscript file for our public libraries''' + if abi_directory: + source = bld.path.ant_glob('%s/%s-[0-9]*.sigs' % (abi_directory, libname), flat=True) + def abi_file_key(path): + return version_key(path[:-len(".sigs")].rsplit("-")[-1]) + source = sorted(source.split(), key=abi_file_key) + else: + source = '' + + libname = os.path.basename(libname) + version = os.path.basename(version) + libname = libname.replace("-", "_").replace("+","_").upper() + version = version.replace("-", "_").replace("+","_").upper() + + t = bld.SAMBA_GENERATOR(vscript, + rule=abi_build_vscript, + source=source, + group='vscripts', + target=vscript) + if abi_match is None: + abi_match = ["*"] + else: + abi_match = samba_utils.TO_LIST(abi_match) + t.env.ABI_MATCH = abi_match + t.env.VERSION = version + t.env.LIBNAME = libname + t.vars = ['LIBNAME', 'VERSION', 'ABI_MATCH'] +Build.BuildContext.ABI_VSCRIPT = ABI_VSCRIPT diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_autoconf.py b/ldb-2.0.8/buildtools/wafsamba/samba_autoconf.py new file mode 100644 index 0000000..62d3e20 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_autoconf.py @@ -0,0 +1,948 @@ +# a waf tool to add autoconf-like macros to the configure section + +import os, sys +from waflib import Build, Options, Logs, Context +from waflib.Configure import conf +from waflib.TaskGen import feature +from waflib.Tools import c_preproc as preproc +from samba_utils import TO_LIST, GET_TARGET_TYPE, SET_TARGET_TYPE, unique_list, mkdir_p + +missing_headers = set() + +#################################################### +# some autoconf like helpers, to make the transition +# to waf a bit easier for those used to autoconf +# m4 files + +@conf +def DEFINE(conf, d, v, add_to_cflags=False, quote=False): + '''define a config option''' + conf.define(d, v, quote=quote) + if add_to_cflags: + conf.env.append_value('CFLAGS', '-D%s=%s' % (d, str(v))) + +def hlist_to_string(conf, headers=None): + '''convert a headers list to a set of #include lines''' + hdrs='' + hlist = conf.env.hlist + if headers: + hlist = hlist[:] + hlist.extend(TO_LIST(headers)) + for h in hlist: + hdrs += '#include <%s>\n' % h + return hdrs + + +@conf +def COMPOUND_START(conf, msg): + '''start a compound test''' + def null_check_message_1(self,*k,**kw): + return + def null_check_message_2(self,*k,**kw): + return + + v = getattr(conf.env, 'in_compound', []) + if v != [] and v != 0: + conf.env.in_compound = v + 1 + return + conf.start_msg(msg) + conf.saved_check_message_1 = conf.start_msg + conf.start_msg = null_check_message_1 + conf.saved_check_message_2 = conf.end_msg + conf.end_msg = null_check_message_2 + conf.env.in_compound = 1 + + +@conf +def COMPOUND_END(conf, result): + '''start a compound test''' + conf.env.in_compound -= 1 + if conf.env.in_compound != 0: + return + conf.start_msg = conf.saved_check_message_1 + conf.end_msg = conf.saved_check_message_2 + p = conf.end_msg + if result is True: + p('ok') + elif not result: + p('not found', 'YELLOW') + else: + p(result) + + +@feature('nolink') +def nolink(self): + '''using the nolink type in conf.check() allows us to avoid + the link stage of a test, thus speeding it up for tests + that where linking is not needed''' + pass + + +def CHECK_HEADER(conf, h, add_headers=False, lib=None): + '''check for a header''' + if h in missing_headers and lib is None: + return False + d = h.upper().replace('/', '_') + d = d.replace('.', '_') + d = d.replace('-', '_') + d = 'HAVE_%s' % d + if CONFIG_SET(conf, d): + if add_headers: + if not h in conf.env.hlist: + conf.env.hlist.append(h) + return True + + (ccflags, ldflags, cpppath) = library_flags(conf, lib) + + hdrs = hlist_to_string(conf, headers=h) + if lib is None: + lib = "" + ret = conf.check(fragment='%s\nint main(void) { return 0; }\n' % hdrs, + type='nolink', + execute=0, + cflags=ccflags, + mandatory=False, + includes=cpppath, + uselib=lib.upper(), + msg="Checking for header %s" % h) + if not ret: + missing_headers.add(h) + return False + + conf.DEFINE(d, 1) + if add_headers and not h in conf.env.hlist: + conf.env.hlist.append(h) + return ret + + +@conf +def CHECK_HEADERS(conf, headers, add_headers=False, together=False, lib=None): + '''check for a list of headers + + when together==True, then the headers accumulate within this test. + This is useful for interdependent headers + ''' + ret = True + if not add_headers and together: + saved_hlist = conf.env.hlist[:] + set_add_headers = True + else: + set_add_headers = add_headers + for hdr in TO_LIST(headers): + if not CHECK_HEADER(conf, hdr, set_add_headers, lib=lib): + ret = False + if not add_headers and together: + conf.env.hlist = saved_hlist + return ret + + +def header_list(conf, headers=None, lib=None): + '''form a list of headers which exist, as a string''' + hlist=[] + if headers is not None: + for h in TO_LIST(headers): + if CHECK_HEADER(conf, h, add_headers=False, lib=lib): + hlist.append(h) + return hlist_to_string(conf, headers=hlist) + + +@conf +def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None): + '''check for a single type''' + if define is None: + define = 'HAVE_' + t.upper().replace(' ', '_') + if msg is None: + msg='Checking for %s' % t + ret = CHECK_CODE(conf, '%s _x' % t, + define, + execute=False, + headers=headers, + local_include=False, + msg=msg, + lib=lib, + link=False) + if not ret and alternate: + conf.DEFINE(t, alternate) + return ret + + +@conf +def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None): + '''check for a list of types''' + ret = True + for t in TO_LIST(list): + if not CHECK_TYPE(conf, t, headers=headers, + define=define, alternate=alternate, lib=lib): + ret = False + return ret + + +@conf +def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None): + '''check for a single type with a header''' + return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define) + + +@conf +def CHECK_VARIABLE(conf, v, define=None, always=False, + headers=None, msg=None, lib=None): + '''check for a variable declaration (or define)''' + if define is None: + define = 'HAVE_%s' % v.upper() + + if msg is None: + msg="Checking for variable %s" % v + + return CHECK_CODE(conf, + # we need to make sure the compiler doesn't + # optimize it out... + ''' + #ifndef %s + void *_x; _x=(void *)&%s; return (int)_x; + #endif + return 0 + ''' % (v, v), + execute=False, + link=False, + msg=msg, + local_include=False, + lib=lib, + headers=headers, + define=define, + always=always) + + +@conf +def CHECK_DECLS(conf, vars, reverse=False, headers=None, always=False): + '''check a list of variable declarations, using the HAVE_DECL_xxx form + of define + + When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx + ''' + ret = True + for v in TO_LIST(vars): + if not reverse: + define='HAVE_DECL_%s' % v.upper() + else: + define='HAVE_%s_DECL' % v.upper() + if not CHECK_VARIABLE(conf, v, + define=define, + headers=headers, + msg='Checking for declaration of %s' % v, + always=always): + if not CHECK_CODE(conf, + ''' + return (int)%s; + ''' % (v), + execute=False, + link=False, + msg='Checking for declaration of %s (as enum)' % v, + local_include=False, + headers=headers, + define=define, + always=always): + ret = False + return ret + + +def CHECK_FUNC(conf, f, link=True, lib=None, headers=None): + '''check for a function''' + define='HAVE_%s' % f.upper() + + ret = False + + in_lib_str = "" + if lib: + in_lib_str = " in %s" % lib + conf.COMPOUND_START('Checking for %s%s' % (f, in_lib_str)) + + if link is None or link: + ret = CHECK_CODE(conf, + # this is based on the autoconf strategy + ''' + #define %s __fake__%s + #ifdef HAVE_LIMITS_H + # include + #else + # include + #endif + #undef %s + #if defined __stub_%s || defined __stub___%s + #error "bad glibc stub" + #endif + extern char %s(); + int main() { return %s(); } + ''' % (f, f, f, f, f, f, f), + execute=False, + link=True, + addmain=False, + add_headers=False, + define=define, + local_include=False, + lib=lib, + headers=headers, + msg='Checking for %s' % f) + + if not ret: + ret = CHECK_CODE(conf, + # it might be a macro + # we need to make sure the compiler doesn't + # optimize it out... + 'void *__x = (void *)%s; return (int)__x' % f, + execute=False, + link=True, + addmain=True, + add_headers=True, + define=define, + local_include=False, + lib=lib, + headers=headers, + msg='Checking for macro %s' % f) + + if not ret and (link is None or not link): + ret = CHECK_VARIABLE(conf, f, + define=define, + headers=headers, + msg='Checking for declaration of %s' % f) + conf.COMPOUND_END(ret) + return ret + + +@conf +def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None): + '''check for a list of functions''' + ret = True + for f in TO_LIST(list): + if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers): + ret = False + return ret + + +@conf +def CHECK_SIZEOF(conf, vars, headers=None, define=None, critical=True): + '''check the size of a type''' + for v in TO_LIST(vars): + v_define = define + ret = False + if v_define is None: + v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_') + for size in list((1, 2, 4, 8, 16, 32, 64)): + if CHECK_CODE(conf, + 'static int test_array[1 - 2 * !(((long int)(sizeof(%s))) <= %d)];' % (v, size), + define=v_define, + quote=False, + headers=headers, + local_include=False, + msg="Checking if size of %s == %d" % (v, size)): + conf.DEFINE(v_define, size) + ret = True + break + if not ret and critical: + Logs.error("Couldn't determine size of '%s'" % v) + sys.exit(1) + return ret + +@conf +def CHECK_VALUEOF(conf, v, headers=None, define=None): + '''check the value of a variable/define''' + ret = True + v_define = define + if v_define is None: + v_define = 'VALUEOF_%s' % v.upper().replace(' ', '_') + if CHECK_CODE(conf, + 'printf("%%u", (unsigned)(%s))' % v, + define=v_define, + execute=True, + define_ret=True, + quote=False, + headers=headers, + local_include=False, + msg="Checking value of %s" % v): + return int(conf.env[v_define]) + + return None + +@conf +def CHECK_CODE(conf, code, define, + always=False, execute=False, addmain=True, + add_headers=True, mandatory=False, + headers=None, msg=None, cflags='', includes='# .', + local_include=True, lib=None, link=True, + define_ret=False, quote=False, + on_target=True, strict=False): + '''check if some code compiles and/or runs''' + + if CONFIG_SET(conf, define): + return True + + if headers is not None: + CHECK_HEADERS(conf, headers=headers, lib=lib) + + if add_headers: + hdrs = header_list(conf, headers=headers, lib=lib) + else: + hdrs = '' + if execute: + execute = 1 + else: + execute = 0 + + if addmain: + fragment='%s\n int main(void) { %s; return 0; }\n' % (hdrs, code) + else: + fragment='%s\n%s\n' % (hdrs, code) + + if msg is None: + msg="Checking for %s" % define + + cflags = TO_LIST(cflags) + + # Be strict when relying on a compiler check + # Some compilers (e.g. xlc) ignore non-supported features as warnings + if strict: + if 'WERROR_CFLAGS' in conf.env: + cflags.extend(conf.env['WERROR_CFLAGS']) + + if local_include: + cflags.append('-I%s' % conf.path.abspath()) + + if not link: + type='nolink' + else: + type='cprogram' + + uselib = TO_LIST(lib) + + (ccflags, ldflags, cpppath) = library_flags(conf, uselib) + + includes = TO_LIST(includes) + includes.extend(cpppath) + + uselib = [l.upper() for l in uselib] + + cflags.extend(ccflags) + + if on_target: + test_args = conf.SAMBA_CROSS_ARGS(msg=msg) + else: + test_args = [] + + conf.COMPOUND_START(msg) + + try: + ret = conf.check(fragment=fragment, + execute=execute, + define_name = define, + cflags=cflags, + ldflags=ldflags, + includes=includes, + uselib=uselib, + type=type, + msg=msg, + quote=quote, + test_args=test_args, + define_ret=define_ret) + except Exception: + if always: + conf.DEFINE(define, 0) + else: + conf.undefine(define) + conf.COMPOUND_END(False) + if mandatory: + raise + return False + else: + # Success is indicated by ret but we should unset + # defines set by WAF's c_config.check() because it + # defines it to int(ret) and we want to undefine it + if not ret: + conf.undefine(define) + conf.COMPOUND_END(False) + return False + if not define_ret: + conf.DEFINE(define, 1) + conf.COMPOUND_END(True) + else: + conf.DEFINE(define, ret, quote=quote) + conf.COMPOUND_END(ret) + return True + + +@conf +def CHECK_STRUCTURE_MEMBER(conf, structname, member, + always=False, define=None, headers=None, + lib=None): + '''check for a structure member''' + if define is None: + define = 'HAVE_%s' % member.upper() + return CHECK_CODE(conf, + '%s s; void *_x; _x=(void *)&s.%s' % (structname, member), + define, + execute=False, + link=False, + lib=lib, + always=always, + headers=headers, + local_include=False, + msg="Checking for member %s in %s" % (member, structname)) + + +@conf +def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n'): + '''check if the given cflags are accepted by the compiler + ''' + check_cflags = TO_LIST(cflags) + if 'WERROR_CFLAGS' in conf.env: + check_cflags.extend(conf.env['WERROR_CFLAGS']) + return conf.check(fragment=fragment, + execute=0, + mandatory=False, + type='nolink', + cflags=check_cflags, + msg="Checking compiler accepts %s" % cflags) + +@conf +def CHECK_LDFLAGS(conf, ldflags): + '''check if the given ldflags are accepted by the linker + ''' + return conf.check(fragment='int main(void) { return 0; }\n', + execute=0, + ldflags=ldflags, + mandatory=False, + msg="Checking linker accepts %s" % ldflags) + + +@conf +def CONFIG_GET(conf, option): + '''return True if a configuration option was found''' + if (option in conf.env): + return conf.env[option] + else: + return None + +@conf +def CONFIG_SET(conf, option): + '''return True if a configuration option was found''' + if option not in conf.env: + return False + v = conf.env[option] + if v is None: + return False + if v == []: + return False + if v == (): + return False + return True + +@conf +def CONFIG_RESET(conf, option): + if option not in conf.env: + return + del conf.env[option] + +Build.BuildContext.CONFIG_RESET = CONFIG_RESET +Build.BuildContext.CONFIG_SET = CONFIG_SET +Build.BuildContext.CONFIG_GET = CONFIG_GET + + +def library_flags(self, libs): + '''work out flags from pkg_config''' + ccflags = [] + ldflags = [] + cpppath = [] + for lib in TO_LIST(libs): + # note that we do not add the -I and -L in here, as that is added by the waf + # core. Adding it here would just change the order that it is put on the link line + # which can cause system paths to be added before internal libraries + extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), [])) + extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), [])) + extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), [])) + ccflags.extend(extra_ccflags) + ldflags.extend(extra_ldflags) + cpppath.extend(extra_cpppath) + + extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), [])) + cpppath.extend(extra_cpppath) + if 'EXTRA_LDFLAGS' in self.env: + ldflags.extend(self.env['EXTRA_LDFLAGS']) + + ccflags = unique_list(ccflags) + ldflags = unique_list(ldflags) + cpppath = unique_list(cpppath) + return (ccflags, ldflags, cpppath) + + +@conf +def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False): + '''check if a set of libraries exist as system libraries + + returns the sublist of libs that do exist as a syslib or [] + ''' + + fragment= ''' +int foo() +{ + int v = 2; + return v*2; +} +''' + ret = [] + liblist = TO_LIST(libs) + for lib in liblist[:]: + if GET_TARGET_TYPE(conf, lib) == 'SYSLIB': + ret.append(lib) + continue + + (ccflags, ldflags, cpppath) = library_flags(conf, lib) + if shlib: + res = conf.check(features='c cshlib', fragment=fragment, lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False) + else: + res = conf.check(lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False) + + if not res: + if mandatory: + Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list)) + sys.exit(1) + if empty_decl: + # if it isn't a mandatory library, then remove it from dependency lists + if set_target: + SET_TARGET_TYPE(conf, lib, 'EMPTY') + else: + conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1) + conf.env['LIB_' + lib.upper()] = lib + if set_target: + conf.SET_TARGET_TYPE(lib, 'SYSLIB') + ret.append(lib) + + return ret + + + +@conf +def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False, + headers=None, link=True, empty_decl=True, set_target=True): + """ + check that the functions in 'list' are available in 'library' + if they are, then make that library available as a dependency + + if the library is not available and mandatory==True, then + raise an error. + + If the library is not available and mandatory==False, then + add the library to the list of dependencies to remove from + build rules + + optionally check for the functions first in libc + """ + remaining = TO_LIST(list) + liblist = TO_LIST(library) + + # check if some already found + for f in remaining[:]: + if CONFIG_SET(conf, 'HAVE_%s' % f.upper()): + remaining.remove(f) + + # see if the functions are in libc + if checklibc: + for f in remaining[:]: + if CHECK_FUNC(conf, f, link=True, headers=headers): + remaining.remove(f) + + if remaining == []: + for lib in liblist: + if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl: + SET_TARGET_TYPE(conf, lib, 'EMPTY') + return True + + checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target) + for lib in liblist[:]: + if not lib in checklist and mandatory: + Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list)) + sys.exit(1) + + ret = True + for f in remaining: + if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link): + ret = False + + return ret + + +@conf +def IN_LAUNCH_DIR(conf): + '''return True if this rule is being run from the launch directory''' + return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir) +Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR + + +@conf +def SAMBA_CONFIG_H(conf, path=None): + '''write out config.h in the right directory''' + # we don't want to produce a config.h in places like lib/replace + # when we are building projects that depend on lib/replace + if not IN_LAUNCH_DIR(conf): + return + + # we need to build real code that can't be optimized away to test + stack_protect_list = ['-fstack-protector-strong', '-fstack-protector'] + for stack_protect_flag in stack_protect_list: + flag_supported = conf.check(fragment=''' + #include + + int main(void) + { + char t[100000]; + while (fgets(t, sizeof(t), stdin)); + return 0; + } + ''', + execute=0, + cflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag], + mandatory=False, + msg='Checking if compiler accepts %s' % (stack_protect_flag)) + if flag_supported: + conf.ADD_CFLAGS('%s' % (stack_protect_flag)) + break + + flag_supported = conf.check(fragment=''' + #include + + int main(void) + { + char t[100000]; + while (fgets(t, sizeof(t), stdin)); + return 0; + } + ''', + execute=0, + cflags=[ '-Werror', '-fstack-clash-protection'], + mandatory=False, + msg='Checking if compiler accepts -fstack-clash-protection') + if flag_supported: + conf.ADD_CFLAGS('-fstack-clash-protection') + + if Options.options.debug: + conf.ADD_CFLAGS('-g', testflags=True) + + if Options.options.developer: + conf.env.DEVELOPER_MODE = True + + conf.ADD_CFLAGS('-g', testflags=True) + conf.ADD_CFLAGS('-Wall', testflags=True) + conf.ADD_CFLAGS('-Wshadow', testflags=True) + conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True) + if CHECK_CODE(conf, + 'struct a { int b; }; struct c { struct a d; } e = { };', + 'CHECK_C99_INIT', + link=False, + cflags='-Wmissing-field-initializers -Werror=missing-field-initializers', + msg="Checking C99 init of nested structs."): + conf.ADD_CFLAGS('-Wmissing-field-initializers', testflags=True) + conf.ADD_CFLAGS('-Wformat-overflow=2', testflags=True) + conf.ADD_CFLAGS('-Wformat-zero-length', testflags=True) + conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True) + conf.ADD_CFLAGS('-fno-common', testflags=True) + + conf.ADD_CFLAGS('-Werror=address', testflags=True) + # we add these here to ensure that -Wstrict-prototypes is not set during configure + conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes', + testflags=True) + conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings', + testflags=True) + conf.ADD_CFLAGS('-Werror-implicit-function-declaration', + testflags=True) + conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith', + testflags=True) + conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement', + testflags=True) + conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type', + testflags=True) + conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized', + testflags=True) + conf.ADD_CFLAGS('-Wimplicit-fallthrough', + testflags=True) + conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2', + testflags=True) + + conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True) + conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True) + conf.ADD_CFLAGS('-Werror=format-security -Wformat-security', + testflags=True, prereq_flags='-Wformat') + # 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"], ''' +int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2))); + +int main(void) { + testformat(0); + return 0; +} + +'''): + if not 'EXTRA_CFLAGS' in conf.env: + conf.env['EXTRA_CFLAGS'] = [] + conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format")) + + 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) + + if Options.options.pedantic: + conf.ADD_CFLAGS('-W', testflags=True) + + if (Options.options.address_sanitizer or + Options.options.undefined_sanitizer): + conf.ADD_CFLAGS('-g -O1', testflags=True) + if Options.options.address_sanitizer: + conf.ADD_CFLAGS('-fno-omit-frame-pointer', testflags=True) + conf.ADD_CFLAGS('-fsanitize=address', testflags=True) + conf.ADD_LDFLAGS('-fsanitize=address', testflags=True) + conf.env['ADDRESS_SANITIZER'] = True + if Options.options.undefined_sanitizer: + conf.ADD_CFLAGS('-fsanitize=undefined', testflags=True) + conf.ADD_CFLAGS('-fsanitize=null', testflags=True) + conf.ADD_CFLAGS('-fsanitize=alignment', testflags=True) + conf.ADD_LDFLAGS('-fsanitize=undefined', testflags=True) + conf.env['UNDEFINED_SANITIZER'] = True + + + # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS} + # environment variables which are only used the for final build. + # + # The CFLAGS and LDFLAGS environment variables are also + # used for the configure checks which might impact their results. + conf.add_os_flags('ADDITIONAL_CFLAGS') + if conf.env.ADDITIONAL_CFLAGS and conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS']): + conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS']) + conf.add_os_flags('ADDITIONAL_LDFLAGS') + if conf.env.ADDITIONAL_LDFLAGS and conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS']): + conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS']) + + if path is None: + conf.write_config_header('default/config.h', top=True, remove=False) + else: + conf.write_config_header(os.path.join(conf.variant, path), remove=False) + for key in conf.env.define_key: + conf.undefine(key, from_env=False) + conf.env.define_key = [] + conf.SAMBA_CROSS_CHECK_COMPLETE() + + +@conf +def CONFIG_PATH(conf, name, default): + '''setup a configurable path''' + if not name in conf.env: + if default[0] == '/': + conf.env[name] = default + else: + conf.env[name] = conf.env['PREFIX'] + default + +@conf +def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=[]): + '''add some CFLAGS to the command line + optionally set testflags to ensure all the flags work + ''' + prereq_flags = TO_LIST(prereq_flags) + if testflags: + ok_flags=[] + for f in flags.split(): + if CHECK_CFLAGS(conf, [f] + prereq_flags): + ok_flags.append(f) + flags = ok_flags + if not name in conf.env: + conf.env[name] = [] + conf.env[name].extend(TO_LIST(flags)) + +@conf +def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=[]): + '''add some CFLAGS to the command line + optionally set testflags to ensure all the flags work + ''' + ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags, + prereq_flags=prereq_flags) + +@conf +def ADD_LDFLAGS(conf, flags, testflags=False): + '''add some LDFLAGS to the command line + optionally set testflags to ensure all the flags work + + this will return the flags that are added, if any + ''' + if testflags: + ok_flags=[] + for f in flags.split(): + if CHECK_LDFLAGS(conf, f): + ok_flags.append(f) + flags = ok_flags + if not 'EXTRA_LDFLAGS' in conf.env: + conf.env['EXTRA_LDFLAGS'] = [] + conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags)) + return flags + + +@conf +def ADD_EXTRA_INCLUDES(conf, includes): + '''add some extra include directories to all builds''' + if not 'EXTRA_INCLUDES' in conf.env: + conf.env['EXTRA_INCLUDES'] = [] + conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes)) + + + +def CURRENT_CFLAGS(bld, target, cflags, allow_warnings=False, hide_symbols=False): + '''work out the current flags. local flags are added first''' + ret = TO_LIST(cflags) + if not 'EXTRA_CFLAGS' in bld.env: + list = [] + else: + list = bld.env['EXTRA_CFLAGS']; + ret.extend(list) + if not allow_warnings and 'PICKY_CFLAGS' in bld.env: + list = bld.env['PICKY_CFLAGS']; + ret.extend(list) + if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR: + ret.append(bld.env.VISIBILITY_CFLAGS) + return ret + + +@conf +def CHECK_CC_ENV(conf): + """trim whitespaces from 'CC'. + The build farm sometimes puts a space at the start""" + if os.environ.get('CC'): + conf.env.CC = TO_LIST(os.environ.get('CC')) + + +@conf +def SETUP_CONFIGURE_CACHE(conf, enable): + '''enable/disable cache of configure results''' + if enable: + # when -C is chosen, we will use a private cache and will + # not look into system includes. This roughtly matches what + # autoconf does with -C + cache_path = os.path.join(conf.bldnode.abspath(), '.confcache') + mkdir_p(cache_path) + Options.cache_global = os.environ['WAFCACHE'] = cache_path + else: + # when -C is not chosen we will not cache configure checks + # We set the recursion limit low to prevent waf from spending + # a lot of time on the signatures of the files. + Options.cache_global = os.environ['WAFCACHE'] = '' + preproc.recursion_limit = 1 + # in either case we don't need to scan system includes + preproc.go_absolute = False + + +@conf +def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf): + if not sys.platform.startswith("openbsd"): + # we don't want any libraries or modules to rely on runtime + # resolution of symbols + conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True) + + if (conf.env.undefined_ignore_ldflags == [] and + conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup'])): + conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup'] diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_autoproto.py b/ldb-2.0.8/buildtools/wafsamba/samba_autoproto.py new file mode 100644 index 0000000..ace434f --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_autoproto.py @@ -0,0 +1,24 @@ +# waf build tool for building automatic prototypes from C source + +import os +from waflib import Build +from samba_utils import SET_TARGET_TYPE, os_path_relpath + +def SAMBA_AUTOPROTO(bld, header, source): + '''rule for samba prototype generation''' + bld.SET_BUILD_GROUP('prototypes') + relpath = os_path_relpath(bld.path.abspath(), bld.srcnode.abspath()) + name = os.path.join(relpath, header) + SET_TARGET_TYPE(bld, name, 'PROTOTYPE') + t = bld( + name = name, + source = source, + target = header, + update_outputs=True, + ext_out='.c', + before ='c', + rule = '${PERL} "${SCRIPT}/mkproto.pl" --srcdir=.. --builddir=. --public=/dev/null --private="${TGT}" ${SRC}' + ) + t.env.SCRIPT = os.path.join(bld.srcnode.abspath(), 'source4/script') +Build.BuildContext.SAMBA_AUTOPROTO = SAMBA_AUTOPROTO + diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_bundled.py b/ldb-2.0.8/buildtools/wafsamba/samba_bundled.py new file mode 100644 index 0000000..60ce7da --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_bundled.py @@ -0,0 +1,274 @@ +# functions to support bundled libraries + +import sys +from waflib import Build, Options, Logs +from waflib.Configure import conf +from wafsamba import samba_utils + +def PRIVATE_NAME(bld, name, private_extension, private_library): + '''possibly rename a library to include a bundled extension''' + + if not private_library: + return name + + # we now use the same private name for libraries as the public name. + # see http://git.samba.org/?p=tridge/junkcode.git;a=tree;f=shlib for a + # demonstration that this is the right thing to do + # also see http://lists.samba.org/archive/samba-technical/2011-January/075816.html + if private_extension: + return name + + extension = bld.env.PRIVATE_EXTENSION + + if extension and name.startswith('%s' % extension): + return name + + if extension and name.endswith('%s' % extension): + return name + + return "%s-%s" % (name, extension) + + +def target_in_list(target, lst, default): + for l in lst: + if target == l: + return True + if '!' + target == l: + return False + if l == 'ALL': + return True + if l == 'NONE': + return False + return default + + +def BUILTIN_LIBRARY(bld, name): + '''return True if a library should be builtin + instead of being built as a shared lib''' + return target_in_list(name, bld.env.BUILTIN_LIBRARIES, False) +Build.BuildContext.BUILTIN_LIBRARY = BUILTIN_LIBRARY + + +def BUILTIN_DEFAULT(opt, builtins): + '''set a comma separated default list of builtin libraries for this package''' + if 'BUILTIN_LIBRARIES_DEFAULT' in Options.options.__dict__: + return + Options.options.__dict__['BUILTIN_LIBRARIES_DEFAULT'] = builtins +Options.OptionsContext.BUILTIN_DEFAULT = BUILTIN_DEFAULT + + +def PRIVATE_EXTENSION_DEFAULT(opt, extension, noextension=''): + '''set a default private library extension''' + if 'PRIVATE_EXTENSION_DEFAULT' in Options.options.__dict__: + return + Options.options.__dict__['PRIVATE_EXTENSION_DEFAULT'] = extension + Options.options.__dict__['PRIVATE_EXTENSION_EXCEPTION'] = noextension +Options.OptionsContext.PRIVATE_EXTENSION_DEFAULT = PRIVATE_EXTENSION_DEFAULT + + +def minimum_library_version(conf, libname, default): + '''allow override of mininum system library version''' + + minlist = Options.options.MINIMUM_LIBRARY_VERSION + if not minlist: + return default + + for m in minlist.split(','): + a = m.split(':') + if len(a) != 2: + Logs.error("Bad syntax for --minimum-library-version of %s" % m) + sys.exit(1) + if a[0] == libname: + return a[1] + return default + + +@conf +def LIB_MAY_BE_BUNDLED(conf, libname): + if libname in conf.env.SYSTEM_LIBS: + return False + if libname in conf.env.BUNDLED_LIBS: + return True + if '!%s' % libname in conf.env.BUNDLED_LIBS: + return False + if 'NONE' in conf.env.BUNDLED_LIBS: + return False + return True + +@conf +def LIB_MUST_BE_BUNDLED(conf, libname): + if libname in conf.env.BUNDLED_LIBS: + return True + if '!%s' % libname in conf.env.BUNDLED_LIBS: + return False + if 'ALL' in conf.env.BUNDLED_LIBS: + return True + return False + +@conf +def LIB_MUST_BE_PRIVATE(conf, libname): + return ('ALL' in conf.env.PRIVATE_LIBS or + libname in conf.env.PRIVATE_LIBS) + +@conf +def CHECK_BUNDLED_SYSTEM_PKG(conf, libname, minversion='0.0.0', + maxversion=None, version_blacklist=[], + onlyif=None, implied_deps=None, pkg=None): + '''check if a library is available as a system library. + + This only tries using pkg-config + ''' + return conf.CHECK_BUNDLED_SYSTEM(libname, + minversion=minversion, + maxversion=maxversion, + version_blacklist=version_blacklist, + onlyif=onlyif, + implied_deps=implied_deps, + pkg=pkg) + +@conf +def CHECK_BUNDLED_SYSTEM(conf, libname, minversion='0.0.0', + maxversion=None, version_blacklist=[], + checkfunctions=None, headers=None, checkcode=None, + onlyif=None, implied_deps=None, + require_headers=True, pkg=None, set_target=True): + '''check if a library is available as a system library. + this first tries via pkg-config, then if that fails + tries by testing for a specified function in the specified lib + ''' + # We always do a logic validation of 'onlyif' first + missing = [] + if onlyif: + for l in samba_utils.TO_LIST(onlyif): + f = 'FOUND_SYSTEMLIB_%s' % l + if not f in conf.env: + Logs.error('ERROR: CHECK_BUNDLED_SYSTEM(%s) - ' % (libname) + + 'missing prerequisite check for ' + + 'system library %s, onlyif=%r' % (l, onlyif)) + sys.exit(1) + if not conf.env[f]: + missing.append(l) + found = 'FOUND_SYSTEMLIB_%s' % libname + if found in conf.env: + return conf.env[found] + if conf.LIB_MUST_BE_BUNDLED(libname): + conf.env[found] = False + return False + + # see if the library should only use a system version if another dependent + # system version is found. That prevents possible use of mixed library + # versions + if missing: + if not conf.LIB_MAY_BE_BUNDLED(libname): + Logs.error('ERROR: Use of system library %s depends on missing system library/libraries %r' % (libname, missing)) + sys.exit(1) + conf.env[found] = False + return False + + def check_functions_headers_code(): + '''helper function for CHECK_BUNDLED_SYSTEM''' + if require_headers and headers and not conf.CHECK_HEADERS(headers, lib=libname): + return False + if checkfunctions is not None: + ok = conf.CHECK_FUNCS_IN(checkfunctions, libname, headers=headers, + empty_decl=False, set_target=False) + if not ok: + return False + if checkcode is not None: + define='CHECK_BUNDLED_SYSTEM_%s' % libname.upper() + ok = conf.CHECK_CODE(checkcode, lib=libname, + headers=headers, local_include=False, + msg=msg, define=define) + conf.CONFIG_RESET(define) + if not ok: + return False + return True + + minversion = minimum_library_version(conf, libname, minversion) + + msg = 'Checking for system %s' % libname + msg_ver = [] + if minversion != '0.0.0': + msg_ver.append('>=%s' % minversion) + if maxversion is not None: + msg_ver.append('<=%s' % maxversion) + for v in version_blacklist: + msg_ver.append('!=%s' % v) + if msg_ver != []: + msg += " (%s)" % (" ".join(msg_ver)) + + uselib_store=libname.upper() + if pkg is None: + pkg = libname + + version_checks = '%s >= %s' % (pkg, minversion) + if maxversion is not None: + version_checks += ' %s <= %s' % (pkg, maxversion) + for v in version_blacklist: + version_checks += ' %s != %s' % (pkg, v) + + # try pkgconfig first + if (conf.CHECK_CFG(package=pkg, + args='"%s" --cflags --libs' % (version_checks), + msg=msg, uselib_store=uselib_store) and + check_functions_headers_code()): + if set_target: + conf.SET_TARGET_TYPE(libname, 'SYSLIB') + conf.env[found] = True + if implied_deps: + conf.SET_SYSLIB_DEPS(libname, implied_deps) + return True + if checkfunctions is not None: + if check_functions_headers_code(): + conf.env[found] = True + if implied_deps: + conf.SET_SYSLIB_DEPS(libname, implied_deps) + if set_target: + conf.SET_TARGET_TYPE(libname, 'SYSLIB') + return True + conf.env[found] = False + if not conf.LIB_MAY_BE_BUNDLED(libname): + Logs.error('ERROR: System library %s of version %s not found, and bundling disabled' % (libname, minversion)) + sys.exit(1) + return False + + +def tuplize_version(version): + return tuple([int(x) for x in version.split(".")]) + +@conf +def CHECK_BUNDLED_SYSTEM_PYTHON(conf, libname, modulename, minversion='0.0.0'): + '''check if a python module is available on the system and + has the specified minimum version. + ''' + if conf.LIB_MUST_BE_BUNDLED(libname): + return False + + # see if the library should only use a system version if another dependent + # system version is found. That prevents possible use of mixed library + # versions + minversion = minimum_library_version(conf, libname, minversion) + + try: + m = __import__(modulename) + except ImportError: + found = False + else: + try: + version = m.__version__ + except AttributeError: + found = False + else: + found = tuplize_version(version) >= tuplize_version(minversion) + if not found and not conf.LIB_MAY_BE_BUNDLED(libname): + Logs.error('ERROR: Python module %s of version %s not found, and bundling disabled' % (libname, minversion)) + sys.exit(1) + return found + + +def NONSHARED_BINARY(bld, name): + '''return True if a binary should be built without non-system shared libs''' + return target_in_list(name, bld.env.NONSHARED_BINARIES, False) +Build.BuildContext.NONSHARED_BINARY = NONSHARED_BINARY + + diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_conftests.py b/ldb-2.0.8/buildtools/wafsamba/samba_conftests.py new file mode 100644 index 0000000..ef632ba --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_conftests.py @@ -0,0 +1,528 @@ +# a set of config tests that use the samba_autoconf functions +# to test for commonly needed configuration options + +import os, shutil, re +from waflib import Build, Configure, Utils, Options, Logs, Errors +from waflib.Configure import conf +from samba_utils import TO_LIST, ADD_LD_LIBRARY_PATH, get_string + + +def add_option(self, *k, **kw): + '''syntax help: provide the "match" attribute to opt.add_option() so that folders can be added to specific config tests''' + Options.OptionsContext.parser = self + match = kw.get('match', []) + if match: + del kw['match'] + opt = self.parser.add_option(*k, **kw) + opt.match = match + return opt +Options.OptionsContext.add_option = add_option + +@conf +def check(self, *k, **kw): + '''Override the waf defaults to inject --with-directory options''' + + if not 'env' in kw: + kw['env'] = self.env.derive() + + # match the configuration test with specific options, for example: + # --with-libiconv -> Options.options.iconv_open -> "Checking for library iconv" + additional_dirs = [] + if 'msg' in kw: + msg = kw['msg'] + for x in Options.OptionsContext.parser.parser.option_list: + if getattr(x, 'match', None) and msg in x.match: + d = getattr(Options.options, x.dest, '') + if d: + additional_dirs.append(d) + + # we add the additional dirs twice: once for the test data, and again if the compilation test suceeds below + def add_options_dir(dirs, env): + for x in dirs: + if not x in env.CPPPATH: + env.CPPPATH = [os.path.join(x, 'include')] + env.CPPPATH + if not x in env.LIBPATH: + env.LIBPATH = [os.path.join(x, 'lib')] + env.LIBPATH + + add_options_dir(additional_dirs, kw['env']) + + self.validate_c(kw) + self.start_msg(kw['msg']) + ret = None + try: + ret = self.run_c_code(*k, **kw) + except Configure.ConfigurationError as e: + self.end_msg(kw['errmsg'], 'YELLOW') + if 'mandatory' in kw and kw['mandatory']: + if Logs.verbose > 1: + raise + else: + self.fatal('the configuration failed (see %r)' % self.log.name) + else: + kw['success'] = ret + self.end_msg(self.ret_msg(kw['okmsg'], kw)) + + # success! keep the CPPPATH/LIBPATH + add_options_dir(additional_dirs, self.env) + + self.post_check(*k, **kw) + if not kw.get('execute', False): + return ret == 0 + return ret + + +@conf +def CHECK_ICONV(conf, define='HAVE_NATIVE_ICONV'): + '''check if the iconv library is installed + optionally pass a define''' + if conf.CHECK_FUNCS_IN('iconv_open', 'iconv', checklibc=True, headers='iconv.h'): + conf.DEFINE(define, 1) + return True + return False + + +@conf +def CHECK_LARGEFILE(conf, define='HAVE_LARGEFILE'): + '''see what we need for largefile support''' + getconf_cflags = conf.CHECK_COMMAND(['getconf', 'LFS_CFLAGS']); + if getconf_cflags is not False: + if (conf.CHECK_CODE('if (sizeof(off_t) < 8) return 1', + define='WORKING_GETCONF_LFS_CFLAGS', + execute=True, + cflags=getconf_cflags, + msg='Checking getconf large file support flags work')): + conf.ADD_CFLAGS(getconf_cflags) + getconf_cflags_list=TO_LIST(getconf_cflags) + for flag in getconf_cflags_list: + if flag[:2] == "-D": + flag_split = flag[2:].split('=') + if len(flag_split) == 1: + conf.DEFINE(flag_split[0], '1') + else: + conf.DEFINE(flag_split[0], flag_split[1]) + + if conf.CHECK_CODE('if (sizeof(off_t) < 8) return 1', + define, + execute=True, + msg='Checking for large file support without additional flags'): + return True + + if conf.CHECK_CODE('if (sizeof(off_t) < 8) return 1', + define, + execute=True, + cflags='-D_FILE_OFFSET_BITS=64', + msg='Checking for -D_FILE_OFFSET_BITS=64'): + conf.DEFINE('_FILE_OFFSET_BITS', 64) + return True + + if conf.CHECK_CODE('if (sizeof(off_t) < 8) return 1', + define, + execute=True, + cflags='-D_LARGE_FILES', + msg='Checking for -D_LARGE_FILES'): + conf.DEFINE('_LARGE_FILES', 1) + return True + return False + + +@conf +def CHECK_C_PROTOTYPE(conf, function, prototype, define, headers=None, msg=None): + '''verify that a C prototype matches the one on the current system''' + if not conf.CHECK_DECLS(function, headers=headers): + return False + if not msg: + msg = 'Checking C prototype for %s' % function + return conf.CHECK_CODE('%s; void *_x = (void *)%s' % (prototype, function), + define=define, + local_include=False, + headers=headers, + link=False, + execute=False, + msg=msg) + + +@conf +def CHECK_CHARSET_EXISTS(conf, charset, outcharset='UCS-2LE', headers=None, define=None): + '''check that a named charset is able to be used with iconv_open() for conversion + to a target charset + ''' + msg = 'Checking if can we convert from %s to %s' % (charset, outcharset) + if define is None: + define = 'HAVE_CHARSET_%s' % charset.upper().replace('-','_') + return conf.CHECK_CODE(''' + iconv_t cd = iconv_open("%s", "%s"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + ''' % (charset, outcharset), + define=define, + execute=True, + msg=msg, + lib='iconv', + headers=headers) + +def find_config_dir(conf): + '''find a directory to run tests in''' + k = 0 + while k < 10000: + dir = os.path.join(conf.bldnode.abspath(), '.conf_check_%d' % k) + try: + shutil.rmtree(dir) + except OSError: + pass + try: + os.stat(dir) + except: + break + k += 1 + + try: + os.makedirs(dir) + except: + conf.fatal('cannot create a configuration test folder %r' % dir) + + try: + os.stat(dir) + except: + conf.fatal('cannot use the configuration test folder %r' % dir) + return dir + +@conf +def CHECK_SHLIB_INTRASINC_NAME_FLAGS(conf, msg): + ''' + check if the waf default flags for setting the name of lib + are ok + ''' + + snip = ''' +int foo(int v) { + return v * 2; +} +''' + return conf.check(features='c cshlib',vnum="1",fragment=snip,msg=msg, mandatory=False) + +@conf +def CHECK_NEED_LC(conf, msg): + '''check if we need -lc''' + + dir = find_config_dir(conf) + + env = conf.env + + bdir = os.path.join(dir, 'testbuild2') + if not os.path.exists(bdir): + os.makedirs(bdir) + + + subdir = os.path.join(dir, "liblctest") + + os.makedirs(subdir) + + Utils.writef(os.path.join(subdir, 'liblc1.c'), '#include \nint lib_func(void) { FILE *f = fopen("foo", "r");}\n') + + bld = Build.BuildContext() + bld.log = conf.log + bld.all_envs.update(conf.all_envs) + bld.all_envs['default'] = env + bld.lst_variants = bld.all_envs.keys() + bld.load_dirs(dir, bdir) + + bld.rescan(bld.srcnode) + + bld(features='c cshlib', + source='liblctest/liblc1.c', + ldflags=conf.env['EXTRA_LDFLAGS'], + target='liblc', + name='liblc') + + try: + bld.compile() + conf.check_message(msg, '', True) + return True + except: + conf.check_message(msg, '', False) + return False + + +@conf +def CHECK_SHLIB_W_PYTHON(conf, msg): + '''check if we need -undefined dynamic_lookup''' + + dir = find_config_dir(conf) + snip = ''' +#include +#include +#define environ (*_NSGetEnviron()) + +static PyObject *ldb_module = NULL; +int foo(int v) { + extern char **environ; + environ[0] = 1; + ldb_module = PyImport_ImportModule("ldb"); + return v * 2; +} +''' + return conf.check(features='c cshlib',uselib='PYEMBED',fragment=snip,msg=msg, mandatory=False) + +# this one is quite complex, and should probably be broken up +# into several parts. I'd quite like to create a set of CHECK_COMPOUND() +# functions that make writing complex compound tests like this much easier +@conf +def CHECK_LIBRARY_SUPPORT(conf, rpath=False, version_script=False, msg=None): + '''see if the platform supports building libraries''' + + if msg is None: + if rpath: + msg = "rpath library support" + else: + msg = "building library support" + + dir = find_config_dir(conf) + + bdir = os.path.join(dir, 'testbuild') + if not os.path.exists(bdir): + os.makedirs(bdir) + + env = conf.env + + subdir = os.path.join(dir, "libdir") + + os.makedirs(subdir) + + Utils.writef(os.path.join(subdir, 'lib1.c'), 'int lib_func(void) { return 42; }\n') + Utils.writef(os.path.join(dir, 'main.c'), + 'int lib_func(void);\n' + 'int main(void) {return !(lib_func() == 42);}\n') + + bld = Build.BuildContext() + bld.log = conf.log + bld.all_envs.update(conf.all_envs) + bld.all_envs['default'] = env + bld.lst_variants = bld.all_envs.keys() + bld.load_dirs(dir, bdir) + + bld.rescan(bld.srcnode) + + ldflags = [] + if version_script: + ldflags.append("-Wl,--version-script=%s/vscript" % bld.path.abspath()) + Utils.writef(os.path.join(dir,'vscript'), 'TEST_1.0A2 { global: *; };\n') + + bld(features='c cshlib', + source='libdir/lib1.c', + target='libdir/lib1', + ldflags=ldflags, + name='lib1') + + o = bld(features='c cprogram', + source='main.c', + target='prog1', + uselib_local='lib1') + + if rpath: + o.rpath=os.path.join(bdir, 'default/libdir') + + # compile the program + try: + bld.compile() + except: + conf.check_message(msg, '', False) + return False + + # path for execution + lastprog = o.link_task.outputs[0].abspath(env) + + if not rpath: + if 'LD_LIBRARY_PATH' in os.environ: + old_ld_library_path = os.environ['LD_LIBRARY_PATH'] + else: + old_ld_library_path = None + ADD_LD_LIBRARY_PATH(os.path.join(bdir, 'default/libdir')) + + # we need to run the program, try to get its result + args = conf.SAMBA_CROSS_ARGS(msg=msg) + proc = Utils.subprocess.Popen([lastprog] + args, + stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE) + (out, err) = proc.communicate() + w = conf.log.write + w(str(out)) + w('\n') + w(str(err)) + w('\nreturncode %r\n' % proc.returncode) + ret = (proc.returncode == 0) + + if not rpath: + os.environ['LD_LIBRARY_PATH'] = old_ld_library_path or '' + + conf.check_message(msg, '', ret) + return ret + + + +@conf +def CHECK_PERL_MANPAGE(conf, msg=None, section=None): + '''work out what extension perl uses for manpages''' + + if msg is None: + if section: + msg = "perl man%s extension" % section + else: + msg = "perl manpage generation" + + conf.start_msg(msg) + + dir = find_config_dir(conf) + + bdir = os.path.join(dir, 'testbuild') + if not os.path.exists(bdir): + os.makedirs(bdir) + + Utils.writef(os.path.join(bdir, 'Makefile.PL'), """ +use ExtUtils::MakeMaker; +WriteMakefile( + 'NAME' => 'WafTest', + 'EXE_FILES' => [ 'WafTest' ] +); +""") + back = os.path.abspath('.') + os.chdir(bdir) + proc = Utils.subprocess.Popen(['perl', 'Makefile.PL'], + stdout=Utils.subprocess.PIPE, + stderr=Utils.subprocess.PIPE) + (out, err) = proc.communicate() + os.chdir(back) + + ret = (proc.returncode == 0) + if not ret: + conf.end_msg('not found', color='YELLOW') + return + + if section: + man = Utils.readf(os.path.join(bdir,'Makefile')) + m = re.search('MAN%sEXT\s+=\s+(\w+)' % section, man) + if not m: + conf.end_msg('not found', color='YELLOW') + return + ext = m.group(1) + conf.end_msg(ext) + return ext + + conf.end_msg('ok') + return True + + +@conf +def CHECK_COMMAND(conf, cmd, msg=None, define=None, on_target=True, boolean=False): + '''run a command and return result''' + if msg is None: + msg = 'Checking %s' % ' '.join(cmd) + conf.COMPOUND_START(msg) + cmd = cmd[:] + if on_target: + cmd.extend(conf.SAMBA_CROSS_ARGS(msg=msg)) + try: + ret = get_string(Utils.cmd_output(cmd)) + except: + conf.COMPOUND_END(False) + return False + if boolean: + conf.COMPOUND_END('ok') + if define: + conf.DEFINE(define, '1') + else: + ret = ret.strip() + conf.COMPOUND_END(ret) + if define: + conf.DEFINE(define, ret, quote=True) + return ret + + +@conf +def CHECK_UNAME(conf): + '''setup SYSTEM_UNAME_* defines''' + ret = True + for v in "sysname machine release version".split(): + if not conf.CHECK_CODE(''' + int printf(const char *format, ...); + struct utsname n; + if (uname(&n) == -1) return -1; + printf("%%s", n.%s); + ''' % v, + define='SYSTEM_UNAME_%s' % v.upper(), + execute=True, + define_ret=True, + quote=True, + headers='sys/utsname.h', + local_include=False, + msg="Checking uname %s type" % v): + ret = False + return ret + +@conf +def CHECK_INLINE(conf): + '''check for the right value for inline''' + conf.COMPOUND_START('Checking for inline') + for i in ['inline', '__inline__', '__inline']: + ret = conf.CHECK_CODE(''' + typedef int foo_t; + static %s foo_t static_foo () {return 0; } + %s foo_t foo () {return 0; }\n''' % (i, i), + define='INLINE_MACRO', + addmain=False, + link=False) + if ret: + if i != 'inline': + conf.DEFINE('inline', i, quote=False) + break + if not ret: + conf.COMPOUND_END(ret) + else: + conf.COMPOUND_END(i) + return ret + +@conf +def CHECK_XSLTPROC_MANPAGES(conf): + '''check if xsltproc can run with the given stylesheets''' + + + if not conf.CONFIG_SET('XSLTPROC'): + conf.find_program('xsltproc', var='XSLTPROC') + if not conf.CONFIG_SET('XSLTPROC'): + return False + + s='http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl' + conf.CHECK_COMMAND('%s --nonet %s 2> /dev/null' % (conf.env.get_flat('XSLTPROC'), s), + msg='Checking for stylesheet %s' % s, + define='XSLTPROC_MANPAGES', on_target=False, + boolean=True) + if not conf.CONFIG_SET('XSLTPROC_MANPAGES'): + print("A local copy of the docbook.xsl wasn't found on your system" \ + " consider installing package like docbook-xsl") + +# +# Determine the standard libpath for the used compiler, +# so we can later use that to filter out these standard +# library paths when some tools like cups-config or +# python-config report standard lib paths with their +# ldflags (-L...) +# +@conf +def CHECK_STANDARD_LIBPATH(conf): + # at least gcc and clang support this: + try: + cmd = conf.env.CC + ['-print-search-dirs'] + out = get_string(Utils.cmd_output(cmd)).split('\n') + except ValueError: + # option not supported by compiler - use a standard list of directories + dirlist = [ '/usr/lib', '/usr/lib64' ] + except: + raise Errors.WafError('Unexpected error running "%s"' % (cmd)) + else: + dirlist = [] + for line in out: + line = line.strip() + if line.startswith("libraries: ="): + dirliststr = line[len("libraries: ="):] + dirlist = [ os.path.normpath(x) for x in dirliststr.split(':') ] + break + + conf.env.STANDARD_LIBPATH = dirlist + diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_cross.py b/ldb-2.0.8/buildtools/wafsamba/samba_cross.py new file mode 100644 index 0000000..0868a85 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_cross.py @@ -0,0 +1,175 @@ +# functions for handling cross-compilation + +import os, sys, re, shlex +from waflib import Utils, Logs, Options, Errors, Context +from waflib.Configure import conf +from wafsamba import samba_utils + +real_Popen = None + +ANSWER_UNKNOWN = (254, "") +ANSWER_NO = (1, "") +ANSWER_OK = (0, "") + +cross_answers_incomplete = False + + +def add_answer(ca_file, msg, answer): + '''add an answer to a set of cross answers''' + try: + f = open(ca_file, 'a') + except: + Logs.error("Unable to open cross-answers file %s" % ca_file) + sys.exit(1) + (retcode, retstring) = answer + # if retstring is more than one line then we probably + # don't care about its actual content (the tests should + # yield one-line output in order to comply with the cross-answer + # format) + retstring = retstring.strip() + if len(retstring.split('\n')) > 1: + retstring = '' + answer = (retcode, retstring) + + if answer == ANSWER_OK: + f.write('%s: OK\n' % msg) + elif answer == ANSWER_UNKNOWN: + f.write('%s: UNKNOWN\n' % msg) + elif answer == ANSWER_NO: + f.write('%s: NO\n' % msg) + else: + if retcode == 0: + f.write('%s: "%s"\n' % (msg, retstring)) + else: + f.write('%s: (%d, "%s")\n' % (msg, retcode, retstring)) + f.close() + + +def cross_answer(ca_file, msg): + '''return a (retcode,retstring) tuple from a answers file''' + try: + f = open(ca_file, 'r') + except: + return ANSWER_UNKNOWN + for line in f: + line = line.strip() + if line == '' or line[0] == '#': + continue + if line.find(':') != -1: + a = line.split(':', 1) + thismsg = a[0].strip() + if thismsg != msg: + continue + ans = a[1].strip() + if ans == "OK" or ans == "YES": + f.close() + return ANSWER_OK + elif ans == "UNKNOWN": + f.close() + return ANSWER_UNKNOWN + elif ans == "FAIL" or ans == "NO": + f.close() + return ANSWER_NO + elif ans[0] == '"': + f.close() + return (0, ans.strip('"')) + elif ans[0] == "'": + f.close() + return (0, ans.strip("'")) + else: + m = re.match('\(\s*(-?\d+)\s*,\s*\"(.*)\"\s*\)', ans) + if m: + f.close() + return (int(m.group(1)), m.group(2)) + else: + raise Errors.WafError("Bad answer format '%s' in %s" % (line, ca_file)) + f.close() + return ANSWER_UNKNOWN + + +class cross_Popen(Utils.subprocess.Popen): + '''cross-compilation wrapper for Popen''' + def __init__(*k, **kw): + (obj, args) = k + use_answers = False + ans = ANSWER_UNKNOWN + + # Three possibilities: + # 1. Only cross-answers - try the cross-answers file, and if + # there's no corresponding answer, add to the file and mark + # the configure process as unfinished. + # 2. Only cross-execute - get the answer from cross-execute + # 3. Both - try the cross-answers file, and if there is no + # corresponding answer - use cross-execute to get an answer, + # and add that answer to the file. + if '--cross-answers' in args: + # when --cross-answers is set, then change the arguments + # to use the cross answers if available + use_answers = True + i = args.index('--cross-answers') + ca_file = args[i+1] + msg = args[i+2] + ans = cross_answer(ca_file, msg) + + if '--cross-execute' in args and ans == ANSWER_UNKNOWN: + # when --cross-execute is set, then change the arguments + # to use the cross emulator + i = args.index('--cross-execute') + newargs = shlex.split(args[i+1]) + newargs.extend(args[0:i]) + if use_answers: + p = real_Popen(newargs, + stdout=Utils.subprocess.PIPE, + stderr=Utils.subprocess.PIPE, + env=kw.get('env', {})) + ce_out, ce_err = p.communicate() + ans = (p.returncode, samba_utils.get_string(ce_out)) + add_answer(ca_file, msg, ans) + else: + args = newargs + + if use_answers: + if ans == ANSWER_UNKNOWN: + global cross_answers_incomplete + cross_answers_incomplete = True + add_answer(ca_file, msg, ans) + (retcode, retstring) = ans + args = ['/bin/sh', '-c', "echo -n '%s'; exit %d" % (retstring, retcode)] + real_Popen.__init__(*(obj, args), **kw) + + +@conf +def SAMBA_CROSS_ARGS(conf, msg=None): + '''get test_args to pass when running cross compiled binaries''' + if not conf.env.CROSS_COMPILE: + return [] + + global real_Popen + if real_Popen is None: + real_Popen = Utils.subprocess.Popen + Utils.subprocess.Popen = cross_Popen + Utils.run_process = Utils.run_regular_process + Utils.get_process = Utils.alloc_process_pool = Utils.nada + + ret = [] + + if conf.env.CROSS_EXECUTE: + ret.extend(['--cross-execute', conf.env.CROSS_EXECUTE]) + + if conf.env.CROSS_ANSWERS: + if msg is None: + raise Errors.WafError("Cannot have NULL msg in cross-answers") + ret.extend(['--cross-answers', os.path.join(Context.launch_dir, conf.env.CROSS_ANSWERS), msg]) + + if ret == []: + raise Errors.WafError("Cannot cross-compile without either --cross-execute or --cross-answers") + + return ret + +@conf +def SAMBA_CROSS_CHECK_COMPLETE(conf): + '''check if we have some unanswered questions''' + global cross_answers_incomplete + if conf.env.CROSS_COMPILE and cross_answers_incomplete: + raise Errors.WafError("Cross answers file %s is incomplete" % conf.env.CROSS_ANSWERS) + return True diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_deps.py b/ldb-2.0.8/buildtools/wafsamba/samba_deps.py new file mode 100644 index 0000000..03c3707 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_deps.py @@ -0,0 +1,1181 @@ +# Samba automatic dependency handling and project rules + +import os, sys, re + +from waflib import Build, Options, Logs, Utils, Errors +from waflib.Logs import debug +from waflib.Configure import conf +from waflib import ConfigSet + +from samba_bundled import BUILTIN_LIBRARY +from samba_utils import LOCAL_CACHE, TO_LIST, get_tgt_list, unique_list, os_path_relpath +from samba_autoconf import library_flags + +@conf +def ADD_GLOBAL_DEPENDENCY(ctx, dep): + '''add a dependency for all binaries and libraries''' + if not 'GLOBAL_DEPENDENCIES' in ctx.env: + ctx.env.GLOBAL_DEPENDENCIES = [] + ctx.env.GLOBAL_DEPENDENCIES.append(dep) + + +@conf +def BREAK_CIRCULAR_LIBRARY_DEPENDENCIES(ctx): + '''indicate that circular dependencies between libraries should be broken.''' + ctx.env.ALLOW_CIRCULAR_LIB_DEPENDENCIES = True + + +@conf +def SET_SYSLIB_DEPS(conf, target, deps): + '''setup some implied dependencies for a SYSLIB''' + cache = LOCAL_CACHE(conf, 'SYSLIB_DEPS') + cache[target] = deps + + +def expand_subsystem_deps(bld): + '''expand the reverse dependencies resulting from subsystem + attributes of modules. This is walking over the complete list + of declared subsystems, and expands the samba_deps_extended list for any + module<->subsystem dependencies''' + + subsystem_list = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + for subsystem_name in subsystem_list: + bld.ASSERT(subsystem_name in targets, "Subsystem target %s not declared" % subsystem_name) + type = targets[subsystem_name] + if type == 'DISABLED' or type == 'EMPTY': + continue + + # for example, + # subsystem_name = dcerpc_server (a subsystem) + # subsystem = dcerpc_server (a subsystem object) + # module_name = rpc_epmapper (a module within the dcerpc_server subsystem) + # module = rpc_epmapper (a module object within the dcerpc_server subsystem) + + subsystem = bld.get_tgen_by_name(subsystem_name) + bld.ASSERT(subsystem is not None, "Unable to find subsystem %s" % subsystem_name) + for d in subsystem_list[subsystem_name]: + module_name = d['TARGET'] + module_type = targets[module_name] + if module_type in ['DISABLED', 'EMPTY']: + continue + bld.ASSERT(subsystem is not None, + "Subsystem target %s for %s (%s) not found" % (subsystem_name, module_name, module_type)) + if module_type in ['SUBSYSTEM']: + # if a module is a plain object type (not a library) then the + # subsystem it is part of needs to have it as a dependency, so targets + # that depend on this subsystem get the modules of that subsystem + subsystem.samba_deps_extended.append(module_name) + subsystem.samba_deps_extended = unique_list(subsystem.samba_deps_extended) + + + +def build_dependencies(self): + '''This builds the dependency list for a target. It runs after all the targets are declared + + The reason this is not just done in the SAMBA_*() rules is that we have no way of knowing + the full dependency list for a target until we have all of the targets declared. + ''' + + if self.samba_type in ['LIBRARY', 'BINARY', 'PYTHON']: + self.uselib = list(self.final_syslibs) + self.uselib_local = list(self.final_libs) + self.add_objects = list(self.final_objects) + + # extra link flags from pkg_config + libs = self.final_syslibs.copy() + + (cflags, ldflags, cpppath) = library_flags(self, list(libs)) + new_ldflags = getattr(self, 'samba_ldflags', [])[:] + new_ldflags.extend(ldflags) + self.ldflags = new_ldflags + + if getattr(self, 'allow_undefined_symbols', False) and self.env.undefined_ldflags: + for f in self.env.undefined_ldflags: + self.ldflags.remove(f) + + if getattr(self, 'allow_undefined_symbols', False) and self.env.undefined_ignore_ldflags: + for f in self.env.undefined_ignore_ldflags: + self.ldflags.append(f) + + debug('deps: computed dependencies for target %s: uselib=%s uselib_local=%s add_objects=%s', + self.sname, self.uselib, self.uselib_local, self.add_objects) + + if self.samba_type in ['SUBSYSTEM']: + # this is needed for the cflags of libs that come from pkg_config + self.uselib = list(self.final_syslibs) + self.uselib.extend(list(self.direct_syslibs)) + for lib in self.final_libs: + t = self.bld.get_tgen_by_name(lib) + self.uselib.extend(list(t.final_syslibs)) + self.uselib = unique_list(self.uselib) + + if getattr(self, 'uselib', None): + up_list = [] + for l in self.uselib: + up_list.append(l.upper()) + self.uselib = up_list + + +def build_includes(self): + '''This builds the right set of includes for a target. + + One tricky part of this is that the includes= attribute for a + target needs to use paths which are relative to that targets + declaration directory (which we can get at via t.path). + + The way this works is the includes list gets added as + samba_includes in the main build task declaration. Then this + function runs after all of the tasks are declared, and it + processes the samba_includes attribute to produce a includes= + attribute + ''' + + if getattr(self, 'samba_includes', None) is None: + return + + bld = self.bld + + inc_deps = includes_objects(bld, self, set(), {}) + + includes = [] + + # maybe add local includes + if getattr(self, 'local_include', True) and getattr(self, 'local_include_first', True): + includes.append('.') + + includes.extend(self.samba_includes_extended) + + if 'EXTRA_INCLUDES' in bld.env and getattr(self, 'global_include', True): + includes.extend(bld.env['EXTRA_INCLUDES']) + + includes.append('#') + + inc_set = set() + inc_abs = [] + + for d in inc_deps: + t = bld.get_tgen_by_name(d) + bld.ASSERT(t is not None, "Unable to find dependency %s for %s" % (d, self.sname)) + inclist = getattr(t, 'samba_includes_extended', [])[:] + if getattr(t, 'local_include', True): + inclist.append('.') + if inclist == []: + continue + tpath = t.samba_abspath + for inc in inclist: + npath = tpath + '/' + inc + if not npath in inc_set: + inc_abs.append(npath) + inc_set.add(npath) + + mypath = self.path.abspath(bld.env) + for inc in inc_abs: + relpath = os_path_relpath(inc, mypath) + includes.append(relpath) + + if getattr(self, 'local_include', True) and not getattr(self, 'local_include_first', True): + includes.append('.') + + # now transform the includes list to be relative to the top directory + # which is represented by '#' in waf. This allows waf to cache the + # includes lists more efficiently + includes_top = [] + for i in includes: + if i[0] == '#': + # some are already top based + includes_top.append(i) + continue + absinc = os.path.join(self.path.abspath(), i) + relinc = os_path_relpath(absinc, self.bld.srcnode.abspath()) + includes_top.append('#' + relinc) + + self.includes = unique_list(includes_top) + debug('deps: includes for target %s: includes=%s', + self.sname, self.includes) + + +def add_init_functions(self): + '''This builds the right set of init functions''' + + bld = self.bld + + subsystems = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') + + # cope with the separated object lists from BINARY and LIBRARY targets + sname = self.sname + if sname.endswith('.objlist'): + sname = sname[0:-8] + + modules = [] + if sname in subsystems: + modules.append(sname) + + m = getattr(self, 'samba_modules', None) + if m is not None: + modules.extend(TO_LIST(m)) + + m = getattr(self, 'samba_subsystem', None) + if m is not None: + modules.append(m) + + if 'pyembed' in self.features: + return + + sentinel = getattr(self, 'init_function_sentinel', 'NULL') + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + cflags = getattr(self, 'samba_cflags', [])[:] + + if modules == []: + sname = sname.replace('-','_') + sname = sname.replace('.','_') + sname = sname.replace('/','_') + cflags.append('-DSTATIC_%s_MODULES=%s' % (sname, sentinel)) + if sentinel == 'NULL': + proto = "extern void __%s_dummy_module_proto(void)" % (sname) + cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (sname, proto)) + self.cflags = cflags + return + + for m in modules: + bld.ASSERT(m in subsystems, + "No init_function defined for module '%s' in target '%s'" % (m, self.sname)) + init_fn_list = [] + for d in subsystems[m]: + if targets[d['TARGET']] != 'DISABLED': + init_fn_list.append(d['INIT_FUNCTION']) + if init_fn_list == []: + cflags.append('-DSTATIC_%s_MODULES=%s' % (m, sentinel)) + if sentinel == 'NULL': + proto = "extern void __%s_dummy_module_proto(void)" % (m) + cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (m, proto)) + else: + cflags.append('-DSTATIC_%s_MODULES=%s' % (m, ','.join(init_fn_list) + ',' + sentinel)) + proto='' + for f in init_fn_list: + proto += '_MODULE_PROTO(%s)' % f + proto += "extern void __%s_dummy_module_proto(void)" % (m) + cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (m, proto)) + self.cflags = cflags + + +def check_duplicate_sources(bld, tgt_list): + '''see if we are compiling the same source file more than once''' + + debug('deps: checking for duplicate sources') + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + for t in tgt_list: + source_list = TO_LIST(getattr(t, 'source', '')) + tpath = os.path.normpath(os_path_relpath(t.path.abspath(bld.env), t.env.BUILD_DIRECTORY + '/default')) + obj_sources = set() + for s in source_list: + if not isinstance(s, str): + print('strange path in check_duplicate_sources %r' % s) + s = s.abspath() + p = os.path.normpath(os.path.join(tpath, s)) + if p in obj_sources: + Logs.error("ERROR: source %s appears twice in target '%s'" % (p, t.sname)) + sys.exit(1) + obj_sources.add(p) + t.samba_source_set = obj_sources + + subsystems = {} + + # build a list of targets that each source file is part of + for t in tgt_list: + if not targets[t.sname] in [ 'LIBRARY', 'BINARY', 'PYTHON' ]: + continue + for obj in t.add_objects: + t2 = t.bld.get_tgen_by_name(obj) + source_set = getattr(t2, 'samba_source_set', set()) + for s in source_set: + if not s in subsystems: + subsystems[s] = {} + if not t.sname in subsystems[s]: + subsystems[s][t.sname] = [] + subsystems[s][t.sname].append(t2.sname) + + for s in subsystems: + if len(subsystems[s]) > 1 and Options.options.SHOW_DUPLICATES: + Logs.warn("WARNING: source %s is in more than one target: %s" % (s, subsystems[s].keys())) + for tname in subsystems[s]: + if len(subsystems[s][tname]) > 1: + raise Errors.WafError("ERROR: source %s is in more than one subsystem of target '%s': %s" % (s, tname, subsystems[s][tname])) + + return True + +def check_group_ordering(bld, tgt_list): + '''see if we have any dependencies that violate the group ordering + + It is an error for a target to depend on a target from a later + build group + ''' + + def group_name(g): + tm = bld.task_manager + return [x for x in tm.groups_names if id(tm.groups_names[x]) == id(g)][0] + + for g in bld.task_manager.groups: + gname = group_name(g) + for t in g.tasks_gen: + t.samba_group = gname + + grp_map = {} + idx = 0 + for g in bld.task_manager.groups: + name = group_name(g) + grp_map[name] = idx + idx += 1 + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + ret = True + for t in tgt_list: + tdeps = getattr(t, 'add_objects', []) + getattr(t, 'uselib_local', []) + for d in tdeps: + t2 = bld.get_tgen_by_name(d) + if t2 is None: + continue + map1 = grp_map[t.samba_group] + map2 = grp_map[t2.samba_group] + + if map2 > map1: + Logs.error("Target %r in build group %r depends on target %r from later build group %r" % ( + t.sname, t.samba_group, t2.sname, t2.samba_group)) + ret = False + + return ret +Build.BuildContext.check_group_ordering = check_group_ordering + +def show_final_deps(bld, tgt_list): + '''show the final dependencies for all targets''' + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + for t in tgt_list: + if not targets[t.sname] in ['LIBRARY', 'BINARY', 'PYTHON', 'SUBSYSTEM']: + continue + debug('deps: final dependencies for target %s: uselib=%s uselib_local=%s add_objects=%s', + t.sname, t.uselib, getattr(t, 'uselib_local', []), getattr(t, 'add_objects', [])) + + +def add_samba_attributes(bld, tgt_list): + '''ensure a target has a the required samba attributes''' + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + for t in tgt_list: + if t.name != '': + t.sname = t.name + else: + t.sname = t.target + t.samba_type = targets[t.sname] + t.samba_abspath = t.path.abspath(bld.env) + t.samba_deps_extended = t.samba_deps[:] + t.samba_includes_extended = TO_LIST(t.samba_includes)[:] + t.cflags = getattr(t, 'samba_cflags', '') + +def replace_grouping_libraries(bld, tgt_list): + '''replace dependencies based on grouping libraries + + If a library is marked as a grouping library, then any target that + depends on a subsystem that is part of that grouping library gets + that dependency replaced with a dependency on the grouping library + ''' + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + grouping = {} + + # find our list of grouping libraries, mapped from the subsystems they depend on + for t in tgt_list: + if not getattr(t, 'grouping_library', False): + continue + for dep in t.samba_deps_extended: + bld.ASSERT(dep in targets, "grouping library target %s not declared in %s" % (dep, t.sname)) + if targets[dep] == 'SUBSYSTEM': + grouping[dep] = t.sname + + # now replace any dependencies on elements of grouping libraries + for t in tgt_list: + for i in range(len(t.samba_deps_extended)): + dep = t.samba_deps_extended[i] + if dep in grouping: + if t.sname != grouping[dep]: + debug("deps: target %s: replacing dependency %s with grouping library %s" % (t.sname, dep, grouping[dep])) + t.samba_deps_extended[i] = grouping[dep] + + + +def build_direct_deps(bld, tgt_list): + '''build the direct_objects and direct_libs sets for each target''' + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + syslib_deps = LOCAL_CACHE(bld, 'SYSLIB_DEPS') + + global_deps = bld.env.GLOBAL_DEPENDENCIES + global_deps_exclude = set() + for dep in global_deps: + t = bld.get_tgen_by_name(dep) + for d in t.samba_deps: + # prevent loops from the global dependencies list + global_deps_exclude.add(d) + global_deps_exclude.add(d + '.objlist') + + for t in tgt_list: + t.direct_objects = set() + t.direct_libs = set() + t.direct_syslibs = set() + deps = t.samba_deps_extended[:] + if getattr(t, 'samba_use_global_deps', False) and not t.sname in global_deps_exclude: + deps.extend(global_deps) + for d in deps: + if d == t.sname: continue + if not d in targets: + Logs.error("Unknown dependency '%s' in '%s'" % (d, t.sname)) + sys.exit(1) + if targets[d] in [ 'EMPTY', 'DISABLED' ]: + continue + if targets[d] == 'PYTHON' and targets[t.sname] != 'PYTHON' and t.sname.find('.objlist') == -1: + # this check should be more restrictive, but for now we have pidl-generated python + # code that directly depends on other python modules + Logs.error('ERROR: Target %s has dependency on python module %s' % (t.sname, d)) + sys.exit(1) + if targets[d] == 'SYSLIB': + t.direct_syslibs.add(d) + if d in syslib_deps: + for implied in TO_LIST(syslib_deps[d]): + if BUILTIN_LIBRARY(bld, implied): + t.direct_objects.add(implied) + elif targets[implied] == 'SYSLIB': + t.direct_syslibs.add(implied) + elif targets[implied] in ['LIBRARY', 'MODULE']: + t.direct_libs.add(implied) + else: + Logs.error('Implied dependency %s in %s is of type %s' % ( + implied, t.sname, targets[implied])) + sys.exit(1) + continue + t2 = bld.get_tgen_by_name(d) + if t2 is None: + Logs.error("no task %s of type %s in %s" % (d, targets[d], t.sname)) + sys.exit(1) + if t2.samba_type in [ 'LIBRARY', 'MODULE' ]: + t.direct_libs.add(d) + elif t2.samba_type in [ 'SUBSYSTEM', 'ASN1', 'PYTHON' ]: + t.direct_objects.add(d) + debug('deps: built direct dependencies') + + +def dependency_loop(loops, t, target): + '''add a dependency loop to the loops dictionary''' + if t.sname == target: + return + if not target in loops: + loops[target] = set() + if not t.sname in loops[target]: + loops[target].add(t.sname) + + +def indirect_libs(bld, t, chain, loops): + '''recursively calculate the indirect library dependencies for a target + + An indirect library is a library that results from a dependency on + a subsystem + ''' + + ret = getattr(t, 'indirect_libs', None) + if ret is not None: + return ret + + ret = set() + for obj in t.direct_objects: + if obj in chain: + dependency_loop(loops, t, obj) + continue + chain.add(obj) + t2 = bld.get_tgen_by_name(obj) + r2 = indirect_libs(bld, t2, chain, loops) + chain.remove(obj) + ret = ret.union(t2.direct_libs) + ret = ret.union(r2) + + for obj in indirect_objects(bld, t, set(), loops): + if obj in chain: + dependency_loop(loops, t, obj) + continue + chain.add(obj) + t2 = bld.get_tgen_by_name(obj) + r2 = indirect_libs(bld, t2, chain, loops) + chain.remove(obj) + ret = ret.union(t2.direct_libs) + ret = ret.union(r2) + + t.indirect_libs = ret + + return ret + + +def indirect_objects(bld, t, chain, loops): + '''recursively calculate the indirect object dependencies for a target + + indirect objects are the set of objects from expanding the + subsystem dependencies + ''' + + ret = getattr(t, 'indirect_objects', None) + if ret is not None: return ret + + ret = set() + for lib in t.direct_objects: + if lib in chain: + dependency_loop(loops, t, lib) + continue + chain.add(lib) + t2 = bld.get_tgen_by_name(lib) + r2 = indirect_objects(bld, t2, chain, loops) + chain.remove(lib) + ret = ret.union(t2.direct_objects) + ret = ret.union(r2) + + t.indirect_objects = ret + return ret + + +def extended_objects(bld, t, chain): + '''recursively calculate the extended object dependencies for a target + + extended objects are the union of: + - direct objects + - indirect objects + - direct and indirect objects of all direct and indirect libraries + ''' + + ret = getattr(t, 'extended_objects', None) + if ret is not None: return ret + + ret = set() + ret = ret.union(t.final_objects) + + for lib in t.final_libs: + if lib in chain: + continue + t2 = bld.get_tgen_by_name(lib) + chain.add(lib) + r2 = extended_objects(bld, t2, chain) + chain.remove(lib) + ret = ret.union(t2.final_objects) + ret = ret.union(r2) + + t.extended_objects = ret + return ret + + +def includes_objects(bld, t, chain, inc_loops): + '''recursively calculate the includes object dependencies for a target + + includes dependencies come from either library or object dependencies + ''' + ret = getattr(t, 'includes_objects', None) + if ret is not None: + return ret + + ret = t.direct_objects.copy() + ret = ret.union(t.direct_libs) + + for obj in t.direct_objects: + if obj in chain: + dependency_loop(inc_loops, t, obj) + continue + chain.add(obj) + t2 = bld.get_tgen_by_name(obj) + r2 = includes_objects(bld, t2, chain, inc_loops) + chain.remove(obj) + ret = ret.union(t2.direct_objects) + ret = ret.union(r2) + + for lib in t.direct_libs: + if lib in chain: + dependency_loop(inc_loops, t, lib) + continue + chain.add(lib) + t2 = bld.get_tgen_by_name(lib) + if t2 is None: + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + Logs.error('Target %s of type %s not found in direct_libs for %s' % ( + lib, targets[lib], t.sname)) + sys.exit(1) + r2 = includes_objects(bld, t2, chain, inc_loops) + chain.remove(lib) + ret = ret.union(t2.direct_objects) + ret = ret.union(r2) + + t.includes_objects = ret + return ret + + +def break_dependency_loops(bld, tgt_list): + '''find and break dependency loops''' + loops = {} + inc_loops = {} + + # build up the list of loops + for t in tgt_list: + indirect_objects(bld, t, set(), loops) + indirect_libs(bld, t, set(), loops) + includes_objects(bld, t, set(), inc_loops) + + # break the loops + for t in tgt_list: + if t.sname in loops: + for attr in ['direct_objects', 'indirect_objects', 'direct_libs', 'indirect_libs']: + objs = getattr(t, attr, set()) + setattr(t, attr, objs.difference(loops[t.sname])) + + for loop in loops: + debug('deps: Found dependency loops for target %s : %s', loop, loops[loop]) + + for loop in inc_loops: + debug('deps: Found include loops for target %s : %s', loop, inc_loops[loop]) + + # expand the loops mapping by one level + for loop in loops.copy(): + for tgt in loops[loop]: + if tgt in loops: + loops[loop] = loops[loop].union(loops[tgt]) + + for loop in inc_loops.copy(): + for tgt in inc_loops[loop]: + if tgt in inc_loops: + inc_loops[loop] = inc_loops[loop].union(inc_loops[tgt]) + + + # expand indirect subsystem and library loops + for loop in loops.copy(): + t = bld.get_tgen_by_name(loop) + if t.samba_type in ['SUBSYSTEM']: + loops[loop] = loops[loop].union(t.indirect_objects) + loops[loop] = loops[loop].union(t.direct_objects) + if t.samba_type in ['LIBRARY','PYTHON']: + loops[loop] = loops[loop].union(t.indirect_libs) + loops[loop] = loops[loop].union(t.direct_libs) + if loop in loops[loop]: + loops[loop].remove(loop) + + # expand indirect includes loops + for loop in inc_loops.copy(): + t = bld.get_tgen_by_name(loop) + inc_loops[loop] = inc_loops[loop].union(t.includes_objects) + if loop in inc_loops[loop]: + inc_loops[loop].remove(loop) + + # add in the replacement dependencies + for t in tgt_list: + for loop in loops: + for attr in ['indirect_objects', 'indirect_libs']: + objs = getattr(t, attr, set()) + if loop in objs: + diff = loops[loop].difference(objs) + if t.sname in diff: + diff.remove(t.sname) + if diff: + debug('deps: Expanded target %s of type %s from loop %s by %s', t.sname, t.samba_type, loop, diff) + objs = objs.union(diff) + setattr(t, attr, objs) + + for loop in inc_loops: + objs = getattr(t, 'includes_objects', set()) + if loop in objs: + diff = inc_loops[loop].difference(objs) + if t.sname in diff: + diff.remove(t.sname) + if diff: + debug('deps: Expanded target %s includes of type %s from loop %s by %s', t.sname, t.samba_type, loop, diff) + objs = objs.union(diff) + setattr(t, 'includes_objects', objs) + + +def reduce_objects(bld, tgt_list): + '''reduce objects by looking for indirect object dependencies''' + rely_on = {} + + for t in tgt_list: + t.extended_objects = None + + changed = False + + for type in ['BINARY', 'PYTHON', 'LIBRARY']: + for t in tgt_list: + if t.samba_type != type: continue + # if we will indirectly link to a target then we don't need it + new = t.final_objects.copy() + for l in t.final_libs: + t2 = bld.get_tgen_by_name(l) + t2_obj = extended_objects(bld, t2, set()) + dup = new.intersection(t2_obj) + if t.sname in rely_on: + dup = dup.difference(rely_on[t.sname]) + if dup: + # Do not remove duplicates of BUILTINS + d = next(iter(dup)) + if BUILTIN_LIBRARY(bld, d): + continue + + debug('deps: removing dups from %s of type %s: %s also in %s %s', + t.sname, t.samba_type, dup, t2.samba_type, l) + new = new.difference(dup) + changed = True + if not l in rely_on: + rely_on[l] = set() + rely_on[l] = rely_on[l].union(dup) + t.final_objects = new + + if not changed: + return False + + # add back in any objects that were relied upon by the reduction rules + for r in rely_on: + t = bld.get_tgen_by_name(r) + t.final_objects = t.final_objects.union(rely_on[r]) + + return True + + +def show_library_loop(bld, lib1, lib2, path, seen): + '''show the detailed path of a library loop between lib1 and lib2''' + + t = bld.get_tgen_by_name(lib1) + if not lib2 in getattr(t, 'final_libs', set()): + return + + for d in t.samba_deps_extended: + if d in seen: + continue + seen.add(d) + path2 = path + '=>' + d + if d == lib2: + Logs.warn('library loop path: ' + path2) + return + show_library_loop(bld, d, lib2, path2, seen) + seen.remove(d) + + +def calculate_final_deps(bld, tgt_list, loops): + '''calculate the final library and object dependencies''' + for t in tgt_list: + # start with the maximum possible list + t.final_libs = t.direct_libs.union(indirect_libs(bld, t, set(), loops)) + t.final_objects = t.direct_objects.union(indirect_objects(bld, t, set(), loops)) + + for t in tgt_list: + # don't depend on ourselves + if t.sname in t.final_libs: + t.final_libs.remove(t.sname) + if t.sname in t.final_objects: + t.final_objects.remove(t.sname) + + # handle any non-shared binaries + for t in tgt_list: + if t.samba_type == 'BINARY' and bld.NONSHARED_BINARY(t.sname): + subsystem_list = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + # replace lib deps with objlist deps + for l in t.final_libs: + objname = l + '.objlist' + t2 = bld.get_tgen_by_name(objname) + if t2 is None: + Logs.error('ERROR: subsystem %s not found' % objname) + sys.exit(1) + t.final_objects.add(objname) + t.final_objects = t.final_objects.union(extended_objects(bld, t2, set())) + if l in subsystem_list: + # its a subsystem - we also need the contents of any modules + for d in subsystem_list[l]: + module_name = d['TARGET'] + if targets[module_name] == 'LIBRARY': + objname = module_name + '.objlist' + elif targets[module_name] == 'SUBSYSTEM': + objname = module_name + else: + continue + t2 = bld.get_tgen_by_name(objname) + if t2 is None: + Logs.error('ERROR: subsystem %s not found' % objname) + sys.exit(1) + t.final_objects.add(objname) + t.final_objects = t.final_objects.union(extended_objects(bld, t2, set())) + t.final_libs = set() + + # find any library loops + for t in tgt_list: + if t.samba_type in ['LIBRARY', 'PYTHON']: + for l in t.final_libs.copy(): + t2 = bld.get_tgen_by_name(l) + if t.sname in t2.final_libs: + if getattr(bld.env, "ALLOW_CIRCULAR_LIB_DEPENDENCIES", False): + # we could break this in either direction. If one of the libraries + # has a version number, and will this be distributed publicly, then + # we should make it the lower level library in the DAG + Logs.warn('deps: removing library loop %s from %s' % (t.sname, t2.sname)) + dependency_loop(loops, t, t2.sname) + t2.final_libs.remove(t.sname) + else: + Logs.error('ERROR: circular library dependency between %s and %s' + % (t.sname, t2.sname)) + show_library_loop(bld, t.sname, t2.sname, t.sname, set()) + show_library_loop(bld, t2.sname, t.sname, t2.sname, set()) + sys.exit(1) + + for loop in loops: + debug('deps: Found dependency loops for target %s : %s', loop, loops[loop]) + + # we now need to make corrections for any library loops we broke up + # any target that depended on the target of the loop and doesn't + # depend on the source of the loop needs to get the loop source added + for type in ['BINARY','PYTHON','LIBRARY','BINARY']: + for t in tgt_list: + if t.samba_type != type: continue + for loop in loops: + if loop in t.final_libs: + diff = loops[loop].difference(t.final_libs) + if t.sname in diff: + diff.remove(t.sname) + if t.sname in diff: + diff.remove(t.sname) + # make sure we don't recreate the loop again! + for d in diff.copy(): + t2 = bld.get_tgen_by_name(d) + if t2.samba_type == 'LIBRARY': + if t.sname in t2.final_libs: + debug('deps: removing expansion %s from %s', d, t.sname) + diff.remove(d) + if diff: + debug('deps: Expanded target %s by loop %s libraries (loop %s) %s', t.sname, loop, + loops[loop], diff) + t.final_libs = t.final_libs.union(diff) + + # remove objects that are also available in linked libs + count = 0 + while reduce_objects(bld, tgt_list): + count += 1 + if count > 100: + Logs.warn("WARNING: Unable to remove all inter-target object duplicates") + break + debug('deps: Object reduction took %u iterations', count) + + # add in any syslib dependencies + for t in tgt_list: + if not t.samba_type in ['BINARY','PYTHON','LIBRARY','SUBSYSTEM']: + continue + syslibs = set() + for d in t.final_objects: + t2 = bld.get_tgen_by_name(d) + syslibs = syslibs.union(t2.direct_syslibs) + # this adds the indirect syslibs as well, which may not be needed + # depending on the linker flags + for d in t.final_libs: + t2 = bld.get_tgen_by_name(d) + syslibs = syslibs.union(t2.direct_syslibs) + t.final_syslibs = syslibs + + + # find any unresolved library loops + lib_loop_error = False + for t in tgt_list: + if t.samba_type in ['LIBRARY', 'PYTHON']: + for l in t.final_libs.copy(): + t2 = bld.get_tgen_by_name(l) + if t.sname in t2.final_libs: + Logs.error('ERROR: Unresolved library loop %s from %s' % (t.sname, t2.sname)) + lib_loop_error = True + if lib_loop_error: + sys.exit(1) + + debug('deps: removed duplicate dependencies') + + +def show_dependencies(bld, target, seen): + '''recursively show the dependencies of target''' + + if target in seen: + return + + t = bld.get_tgen_by_name(target) + if t is None: + Logs.error("ERROR: Unable to find target '%s'" % target) + sys.exit(1) + + Logs.info('%s(OBJECTS): %s' % (target, t.direct_objects)) + Logs.info('%s(LIBS): %s' % (target, t.direct_libs)) + Logs.info('%s(SYSLIBS): %s' % (target, t.direct_syslibs)) + + seen.add(target) + + for t2 in t.direct_objects: + show_dependencies(bld, t2, seen) + + +def show_object_duplicates(bld, tgt_list): + '''show a list of object files that are included in more than + one library or binary''' + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + used_by = {} + + Logs.info("showing duplicate objects") + + for t in tgt_list: + if not targets[t.sname] in [ 'LIBRARY', 'PYTHON' ]: + continue + for n in getattr(t, 'final_objects', set()): + t2 = bld.get_tgen_by_name(n) + if not n in used_by: + used_by[n] = set() + used_by[n].add(t.sname) + + for n in used_by: + if len(used_by[n]) > 1: + Logs.info("target '%s' is used by %s" % (n, used_by[n])) + + Logs.info("showing indirect dependency counts (sorted by count)") + + def indirect_count(t1, t2): + return len(t2.indirect_objects) - len(t1.indirect_objects) + + sorted_list = sorted(tgt_list, cmp=indirect_count) + for t in sorted_list: + if len(t.indirect_objects) > 1: + Logs.info("%s depends on %u indirect objects" % (t.sname, len(t.indirect_objects))) + + +###################################################################### +# this provides a way to save our dependency calculations between runs +savedeps_version = 3 +savedeps_inputs = ['samba_deps', 'samba_includes', 'local_include', 'local_include_first', 'samba_cflags', + 'source', 'grouping_library', 'samba_ldflags', 'allow_undefined_symbols', + 'use_global_deps', 'global_include' ] +savedeps_outputs = ['uselib', 'uselib_local', 'add_objects', 'includes', + 'cflags', 'ldflags', 'samba_deps_extended', 'final_libs'] +savedeps_outenv = ['INC_PATHS'] +savedeps_envvars = ['NONSHARED_BINARIES', 'GLOBAL_DEPENDENCIES', 'EXTRA_CFLAGS', 'EXTRA_LDFLAGS', 'EXTRA_INCLUDES' ] +savedeps_caches = ['GLOBAL_DEPENDENCIES', 'TARGET_TYPE', 'INIT_FUNCTIONS', 'SYSLIB_DEPS'] +savedeps_files = ['buildtools/wafsamba/samba_deps.py'] + +def save_samba_deps(bld, tgt_list): + '''save the dependency calculations between builds, to make + further builds faster''' + denv = ConfigSet.ConfigSet() + + denv.version = savedeps_version + denv.savedeps_inputs = savedeps_inputs + denv.savedeps_outputs = savedeps_outputs + denv.input = {} + denv.output = {} + denv.outenv = {} + denv.caches = {} + denv.envvar = {} + denv.files = {} + + for f in savedeps_files: + denv.files[f] = os.stat(os.path.join(bld.srcnode.abspath(), f)).st_mtime + + for c in savedeps_caches: + denv.caches[c] = LOCAL_CACHE(bld, c) + + for e in savedeps_envvars: + denv.envvar[e] = bld.env[e] + + for t in tgt_list: + # save all the input attributes for each target + tdeps = {} + for attr in savedeps_inputs: + v = getattr(t, attr, None) + if v is not None: + tdeps[attr] = v + if tdeps != {}: + denv.input[t.sname] = tdeps + + # save all the output attributes for each target + tdeps = {} + for attr in savedeps_outputs: + v = getattr(t, attr, None) + if v is not None: + tdeps[attr] = v + if tdeps != {}: + denv.output[t.sname] = tdeps + + tdeps = {} + for attr in savedeps_outenv: + if attr in t.env: + tdeps[attr] = t.env[attr] + if tdeps != {}: + denv.outenv[t.sname] = tdeps + + depsfile = os.path.join(bld.cache_dir, "sambadeps") + denv.store_fast(depsfile) + + + +def load_samba_deps(bld, tgt_list): + '''load a previous set of build dependencies if possible''' + depsfile = os.path.join(bld.cache_dir, "sambadeps") + denv = ConfigSet.ConfigSet() + try: + debug('deps: checking saved dependencies') + denv.load_fast(depsfile) + if (denv.version != savedeps_version or + denv.savedeps_inputs != savedeps_inputs or + denv.savedeps_outputs != savedeps_outputs): + return False + except Exception: + return False + + # check if critical files have changed + for f in savedeps_files: + if f not in denv.files: + return False + if denv.files[f] != os.stat(os.path.join(bld.srcnode.abspath(), f)).st_mtime: + return False + + # check if caches are the same + for c in savedeps_caches: + if c not in denv.caches or denv.caches[c] != LOCAL_CACHE(bld, c): + return False + + # check if caches are the same + for e in savedeps_envvars: + if e not in denv.envvar or denv.envvar[e] != bld.env[e]: + return False + + # check inputs are the same + for t in tgt_list: + tdeps = {} + for attr in savedeps_inputs: + v = getattr(t, attr, None) + if v is not None: + tdeps[attr] = v + if t.sname in denv.input: + olddeps = denv.input[t.sname] + else: + olddeps = {} + if tdeps != olddeps: + #print '%s: \ntdeps=%s \nodeps=%s' % (t.sname, tdeps, olddeps) + return False + + # put outputs in place + for t in tgt_list: + if not t.sname in denv.output: continue + tdeps = denv.output[t.sname] + for a in tdeps: + setattr(t, a, tdeps[a]) + + # put output env vars in place + for t in tgt_list: + if not t.sname in denv.outenv: continue + tdeps = denv.outenv[t.sname] + for a in tdeps: + t.env[a] = tdeps[a] + + debug('deps: loaded saved dependencies') + return True + + + +def check_project_rules(bld): + '''check the project rules - ensuring the targets are sane''' + + loops = {} + inc_loops = {} + + tgt_list = get_tgt_list(bld) + + add_samba_attributes(bld, tgt_list) + + force_project_rules = (Options.options.SHOWDEPS or + Options.options.SHOW_DUPLICATES) + + if not force_project_rules and load_samba_deps(bld, tgt_list): + return + + timer = Utils.Timer() + + bld.new_rules = True + Logs.info("Checking project rules ...") + + debug('deps: project rules checking started') + + expand_subsystem_deps(bld) + + debug("deps: expand_subsystem_deps: %s" % str(timer)) + + replace_grouping_libraries(bld, tgt_list) + + debug("deps: replace_grouping_libraries: %s" % str(timer)) + + build_direct_deps(bld, tgt_list) + + debug("deps: build_direct_deps: %s" % str(timer)) + + break_dependency_loops(bld, tgt_list) + + debug("deps: break_dependency_loops: %s" % str(timer)) + + if Options.options.SHOWDEPS: + show_dependencies(bld, Options.options.SHOWDEPS, set()) + + calculate_final_deps(bld, tgt_list, loops) + + debug("deps: calculate_final_deps: %s" % str(timer)) + + if Options.options.SHOW_DUPLICATES: + show_object_duplicates(bld, tgt_list) + + # run the various attribute generators + for f in [ build_dependencies, build_includes, add_init_functions ]: + debug('deps: project rules checking %s', f) + for t in tgt_list: f(t) + debug("deps: %s: %s" % (f, str(timer))) + + debug('deps: project rules stage1 completed') + + if not check_duplicate_sources(bld, tgt_list): + Logs.error("Duplicate sources present - aborting") + sys.exit(1) + + debug("deps: check_duplicate_sources: %s" % str(timer)) + + if not bld.check_group_ordering(tgt_list): + Logs.error("Bad group ordering - aborting") + sys.exit(1) + + debug("deps: check_group_ordering: %s" % str(timer)) + + show_final_deps(bld, tgt_list) + + debug("deps: show_final_deps: %s" % str(timer)) + + debug('deps: project rules checking completed - %u targets checked', + len(tgt_list)) + + if not bld.is_install: + save_samba_deps(bld, tgt_list) + + debug("deps: save_samba_deps: %s" % str(timer)) + + Logs.info("Project rules pass") + + +def CHECK_PROJECT_RULES(bld): + '''enable checking of project targets for sanity''' + if bld.env.added_project_rules: + return + bld.env.added_project_rules = True + bld.add_pre_fun(check_project_rules) +Build.BuildContext.CHECK_PROJECT_RULES = CHECK_PROJECT_RULES + + diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_dist.py b/ldb-2.0.8/buildtools/wafsamba/samba_dist.py new file mode 100644 index 0000000..6af7bb4 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_dist.py @@ -0,0 +1,280 @@ +# customised version of 'waf dist' for Samba tools +# uses git ls-files to get file lists + +import os, sys, tarfile +from waflib import Utils, Scripting, Logs, Options +from waflib.Configure import conf +from samba_utils import os_path_relpath, get_string +from waflib import Context + +dist_dirs = None +dist_files = None +dist_blacklist = "" +dist_archive = None + +class Dist(Context.Context): + # TODO remove + cmd = 'dist' + fun = 'dist' + def execute(self): + Context.g_module.dist() + +class DistCheck(Scripting.DistCheck): + fun = 'distcheck' + cmd = 'distcheck' + def execute(self): + Options.options.distcheck_args = '' + if Context.g_module.distcheck is Scripting.distcheck: + # default + Context.g_module.distcheck(self) + else: + Context.g_module.distcheck() + Context.g_module.dist() + self.check() + def get_arch_name(self): + global dist_archive + return dist_archive + def make_distcheck_cmd(self, tmpdir): + waf = os.path.abspath(sys.argv[0]) + return [sys.executable, waf, 'configure', 'build', 'install', 'uninstall', '--destdir=' + tmpdir] + +def add_symlink(tar, fname, abspath, basedir): + '''handle symlinks to directories that may move during packaging''' + if not os.path.islink(abspath): + return False + tinfo = tar.gettarinfo(name=abspath, arcname=fname) + tgt = os.readlink(abspath) + + if dist_dirs: + # we need to find the target relative to the main directory + # this is here to cope with symlinks into the buildtools + # directory from within the standalone libraries in Samba. For example, + # a symlink to ../../builtools/scripts/autogen-waf.sh needs + # to be rewritten as a symlink to buildtools/scripts/autogen-waf.sh + # when the tarball for talloc is built + + # the filename without the appname-version + rel_fname = '/'.join(fname.split('/')[1:]) + + # join this with the symlink target + tgt_full = os.path.join(os.path.dirname(rel_fname), tgt) + + # join with the base directory + tgt_base = os.path.normpath(os.path.join(basedir, tgt_full)) + + # see if this is inside one of our dist_dirs + for dir in dist_dirs.split(): + if dir.find(':') != -1: + destdir=dir.split(':')[1] + dir=dir.split(':')[0] + else: + destdir = '.' + if dir == basedir: + # internal links don't get rewritten + continue + if dir == tgt_base[0:len(dir)] and tgt_base[len(dir)] == '/': + new_tgt = destdir + tgt_base[len(dir):] + tinfo.linkname = new_tgt + break + + tinfo.uid = 0 + tinfo.gid = 0 + tinfo.uname = 'root' + tinfo.gname = 'root' + tar.addfile(tinfo) + return True + +def add_tarfile(tar, fname, abspath, basedir): + '''add a file to the tarball''' + if add_symlink(tar, fname, abspath, basedir): + return + try: + tinfo = tar.gettarinfo(name=abspath, arcname=fname) + except OSError: + Logs.error('Unable to find file %s - missing from git checkout?' % abspath) + sys.exit(1) + tinfo.uid = 0 + tinfo.gid = 0 + tinfo.uname = 'root' + tinfo.gname = 'root' + fh = open(abspath, "rb") + tar.addfile(tinfo, fileobj=fh) + fh.close() + + +def vcs_dir_contents(path): + """Return the versioned files under a path. + + :return: List of paths relative to path + """ + repo = path + while repo != "/": + if os.path.isdir(os.path.join(repo, ".git")): + ls_files_cmd = [ 'git', 'ls-files', '--full-name', + os_path_relpath(path, repo) ] + cwd = None + env = dict(os.environ) + env["GIT_DIR"] = os.path.join(repo, ".git") + break + repo = os.path.dirname(repo) + if repo == "/": + raise Exception("unsupported or no vcs for %s" % path) + return get_string(Utils.cmd_output(ls_files_cmd, cwd=cwd, env=env)).split('\n') + + +def dist(appname='', version=''): + + def add_files_to_tarball(tar, srcdir, srcsubdir, dstdir, dstsubdir, blacklist, files): + if blacklist is None: + blacklist = [] + for f in files: + abspath = os.path.join(srcdir, f) + + if srcsubdir != '.': + f = f[len(srcsubdir)+1:] + + # Remove files in the blacklist + if f in blacklist: + continue + blacklisted = False + # Remove directories in the blacklist + for d in blacklist: + if f.startswith(d): + blacklisted = True + if blacklisted: + continue + if os.path.isdir(abspath) and not os.path.islink(abspath): + continue + if dstsubdir != '.': + f = dstsubdir + '/' + f + fname = dstdir + '/' + f + add_tarfile(tar, fname, abspath, srcsubdir) + + + def list_directory_files(path): + curdir = os.getcwd() + os.chdir(srcdir) + out_files = [] + for root, dirs, files in os.walk(path): + for f in files: + out_files.append(os.path.join(root, f)) + os.chdir(curdir) + return out_files + + + if not isinstance(appname, str) or not appname: + # this copes with a mismatch in the calling arguments for dist() + appname = Context.g_module.APPNAME + version = Context.g_module.VERSION + if not version: + version = Context.g_module.VERSION + + srcdir = os.path.normpath( + os.path.join(os.path.dirname(Context.g_module.root_path), + Context.g_module.top)) + + if not dist_dirs: + Logs.error('You must use samba_dist.DIST_DIRS() to set which directories to package') + sys.exit(1) + + dist_base = '%s-%s' % (appname, version) + + if Options.options.SIGN_RELEASE: + dist_name = '%s.tar' % (dist_base) + tar = tarfile.open(dist_name, 'w') + else: + dist_name = '%s.tar.gz' % (dist_base) + tar = tarfile.open(dist_name, 'w:gz') + + blacklist = dist_blacklist.split() + + for dir in dist_dirs.split(): + if dir.find(':') != -1: + destdir=dir.split(':')[1] + dir=dir.split(':')[0] + else: + destdir = '.' + absdir = os.path.join(srcdir, dir) + try: + files = vcs_dir_contents(absdir) + except Exception as e: + Logs.error('unable to get contents of %s: %s' % (absdir, e)) + sys.exit(1) + add_files_to_tarball(tar, srcdir, dir, dist_base, destdir, blacklist, files) + + if dist_files: + for file in dist_files.split(): + if file.find(':') != -1: + destfile = file.split(':')[1] + file = file.split(':')[0] + else: + destfile = file + + absfile = os.path.join(srcdir, file) + + if os.path.isdir(absfile) and not os.path.islink(absfile): + destdir = destfile + dir = file + files = list_directory_files(dir) + add_files_to_tarball(tar, srcdir, dir, dist_base, destdir, blacklist, files) + else: + fname = dist_base + '/' + destfile + add_tarfile(tar, fname, absfile, destfile) + + tar.close() + + if Options.options.SIGN_RELEASE: + import gzip + try: + os.unlink(dist_name + '.asc') + except OSError: + pass + + cmd = "gpg --detach-sign --armor " + dist_name + os.system(cmd) + uncompressed_tar = open(dist_name, 'rb') + compressed_tar = gzip.open(dist_name + '.gz', 'wb') + while 1: + buffer = uncompressed_tar.read(1048576) + if buffer: + compressed_tar.write(buffer) + else: + break + uncompressed_tar.close() + compressed_tar.close() + os.unlink(dist_name) + Logs.info('Created %s.gz %s.asc' % (dist_name, dist_name)) + dist_name = dist_name + '.gz' + else: + Logs.info('Created %s' % dist_name) + + # TODO use the ctx object instead + global dist_archive + dist_archive = dist_name + return dist_name + + +@conf +def DIST_DIRS(dirs): + '''set the directories to package, relative to top srcdir''' + global dist_dirs + if not dist_dirs: + dist_dirs = dirs + +@conf +def DIST_FILES(files, extend=False): + '''set additional files for packaging, relative to top srcdir''' + global dist_files + if not dist_files: + dist_files = files + elif extend: + dist_files = dist_files + " " + files + +@conf +def DIST_BLACKLIST(blacklist): + '''set the files to exclude from packaging, relative to top srcdir''' + global dist_blacklist + if not dist_blacklist: + dist_blacklist = blacklist + +Scripting.dist = dist diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_git.py b/ldb-2.0.8/buildtools/wafsamba/samba_git.py new file mode 100644 index 0000000..09a204f --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_git.py @@ -0,0 +1,57 @@ +import os +import subprocess + +def find_git(env=None): + """Find the git binary.""" + if env is not None and 'GIT' in env: + return env.get_flat('GIT') + + # Get version from GIT + if os.path.exists("/usr/bin/git"): + # this is useful when doing make dist without configuring + return "/usr/bin/git" + + return None + + +def has_submodules(path): + """Check whether a source directory is git-versioned and has submodules. + + :param path: Path to Samba source directory + """ + return (os.path.isdir(os.path.join(path, ".git")) and + os.path.isfile(os.path.join(path, ".gitmodules"))) + + +def read_submodule_status(path, env=None): + """Check status of submodules. + + :param path: Path to git directory + :param env: Optional waf environment + :return: Yields tuples with submodule relpath and status + (one of: 'out-of-date', 'not-checked-out', 'up-to-date') + :raise RuntimeError: raised when parsing of 'git submodule status' output + fails. + """ + if not has_submodules(path): + # No point in running git. + return + git = find_git(env) + if git is None: + return + p = subprocess.Popen([git, "submodule", "status"], stdout=subprocess.PIPE, + cwd=path) + (stdout, stderr) = p.communicate(None) + for l in stdout.splitlines(): + l = l.rstrip() + status = l[0] + l = l[1:] + parts = l.split(" ") + if len(parts) > 2 and status in ("-", "+"): + yield (parts[1], "out-of-date") + elif len(parts) == 2 and status == "-": + yield (parts[1], "not-checked-out") + elif len(parts) > 2 and status == " ": + yield (parts[1], "up-to-date") + else: + raise RuntimeError("Unable to parse submodule status: %r, %r" % (status, parts)) diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_headers.py b/ldb-2.0.8/buildtools/wafsamba/samba_headers.py new file mode 100644 index 0000000..a268c01 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_headers.py @@ -0,0 +1,181 @@ +# specialist handling of header files for Samba + +import os, re, sys, fnmatch +from waflib import Build, Logs, Utils, Errors +from samba_utils import TO_LIST, os_path_relpath + + +def header_install_path(header, header_path): + '''find the installation path for a header, given a header_path option''' + if not header_path: + return '' + if not isinstance(header_path, list): + return header_path + for (p1, dir) in header_path: + for p2 in TO_LIST(p1): + if fnmatch.fnmatch(header, p2): + return dir + # default to current path + return '' + + +re_header = re.compile('^\s*#\s*include[ \t]*"([^"]+)"', re.I | re.M) + +# a dictionary mapping source header paths to public header paths +header_map = {} + +def find_suggested_header(hpath): + '''find a suggested header path to use''' + base = os.path.basename(hpath) + ret = [] + for h in header_map: + if os.path.basename(h) == base: + ret.append('<%s>' % header_map[h]) + ret.append('"%s"' % h) + return ret + +def create_public_header(task): + '''create a public header from a private one, output within the build tree''' + src = task.inputs[0].abspath(task.env) + tgt = task.outputs[0].bldpath(task.env) + + if os.path.exists(tgt): + os.unlink(tgt) + + relsrc = os_path_relpath(src, task.env.TOPDIR) + + infile = open(src, mode='r') + outfile = open(tgt, mode='w') + linenumber = 0 + + search_paths = [ '', task.env.RELPATH ] + for i in task.env.EXTRA_INCLUDES: + if i.startswith('#'): + search_paths.append(i[1:]) + + for line in infile: + linenumber += 1 + + # allow some straight substitutions + if task.env.public_headers_replace and line.strip() in task.env.public_headers_replace: + outfile.write(task.env.public_headers_replace[line.strip()] + '\n') + continue + + # see if its an include line + m = re_header.match(line) + if m is None: + outfile.write(line) + continue + + # its an include, get the header path + hpath = m.group(1) + if hpath.startswith("bin/default/"): + hpath = hpath[12:] + + # some are always allowed + if task.env.public_headers_skip and hpath in task.env.public_headers_skip: + outfile.write(line) + continue + + # work out the header this refers to + found = False + for s in search_paths: + p = os.path.normpath(os.path.join(s, hpath)) + if p in header_map: + outfile.write("#include <%s>\n" % header_map[p]) + found = True + break + if found: + continue + + if task.env.public_headers_allow_broken: + Logs.warn("Broken public header include '%s' in '%s'" % (hpath, relsrc)) + outfile.write(line) + continue + + # try to be nice to the developer by suggesting an alternative + suggested = find_suggested_header(hpath) + outfile.close() + os.unlink(tgt) + sys.stderr.write("%s:%u:Error: unable to resolve public header %s (maybe try one of %s)\n" % ( + os.path.relpath(src, os.getcwd()), linenumber, hpath, suggested)) + raise Errors.WafError("Unable to resolve header path '%s' in public header '%s' in directory %s" % ( + hpath, relsrc, task.env.RELPATH)) + infile.close() + outfile.close() + + +def public_headers_simple(bld, public_headers, header_path=None, public_headers_install=True): + '''install some headers - simple version, no munging needed + ''' + if not public_headers_install: + return + for h in TO_LIST(public_headers): + inst_path = header_install_path(h, header_path) + if h.find(':') != -1: + s = h.split(":") + h_name = s[0] + inst_name = s[1] + else: + h_name = h + inst_name = os.path.basename(h) + bld.INSTALL_FILES('${INCLUDEDIR}', h_name, destname=inst_name) + + +def PUBLIC_HEADERS(bld, public_headers, header_path=None, public_headers_install=True): + '''install some headers + + header_path may either be a string that is added to the INCLUDEDIR, + or it can be a dictionary of wildcard patterns which map to destination + directories relative to INCLUDEDIR + ''' + bld.SET_BUILD_GROUP('final') + + if not bld.env.build_public_headers: + # in this case no header munging neeeded. Used for tdb, talloc etc + public_headers_simple(bld, public_headers, header_path=header_path, + public_headers_install=public_headers_install) + return + + # create the public header in the given path + # in the build tree + for h in TO_LIST(public_headers): + inst_path = header_install_path(h, header_path) + if h.find(':') != -1: + s = h.split(":") + h_name = s[0] + inst_name = s[1] + else: + h_name = h + inst_name = os.path.basename(h) + curdir = bld.path.abspath() + relpath1 = os_path_relpath(bld.srcnode.abspath(), curdir) + relpath2 = os_path_relpath(curdir, bld.srcnode.abspath()) + targetdir = os.path.normpath(os.path.join(relpath1, bld.env.build_public_headers, inst_path)) + if not os.path.exists(os.path.join(curdir, targetdir)): + raise Errors.WafError("missing source directory %s for public header %s" % (targetdir, inst_name)) + target = os.path.join(targetdir, inst_name) + + # the source path of the header, relative to the top of the source tree + src_path = os.path.normpath(os.path.join(relpath2, h_name)) + + # the install path of the header, relative to the public include directory + target_path = os.path.normpath(os.path.join(inst_path, inst_name)) + + header_map[src_path] = target_path + + t = bld.SAMBA_GENERATOR('HEADER_%s/%s/%s' % (relpath2, inst_path, inst_name), + group='headers', + rule=create_public_header, + source=h_name, + target=target) + t.env.RELPATH = relpath2 + t.env.TOPDIR = bld.srcnode.abspath() + if not bld.env.public_headers_list: + bld.env.public_headers_list = [] + bld.env.public_headers_list.append(os.path.join(inst_path, inst_name)) + if public_headers_install: + bld.INSTALL_FILES('${INCLUDEDIR}', + target, + destname=os.path.join(inst_path, inst_name), flat=True) +Build.BuildContext.PUBLIC_HEADERS = PUBLIC_HEADERS diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_install.py b/ldb-2.0.8/buildtools/wafsamba/samba_install.py new file mode 100644 index 0000000..07b01d6 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_install.py @@ -0,0 +1,236 @@ +########################### +# this handles the magic we need to do for installing +# with all the configure options that affect rpath and shared +# library use + +import os +from waflib import Utils, Errors +from waflib.TaskGen import feature, before, after +from samba_utils import LIB_PATH, MODE_755, install_rpath, build_rpath + +@feature('install_bin') +@after('apply_core') +@before('apply_link', 'apply_obj_vars') +def install_binary(self): + '''install a binary, taking account of the different rpath varients''' + bld = self.bld + + # get the ldflags we will use for install and build + install_ldflags = install_rpath(self) + build_ldflags = build_rpath(bld) + + if not self.bld.is_install: + # just need to set rpath if we are not installing + self.env.RPATH = build_ldflags + return + + # work out the install path, expanding variables + install_path = getattr(self, 'samba_inst_path', None) or '${BINDIR}' + install_path = bld.EXPAND_VARIABLES(install_path) + + orig_target = os.path.basename(self.target) + + if install_ldflags != build_ldflags: + # we will be creating a new target name, and using that for the + # install link. That stops us from overwriting the existing build + # target, which has different ldflags + self.target += '.inst' + + # setup the right rpath link flags for the install + self.env.RPATH = install_ldflags + + if not self.samba_install: + # this binary is marked not to be installed + return + + # tell waf to install the right binary + bld.install_as(os.path.join(install_path, orig_target), + self.path.find_or_declare(self.target), + chmod=MODE_755) + + + +@feature('install_lib') +@after('apply_core') +@before('apply_link', 'apply_obj_vars') +def install_library(self): + '''install a library, taking account of the different rpath varients''' + if getattr(self, 'done_install_library', False): + return + + bld = self.bld + + default_env = bld.all_envs['default'] + try: + install_ldflags = install_rpath(self) + build_ldflags = build_rpath(bld) + + if not self.bld.is_install or not getattr(self, 'samba_install', True): + # just need to set the build rpath if we are not installing + self.env.RPATH = build_ldflags + return + + # setup the install path, expanding variables + install_path = getattr(self, 'samba_inst_path', None) + if install_path is None: + if getattr(self, 'private_library', False): + install_path = '${PRIVATELIBDIR}' + else: + install_path = '${LIBDIR}' + install_path = bld.EXPAND_VARIABLES(install_path) + + target_name = self.target + + if install_ldflags != build_ldflags: + # we will be creating a new target name, and using that for the + # install link. That stops us from overwriting the existing build + # target, which has different ldflags + self.done_install_library = True + t = self.clone(self.env) + t.posted = False + t.target += '.inst' + t.name = self.name + '.inst' + self.env.RPATH = build_ldflags + else: + t = self + + t.env.RPATH = install_ldflags + + dev_link = None + + # in the following the names are: + # - inst_name is the name with .inst. in it, in the build + # directory + # - install_name is the name in the install directory + # - install_link is a symlink in the install directory, to install_name + + if getattr(self, 'samba_realname', None): + install_name = self.samba_realname + install_link = None + if getattr(self, 'soname', ''): + install_link = self.soname + if getattr(self, 'samba_type', None) == 'PYTHON': + inst_name = bld.make_libname(t.target, nolibprefix=True, python=True) + else: + inst_name = bld.make_libname(t.target) + elif self.vnum: + vnum_base = self.vnum.split('.')[0] + install_name = bld.make_libname(target_name, version=self.vnum) + install_link = bld.make_libname(target_name, version=vnum_base) + inst_name = bld.make_libname(t.target) + if not self.private_library or not t.env.SONAME_ST: + # only generate the dev link for non-bundled libs + dev_link = bld.make_libname(target_name) + elif getattr(self, 'soname', ''): + install_name = bld.make_libname(target_name) + install_link = self.soname + inst_name = bld.make_libname(t.target) + else: + install_name = bld.make_libname(target_name) + install_link = None + inst_name = bld.make_libname(t.target) + + if t.env.SONAME_ST: + # ensure we get the right names in the library + if install_link: + t.env.append_value('LINKFLAGS', t.env.SONAME_ST % install_link) + else: + t.env.append_value('LINKFLAGS', t.env.SONAME_ST % install_name) + t.env.SONAME_ST = '' + + # tell waf to install the library + bld.install_as(os.path.join(install_path, install_name), + self.path.find_or_declare(inst_name), + chmod=MODE_755) + + if install_link and install_link != install_name: + # and the symlink if needed + bld.symlink_as(os.path.join(install_path, install_link), os.path.basename(install_name)) + if dev_link: + bld.symlink_as(os.path.join(install_path, dev_link), os.path.basename(install_name)) + finally: + bld.all_envs['default'] = default_env + + +@feature('cshlib') +@after('apply_implib') +@before('apply_vnum') +def apply_soname(self): + '''install a library, taking account of the different rpath varients''' + + if self.env.SONAME_ST and getattr(self, 'soname', ''): + self.env.append_value('LINKFLAGS', self.env.SONAME_ST % self.soname) + self.env.SONAME_ST = '' + +@feature('cshlib') +@after('apply_implib') +@before('apply_vnum') +def apply_vscript(self): + '''add version-script arguments to library build''' + + if self.env.HAVE_LD_VERSION_SCRIPT and getattr(self, 'version_script', ''): + self.env.append_value('LINKFLAGS', "-Wl,--version-script=%s" % + self.version_script) + self.version_script = None + + +############################## +# handle the creation of links for libraries and binaries in the build tree + +@feature('symlink_lib') +@after('apply_link') +def symlink_lib(self): + '''symlink a shared lib''' + + if self.target.endswith('.inst'): + return + + blddir = os.path.dirname(self.bld.srcnode.abspath(self.bld.env)) + libpath = self.link_task.outputs[0].abspath(self.env) + + # calculat the link target and put it in the environment + soext="" + vnum = getattr(self, 'vnum', None) + if vnum is not None: + soext = '.' + vnum.split('.')[0] + + link_target = getattr(self, 'link_name', '') + if link_target == '': + basename = os.path.basename(self.bld.make_libname(self.target, version=soext)) + if getattr(self, "private_library", False): + link_target = '%s/private/%s' % (LIB_PATH, basename) + else: + link_target = '%s/%s' % (LIB_PATH, basename) + + link_target = os.path.join(blddir, link_target) + + if os.path.lexists(link_target): + if os.path.islink(link_target) and os.readlink(link_target) == libpath: + return + os.unlink(link_target) + + link_container = os.path.dirname(link_target) + if not os.path.isdir(link_container): + os.makedirs(link_container) + + os.symlink(libpath, link_target) + + +@feature('symlink_bin') +@after('apply_link') +def symlink_bin(self): + '''symlink a binary into the build directory''' + + if self.target.endswith('.inst'): + return + + if not self.link_task.outputs or not self.link_task.outputs[0]: + raise Errors.WafError('no outputs found for %s in symlink_bin' % self.name) + binpath = self.link_task.outputs[0].abspath(self.env) + bldpath = os.path.join(self.bld.env.BUILD_DIRECTORY, self.link_task.outputs[0].name) + + if os.path.lexists(bldpath): + if os.path.islink(bldpath) and os.readlink(bldpath) == binpath: + return + os.unlink(bldpath) + os.symlink(binpath, bldpath) diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_patterns.py b/ldb-2.0.8/buildtools/wafsamba/samba_patterns.py new file mode 100644 index 0000000..d0fe965 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_patterns.py @@ -0,0 +1,201 @@ +# a waf tool to add extension based build patterns for Samba + +import sys +from waflib import Build +from wafsamba import samba_version_file + +def write_version_header(task): + '''print version.h contents''' + src = task.inputs[0].srcpath(task.env) + + version = samba_version_file(src, task.env.srcdir, env=task.env, is_install=task.generator.bld.is_install) + string = str(version) + + task.outputs[0].write(string) + return 0 + + +def SAMBA_MKVERSION(bld, target, source='VERSION'): + '''generate the version.h header for Samba''' + + # We only force waf to re-generate this file if we are installing, + # because only then is information not included in the deps (the + # git revision) included in the version. + t = bld.SAMBA_GENERATOR('VERSION', + rule=write_version_header, + source=source, + target=target, + always=bld.is_install) +Build.BuildContext.SAMBA_MKVERSION = SAMBA_MKVERSION + + +def write_build_options_header(fp): + '''write preamble for build_options.c''' + fp.write("/*\n") + fp.write(" Unix SMB/CIFS implementation.\n") + fp.write(" Build Options for Samba Suite\n") + fp.write(" Copyright (C) Vance Lankhaar 2003\n") + fp.write(" Copyright (C) Andrew Bartlett 2001\n") + fp.write("\n") + fp.write(" This program is free software; you can redistribute it and/or modify\n") + fp.write(" it under the terms of the GNU General Public License as published by\n") + fp.write(" the Free Software Foundation; either version 3 of the License, or\n") + fp.write(" (at your option) any later version.\n") + fp.write("\n") + fp.write(" This program is distributed in the hope that it will be useful,\n") + fp.write(" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") + fp.write(" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") + fp.write(" GNU General Public License for more details.\n") + fp.write("\n") + fp.write(" You should have received a copy of the GNU General Public License\n") + fp.write(" along with this program; if not, see .\n") + fp.write("*/\n") + fp.write("\n") + fp.write("#include \"includes.h\"\n") + fp.write("#include \"dynconfig/dynconfig.h\"\n") + fp.write("#include \"lib/cluster_support.h\"\n") + + fp.write("\n") + fp.write("static int output(bool screen, const char *format, ...) PRINTF_ATTRIBUTE(2,3);\n") + fp.write("void build_options(bool screen);\n") + fp.write("\n") + fp.write("\n") + fp.write("/****************************************************************************\n") + fp.write("helper function for build_options\n") + fp.write("****************************************************************************/\n") + fp.write("static int output(bool screen, const char *format, ...)\n") + fp.write("{\n") + fp.write(" char *ptr = NULL;\n") + fp.write(" int ret = 0;\n") + fp.write(" va_list ap;\n") + fp.write(" \n") + fp.write(" va_start(ap, format);\n") + fp.write(" ret = vasprintf(&ptr,format,ap);\n") + fp.write(" va_end(ap);\n") + fp.write("\n") + fp.write(" if (screen) {\n") + fp.write(" d_printf(\"%s\", ptr ? ptr : \"\");\n") + fp.write(" } else {\n") + fp.write(" DEBUG(4,(\"%s\", ptr ? ptr : \"\"));\n") + fp.write(" }\n") + fp.write(" \n") + fp.write(" SAFE_FREE(ptr);\n") + fp.write(" return ret;\n") + fp.write("}\n") + fp.write("\n") + fp.write("/****************************************************************************\n") + fp.write("options set at build time for the samba suite\n") + fp.write("****************************************************************************/\n") + fp.write("void build_options(bool screen)\n") + fp.write("{\n") + fp.write(" if ((DEBUGLEVEL < 4) && (!screen)) {\n") + fp.write(" return;\n") + fp.write(" }\n") + fp.write("\n") + fp.write("\n") + fp.write(" /* Output various paths to files and directories */\n") + fp.write(" output(screen,\"\\nPaths:\\n\");\n") + fp.write(" output(screen,\" SBINDIR: %s\\n\", get_dyn_SBINDIR());\n") + fp.write(" output(screen,\" BINDIR: %s\\n\", get_dyn_BINDIR());\n") + fp.write(" output(screen,\" CONFIGFILE: %s\\n\", get_dyn_CONFIGFILE());\n") + fp.write(" output(screen,\" LOGFILEBASE: %s\\n\", get_dyn_LOGFILEBASE());\n") + fp.write(" output(screen,\" LMHOSTSFILE: %s\\n\",get_dyn_LMHOSTSFILE());\n") + fp.write(" output(screen,\" LIBDIR: %s\\n\",get_dyn_LIBDIR());\n") + fp.write(" output(screen,\" MODULESDIR: %s\\n\",get_dyn_MODULESDIR());\n") + fp.write(" output(screen,\" SHLIBEXT: %s\\n\",get_dyn_SHLIBEXT());\n") + fp.write(" output(screen,\" LOCKDIR: %s\\n\",get_dyn_LOCKDIR());\n") + fp.write(" output(screen,\" STATEDIR: %s\\n\",get_dyn_STATEDIR());\n") + fp.write(" output(screen,\" CACHEDIR: %s\\n\",get_dyn_CACHEDIR());\n") + fp.write(" output(screen,\" PIDDIR: %s\\n\", get_dyn_PIDDIR());\n") + fp.write(" output(screen,\" SMB_PASSWD_FILE: %s\\n\",get_dyn_SMB_PASSWD_FILE());\n") + fp.write(" output(screen,\" PRIVATE_DIR: %s\\n\",get_dyn_PRIVATE_DIR());\n") + fp.write(" output(screen,\" BINDDNS_DIR: %s\\n\",get_dyn_BINDDNS_DIR());\n") + fp.write("\n") + +def write_build_options_footer(fp): + fp.write(" /* Output the sizes of the various cluster features */\n") + fp.write(" output(screen, \"\\n%s\", cluster_support_features());\n") + fp.write("\n") + fp.write(" /* Output the sizes of the various types */\n") + fp.write(" output(screen, \"\\nType sizes:\\n\");\n") + fp.write(" output(screen, \" sizeof(char): %lu\\n\",(unsigned long)sizeof(char));\n") + fp.write(" output(screen, \" sizeof(int): %lu\\n\",(unsigned long)sizeof(int));\n") + fp.write(" output(screen, \" sizeof(long): %lu\\n\",(unsigned long)sizeof(long));\n") + fp.write(" output(screen, \" sizeof(long long): %lu\\n\",(unsigned long)sizeof(long long));\n") + fp.write(" output(screen, \" sizeof(uint8_t): %lu\\n\",(unsigned long)sizeof(uint8_t));\n") + fp.write(" output(screen, \" sizeof(uint16_t): %lu\\n\",(unsigned long)sizeof(uint16_t));\n") + fp.write(" output(screen, \" sizeof(uint32_t): %lu\\n\",(unsigned long)sizeof(uint32_t));\n") + fp.write(" output(screen, \" sizeof(short): %lu\\n\",(unsigned long)sizeof(short));\n") + fp.write(" output(screen, \" sizeof(void*): %lu\\n\",(unsigned long)sizeof(void*));\n") + fp.write(" output(screen, \" sizeof(size_t): %lu\\n\",(unsigned long)sizeof(size_t));\n") + fp.write(" output(screen, \" sizeof(off_t): %lu\\n\",(unsigned long)sizeof(off_t));\n") + fp.write(" output(screen, \" sizeof(ino_t): %lu\\n\",(unsigned long)sizeof(ino_t));\n") + fp.write(" output(screen, \" sizeof(dev_t): %lu\\n\",(unsigned long)sizeof(dev_t));\n") + fp.write("\n") + fp.write(" output(screen, \"\\nBuiltin modules:\\n\");\n") + fp.write(" output(screen, \" %s\\n\", STRING_STATIC_MODULES);\n") + fp.write("}\n") + +def write_build_options_section(fp, keys, section): + fp.write("\n\t/* Show %s */\n" % section) + fp.write(" output(screen, \"\\n%s:\\n\");\n\n" % section) + + for k in sorted(keys): + fp.write("#ifdef %s\n" % k) + fp.write(" output(screen, \" %s\\n\");\n" % k) + fp.write("#endif\n") + fp.write("\n") + +def write_build_options(task): + tbl = task.env + keys_option_with = [] + keys_option_utmp = [] + keys_option_have = [] + keys_header_sys = [] + keys_header_other = [] + keys_misc = [] + if sys.hexversion>0x300000f: + trans_table = bytes.maketrans(b'.-()', b'____') + else: + import string + trans_table = string.maketrans('.-()', '____') + + for key in tbl: + if key.startswith("HAVE_UT_UT_") or key.find("UTMP") >= 0: + keys_option_utmp.append(key) + elif key.startswith("WITH_"): + keys_option_with.append(key) + elif key.startswith("HAVE_SYS_"): + keys_header_sys.append(key) + elif key.startswith("HAVE_"): + if key.endswith("_H"): + keys_header_other.append(key) + else: + keys_option_have.append(key) + elif key.startswith("static_init_"): + l = key.split("(") + keys_misc.append(l[0]) + else: + keys_misc.append(key.translate(trans_table)) + + tgt = task.outputs[0].bldpath(task.env) + f = open(tgt, 'w') + write_build_options_header(f) + write_build_options_section(f, keys_header_sys, "System Headers") + write_build_options_section(f, keys_header_other, "Headers") + write_build_options_section(f, keys_option_utmp, "UTMP Options") + write_build_options_section(f, keys_option_have, "HAVE_* Defines") + write_build_options_section(f, keys_option_with, "--with Options") + write_build_options_section(f, keys_misc, "Build Options") + write_build_options_footer(f) + f.close() + return 0 + + +def SAMBA_BLDOPTIONS(bld, target): + '''generate the bld_options.c for Samba''' + t = bld.SAMBA_GENERATOR(target, + rule=write_build_options, + dep_vars=['defines'], + target=target) +Build.BuildContext.SAMBA_BLDOPTIONS = SAMBA_BLDOPTIONS diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_perl.py b/ldb-2.0.8/buildtools/wafsamba/samba_perl.py new file mode 100644 index 0000000..e019acb --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_perl.py @@ -0,0 +1,59 @@ +from waflib import Utils +from waflib.Configure import conf +from samba_utils import get_string +done = {} + +@conf +def SAMBA_CHECK_PERL(conf, mandatory=True, version=(5,0,0)): + if "done" in done: + return + done["done"] = True + conf.find_program('perl', var='PERL', mandatory=mandatory) + conf.load('perl') + path_perl = conf.find_program('perl') + conf.env.PERL_SPECIFIED = (conf.env.PERL != path_perl) + conf.check_perl_version(version) + + def read_perl_config_var(cmd): + output = Utils.cmd_output([conf.env.get_flat('PERL'), '-MConfig', '-e', cmd]) + if not isinstance(output, str): + output = get_string(output) + return Utils.to_list(output) + + def check_perl_config_var(var): + conf.start_msg("Checking for perl $Config{%s}:" % var) + try: + v = read_perl_config_var('print $Config{%s}' % var)[0] + conf.end_msg("'%s'" % (v), 'GREEN') + return v + except IndexError: + conf.end_msg(False, 'YELLOW') + pass + return None + + vendor_prefix = check_perl_config_var('vendorprefix') + + perl_arch_install_dir = None + if vendor_prefix == conf.env.PREFIX: + perl_arch_install_dir = check_perl_config_var('vendorarch'); + if perl_arch_install_dir is None: + perl_arch_install_dir = "${LIBDIR}/perl5"; + conf.start_msg("PERL_ARCH_INSTALL_DIR: ") + conf.end_msg("'%s'" % (perl_arch_install_dir), 'GREEN') + conf.env.PERL_ARCH_INSTALL_DIR = perl_arch_install_dir + + perl_lib_install_dir = None + if vendor_prefix == conf.env.PREFIX: + perl_lib_install_dir = check_perl_config_var('vendorlib'); + if perl_lib_install_dir is None: + perl_lib_install_dir = "${DATADIR}/perl5"; + conf.start_msg("PERL_LIB_INSTALL_DIR: ") + conf.end_msg("'%s'" % (perl_lib_install_dir), 'GREEN') + conf.env.PERL_LIB_INSTALL_DIR = perl_lib_install_dir + + perl_inc = read_perl_config_var('print "@INC"') + 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/ldb-2.0.8/buildtools/wafsamba/samba_pidl.py b/ldb-2.0.8/buildtools/wafsamba/samba_pidl.py new file mode 100644 index 0000000..3fecfa9 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_pidl.py @@ -0,0 +1,150 @@ +# waf build tool for building IDL files with pidl + +import os +from waflib import Build, Utils +from waflib.TaskGen import feature, before +from samba_utils import SET_TARGET_TYPE, TO_LIST, LOCAL_CACHE + +def SAMBA_PIDL(bld, pname, source, + options='', + output_dir='.', + generate_tables=True): + '''Build a IDL file using pidl. + This will produce up to 13 output files depending on the options used''' + + bname = source[0:-4]; # strip off the .idl suffix + bname = os.path.basename(bname) + name = "%s_%s" % (pname, bname.upper()) + + if not SET_TARGET_TYPE(bld, name, 'PIDL'): + return + + bld.SET_BUILD_GROUP('build_source') + + # the output files depend on the options used. Use this dictionary + # to map between the options and the resulting file names + options_map = { '--header' : '%s.h', + '--ndr-parser' : 'ndr_%s.c ndr_%s.h', + '--samba3-ndr-server' : 'srv_%s.c srv_%s.h', + '--samba3-ndr-client' : 'cli_%s.c cli_%s.h', + '--server' : 'ndr_%s_s.c', + '--client' : 'ndr_%s_c.c ndr_%s_c.h', + '--python' : 'py_%s.c', + '--tdr-parser' : 'tdr_%s.c tdr_%s.h', + '--dcom-proxy' : '%s_p.c', + '--com-header' : 'com_%s.h' + } + + table_header_idx = None + out_files = [] + options_list = TO_LIST(options) + + for o in options_list: + if o in options_map: + ofiles = TO_LIST(options_map[o]) + for f in ofiles: + out_files.append(os.path.join(output_dir, f % bname)) + if f == 'ndr_%s.h': + # remember this one for the tables generation + table_header_idx = len(out_files) - 1 + + # depend on the full pidl sources + source = TO_LIST(source) + try: + pidl_src_nodes = bld.pidl_files_cache + except AttributeError: + bld.pidl_files_cache = bld.srcnode.ant_glob('pidl/lib/Parse/**/*.pm', flat=False) + bld.pidl_files_cache.extend(bld.srcnode.ant_glob('pidl', flat=False)) + pidl_src_nodes = bld.pidl_files_cache + + # the cd .. is needed because pidl currently is sensitive to the directory it is run in + cpp = "" + cc = "" + if bld.CONFIG_SET("CPP") and bld.CONFIG_GET("CPP") != "": + if isinstance(bld.CONFIG_GET("CPP"), list): + cpp = 'CPP="%s"' % " ".join(bld.CONFIG_GET("CPP")) + else: + cpp = 'CPP="%s"' % bld.CONFIG_GET("CPP") + + if cpp == "CPP=xlc_r": + cpp = "" + + + if bld.CONFIG_SET("CC"): + if isinstance(bld.CONFIG_GET("CC"), list): + cc = 'CC="%s"' % " ".join(bld.CONFIG_GET("CC")) + else: + cc = 'CC="%s"' % bld.CONFIG_GET("CC") + + t = bld(rule='cd ${PIDL_LAUNCH_DIR} && %s %s ${PERL} ${PIDL} --quiet ${OPTIONS} --outputdir ${OUTPUTDIR} -- "${IDLSRC}"' % (cpp, cc), + ext_out = '.c', + before = 'c', + update_outputs = True, + shell = True, + source = source, + target = out_files, + name = name, + samba_type = 'PIDL') + + + t.env.PIDL_LAUNCH_DIR = bld.srcnode.path_from(bld.bldnode) + pnode = bld.srcnode.find_resource('pidl/pidl') + t.env.PIDL = pnode.path_from(bld.srcnode) + t.env.OPTIONS = TO_LIST(options) + snode = t.path.find_resource(source[0]) + t.env.IDLSRC = snode.path_from(bld.srcnode) + t.env.OUTPUTDIR = bld.bldnode.path_from(bld.srcnode) + '/' + bld.path.find_dir(output_dir).path_from(bld.srcnode) + + bld.add_manual_dependency(snode, pidl_src_nodes) + + if generate_tables and table_header_idx is not None: + pidl_headers = LOCAL_CACHE(bld, 'PIDL_HEADERS') + pidl_headers[name] = [bld.path.find_or_declare(out_files[table_header_idx])] + + t.more_includes = '#' + bld.path.path_from(bld.srcnode) +Build.BuildContext.SAMBA_PIDL = SAMBA_PIDL + + +def SAMBA_PIDL_LIST(bld, name, source, + options='', + output_dir='.', + generate_tables=True): + '''A wrapper for building a set of IDL files''' + for p in TO_LIST(source): + bld.SAMBA_PIDL(name, p, options=options, output_dir=output_dir, generate_tables=generate_tables) +Build.BuildContext.SAMBA_PIDL_LIST = SAMBA_PIDL_LIST + + +################################################################# +# the rule for generating the NDR tables +@feature('collect') +@before('exec_rule') +def collect(self): + pidl_headers = LOCAL_CACHE(self.bld, 'PIDL_HEADERS') + # The first source is tables.pl itself + self.source = Utils.to_list(self.source) + for (name, hd) in pidl_headers.items(): + y = self.bld.get_tgen_by_name(name) + self.bld.ASSERT(y is not None, 'Failed to find PIDL header %s' % name) + y.post() + for node in hd: + self.bld.ASSERT(node is not None, 'Got None as build node generating PIDL table for %s' % name) + self.source.append(node) + + +def SAMBA_PIDL_TABLES(bld, name, target): + '''generate the pidl NDR tables file''' + bld.SET_BUILD_GROUP('main') + t = bld( + features = 'collect', + rule = '${PERL} ${SRC} > ${TGT}', + ext_out = '.c', + before = 'c', + update_outputs = True, + shell = True, + source = '../../librpc/tables.pl', + target = target, + name = name) + t.env.LIBRPC = os.path.join(bld.srcnode.abspath(), 'librpc') +Build.BuildContext.SAMBA_PIDL_TABLES = SAMBA_PIDL_TABLES + diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_python.py b/ldb-2.0.8/buildtools/wafsamba/samba_python.py new file mode 100644 index 0000000..4476d33 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_python.py @@ -0,0 +1,159 @@ +# waf build tool for building IDL files with pidl + +import os, sys +from waflib import Build, Logs, Utils, Configure, Errors +from waflib.Configure import conf + +@conf +def SAMBA_CHECK_PYTHON(conf, version=(3,4,0)): + + if conf.env.disable_python: + version=(2,6,0) + + # enable tool to build python extensions + if conf.env.HAVE_PYTHON_H: + conf.check_python_version(version) + return + + interpreters = [] + + conf.find_program('python3', var='PYTHON', + mandatory=not conf.env.disable_python) + conf.load('python') + path_python = conf.find_program('python3') + + conf.env.PYTHON_SPECIFIED = (conf.env.PYTHON != path_python) + conf.check_python_version(version) + + interpreters.append(conf.env['PYTHON']) + conf.env.python_interpreters = interpreters + + +@conf +def SAMBA_CHECK_PYTHON_HEADERS(conf): + if conf.env.disable_python: + + conf.msg("python headers", "Check disabled due to --disable-python") + # we don't want PYTHONDIR in config.h, as otherwise changing + # --prefix causes a complete rebuild + conf.env.DEFINES = [x for x in conf.env.DEFINES + if not x.startswith('PYTHONDIR=') + and not x.startswith('PYTHONARCHDIR=')] + + return + + if conf.env["python_headers_checked"] == []: + _check_python_headers(conf) + conf.env["python_headers_checked"] = "yes" + + else: + conf.msg("python headers", "using cache") + + # we don't want PYTHONDIR in config.h, as otherwise changing + # --prefix causes a complete rebuild + conf.env.DEFINES = [x for x in conf.env.DEFINES + if not x.startswith('PYTHONDIR=') + and not x.startswith('PYTHONARCHDIR=')] + +def _check_python_headers(conf): + conf.check_python_headers() + + if conf.env['PYTHON_VERSION'] > '3': + abi_pattern = os.path.splitext(conf.env['pyext_PATTERN'])[0] + conf.env['PYTHON_SO_ABI_FLAG'] = abi_pattern % '' + else: + conf.env['PYTHON_SO_ABI_FLAG'] = '' + conf.env['PYTHON_LIBNAME_SO_ABI_FLAG'] = ( + conf.env['PYTHON_SO_ABI_FLAG'].replace('_', '-')) + + for lib in conf.env['LINKFLAGS_PYEMBED']: + if lib.startswith('-L'): + conf.env.append_unique('LIBPATH_PYEMBED', lib[2:]) # strip '-L' + conf.env['LINKFLAGS_PYEMBED'].remove(lib) + + # same as in waf 1.5, keep only '-fno-strict-aliasing' + # and ignore defines such as NDEBUG _FORTIFY_SOURCE=2 + conf.env.DEFINES_PYEXT = [] + conf.env.CFLAGS_PYEXT = ['-fno-strict-aliasing'] + + return + +def PYTHON_BUILD_IS_ENABLED(self): + return self.CONFIG_SET('HAVE_PYTHON_H') + +Build.BuildContext.PYTHON_BUILD_IS_ENABLED = PYTHON_BUILD_IS_ENABLED + + +def SAMBA_PYTHON(bld, name, + source='', + deps='', + public_deps='', + realname=None, + cflags='', + cflags_end=None, + includes='', + init_function_sentinel=None, + local_include=True, + vars=None, + install=True, + enabled=True): + '''build a python extension for Samba''' + + # force-disable when we can't build python modules, so + # every single call doesn't need to pass this in. + if not bld.PYTHON_BUILD_IS_ENABLED(): + enabled = False + + # when we support static python modules we'll need to gather + # the list from all the SAMBA_PYTHON() targets + if init_function_sentinel is not None: + cflags += ' -DSTATIC_LIBPYTHON_MODULES=%s' % init_function_sentinel + + # From https://docs.python.org/2/c-api/arg.html: + # Starting with Python 2.5 the type of the length argument to + # PyArg_ParseTuple(), PyArg_ParseTupleAndKeywords() and PyArg_Parse() + # can be controlled by defining the macro PY_SSIZE_T_CLEAN before + # including Python.h. If the macro is defined, length is a Py_ssize_t + # rather than an int. + + # Because if often included before includes.h/config.h + # This must be in the -D compiler options + cflags += ' -DPY_SSIZE_T_CLEAN=1' + + source = bld.EXPAND_VARIABLES(source, vars=vars) + + if realname is not None: + link_name = 'python/%s' % realname + else: + link_name = None + + bld.SAMBA_LIBRARY(name, + source=source, + deps=deps, + public_deps=public_deps, + includes=includes, + cflags=cflags, + cflags_end=cflags_end, + local_include=local_include, + vars=vars, + realname=realname, + link_name=link_name, + pyext=True, + target_type='PYTHON', + install_path='${PYTHONARCHDIR}', + allow_undefined_symbols=True, + install=install, + enabled=enabled) + +Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON + + +def pyembed_libname(bld, name): + if bld.env['PYTHON_SO_ABI_FLAG']: + return name + bld.env['PYTHON_SO_ABI_FLAG'] + else: + return name + +Build.BuildContext.pyembed_libname = pyembed_libname + + diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_third_party.py b/ldb-2.0.8/buildtools/wafsamba/samba_third_party.py new file mode 100644 index 0000000..f7410ec --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_third_party.py @@ -0,0 +1,66 @@ +# functions to support third party libraries + +import os +from waflib import Utils, Build, Context +from waflib.Configure import conf + +@conf +def CHECK_FOR_THIRD_PARTY(conf): + return os.path.exists(os.path.join(Context.g_module.top, 'third_party')) + +Build.BuildContext.CHECK_FOR_THIRD_PARTY = CHECK_FOR_THIRD_PARTY + +@conf +def CHECK_ZLIB(conf): + version_check=''' + #if (ZLIB_VERNUM >= 0x1230) + #else + #error "ZLIB_VERNUM < 0x1230" + #endif + z_stream *z; + inflateInit2(z, -15); + ''' + return conf.CHECK_BUNDLED_SYSTEM('z', minversion='1.2.3', pkg='zlib', + checkfunctions='zlibVersion', + headers='zlib.h', + checkcode=version_check, + implied_deps='replace') + +Build.BuildContext.CHECK_ZLIB = CHECK_ZLIB + +@conf +def CHECK_POPT(conf): + return conf.CHECK_BUNDLED_SYSTEM('popt', checkfunctions='poptGetContext', headers='popt.h') + +Build.BuildContext.CHECK_POPT = CHECK_POPT + +@conf +def CHECK_CMOCKA(conf): + return conf.CHECK_BUNDLED_SYSTEM_PKG('cmocka', minversion='1.1.3') + +Build.BuildContext.CHECK_CMOCKA = CHECK_CMOCKA + +@conf +def CHECK_SOCKET_WRAPPER(conf): + return conf.CHECK_BUNDLED_SYSTEM_PKG('socket_wrapper', minversion='1.2.3') +Build.BuildContext.CHECK_SOCKET_WRAPPER = CHECK_SOCKET_WRAPPER + +@conf +def CHECK_NSS_WRAPPER(conf): + return conf.CHECK_BUNDLED_SYSTEM_PKG('nss_wrapper', minversion='1.1.6') +Build.BuildContext.CHECK_NSS_WRAPPER = CHECK_NSS_WRAPPER + +@conf +def CHECK_RESOLV_WRAPPER(conf): + return conf.CHECK_BUNDLED_SYSTEM_PKG('resolv_wrapper', minversion='1.1.4') +Build.BuildContext.CHECK_RESOLV_WRAPPER = CHECK_RESOLV_WRAPPER + +@conf +def CHECK_UID_WRAPPER(conf): + return conf.CHECK_BUNDLED_SYSTEM_PKG('uid_wrapper', minversion='1.2.4') +Build.BuildContext.CHECK_UID_WRAPPER = CHECK_UID_WRAPPER + +@conf +def CHECK_PAM_WRAPPER(conf): + return conf.CHECK_BUNDLED_SYSTEM_PKG('pam_wrapper', minversion='1.0.7') +Build.BuildContext.CHECK_PAM_WRAPPER = CHECK_PAM_WRAPPER diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_utils.py b/ldb-2.0.8/buildtools/wafsamba/samba_utils.py new file mode 100644 index 0000000..ad97de1 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_utils.py @@ -0,0 +1,763 @@ +# a waf tool to add autoconf-like macros to the configure section +# and for SAMBA_ macros for building libraries, binaries etc + +import errno +import os, sys, re, fnmatch, shlex, inspect +from optparse import SUPPRESS_HELP +from waflib import Build, Options, Utils, Task, Logs, Configure, Errors, Context +from waflib import Scripting +from waflib.TaskGen import feature, before, after +from waflib.Configure import ConfigurationContext +from waflib.Logs import debug +from waflib import ConfigSet +from waflib.Build import CACHE_SUFFIX + +# TODO: make this a --option +LIB_PATH="shared" + + +PY3 = sys.version_info[0] == 3 + +if PY3: + + # helper function to get a string from a variable that maybe 'str' or + # 'bytes' if 'bytes' then it is decoded using 'utf8'. If 'str' is passed + # it is returned unchanged + # Using this function is PY2/PY3 code should ensure in most cases + # the PY2 code runs unchanged in PY2 whereas the code in PY3 possibly + # decodes the variable (see PY2 implementation of this function below) + def get_string(bytesorstring): + tmp = bytesorstring + if isinstance(bytesorstring, bytes): + tmp = bytesorstring.decode('utf8') + elif not isinstance(bytesorstring, str): + raise ValueError('Expected byte of string for %s:%s' % (type(bytesorstring), bytesorstring)) + return tmp + +else: + + # Helper function to return string. + # if 'str' or 'unicode' passed in they are returned unchanged + # otherwise an exception is generated + # Using this function is PY2/PY3 code should ensure in most cases + # the PY2 code runs unchanged in PY2 whereas the code in PY3 possibly + # decodes the variable (see PY3 implementation of this function above) + def get_string(bytesorstring): + tmp = bytesorstring + if not(isinstance(bytesorstring, str) or isinstance(bytesorstring, unicode)): + raise ValueError('Expected str or unicode for %s:%s' % (type(bytesorstring), bytesorstring)) + return tmp + +# sigh, python octal constants are a mess +MODE_644 = int('644', 8) +MODE_744 = int('744', 8) +MODE_755 = int('755', 8) +MODE_777 = int('777', 8) + +def conf(f): + # override in order to propagate the argument "mandatory" + def fun(*k, **kw): + mandatory = True + if 'mandatory' in kw: + mandatory = kw['mandatory'] + del kw['mandatory'] + + try: + return f(*k, **kw) + except Errors.ConfigurationError: + if mandatory: + raise + + fun.__name__ = f.__name__ + if 'mandatory' in inspect.getsource(f): + fun = f + + setattr(Configure.ConfigurationContext, f.__name__, fun) + setattr(Build.BuildContext, f.__name__, fun) + return f +Configure.conf = conf +Configure.conftest = conf + +@conf +def SET_TARGET_TYPE(ctx, target, value): + '''set the target type of a target''' + cache = LOCAL_CACHE(ctx, 'TARGET_TYPE') + if target in cache and cache[target] != 'EMPTY': + Logs.error("ERROR: Target '%s' in directory %s re-defined as %s - was %s" % (target, ctx.path.abspath(), value, cache[target])) + sys.exit(1) + LOCAL_CACHE_SET(ctx, 'TARGET_TYPE', target, value) + debug("task_gen: Target '%s' created of type '%s' in %s" % (target, value, ctx.path.abspath())) + return True + + +def GET_TARGET_TYPE(ctx, target): + '''get target type from cache''' + cache = LOCAL_CACHE(ctx, 'TARGET_TYPE') + if not target in cache: + return None + return cache[target] + + +def ADD_LD_LIBRARY_PATH(path): + '''add something to LD_LIBRARY_PATH''' + if 'LD_LIBRARY_PATH' in os.environ: + oldpath = os.environ['LD_LIBRARY_PATH'] + else: + oldpath = '' + newpath = oldpath.split(':') + if not path in newpath: + newpath.append(path) + os.environ['LD_LIBRARY_PATH'] = ':'.join(newpath) + + +def needs_private_lib(bld, target): + '''return True if a target links to a private library''' + for lib in getattr(target, "final_libs", []): + t = bld.get_tgen_by_name(lib) + if t and getattr(t, 'private_library', False): + return True + return False + + +def install_rpath(target): + '''the rpath value for installation''' + bld = target.bld + bld.env['RPATH'] = [] + ret = set() + if bld.env.RPATH_ON_INSTALL: + ret.add(bld.EXPAND_VARIABLES(bld.env.LIBDIR)) + if bld.env.RPATH_ON_INSTALL_PRIVATE and needs_private_lib(bld, target): + ret.add(bld.EXPAND_VARIABLES(bld.env.PRIVATELIBDIR)) + return list(ret) + + +def build_rpath(bld): + '''the rpath value for build''' + rpaths = [os.path.normpath('%s/%s' % (bld.env.BUILD_DIRECTORY, d)) for d in ("shared", "shared/private")] + bld.env['RPATH'] = [] + if bld.env.RPATH_ON_BUILD: + return rpaths + for rpath in rpaths: + ADD_LD_LIBRARY_PATH(rpath) + return [] + + +@conf +def LOCAL_CACHE(ctx, name): + '''return a named build cache dictionary, used to store + state inside other functions''' + if name in ctx.env: + return ctx.env[name] + ctx.env[name] = {} + return ctx.env[name] + + +@conf +def LOCAL_CACHE_SET(ctx, cachename, key, value): + '''set a value in a local cache''' + cache = LOCAL_CACHE(ctx, cachename) + cache[key] = value + + +@conf +def ASSERT(ctx, expression, msg): + '''a build assert call''' + if not expression: + raise Errors.WafError("ERROR: %s\n" % msg) +Build.BuildContext.ASSERT = ASSERT + + +def SUBDIR(bld, subdir, list): + '''create a list of files by pre-pending each with a subdir name''' + ret = '' + for l in TO_LIST(list): + ret = ret + os.path.normpath(os.path.join(subdir, l)) + ' ' + return ret +Build.BuildContext.SUBDIR = SUBDIR + + +def dict_concat(d1, d2): + '''concatenate two dictionaries d1 += d2''' + for t in d2: + if t not in d1: + d1[t] = d2[t] + +def ADD_COMMAND(opt, name, function): + '''add a new top level command to waf''' + Context.g_module.__dict__[name] = function + opt.name = function +Options.OptionsContext.ADD_COMMAND = ADD_COMMAND + + +@feature('c', 'cc', 'cshlib', 'cprogram') +@before('apply_core','exec_rule') +def process_depends_on(self): + '''The new depends_on attribute for build rules + allow us to specify a dependency on output from + a source generation rule''' + if getattr(self , 'depends_on', None): + lst = self.to_list(self.depends_on) + for x in lst: + y = self.bld.get_tgen_by_name(x) + self.bld.ASSERT(y is not None, "Failed to find dependency %s of %s" % (x, self.name)) + y.post() + if getattr(y, 'more_includes', None): + self.includes += " " + y.more_includes + + +os_path_relpath = getattr(os.path, 'relpath', None) +if os_path_relpath is None: + # Python < 2.6 does not have os.path.relpath, provide a replacement + # (imported from Python2.6.5~rc2) + def os_path_relpath(path, start): + """Return a relative version of a path""" + start_list = os.path.abspath(start).split("/") + path_list = os.path.abspath(path).split("/") + + # Work out how much of the filepath is shared by start and path. + i = len(os.path.commonprefix([start_list, path_list])) + + rel_list = ['..'] * (len(start_list)-i) + path_list[i:] + if not rel_list: + return start + return os.path.join(*rel_list) + + +def unique_list(seq): + '''return a uniquified list in the same order as the existing list''' + seen = {} + result = [] + for item in seq: + if item in seen: continue + seen[item] = True + result.append(item) + return result + + +def TO_LIST(str, delimiter=None): + '''Split a list, preserving quoted strings and existing lists''' + if str is None: + return [] + if isinstance(str, list): + # we need to return a new independent list... + return list(str) + if len(str) == 0: + return [] + lst = str.split(delimiter) + # the string may have had quotes in it, now we + # check if we did have quotes, and use the slower shlex + # if we need to + for e in lst: + if e[0] == '"': + return shlex.split(str) + return lst + + +def subst_vars_error(string, env): + '''substitute vars, throw an error if a variable is not defined''' + lst = re.split('(\$\{\w+\})', string) + out = [] + for v in lst: + if re.match('\$\{\w+\}', v): + vname = v[2:-1] + if not vname in env: + raise KeyError("Failed to find variable %s in %s in env %s <%s>" % (vname, string, env.__class__, str(env))) + v = env[vname] + if isinstance(v, list): + v = ' '.join(v) + out.append(v) + return ''.join(out) + + +@conf +def SUBST_ENV_VAR(ctx, varname): + '''Substitute an environment variable for any embedded variables''' + return subst_vars_error(ctx.env[varname], ctx.env) +Build.BuildContext.SUBST_ENV_VAR = SUBST_ENV_VAR + + +def recursive_dirlist(dir, relbase, pattern=None): + '''recursive directory list''' + ret = [] + for f in os.listdir(dir): + f2 = dir + '/' + f + if os.path.isdir(f2): + ret.extend(recursive_dirlist(f2, relbase)) + else: + if pattern and not fnmatch.fnmatch(f, pattern): + continue + ret.append(os_path_relpath(f2, relbase)) + return ret + + +def symlink(src, dst, force=True): + """Can create symlink by force""" + try: + os.symlink(src, dst) + except OSError as exc: + if exc.errno == errno.EEXIST and force: + os.remove(dst) + os.symlink(src, dst) + else: + raise + + +def mkdir_p(dir): + '''like mkdir -p''' + if not dir: + return + if dir.endswith("/"): + mkdir_p(dir[:-1]) + return + if os.path.isdir(dir): + return + mkdir_p(os.path.dirname(dir)) + os.mkdir(dir) + + +def SUBST_VARS_RECURSIVE(string, env): + '''recursively expand variables''' + if string is None: + return string + limit=100 + while (string.find('${') != -1 and limit > 0): + string = subst_vars_error(string, env) + limit -= 1 + return string + + +@conf +def EXPAND_VARIABLES(ctx, varstr, vars=None): + '''expand variables from a user supplied dictionary + + This is most useful when you pass vars=locals() to expand + all your local variables in strings + ''' + + if isinstance(varstr, list): + ret = [] + for s in varstr: + ret.append(EXPAND_VARIABLES(ctx, s, vars=vars)) + return ret + + if not isinstance(varstr, str): + return varstr + + env = ConfigSet.ConfigSet() + ret = varstr + # substitute on user supplied dict if avaiilable + if vars is not None: + for v in vars.keys(): + env[v] = vars[v] + ret = SUBST_VARS_RECURSIVE(ret, env) + + # if anything left, subst on the environment as well + if ret.find('${') != -1: + ret = SUBST_VARS_RECURSIVE(ret, ctx.env) + # make sure there is nothing left. Also check for the common + # typo of $( instead of ${ + if ret.find('${') != -1 or ret.find('$(') != -1: + Logs.error('Failed to substitute all variables in varstr=%s' % ret) + sys.exit(1) + return ret +Build.BuildContext.EXPAND_VARIABLES = EXPAND_VARIABLES + + +def RUN_COMMAND(cmd, + env=None, + shell=False): + '''run a external command, return exit code or signal''' + if env: + cmd = SUBST_VARS_RECURSIVE(cmd, env) + + status = os.system(cmd) + if os.WIFEXITED(status): + return os.WEXITSTATUS(status) + if os.WIFSIGNALED(status): + return - os.WTERMSIG(status) + Logs.error("Unknown exit reason %d for command: %s" % (status, cmd)) + return -1 + + +def RUN_PYTHON_TESTS(testfiles, pythonpath=None, extra_env=None): + env = LOAD_ENVIRONMENT() + if pythonpath is None: + pythonpath = os.path.join(Context.g_module.out, 'python') + result = 0 + for interp in env.python_interpreters: + if not isinstance(interp, str): + interp = ' '.join(interp) + for testfile in testfiles: + cmd = "PYTHONPATH=%s %s %s" % (pythonpath, interp, testfile) + if extra_env: + for key, value in extra_env.items(): + cmd = "%s=%s %s" % (key, value, cmd) + print('Running Python test with %s: %s' % (interp, testfile)) + ret = RUN_COMMAND(cmd) + if ret: + print('Python test failed: %s' % cmd) + result = ret + return result + + +# make sure we have md5. some systems don't have it +try: + from hashlib import md5 + # Even if hashlib.md5 exists, it may be unusable. + # Try to use MD5 function. In FIPS mode this will cause an exception + # and we'll get to the replacement code + foo = md5(b'abcd') +except: + try: + import md5 + # repeat the same check here, mere success of import is not enough. + # Try to use MD5 function. In FIPS mode this will cause an exception + foo = md5.md5(b'abcd') + except: + Context.SIG_NIL = hash('abcd') + class replace_md5(object): + def __init__(self): + self.val = None + def update(self, val): + self.val = hash((self.val, val)) + def digest(self): + return str(self.val) + def hexdigest(self): + return self.digest().encode('hex') + def replace_h_file(filename): + f = open(filename, 'rb') + m = replace_md5() + while (filename): + filename = f.read(100000) + m.update(filename) + f.close() + return m.digest() + Utils.md5 = replace_md5 + Task.md5 = replace_md5 + Utils.h_file = replace_h_file + + +def LOAD_ENVIRONMENT(): + '''load the configuration environment, allowing access to env vars + from new commands''' + env = ConfigSet.ConfigSet() + try: + p = os.path.join(Context.g_module.out, 'c4che/default'+CACHE_SUFFIX) + env.load(p) + except (OSError, IOError): + pass + return env + + +def IS_NEWER(bld, file1, file2): + '''return True if file1 is newer than file2''' + curdir = bld.path.abspath() + t1 = os.stat(os.path.join(curdir, file1)).st_mtime + t2 = os.stat(os.path.join(curdir, file2)).st_mtime + return t1 > t2 +Build.BuildContext.IS_NEWER = IS_NEWER + + +@conf +def RECURSE(ctx, directory): + '''recurse into a directory, relative to the curdir or top level''' + try: + visited_dirs = ctx.visited_dirs + except AttributeError: + visited_dirs = ctx.visited_dirs = set() + d = os.path.join(ctx.path.abspath(), directory) + if os.path.exists(d): + abspath = os.path.abspath(d) + else: + abspath = os.path.abspath(os.path.join(Context.g_module.top, directory)) + ctxclass = ctx.__class__.__name__ + key = ctxclass + ':' + abspath + if key in visited_dirs: + # already done it + return + visited_dirs.add(key) + relpath = os_path_relpath(abspath, ctx.path.abspath()) + if ctxclass in ['tmp', 'OptionsContext', 'ConfigurationContext', 'BuildContext']: + return ctx.recurse(relpath) + if 'waflib.extras.compat15' in sys.modules: + return ctx.recurse(relpath) + Logs.error('Unknown RECURSE context class: {}'.format(ctxclass)) + raise +Options.OptionsContext.RECURSE = RECURSE +Build.BuildContext.RECURSE = RECURSE + + +def CHECK_MAKEFLAGS(options): + '''check for MAKEFLAGS environment variable in case we are being + called from a Makefile try to honor a few make command line flags''' + if not 'WAF_MAKE' in os.environ: + return + makeflags = os.environ.get('MAKEFLAGS') + if makeflags is None: + makeflags = "" + jobs_set = False + jobs = None + # we need to use shlex.split to cope with the escaping of spaces + # in makeflags + for opt in shlex.split(makeflags): + # options can come either as -x or as x + if opt[0:2] == 'V=': + options.verbose = Logs.verbose = int(opt[2:]) + if Logs.verbose > 0: + Logs.zones = ['runner'] + if Logs.verbose > 2: + Logs.zones = ['*'] + elif opt[0].isupper() and opt.find('=') != -1: + # this allows us to set waf options on the make command line + # for example, if you do "make FOO=blah", then we set the + # option 'FOO' in Options.options, to blah. If you look in wafsamba/wscript + # you will see that the command line accessible options have their dest= + # set to uppercase, to allow for passing of options from make in this way + # this is also how "make test TESTS=testpattern" works, and + # "make VERBOSE=1" as well as things like "make SYMBOLCHECK=1" + loc = opt.find('=') + setattr(options, opt[0:loc], opt[loc+1:]) + elif opt[0] != '-': + for v in opt: + if re.search(r'j[0-9]*$', v): + jobs_set = True + jobs = opt.strip('j') + elif v == 'k': + options.keep = True + elif re.search(r'-j[0-9]*$', opt): + jobs_set = True + jobs = opt.strip('-j') + elif opt == '-k': + options.keep = True + if not jobs_set: + # default to one job + options.jobs = 1 + elif jobs_set and jobs: + options.jobs = int(jobs) + +waflib_options_parse_cmd_args = Options.OptionsContext.parse_cmd_args +def wafsamba_options_parse_cmd_args(self, _args=None, cwd=None, allow_unknown=False): + (options, commands, envvars) = \ + waflib_options_parse_cmd_args(self, + _args=_args, + cwd=cwd, + allow_unknown=allow_unknown) + CHECK_MAKEFLAGS(options) + if options.jobs == 1: + # + # waflib.Runner.Parallel processes jobs inline if the possible number + # of jobs is just 1. But (at least in waf <= 2.0.12) it still calls + # create a waflib.Runner.Spawner() which creates a single + # waflib.Runner.Consumer() thread that tries to process jobs from the + # queue. + # + # This has strange effects, which are not noticed typically, + # but at least on AIX python has broken threading and fails + # in random ways. + # + # So we just add a dummy Spawner class. + class NoOpSpawner(object): + def __init__(self, master): + return + from waflib import Runner + Runner.Spawner = NoOpSpawner + return options, commands, envvars +Options.OptionsContext.parse_cmd_args = wafsamba_options_parse_cmd_args + +option_groups = {} + +def option_group(opt, name): + '''find or create an option group''' + global option_groups + if name in option_groups: + return option_groups[name] + gr = opt.add_option_group(name) + option_groups[name] = gr + return gr +Options.OptionsContext.option_group = option_group + + +def save_file(filename, contents, create_dir=False): + '''save data to a file''' + if create_dir: + mkdir_p(os.path.dirname(filename)) + try: + f = open(filename, 'w') + f.write(contents) + f.close() + except: + return False + return True + + +def load_file(filename): + '''return contents of a file''' + try: + f = open(filename, 'r') + r = f.read() + f.close() + except: + return None + return r + + +def reconfigure(ctx): + '''rerun configure if necessary''' + if not os.path.exists(os.environ.get('WAFLOCK', '.lock-wscript')): + raise Errors.WafError('configure has not been run') + import samba_wildcard + bld = samba_wildcard.fake_build_environment() + Configure.autoconfig = True + Scripting.check_configured(bld) + + +def map_shlib_extension(ctx, name, python=False): + '''map a filename with a shared library extension of .so to the real shlib name''' + if name is None: + return None + if name[-1:].isdigit(): + # some libraries have specified versions in the wscript rule + return name + (root1, ext1) = os.path.splitext(name) + if python: + return ctx.env.pyext_PATTERN % root1 + else: + (root2, ext2) = os.path.splitext(ctx.env.cshlib_PATTERN) + return root1+ext2 +Build.BuildContext.map_shlib_extension = map_shlib_extension + +def apply_pattern(filename, pattern): + '''apply a filename pattern to a filename that may have a directory component''' + dirname = os.path.dirname(filename) + if not dirname: + return pattern % filename + basename = os.path.basename(filename) + return os.path.join(dirname, pattern % basename) + +def make_libname(ctx, name, nolibprefix=False, version=None, python=False): + """make a library filename + Options: + nolibprefix: don't include the lib prefix + version : add a version number + python : if we should use python module name conventions""" + + if python: + libname = apply_pattern(name, ctx.env.pyext_PATTERN) + else: + libname = apply_pattern(name, ctx.env.cshlib_PATTERN) + if nolibprefix and libname[0:3] == 'lib': + libname = libname[3:] + if version: + if version[0] == '.': + version = version[1:] + (root, ext) = os.path.splitext(libname) + if ext == ".dylib": + # special case - version goes before the prefix + libname = "%s.%s%s" % (root, version, ext) + else: + libname = "%s%s.%s" % (root, ext, version) + return libname +Build.BuildContext.make_libname = make_libname + + +def get_tgt_list(bld): + '''return a list of build objects for samba''' + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + # build a list of task generators we are interested in + tgt_list = [] + for tgt in targets: + type = targets[tgt] + if not type in ['SUBSYSTEM', 'MODULE', 'BINARY', 'LIBRARY', 'ASN1', 'PYTHON']: + continue + t = bld.get_tgen_by_name(tgt) + if t is None: + Logs.error("Target %s of type %s has no task generator" % (tgt, type)) + sys.exit(1) + tgt_list.append(t) + return tgt_list + +from waflib.Context import WSCRIPT_FILE +def PROCESS_SEPARATE_RULE(self, rule): + ''' cause waf to process additional script based on `rule'. + You should have file named wscript__rule in the current directory + where stage is either 'configure' or 'build' + ''' + stage = '' + if isinstance(self, Configure.ConfigurationContext): + stage = 'configure' + elif isinstance(self, Build.BuildContext): + stage = 'build' + file_path = os.path.join(self.path.abspath(), WSCRIPT_FILE+'_'+stage+'_'+rule) + node = self.root.find_node(file_path) + if node: + try: + cache = self.recurse_cache + except AttributeError: + cache = self.recurse_cache = {} + if node not in cache: + cache[node] = True + self.pre_recurse(node) + try: + function_code = node.read('rU', None) + exec(compile(function_code, node.abspath(), 'exec'), self.exec_dict) + finally: + self.post_recurse(node) + +Build.BuildContext.PROCESS_SEPARATE_RULE = PROCESS_SEPARATE_RULE +ConfigurationContext.PROCESS_SEPARATE_RULE = PROCESS_SEPARATE_RULE + +def AD_DC_BUILD_IS_ENABLED(self): + if self.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'): + return True + return False + +Build.BuildContext.AD_DC_BUILD_IS_ENABLED = AD_DC_BUILD_IS_ENABLED + +@feature('cprogram', 'cshlib', 'cstaticlib') +@after('apply_lib_vars') +@before('apply_obj_vars') +def samba_before_apply_obj_vars(self): + """before apply_obj_vars for uselib, this removes the standard paths""" + + def is_standard_libpath(env, path): + for _path in env.STANDARD_LIBPATH: + if _path == os.path.normpath(path): + return True + return False + + v = self.env + + for i in v['RPATH']: + if is_standard_libpath(v, i): + v['RPATH'].remove(i) + + for i in v['LIBPATH']: + if is_standard_libpath(v, i): + v['LIBPATH'].remove(i) + +def samba_add_onoff_option(opt, option, help=(), dest=None, default=True, + with_name="with", without_name="without"): + if default is None: + default_str = "auto" + elif default is True: + default_str = "yes" + elif default is False: + default_str = "no" + else: + default_str = str(default) + + if help == (): + help = ("Build with %s support (default=%s)" % (option, default_str)) + if dest is None: + dest = "with_%s" % option.replace('-', '_') + + with_val = "--%s-%s" % (with_name, option) + without_val = "--%s-%s" % (without_name, option) + + opt.add_option(with_val, help=help, action="store_true", dest=dest, + default=default) + opt.add_option(without_val, help=SUPPRESS_HELP, action="store_false", + dest=dest) +Options.OptionsContext.samba_add_onoff_option = samba_add_onoff_option diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_version.py b/ldb-2.0.8/buildtools/wafsamba/samba_version.py new file mode 100644 index 0000000..f0e7b4d --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_version.py @@ -0,0 +1,267 @@ +import os, sys +from waflib import Utils, Context +import samba_utils +from samba_git import find_git + +def git_version_summary(path, env=None): + git = find_git(env) + + if git is None: + return ("GIT-UNKNOWN", {}) + + env.GIT = git + + environ = dict(os.environ) + environ["GIT_DIR"] = '%s/.git' % path + environ["GIT_WORK_TREE"] = path + git = samba_utils.get_string(Utils.cmd_output(env.GIT + ' show --pretty=format:"%h%n%ct%n%H%n%cd" --stat HEAD', silent=True, env=environ)) + + lines = git.splitlines() + if not lines or len(lines) < 4: + return ("GIT-UNKNOWN", {}) + + fields = { + "GIT_COMMIT_ABBREV": lines[0], + "GIT_COMMIT_FULLREV": lines[2], + "COMMIT_TIME": int(lines[1]), + "COMMIT_DATE": lines[3], + } + + ret = "GIT-" + fields["GIT_COMMIT_ABBREV"] + + if env.GIT_LOCAL_CHANGES: + clean = Utils.cmd_output('%s diff HEAD | wc -l' % env.GIT, silent=True).strip() + if clean == "0": + fields["COMMIT_IS_CLEAN"] = 1 + else: + fields["COMMIT_IS_CLEAN"] = 0 + ret += "+" + + return (ret, fields) + + +def distversion_version_summary(path): + #get version from .distversion file + suffix = None + fields = {} + + for line in Utils.readf(path + '/.distversion').splitlines(): + if line == '': + continue + if line.startswith("#"): + continue + try: + split_line = line.split("=") + if split_line[1] != "": + key = split_line[0] + value = split_line[1] + if key == "SUFFIX": + suffix = value + continue + fields[key] = value + except: + print("Failed to parse line %s from .distversion file." % (line)) + raise + + if "COMMIT_TIME" in fields: + fields["COMMIT_TIME"] = int(fields["COMMIT_TIME"]) + + if suffix is None: + return ("UNKNOWN", fields) + + return (suffix, fields) + + +class SambaVersion(object): + + def __init__(self, version_dict, path, env=None, is_install=True): + '''Determine the version number of samba + +See VERSION for the format. Entries on that file are +also accepted as dictionary entries here + ''' + + self.MAJOR=None + self.MINOR=None + self.RELEASE=None + self.REVISION=None + self.TP_RELEASE=None + self.ALPHA_RELEASE=None + self.BETA_RELEASE=None + self.PRE_RELEASE=None + self.RC_RELEASE=None + self.IS_SNAPSHOT=True + self.RELEASE_NICKNAME=None + self.VENDOR_SUFFIX=None + self.VENDOR_PATCH=None + + for a, b in version_dict.items(): + if a.startswith("SAMBA_VERSION_"): + setattr(self, a[14:], b) + else: + setattr(self, a, b) + + if self.IS_GIT_SNAPSHOT == "yes": + self.IS_SNAPSHOT=True + elif self.IS_GIT_SNAPSHOT == "no": + self.IS_SNAPSHOT=False + else: + raise Exception("Unknown value for IS_GIT_SNAPSHOT: %s" % self.IS_GIT_SNAPSHOT) + + ## + ## start with "3.0.22" + ## + self.MAJOR=int(self.MAJOR) + self.MINOR=int(self.MINOR) + self.RELEASE=int(self.RELEASE) + + SAMBA_VERSION_STRING = ("%u.%u.%u" % (self.MAJOR, self.MINOR, self.RELEASE)) + +## +## maybe add "3.0.22a" or "4.0.0tp11" or "4.0.0alpha1" or "4.0.0beta1" or "3.0.22pre1" or "3.0.22rc1" +## We do not do pre or rc version on patch/letter releases +## + if self.REVISION is not None: + SAMBA_VERSION_STRING += self.REVISION + if self.TP_RELEASE is not None: + self.TP_RELEASE = int(self.TP_RELEASE) + SAMBA_VERSION_STRING += "tp%u" % self.TP_RELEASE + if self.ALPHA_RELEASE is not None: + self.ALPHA_RELEASE = int(self.ALPHA_RELEASE) + SAMBA_VERSION_STRING += ("alpha%u" % self.ALPHA_RELEASE) + if self.BETA_RELEASE is not None: + self.BETA_RELEASE = int(self.BETA_RELEASE) + SAMBA_VERSION_STRING += ("beta%u" % self.BETA_RELEASE) + if self.PRE_RELEASE is not None: + self.PRE_RELEASE = int(self.PRE_RELEASE) + SAMBA_VERSION_STRING += ("pre%u" % self.PRE_RELEASE) + if self.RC_RELEASE is not None: + self.RC_RELEASE = int(self.RC_RELEASE) + SAMBA_VERSION_STRING += ("rc%u" % self.RC_RELEASE) + + if self.IS_SNAPSHOT: + if not is_install: + suffix = "DEVELOPERBUILD" + self.vcs_fields = {} + elif os.path.exists(os.path.join(path, ".git")): + suffix, self.vcs_fields = git_version_summary(path, env=env) + elif os.path.exists(os.path.join(path, ".distversion")): + suffix, self.vcs_fields = distversion_version_summary(path) + else: + suffix = "UNKNOWN" + self.vcs_fields = {} + self.vcs_fields["SUFFIX"] = suffix + SAMBA_VERSION_STRING += "-" + suffix + else: + self.vcs_fields = {} + + self.OFFICIAL_STRING = SAMBA_VERSION_STRING + + if self.VENDOR_SUFFIX is not None: + SAMBA_VERSION_STRING += ("-" + self.VENDOR_SUFFIX) + self.VENDOR_SUFFIX = self.VENDOR_SUFFIX + + if self.VENDOR_PATCH is not None: + SAMBA_VERSION_STRING += ("-" + self.VENDOR_PATCH) + self.VENDOR_PATCH = self.VENDOR_PATCH + + self.STRING = SAMBA_VERSION_STRING + + if self.RELEASE_NICKNAME is not None: + self.STRING_WITH_NICKNAME = "%s (%s)" % (self.STRING, self.RELEASE_NICKNAME) + else: + self.STRING_WITH_NICKNAME = self.STRING + + def __str__(self): + string="/* Autogenerated by waf */\n" + string+="#define SAMBA_VERSION_MAJOR %u\n" % self.MAJOR + string+="#define SAMBA_VERSION_MINOR %u\n" % self.MINOR + string+="#define SAMBA_VERSION_RELEASE %u\n" % self.RELEASE + if self.REVISION is not None: + string+="#define SAMBA_VERSION_REVISION %u\n" % self.REVISION + + if self.TP_RELEASE is not None: + string+="#define SAMBA_VERSION_TP_RELEASE %u\n" % self.TP_RELEASE + + if self.ALPHA_RELEASE is not None: + string+="#define SAMBA_VERSION_ALPHA_RELEASE %u\n" % self.ALPHA_RELEASE + + if self.BETA_RELEASE is not None: + string+="#define SAMBA_VERSION_BETA_RELEASE %u\n" % self.BETA_RELEASE + + if self.PRE_RELEASE is not None: + string+="#define SAMBA_VERSION_PRE_RELEASE %u\n" % self.PRE_RELEASE + + if self.RC_RELEASE is not None: + string+="#define SAMBA_VERSION_RC_RELEASE %u\n" % self.RC_RELEASE + + for name in sorted(self.vcs_fields.keys()): + string+="#define SAMBA_VERSION_%s " % name + value = self.vcs_fields[name] + string_types = str + if sys.version_info[0] < 3: + string_types = basestring + if isinstance(value, string_types): + string += "\"%s\"" % value + elif type(value) is int: + string += "%d" % value + else: + raise Exception("Unknown type for %s: %r" % (name, value)) + string += "\n" + + string+="#define SAMBA_VERSION_OFFICIAL_STRING \"" + self.OFFICIAL_STRING + "\"\n" + + if self.VENDOR_SUFFIX is not None: + string+="#define SAMBA_VERSION_VENDOR_SUFFIX " + self.VENDOR_SUFFIX + "\n" + if self.VENDOR_PATCH is not None: + string+="#define SAMBA_VERSION_VENDOR_PATCH " + self.VENDOR_PATCH + "\n" + + if self.RELEASE_NICKNAME is not None: + string+="#define SAMBA_VERSION_RELEASE_NICKNAME " + self.RELEASE_NICKNAME + "\n" + + # We need to put this #ifdef in to the headers so that vendors can override the version with a function + string+=''' +#ifdef SAMBA_VERSION_VENDOR_FUNCTION +# define SAMBA_VERSION_STRING SAMBA_VERSION_VENDOR_FUNCTION +#else /* SAMBA_VERSION_VENDOR_FUNCTION */ +# define SAMBA_VERSION_STRING "''' + self.STRING_WITH_NICKNAME + '''" +#endif +''' + string+="/* Version for mkrelease.sh: \nSAMBA_VERSION_STRING=" + self.STRING_WITH_NICKNAME + "\n */\n" + + return string + + +def samba_version_file(version_file, path, env=None, is_install=True): + '''Parse the version information from a VERSION file''' + + f = open(version_file, 'r') + version_dict = {} + for line in f: + line = line.strip() + if line == '': + continue + if line.startswith("#"): + continue + try: + split_line = line.split("=") + if split_line[1] != "": + value = split_line[1].strip('"') + version_dict[split_line[0]] = value + except: + print("Failed to parse line %s from %s" % (line, version_file)) + raise + + return SambaVersion(version_dict, path, env=env, is_install=is_install) + + + +def load_version(env=None, is_install=True): + '''load samba versions either from ./VERSION or git + return a version object for detailed breakdown''' + if not env: + env = samba_utils.LOAD_ENVIRONMENT() + + version = samba_version_file("./VERSION", ".", env, is_install=is_install) + Context.g_module.VERSION = version.STRING + return version diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_waf18.py b/ldb-2.0.8/buildtools/wafsamba/samba_waf18.py new file mode 100644 index 0000000..c0bb6bf --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_waf18.py @@ -0,0 +1,431 @@ +# compatibility layer for building with more recent waf versions + +import os, shlex, sys +from waflib import Build, Configure, Node, Utils, Options, Logs, TaskGen +from waflib import ConfigSet +from waflib.TaskGen import feature, after +from waflib.Configure import conf, ConfigurationContext + +from waflib.Tools.flex import decide_ext + +# This version of flexfun runs in tsk.get_cwd() as opposed to the +# bld.variant_dir: since input paths adjusted against tsk.get_cwd(), we have to +# use tsk.get_cwd() for the work directory as well. +def flexfun(tsk): + env = tsk.env + bld = tsk.generator.bld + def to_list(xx): + if isinstance(xx, str): + return [xx] + return xx + tsk.last_cmd = lst = [] + lst.extend(to_list(env.FLEX)) + lst.extend(to_list(env.FLEXFLAGS)) + inputs = [a.path_from(tsk.get_cwd()) for a in tsk.inputs] + if env.FLEX_MSYS: + inputs = [x.replace(os.sep, '/') for x in inputs] + lst.extend(inputs) + lst = [x for x in lst if x] + txt = bld.cmd_and_log(lst, cwd=tsk.get_cwd(), env=env.env or None, quiet=0) + tsk.outputs[0].write(txt.replace('\r\n', '\n').replace('\r', '\n')) # issue #1207 + +TaskGen.declare_chain( + name = 'flex', + rule = flexfun, # issue #854 + ext_in = '.l', + decider = decide_ext, +) + + +for y in (Build.BuildContext, Build.CleanContext, Build.InstallContext, Build.UninstallContext, Build.ListContext): + class tmp(y): + variant = 'default' + +def abspath(self, env=None): + if env and hasattr(self, 'children'): + return self.get_bld().abspath() + return self.old_abspath() +Node.Node.old_abspath = Node.Node.abspath +Node.Node.abspath = abspath + +def bldpath(self, env=None): + return self.abspath() + #return self.path_from(self.ctx.bldnode.parent) +Node.Node.bldpath = bldpath + +def srcpath(self, env=None): + return self.abspath() + #return self.path_from(self.ctx.bldnode.parent) +Node.Node.srcpath = srcpath + +def store_fast(self, filename): + file = open(filename, 'wb') + data = self.get_merged_dict() + try: + Build.cPickle.dump(data, file, -1) + finally: + file.close() +ConfigSet.ConfigSet.store_fast = store_fast + +def load_fast(self, filename): + file = open(filename, 'rb') + try: + data = Build.cPickle.load(file) + finally: + file.close() + self.table.update(data) +ConfigSet.ConfigSet.load_fast = load_fast + +@feature('c', 'cxx', 'd', 'asm', 'fc', 'includes') +@after('propagate_uselib_vars', 'process_source') +def apply_incpaths(self): + lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES']) + self.includes_nodes = lst + cwdx = getattr(self.bld, 'cwdx', self.bld.bldnode) + self.env['INCPATHS'] = [x.path_from(cwdx) for x in lst] + +@conf +def define(self, key, val, quote=True, comment=None): + assert key and isinstance(key, str) + + if val is None: + val = () + elif isinstance(val, bool): + val = int(val) + + # waf 1.5 + self.env[key] = val + + if isinstance(val, int) or isinstance(val, float): + s = '%s=%s' + else: + s = quote and '%s="%s"' or '%s=%s' + app = s % (key, str(val)) + + ban = key + '=' + lst = self.env.DEFINES + for x in lst: + if x.startswith(ban): + lst[lst.index(x)] = app + break + else: + self.env.append_value('DEFINES', app) + + self.env.append_unique('define_key', key) + +# compat15 removes this but we want to keep it +@conf +def undefine(self, key, from_env=True, comment=None): + assert key and isinstance(key, str) + + ban = key + '=' + self.env.DEFINES = [x for x in self.env.DEFINES if not x.startswith(ban)] + self.env.append_unique('define_key', key) + # waf 1.5 + if from_env: + self.env[key] = () + +class ConfigurationContext(Configure.ConfigurationContext): + def init_dirs(self): + self.setenv('default') + self.env.merge_config_header = True + return super(ConfigurationContext, self).init_dirs() + +def find_program_samba(self, *k, **kw): + # Override the waf default set in the @conf decorator in Configure.py + if 'mandatory' not in kw: + kw['mandatory'] = False + ret = self.find_program_old(*k, **kw) + return ret +Configure.ConfigurationContext.find_program_old = Configure.ConfigurationContext.find_program +Configure.ConfigurationContext.find_program = find_program_samba + +Build.BuildContext.ENFORCE_GROUP_ORDERING = Utils.nada +Build.BuildContext.AUTOCLEANUP_STALE_FILES = Utils.nada + +@conf +def check(self, *k, **kw): + '''Override the waf defaults to inject --with-directory options''' + + # match the configuration test with speficic options, for example: + # --with-libiconv -> Options.options.iconv_open -> "Checking for library iconv" + self.validate_c(kw) + + additional_dirs = [] + if 'msg' in kw: + msg = kw['msg'] + for x in Options.OptionsContext.parser.parser.option_list: + if getattr(x, 'match', None) and msg in x.match: + d = getattr(Options.options, x.dest, '') + if d: + additional_dirs.append(d) + + # we add the additional dirs twice: once for the test data, and again if the compilation test suceeds below + def add_options_dir(dirs, env): + for x in dirs: + if not x in env.CPPPATH: + env.CPPPATH = [os.path.join(x, 'include')] + env.CPPPATH + if not x in env.LIBPATH: + env.LIBPATH = [os.path.join(x, 'lib')] + env.LIBPATH + + add_options_dir(additional_dirs, kw['env']) + + self.start_msg(kw['msg'], **kw) + ret = None + try: + ret = self.run_build(*k, **kw) + except self.errors.ConfigurationError: + self.end_msg(kw['errmsg'], 'YELLOW', **kw) + if Logs.verbose > 1: + raise + else: + self.fatal('The configuration failed') + else: + kw['success'] = ret + # success! time for brandy + add_options_dir(additional_dirs, self.env) + + ret = self.post_check(*k, **kw) + if not ret: + self.end_msg(kw['errmsg'], 'YELLOW', **kw) + self.fatal('The configuration failed %r' % ret) + else: + self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) + return ret + +@conf +def CHECK_LIBRARY_SUPPORT(conf, rpath=False, version_script=False, msg=None): + '''see if the platform supports building libraries''' + + if msg is None: + if rpath: + msg = "rpath library support" + else: + msg = "building library support" + + def build(bld): + lib_node = bld.srcnode.make_node('libdir/liblc1.c') + lib_node.parent.mkdir() + lib_node.write('int lib_func(void) { return 42; }\n', 'w') + main_node = bld.srcnode.make_node('main.c') + main_node.write('int main(void) {return !(lib_func() == 42);}', 'w') + linkflags = [] + if version_script: + script = bld.srcnode.make_node('ldscript') + script.write('TEST_1.0A2 { global: *; };\n', 'w') + linkflags.append('-Wl,--version-script=%s' % script.abspath()) + bld(features='c cshlib', source=lib_node, target='lib1', linkflags=linkflags, name='lib1') + o = bld(features='c cprogram', source=main_node, target='prog1', uselib_local='lib1') + if rpath: + o.rpath = [lib_node.parent.abspath()] + def run_app(self): + args = conf.SAMBA_CROSS_ARGS(msg=msg) + env = dict(os.environ) + env['LD_LIBRARY_PATH'] = self.inputs[0].parent.abspath() + os.pathsep + env.get('LD_LIBRARY_PATH', '') + self.generator.bld.cmd_and_log([self.inputs[0].abspath()] + args, env=env) + o.post() + bld(rule=run_app, source=o.link_task.outputs[0]) + + # ok, so it builds + try: + conf.check(build_fun=build, msg='Checking for %s' % msg) + except conf.errors.ConfigurationError: + return False + return True + +@conf +def CHECK_NEED_LC(conf, msg): + '''check if we need -lc''' + def build(bld): + lib_node = bld.srcnode.make_node('libdir/liblc1.c') + lib_node.parent.mkdir() + lib_node.write('#include \nint lib_func(void) { FILE *f = fopen("foo", "r");}\n', 'w') + bld(features='c cshlib', source=[lib_node], linkflags=conf.env.EXTRA_LDFLAGS, target='liblc') + try: + conf.check(build_fun=build, msg=msg, okmsg='-lc is unnecessary', errmsg='-lc is necessary') + except conf.errors.ConfigurationError: + return False + return True + +# already implemented on "waf -v" +def order(bld, tgt_list): + return True +Build.BuildContext.check_group_ordering = order + +@conf +def CHECK_CFG(self, *k, **kw): + if 'args' in kw: + kw['args'] = shlex.split(kw['args']) + if not 'mandatory' in kw: + kw['mandatory'] = False + kw['global_define'] = True + return self.check_cfg(*k, **kw) + +def cmd_output(cmd, **kw): + + silent = False + if 'silent' in kw: + silent = kw['silent'] + del(kw['silent']) + + if 'e' in kw: + tmp = kw['e'] + del(kw['e']) + kw['env'] = tmp + + kw['shell'] = isinstance(cmd, str) + kw['stdout'] = Utils.subprocess.PIPE + if silent: + kw['stderr'] = Utils.subprocess.PIPE + + try: + p = Utils.subprocess.Popen(cmd, **kw) + output = p.communicate()[0] + except OSError as e: + raise ValueError(str(e)) + + if p.returncode: + if not silent: + msg = "command execution failed: %s -> %r" % (cmd, str(output)) + raise ValueError(msg) + output = '' + return output +Utils.cmd_output = cmd_output + + +@TaskGen.feature('c', 'cxx', 'd') +@TaskGen.before('apply_incpaths', 'propagate_uselib_vars') +@TaskGen.after('apply_link', 'process_source') +def apply_uselib_local(self): + """ + process the uselib_local attribute + execute after apply_link because of the execution order set on 'link_task' + """ + env = self.env + from waflib.Tools.ccroot import stlink_task + + # 1. the case of the libs defined in the project (visit ancestors first) + # the ancestors external libraries (uselib) will be prepended + self.uselib = self.to_list(getattr(self, 'uselib', [])) + self.includes = self.to_list(getattr(self, 'includes', [])) + names = self.to_list(getattr(self, 'uselib_local', [])) + get = self.bld.get_tgen_by_name + seen = set() + seen_uselib = set() + tmp = Utils.deque(names) # consume a copy of the list of names + if tmp: + if Logs.verbose: + Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') + while tmp: + lib_name = tmp.popleft() + # visit dependencies only once + if lib_name in seen: + continue + + y = get(lib_name) + y.post() + seen.add(lib_name) + + # object has ancestors to process (shared libraries): add them to the end of the list + if getattr(y, 'uselib_local', None): + for x in self.to_list(getattr(y, 'uselib_local', [])): + obj = get(x) + obj.post() + if getattr(obj, 'link_task', None): + if not isinstance(obj.link_task, stlink_task): + tmp.append(x) + + # link task and flags + if getattr(y, 'link_task', None): + + link_name = y.target[y.target.rfind(os.sep) + 1:] + if isinstance(y.link_task, stlink_task): + env.append_value('STLIB', [link_name]) + else: + # some linkers can link against programs + env.append_value('LIB', [link_name]) + + # the order + self.link_task.set_run_after(y.link_task) + + # for the recompilation + self.link_task.dep_nodes += y.link_task.outputs + + # add the link path too + tmp_path = y.link_task.outputs[0].parent.bldpath() + if not tmp_path in env['LIBPATH']: + env.prepend_value('LIBPATH', [tmp_path]) + + # add ancestors uselib too - but only propagate those that have no staticlib defined + for v in self.to_list(getattr(y, 'uselib', [])): + if v not in seen_uselib: + seen_uselib.add(v) + if not env['STLIB_' + v]: + if not v in self.uselib: + self.uselib.insert(0, v) + + # if the library task generator provides 'export_includes', add to the include path + # the export_includes must be a list of paths relative to the other library + if getattr(y, 'export_includes', None): + self.includes.extend(y.to_incnodes(y.export_includes)) + +@TaskGen.feature('cprogram', 'cxxprogram', 'cstlib', 'cxxstlib', 'cshlib', 'cxxshlib', 'dprogram', 'dstlib', 'dshlib') +@TaskGen.after('apply_link') +def apply_objdeps(self): + "add the .o files produced by some other object files in the same manner as uselib_local" + names = getattr(self, 'add_objects', []) + if not names: + return + names = self.to_list(names) + + get = self.bld.get_tgen_by_name + seen = [] + while names: + x = names[0] + + # visit dependencies only once + if x in seen: + names = names[1:] + continue + + # object does not exist ? + y = get(x) + + # object has ancestors to process first ? update the list of names + if getattr(y, 'add_objects', None): + added = 0 + lst = y.to_list(y.add_objects) + lst.reverse() + for u in lst: + if u in seen: + continue + added = 1 + names = [u]+names + if added: + continue # list of names modified, loop + + # safe to process the current object + y.post() + seen.append(x) + + for t in getattr(y, 'compiled_tasks', []): + self.link_task.inputs.extend(t.outputs) + +@TaskGen.after('apply_link') +def process_obj_files(self): + if not hasattr(self, 'obj_files'): + return + for x in self.obj_files: + node = self.path.find_resource(x) + self.link_task.inputs.append(node) + +@TaskGen.taskgen_method +def add_obj_file(self, file): + """Small example on how to link object files as if they were source + obj = bld.create_obj('cc') + obj.add_obj_file('foo.o')""" + if not hasattr(self, 'obj_files'): + self.obj_files = [] + if not 'process_obj_files' in self.meths: + self.meths.append('process_obj_files') + self.obj_files.append(file) diff --git a/ldb-2.0.8/buildtools/wafsamba/samba_wildcard.py b/ldb-2.0.8/buildtools/wafsamba/samba_wildcard.py new file mode 100644 index 0000000..6173ce8 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/samba_wildcard.py @@ -0,0 +1,151 @@ +# based on playground/evil in the waf svn tree + +import os, datetime, fnmatch +from waflib import Scripting, Utils, Options, Logs, Errors +from waflib import ConfigSet, Context +from samba_utils import LOCAL_CACHE, os_path_relpath + +def run_task(t, k): + '''run a single build task''' + ret = t.run() + if ret: + raise Errors.WafError("Failed to build %s: %u" % (k, ret)) + + +def run_named_build_task(cmd): + '''run a named build task, matching the cmd name using fnmatch + wildcards against inputs and outputs of all build tasks''' + bld = fake_build_environment(info=False) + found = False + cwd_node = bld.root.find_dir(os.getcwd()) + top_node = bld.root.find_dir(bld.srcnode.abspath()) + + cmd = os.path.normpath(cmd) + + # cope with builds of bin/*/* + if os.path.islink(cmd): + cmd = os_path_relpath(os.readlink(cmd), os.getcwd()) + + if cmd[0:12] == "bin/default/": + cmd = cmd[12:] + + for g in bld.task_manager.groups: + for attr in ['outputs', 'inputs']: + for t in g.tasks: + s = getattr(t, attr, []) + for k in s: + relpath1 = k.relpath_gen(cwd_node) + relpath2 = k.relpath_gen(top_node) + if (fnmatch.fnmatch(relpath1, cmd) or + fnmatch.fnmatch(relpath2, cmd)): + t.position = [0,0] + print(t.display()) + run_task(t, k) + found = True + + + if not found: + raise Errors.WafError("Unable to find build target matching %s" % cmd) + + +def rewrite_compile_targets(): + '''cope with the bin/ form of compile target''' + if not Options.options.compile_targets: + return + + bld = fake_build_environment(info=False) + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + tlist = [] + + for t in Options.options.compile_targets.split(','): + if not os.path.islink(t): + tlist.append(t) + continue + link = os.readlink(t) + list = link.split('/') + for name in [list[-1], '/'.join(list[-2:])]: + if name in targets: + tlist.append(name) + continue + Options.options.compile_targets = ",".join(tlist) + + + +def wildcard_main(missing_cmd_fn): + '''this replaces main from Scripting, allowing us to override the + behaviour for unknown commands + + If a unknown command is found, then missing_cmd_fn() is called with + the name of the requested command + ''' + Scripting.commands = Options.arg_line[:] + + # rewrite the compile targets to cope with the bin/xx form + rewrite_compile_targets() + + while Scripting.commands: + x = Scripting.commands.pop(0) + + ini = datetime.datetime.now() + if x == 'configure': + fun = Scripting.configure + elif x == 'build': + fun = Scripting.build + else: + fun = getattr(Utils.g_module, x, None) + + # this is the new addition on top of main from Scripting.py + if not fun: + missing_cmd_fn(x) + break + + ctx = getattr(Utils.g_module, x + '_context', Utils.Context)() + + if x in ['init', 'shutdown', 'dist', 'distclean', 'distcheck']: + try: + fun(ctx) + except TypeError: + fun() + else: + fun(ctx) + + ela = '' + if not Options.options.progress_bar: + ela = ' (%s)' % Utils.get_elapsed_time(ini) + + if x != 'init' and x != 'shutdown': + Logs.info('%r finished successfully%s' % (x, ela)) + + if not Scripting.commands and x != 'shutdown': + Scripting.commands.append('shutdown') + + + + +def fake_build_environment(info=True, flush=False): + """create all the tasks for the project, but do not run the build + return the build context in use""" + bld = getattr(Context.g_module, 'build_context', Utils.Context)() + bld = Scripting.check_configured(bld) + + Options.commands['install'] = False + Options.commands['uninstall'] = False + + bld.is_install = 0 # False + + try: + proj = ConfigSet.ConfigSet(Options.lockfile) + except IOError: + raise Errors.WafError("Project not configured (run 'waf configure' first)") + + bld.load_envs() + + if info: + Logs.info("Waf: Entering directory `%s'" % bld.bldnode.abspath()) + bld.add_subdirs([os.path.split(Context.g_module.root_path)[0]]) + + bld.pre_build() + if flush: + bld.flush() + return bld + diff --git a/ldb-2.0.8/buildtools/wafsamba/stale_files.py b/ldb-2.0.8/buildtools/wafsamba/stale_files.py new file mode 100644 index 0000000..175f573 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/stale_files.py @@ -0,0 +1,113 @@ +# encoding: utf-8 +# Thomas Nagy, 2006-2010 (ita) + +""" +Add a pre-build hook to remove all build files +which do not have a corresponding target + +This can be used for example to remove the targets +that have changed name without performing +a full 'waf clean' + +Of course, it will only work if there are no dynamically generated +nodes/tasks, in which case the method will have to be modified +to exclude some folders for example. +""" + +from waflib import Logs, Build, Options, Utils, Errors +import os +from wafsamba import samba_utils +from Runner import Parallel + +old_refill_task_list = Parallel.refill_task_list +def replace_refill_task_list(self): + '''replacement for refill_task_list() that deletes stale files''' + + iit = old_refill_task_list(self) + bld = self.bld + + if not getattr(bld, 'new_rules', False): + # we only need to check for stale files if the build rules changed + return iit + + if Options.options.compile_targets: + # not safe when --target is used + return iit + + # execute only once + if getattr(self, 'cleanup_done', False): + return iit + self.cleanup_done = True + + def group_name(g): + tm = self.bld.task_manager + return [x for x in tm.groups_names if id(tm.groups_names[x]) == id(g)][0] + + bin_base = bld.bldnode.abspath() + bin_base_len = len(bin_base) + + # paranoia + if bin_base[-4:] != '/bin': + raise Errors.WafError("Invalid bin base: %s" % bin_base) + + # obtain the expected list of files + expected = [] + for i in range(len(bld.task_manager.groups)): + g = bld.task_manager.groups[i] + tasks = g.tasks_gen + for x in tasks: + try: + if getattr(x, 'target'): + tlist = samba_utils.TO_LIST(getattr(x, 'target')) + ttype = getattr(x, 'samba_type', None) + task_list = getattr(x, 'compiled_tasks', []) + if task_list: + # this gets all of the .o files, including the task + # ids, so foo.c maps to foo_3.o for idx=3 + for tsk in task_list: + for output in tsk.outputs: + objpath = os.path.normpath(output.abspath(bld.env)) + expected.append(objpath) + for t in tlist: + if ttype in ['LIBRARY','MODULE']: + t = samba_utils.apply_pattern(t, bld.env.shlib_PATTERN) + if ttype == 'PYTHON': + t = samba_utils.apply_pattern(t, bld.env.pyext_PATTERN) + p = os.path.join(x.path.abspath(bld.env), t) + p = os.path.normpath(p) + expected.append(p) + for n in x.allnodes: + p = n.abspath(bld.env) + if p[0:bin_base_len] == bin_base: + expected.append(p) + except: + pass + + for root, dirs, files in os.walk(bin_base): + for f in files: + p = root + '/' + f + if os.path.islink(p): + link = os.readlink(p) + if link[0:bin_base_len] == bin_base: + p = link + if f in ['config.h']: + continue + (froot, fext) = os.path.splitext(f) + if fext not in [ '.c', '.h', '.so', '.o' ]: + continue + if f[-7:] == '.inst.h': + continue + if p.find("/.conf") != -1: + continue + if not p in expected and os.path.exists(p): + Logs.warn("Removing stale file: %s" % p) + os.unlink(p) + return iit + + +def AUTOCLEANUP_STALE_FILES(bld): + """automatically clean up any files in bin that shouldn't be there""" + old_refill_task_list = Parallel.refill_task_list + Parallel.refill_task_list = replace_refill_task_list + Parallel.bld = bld +Build.BuildContext.AUTOCLEANUP_STALE_FILES = AUTOCLEANUP_STALE_FILES diff --git a/ldb-2.0.8/buildtools/wafsamba/symbols.py b/ldb-2.0.8/buildtools/wafsamba/symbols.py new file mode 100644 index 0000000..3eca3d4 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/symbols.py @@ -0,0 +1,659 @@ +# a waf tool to extract symbols from object files or libraries +# using nm, producing a set of exposed defined/undefined symbols + +import os, re, subprocess +from waflib import Utils, Build, Options, Logs, Errors +from waflib.Logs import debug +from samba_utils import TO_LIST, LOCAL_CACHE, get_tgt_list, os_path_relpath + +# these are the data structures used in symbols.py: +# +# bld.env.symbol_map : dictionary mapping public symbol names to list of +# subsystem names where that symbol exists +# +# t.in_library : list of libraries that t is in +# +# bld.env.public_symbols: set of public symbols for each subsystem +# bld.env.used_symbols : set of used symbols for each subsystem +# +# bld.env.syslib_symbols: dictionary mapping system library name to set of symbols +# for that library +# bld.env.library_dict : dictionary mapping built library paths to subsystem names +# +# LOCAL_CACHE(bld, 'TARGET_TYPE') : dictionary mapping subsystem name to target type + + +def symbols_extract(bld, objfiles, dynamic=False): + '''extract symbols from objfile, returning a dictionary containing + the set of undefined and public symbols for each file''' + + ret = {} + + # see if we can get some results from the nm cache + if not bld.env.nm_cache: + bld.env.nm_cache = {} + + objfiles = set(objfiles).copy() + + remaining = set() + for obj in objfiles: + if obj in bld.env.nm_cache: + ret[obj] = bld.env.nm_cache[obj].copy() + else: + remaining.add(obj) + objfiles = remaining + + if len(objfiles) == 0: + return ret + + cmd = ["nm"] + if dynamic: + # needed for some .so files + cmd.append("-D") + cmd.extend(list(objfiles)) + + nmpipe = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout + if len(objfiles) == 1: + filename = list(objfiles)[0] + ret[filename] = { "PUBLIC": set(), "UNDEFINED" : set()} + + for line in nmpipe: + line = line.strip() + if line.endswith(b':'): + filename = line[:-1] + ret[filename] = { "PUBLIC": set(), "UNDEFINED" : set() } + continue + cols = line.split(b" ") + if cols == [b'']: + continue + # see if the line starts with an address + if len(cols) == 3: + symbol_type = cols[1] + symbol = cols[2] + else: + symbol_type = cols[0] + symbol = cols[1] + if symbol_type in b"BDGTRVWSi": + # its a public symbol + ret[filename]["PUBLIC"].add(symbol) + elif symbol_type in b"U": + ret[filename]["UNDEFINED"].add(symbol) + + # add to the cache + for obj in objfiles: + if obj in ret: + bld.env.nm_cache[obj] = ret[obj].copy() + else: + bld.env.nm_cache[obj] = { "PUBLIC": set(), "UNDEFINED" : set() } + + return ret + + +def real_name(name): + if name.find(".objlist") != -1: + name = name[:-8] + return name + + +def find_ldd_path(bld, libname, binary): + '''find the path to the syslib we will link against''' + ret = None + if not bld.env.syslib_paths: + bld.env.syslib_paths = {} + if libname in bld.env.syslib_paths: + return bld.env.syslib_paths[libname] + + lddpipe = subprocess.Popen(['ldd', binary], stdout=subprocess.PIPE).stdout + for line in lddpipe: + line = line.strip() + cols = line.split(b" ") + if len(cols) < 3 or cols[1] != b"=>": + continue + if cols[0].startswith(b"libc."): + # save this one too + bld.env.libc_path = cols[2] + if cols[0].startswith(libname): + ret = cols[2] + bld.env.syslib_paths[libname] = ret + return ret + + +# some regular expressions for parsing readelf output +re_sharedlib = re.compile(b'Shared library: \[(.*)\]') +# output from readelf could be `Library rpath` or `Libray runpath` +re_rpath = re.compile(b'Library (rpath|runpath): \[(.*)\]') + +def get_libs(bld, binname): + '''find the list of linked libraries for any binary or library + binname is the path to the binary/library on disk + + We do this using readelf instead of ldd as we need to avoid recursing + into system libraries + ''' + + # see if we can get the result from the ldd cache + if not bld.env.lib_cache: + bld.env.lib_cache = {} + if binname in bld.env.lib_cache: + return bld.env.lib_cache[binname].copy() + + rpath = [] + libs = set() + + elfpipe = subprocess.Popen(['readelf', '--dynamic', binname], stdout=subprocess.PIPE).stdout + for line in elfpipe: + m = re_sharedlib.search(line) + if m: + libs.add(m.group(1)) + m = re_rpath.search(line) + if m: + # output from Popen is always bytestr even in py3 + rpath.extend(m.group(2).split(b":")) + + ret = set() + for lib in libs: + found = False + for r in rpath: + path = os.path.join(r, lib) + if os.path.exists(path): + ret.add(os.path.realpath(path)) + found = True + break + if not found: + # we didn't find this lib using rpath. It is probably a system + # library, so to find the path to it we either need to use ldd + # or we need to start parsing /etc/ld.so.conf* ourselves. We'll + # use ldd for now, even though it is slow + path = find_ldd_path(bld, lib, binname) + if path: + ret.add(os.path.realpath(path)) + + bld.env.lib_cache[binname] = ret.copy() + + return ret + + +def get_libs_recursive(bld, binname, seen): + '''find the recursive list of linked libraries for any binary or library + binname is the path to the binary/library on disk. seen is a set used + to prevent loops + ''' + if binname in seen: + return set() + ret = get_libs(bld, binname) + seen.add(binname) + for lib in ret: + # we don't want to recurse into system libraries. If a system + # library that we use (eg. libcups) happens to use another library + # (such as libkrb5) which contains common symbols with our own + # libraries, then that is not an error + if lib in bld.env.library_dict: + ret = ret.union(get_libs_recursive(bld, lib, seen)) + return ret + + + +def find_syslib_path(bld, libname, deps): + '''find the path to the syslib we will link against''' + # the strategy is to use the targets that depend on the library, and run ldd + # on it to find the real location of the library that is used + + linkpath = deps[0].link_task.outputs[0].abspath(bld.env) + + if libname == "python": + libname += bld.env.PYTHON_VERSION + + return find_ldd_path(bld, "lib%s" % libname.lower(), linkpath) + + +def build_symbol_sets(bld, tgt_list): + '''build the public_symbols and undefined_symbols attributes for each target''' + + if bld.env.public_symbols: + return + + objlist = [] # list of object file + objmap = {} # map from object filename to target (subsystem) name + + for t in tgt_list: + t.public_symbols = set() + t.undefined_symbols = set() + t.used_symbols = set() + for tsk in getattr(t, 'compiled_tasks', []): + for output in tsk.outputs: + objpath = output.abspath(bld.env) + objlist.append(objpath) + objmap[objpath] = t + + symbols = symbols_extract(bld, objlist) + for obj in objlist: + t = objmap[obj] + t.public_symbols = t.public_symbols.union(symbols[obj]["PUBLIC"]) + t.undefined_symbols = t.undefined_symbols.union(symbols[obj]["UNDEFINED"]) + t.used_symbols = t.used_symbols.union(symbols[obj]["UNDEFINED"]) + + t.undefined_symbols = t.undefined_symbols.difference(t.public_symbols) + + # and the reverse map of public symbols to subsystem name + bld.env.symbol_map = {} + + for t in tgt_list: + for s in t.public_symbols: + if not s in bld.env.symbol_map: + bld.env.symbol_map[s] = [] + bld.env.symbol_map[s].append(real_name(t.sname)) + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + bld.env.public_symbols = {} + for t in tgt_list: + name = real_name(t.sname) + if name in bld.env.public_symbols: + bld.env.public_symbols[name] = bld.env.public_symbols[name].union(t.public_symbols) + else: + bld.env.public_symbols[name] = t.public_symbols + if t.samba_type == 'LIBRARY': + for dep in t.add_objects: + t2 = bld.get_tgen_by_name(dep) + bld.ASSERT(t2 is not None, "Library '%s' has unknown dependency '%s'" % (name, dep)) + bld.env.public_symbols[name] = bld.env.public_symbols[name].union(t2.public_symbols) + + bld.env.used_symbols = {} + for t in tgt_list: + name = real_name(t.sname) + if name in bld.env.used_symbols: + bld.env.used_symbols[name] = bld.env.used_symbols[name].union(t.used_symbols) + else: + bld.env.used_symbols[name] = t.used_symbols + if t.samba_type == 'LIBRARY': + for dep in t.add_objects: + t2 = bld.get_tgen_by_name(dep) + bld.ASSERT(t2 is not None, "Library '%s' has unknown dependency '%s'" % (name, dep)) + bld.env.used_symbols[name] = bld.env.used_symbols[name].union(t2.used_symbols) + + +def build_library_dict(bld, tgt_list): + '''build the library_dict dictionary''' + + if bld.env.library_dict: + return + + bld.env.library_dict = {} + + for t in tgt_list: + if t.samba_type in [ 'LIBRARY', 'PYTHON' ]: + linkpath = os.path.realpath(t.link_task.outputs[0].abspath(bld.env)) + bld.env.library_dict[linkpath] = t.sname + + +def build_syslib_sets(bld, tgt_list): + '''build the public_symbols for all syslibs''' + + if bld.env.syslib_symbols: + return + + # work out what syslibs we depend on, and what targets those are used in + syslibs = {} + objmap = {} + for t in tgt_list: + if getattr(t, 'uselib', []) and t.samba_type in [ 'LIBRARY', 'BINARY', 'PYTHON' ]: + for lib in t.uselib: + if lib in ['PYEMBED', 'PYEXT']: + lib = "python" + if not lib in syslibs: + syslibs[lib] = [] + syslibs[lib].append(t) + + # work out the paths to each syslib + syslib_paths = [] + for lib in syslibs: + path = find_syslib_path(bld, lib, syslibs[lib]) + if path is None: + Logs.warn("Unable to find syslib path for %s" % lib) + if path is not None: + syslib_paths.append(path) + objmap[path] = lib.lower() + + # add in libc + syslib_paths.append(bld.env.libc_path) + objmap[bld.env.libc_path] = 'c' + + symbols = symbols_extract(bld, syslib_paths, dynamic=True) + + # keep a map of syslib names to public symbols + bld.env.syslib_symbols = {} + for lib in symbols: + bld.env.syslib_symbols[lib] = symbols[lib]["PUBLIC"] + + # add to the map of symbols to dependencies + for lib in symbols: + for sym in symbols[lib]["PUBLIC"]: + if not sym in bld.env.symbol_map: + bld.env.symbol_map[sym] = [] + bld.env.symbol_map[sym].append(objmap[lib]) + + # keep the libc symbols as well, as these are useful for some of the + # sanity checks + bld.env.libc_symbols = symbols[bld.env.libc_path]["PUBLIC"] + + # add to the combined map of dependency name to public_symbols + for lib in bld.env.syslib_symbols: + bld.env.public_symbols[objmap[lib]] = bld.env.syslib_symbols[lib] + + +def build_autodeps(bld, t): + '''build the set of dependencies for a target''' + deps = set() + name = real_name(t.sname) + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + for sym in t.undefined_symbols: + if sym in t.public_symbols: + continue + if sym in bld.env.symbol_map: + depname = bld.env.symbol_map[sym] + if depname == [ name ]: + # self dependencies aren't interesting + continue + if t.in_library == depname: + # no need to depend on the library we are part of + continue + if depname[0] in ['c', 'python']: + # these don't go into autodeps + continue + if targets[depname[0]] in [ 'SYSLIB' ]: + deps.add(depname[0]) + continue + t2 = bld.get_tgen_by_name(depname[0]) + if len(t2.in_library) != 1: + deps.add(depname[0]) + continue + if t2.in_library == t.in_library: + # if we're part of the same library, we don't need to autodep + continue + deps.add(t2.in_library[0]) + t.autodeps = deps + + +def build_library_names(bld, tgt_list): + '''add a in_library attribute to all targets that are part of a library''' + + if bld.env.done_build_library_names: + return + + for t in tgt_list: + t.in_library = [] + + for t in tgt_list: + if t.samba_type in [ 'LIBRARY' ]: + for obj in t.samba_deps_extended: + t2 = bld.get_tgen_by_name(obj) + if t2 and t2.samba_type in [ 'SUBSYSTEM', 'ASN1' ]: + if not t.sname in t2.in_library: + t2.in_library.append(t.sname) + bld.env.done_build_library_names = True + + +def check_library_deps(bld, t): + '''check that all the autodeps that have mutual dependency of this + target are in the same library as the target''' + + name = real_name(t.sname) + + if len(t.in_library) > 1: + Logs.warn("WARNING: Target '%s' in multiple libraries: %s" % (t.sname, t.in_library)) + + for dep in t.autodeps: + t2 = bld.get_tgen_by_name(dep) + if t2 is None: + continue + for dep2 in t2.autodeps: + if dep2 == name and t.in_library != t2.in_library: + Logs.warn("WARNING: mutual dependency %s <=> %s" % (name, real_name(t2.sname))) + Logs.warn("Libraries should match. %s != %s" % (t.in_library, t2.in_library)) + # raise Errors.WafError("illegal mutual dependency") + + +def check_syslib_collisions(bld, tgt_list): + '''check if a target has any symbol collisions with a syslib + + We do not want any code in Samba to use a symbol name from a + system library. The chance of that causing problems is just too + high. Note that libreplace uses a rep_XX approach of renaming + symbols via macros + ''' + + has_error = False + for t in tgt_list: + for lib in bld.env.syslib_symbols: + common = t.public_symbols.intersection(bld.env.syslib_symbols[lib]) + if common: + Logs.error("ERROR: Target '%s' has symbols '%s' which is also in syslib '%s'" % (t.sname, common, lib)) + has_error = True + if has_error: + raise Errors.WafError("symbols in common with system libraries") + + +def check_dependencies(bld, t): + '''check for depenencies that should be changed''' + + if bld.get_tgen_by_name(t.sname + ".objlist"): + return + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + remaining = t.undefined_symbols.copy() + remaining = remaining.difference(t.public_symbols) + + sname = real_name(t.sname) + + deps = set(t.samba_deps) + for d in t.samba_deps: + if targets[d] in [ 'EMPTY', 'DISABLED', 'SYSLIB', 'GENERATOR' ]: + continue + bld.ASSERT(d in bld.env.public_symbols, "Failed to find symbol list for dependency '%s'" % d) + diff = remaining.intersection(bld.env.public_symbols[d]) + if not diff and targets[sname] != 'LIBRARY': + Logs.info("Target '%s' has no dependency on %s" % (sname, d)) + else: + remaining = remaining.difference(diff) + + t.unsatisfied_symbols = set() + needed = {} + for sym in remaining: + if sym in bld.env.symbol_map: + dep = bld.env.symbol_map[sym] + if not dep[0] in needed: + needed[dep[0]] = set() + needed[dep[0]].add(sym) + else: + t.unsatisfied_symbols.add(sym) + + for dep in needed: + Logs.info("Target '%s' should add dep '%s' for symbols %s" % (sname, dep, " ".join(needed[dep]))) + + + +def check_syslib_dependencies(bld, t): + '''check for syslib depenencies''' + + if bld.get_tgen_by_name(t.sname + ".objlist"): + return + + sname = real_name(t.sname) + + remaining = set() + + features = TO_LIST(t.features) + if 'pyembed' in features or 'pyext' in features: + if 'python' in bld.env.public_symbols: + t.unsatisfied_symbols = t.unsatisfied_symbols.difference(bld.env.public_symbols['python']) + + needed = {} + for sym in t.unsatisfied_symbols: + if sym in bld.env.symbol_map: + dep = bld.env.symbol_map[sym][0] + if dep == 'c': + continue + if not dep in needed: + needed[dep] = set() + needed[dep].add(sym) + else: + remaining.add(sym) + + for dep in needed: + Logs.info("Target '%s' should add syslib dep '%s' for symbols %s" % (sname, dep, " ".join(needed[dep]))) + + if remaining: + debug("deps: Target '%s' has unsatisfied symbols: %s" % (sname, " ".join(remaining))) + + + +def symbols_symbolcheck(task): + '''check the internal dependency lists''' + bld = task.env.bld + tgt_list = get_tgt_list(bld) + + build_symbol_sets(bld, tgt_list) + build_library_names(bld, tgt_list) + + for t in tgt_list: + t.autodeps = set() + if getattr(t, 'source', ''): + build_autodeps(bld, t) + + for t in tgt_list: + check_dependencies(bld, t) + + for t in tgt_list: + check_library_deps(bld, t) + +def symbols_syslibcheck(task): + '''check the syslib dependencies''' + bld = task.env.bld + tgt_list = get_tgt_list(bld) + + build_syslib_sets(bld, tgt_list) + check_syslib_collisions(bld, tgt_list) + + for t in tgt_list: + check_syslib_dependencies(bld, t) + + +def symbols_whyneeded(task): + """check why 'target' needs to link to 'subsystem'""" + bld = task.env.bld + tgt_list = get_tgt_list(bld) + + why = Options.options.WHYNEEDED.split(":") + if len(why) != 2: + raise Errors.WafError("usage: WHYNEEDED=TARGET:DEPENDENCY") + target = why[0] + subsystem = why[1] + + build_symbol_sets(bld, tgt_list) + build_library_names(bld, tgt_list) + build_syslib_sets(bld, tgt_list) + + Logs.info("Checking why %s needs to link to %s" % (target, subsystem)) + if not target in bld.env.used_symbols: + Logs.warn("unable to find target '%s' in used_symbols dict" % target) + return + if not subsystem in bld.env.public_symbols: + Logs.warn("unable to find subsystem '%s' in public_symbols dict" % subsystem) + return + overlap = bld.env.used_symbols[target].intersection(bld.env.public_symbols[subsystem]) + if not overlap: + Logs.info("target '%s' doesn't use any public symbols from '%s'" % (target, subsystem)) + else: + Logs.info("target '%s' uses symbols %s from '%s'" % (target, overlap, subsystem)) + + +def report_duplicate(bld, binname, sym, libs, fail_on_error): + '''report duplicated symbols''' + if sym in ['_init', '_fini', '_edata', '_end', '__bss_start']: + return + libnames = [] + for lib in libs: + if lib in bld.env.library_dict: + libnames.append(bld.env.library_dict[lib]) + else: + libnames.append(lib) + if fail_on_error: + raise Errors.WafError("%s: Symbol %s linked in multiple libraries %s" % (binname, sym, libnames)) + else: + print("%s: Symbol %s linked in multiple libraries %s" % (binname, sym, libnames)) + + +def symbols_dupcheck_binary(bld, binname, fail_on_error): + '''check for duplicated symbols in one binary''' + + libs = get_libs_recursive(bld, binname, set()) + symlist = symbols_extract(bld, libs, dynamic=True) + + symmap = {} + for libpath in symlist: + for sym in symlist[libpath]['PUBLIC']: + if sym == '_GLOBAL_OFFSET_TABLE_': + continue + if not sym in symmap: + symmap[sym] = set() + symmap[sym].add(libpath) + for sym in symmap: + if len(symmap[sym]) > 1: + for libpath in symmap[sym]: + if libpath in bld.env.library_dict: + report_duplicate(bld, binname, sym, symmap[sym], fail_on_error) + break + +def symbols_dupcheck(task, fail_on_error=False): + '''check for symbols defined in two different subsystems''' + bld = task.env.bld + tgt_list = get_tgt_list(bld) + + targets = LOCAL_CACHE(bld, 'TARGET_TYPE') + + build_library_dict(bld, tgt_list) + for t in tgt_list: + if t.samba_type == 'BINARY': + binname = os_path_relpath(t.link_task.outputs[0].abspath(bld.env), os.getcwd()) + symbols_dupcheck_binary(bld, binname, fail_on_error) + + +def symbols_dupcheck_fatal(task): + '''check for symbols defined in two different subsystems (and fail if duplicates are found)''' + symbols_dupcheck(task, fail_on_error=True) + + +def SYMBOL_CHECK(bld): + '''check our dependency lists''' + if Options.options.SYMBOLCHECK: + bld.SET_BUILD_GROUP('symbolcheck') + task = bld(rule=symbols_symbolcheck, always=True, name='symbol checking') + task.env.bld = bld + + bld.SET_BUILD_GROUP('syslibcheck') + task = bld(rule=symbols_syslibcheck, always=True, name='syslib checking') + task.env.bld = bld + + bld.SET_BUILD_GROUP('syslibcheck') + task = bld(rule=symbols_dupcheck, always=True, name='symbol duplicate checking') + task.env.bld = bld + + if Options.options.WHYNEEDED: + bld.SET_BUILD_GROUP('syslibcheck') + task = bld(rule=symbols_whyneeded, always=True, name='check why a dependency is needed') + task.env.bld = bld + + +Build.BuildContext.SYMBOL_CHECK = SYMBOL_CHECK + +def DUP_SYMBOL_CHECK(bld): + if Options.options.DUP_SYMBOLCHECK and bld.env.DEVELOPER: + '''check for duplicate symbols''' + bld.SET_BUILD_GROUP('syslibcheck') + task = bld(rule=symbols_dupcheck_fatal, always=True, name='symbol duplicate checking') + task.env.bld = bld + +Build.BuildContext.DUP_SYMBOL_CHECK = DUP_SYMBOL_CHECK diff --git a/ldb-2.0.8/buildtools/wafsamba/test_duplicate_symbol.sh b/ldb-2.0.8/buildtools/wafsamba/test_duplicate_symbol.sh new file mode 100755 index 0000000..46f44a6 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/test_duplicate_symbol.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Run the waf duplicate symbol check, wrapped in subunit. + +. testprogs/blackbox/subunit.sh + +subunit_start_test duplicate_symbols + +if $PYTHON ./buildtools/bin/waf build --dup-symbol-check; then + subunit_pass_test duplicate_symbols +else + echo | subunit_fail_test duplicate_symbols +fi diff --git a/ldb-2.0.8/buildtools/wafsamba/tests/__init__.py b/ldb-2.0.8/buildtools/wafsamba/tests/__init__.py new file mode 100644 index 0000000..ae27418 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/tests/__init__.py @@ -0,0 +1,35 @@ +# Copyright (C) 2012 Jelmer Vernooij + +# This program 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 2.1 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 Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""Tests for wafsamba.""" + +from unittest import ( + TestCase, + TestLoader, + ) + +def test_suite(): + names = [ + 'abi', + 'bundled', + 'utils', + ] + module_names = ['wafsamba.tests.test_' + name for name in names] + loader = TestLoader() + result = loader.suiteClass() + suite = loader.loadTestsFromNames(module_names) + result.addTests(suite) + return result diff --git a/ldb-2.0.8/buildtools/wafsamba/tests/test_abi.py b/ldb-2.0.8/buildtools/wafsamba/tests/test_abi.py new file mode 100644 index 0000000..d6bdb04 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/tests/test_abi.py @@ -0,0 +1,134 @@ +# Copyright (C) 2012 Jelmer Vernooij + +# This program 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 2.1 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 Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from wafsamba.tests import TestCase + +from wafsamba.samba_abi import ( + abi_write_vscript, + normalise_signature, + ) + +from samba.compat import StringIO + + +class NormaliseSignatureTests(TestCase): + + def test_function_simple(self): + self.assertEquals("int (const struct GUID *, const struct GUID *)", + normalise_signature("$2 = {int (const struct GUID *, const struct GUID *)} 0xe871 ")) + + def test_maps_Bool(self): + # Some types have different internal names + self.assertEquals("bool (const struct GUID *)", + normalise_signature("$1 = {_Bool (const struct GUID *)} 0xe75b ")) + + def test_function_keep(self): + self.assertEquals( + "enum ndr_err_code (struct ndr_push *, int, const union winreg_Data *)", + normalise_signature("enum ndr_err_code (struct ndr_push *, int, const union winreg_Data *)")) + + def test_struct_constant(self): + self.assertEquals( + 'uuid = {time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\\000", node = "\\000\\000\\000\\000\\000"}, if_version = 0', + normalise_signature('$239 = {uuid = {time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\\000", node = "\\000\\000\\000\\000\\000"}, if_version = 0}')) + + def test_incomplete_sequence(self): + # Newer versions of gdb insert these incomplete sequence elements + self.assertEquals( + 'uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237\\350", node = "\\b\\000+\\020H`"}, if_version = 2', + normalise_signature('$244 = {uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237", , node = "\\b\\000+\\020H`"}, if_version = 2}')) + self.assertEquals( + 'uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237\\350", node = "\\b\\000+\\020H`"}, if_version = 2', + normalise_signature('$244 = {uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237\\350", node = "\\b\\000+\\020H`"}, if_version = 2}')) + + +class WriteVscriptTests(TestCase): + + def test_one(self): + f = StringIO() + abi_write_vscript(f, "MYLIB", "1.0", [], { + "old": "1.0", + "new": "1.0"}, ["*"]) + self.assertEquals(f.getvalue(), """\ +1.0 { +\tglobal: +\t\t*; +\tlocal: +\t\t_end; +\t\t__bss_start; +\t\t_edata; +}; +""") + + def test_simple(self): + # No restrictions. + f = StringIO() + abi_write_vscript(f, "MYLIB", "1.0", ["0.1"], { + "old": "0.1", + "new": "1.0"}, ["*"]) + self.assertEquals(f.getvalue(), """\ +MYLIB_0.1 { +\tglobal: +\t\told; +}; + +1.0 { +\tglobal: +\t\t*; +\tlocal: +\t\t_end; +\t\t__bss_start; +\t\t_edata; +}; +""") + + def test_exclude(self): + f = StringIO() + abi_write_vscript(f, "MYLIB", "1.0", [], { + "exc_old": "0.1", + "old": "0.1", + "new": "1.0"}, ["!exc_*"]) + self.assertEquals(f.getvalue(), """\ +1.0 { +\tglobal: +\t\t*; +\tlocal: +\t\texc_*; +\t\t_end; +\t\t__bss_start; +\t\t_edata; +}; +""") + + def test_excludes_and_includes(self): + f = StringIO() + abi_write_vscript(f, "MYLIB", "1.0", [], { + "pub_foo": "1.0", + "exc_bar": "1.0", + "other": "1.0" + }, ["pub_*", "!exc_*"]) + self.assertEquals(f.getvalue(), """\ +1.0 { +\tglobal: +\t\tpub_*; +\tlocal: +\t\texc_*; +\t\t_end; +\t\t__bss_start; +\t\t_edata; +\t\t*; +}; +""") diff --git a/ldb-2.0.8/buildtools/wafsamba/tests/test_bundled.py b/ldb-2.0.8/buildtools/wafsamba/tests/test_bundled.py new file mode 100644 index 0000000..c5f0db6 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/tests/test_bundled.py @@ -0,0 +1,27 @@ +# Copyright (C) 2012 Jelmer Vernooij + +# This program 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 2.1 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 Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from wafsamba.tests import TestCase + +from wafsamba.samba_bundled import ( + tuplize_version, + ) + + +class TuplizeVersionTests(TestCase): + + def test_simple(self): + self.assertEquals((1, 2, 10), tuplize_version("1.2.10")) diff --git a/ldb-2.0.8/buildtools/wafsamba/tests/test_utils.py b/ldb-2.0.8/buildtools/wafsamba/tests/test_utils.py new file mode 100644 index 0000000..a9578e2 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/tests/test_utils.py @@ -0,0 +1,76 @@ +# Copyright (C) 2012 Jelmer Vernooij + +# This program 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 2.1 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 Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from wafsamba.tests import TestCase + +from wafsamba.samba_utils import ( + TO_LIST, + dict_concat, + subst_vars_error, + unique_list, + ) + +class ToListTests(TestCase): + + def test_none(self): + self.assertEquals([], TO_LIST(None)) + + def test_already_list(self): + self.assertEquals(["foo", "bar", 1], TO_LIST(["foo", "bar", 1])) + + def test_default_delimiter(self): + self.assertEquals(["foo", "bar"], TO_LIST("foo bar")) + self.assertEquals(["foo", "bar"], TO_LIST(" foo bar ")) + self.assertEquals(["foo ", "bar"], TO_LIST(" \"foo \" bar ")) + + def test_delimiter(self): + self.assertEquals(["foo", "bar"], TO_LIST("foo,bar", ",")) + self.assertEquals([" foo", "bar "], TO_LIST(" foo,bar ", ",")) + self.assertEquals([" \" foo\"", " bar "], TO_LIST(" \" foo\", bar ", ",")) + + +class UniqueListTests(TestCase): + + def test_unique_list(self): + self.assertEquals(["foo", "bar"], unique_list(["foo", "bar", "foo"])) + + +class SubstVarsErrorTests(TestCase): + + def test_valid(self): + self.assertEquals("", subst_vars_error("", {})) + self.assertEquals("FOO bar", subst_vars_error("${F} bar", {"F": "FOO"})) + + def test_invalid(self): + self.assertRaises(KeyError, subst_vars_error, "${F}", {}) + + +class DictConcatTests(TestCase): + + def test_empty(self): + ret = {} + dict_concat(ret, {}) + self.assertEquals({}, ret) + + def test_same(self): + ret = {"foo": "bar"} + dict_concat(ret, {"foo": "bla"}) + self.assertEquals({"foo": "bar"}, ret) + + def test_simple(self): + ret = {"foo": "bar"} + dict_concat(ret, {"blie": "bla"}) + self.assertEquals({"foo": "bar", "blie": "bla"}, ret) diff --git a/ldb-2.0.8/buildtools/wafsamba/wafsamba.py b/ldb-2.0.8/buildtools/wafsamba/wafsamba.py new file mode 100644 index 0000000..205d5b4 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/wafsamba.py @@ -0,0 +1,950 @@ +# a waf tool to add autoconf-like macros to the configure section +# and for SAMBA_ macros for building libraries, binaries etc + +import os, sys, re, shutil, fnmatch +from waflib import Build, Options, Task, Utils, TaskGen, Logs, Context, Errors +from waflib.Configure import conf +from waflib.Logs import debug +from samba_utils import SUBST_VARS_RECURSIVE +TaskGen.task_gen.apply_verif = Utils.nada + +# bring in the other samba modules +from samba_utils import * +from samba_utils import symlink +from samba_version import * +from samba_autoconf import * +from samba_patterns import * +from samba_pidl import * +from samba_autoproto import * +from samba_python import * +from samba_perl import * +from samba_deps import * +from samba_bundled import * +from samba_third_party import * +import samba_cross +import samba_install +import samba_conftests +import samba_abi +import samba_headers +import generic_cc +import samba_dist +import samba_wildcard +import symbols +import pkgconfig +import configure_file +import samba_waf18 + +LIB_PATH="shared" + +os.environ['PYTHONUNBUFFERED'] = '1' + +if Context.HEXVERSION not in (0x2001200,): + Logs.error(''' +Please use the version of waf that comes with Samba, not +a system installed version. See http://wiki.samba.org/index.php/Waf +for details. + +Alternatively, please run ./configure and make as usual. That will +call the right version of waf.''') + sys.exit(1) + +@conf +def SAMBA_BUILD_ENV(conf): + '''create the samba build environment''' + conf.env.BUILD_DIRECTORY = conf.bldnode.abspath() + mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, LIB_PATH)) + mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, LIB_PATH, "private")) + mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, "modules")) + mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, 'python/samba/dcerpc')) + # this allows all of the bin/shared and bin/python targets + # to be expressed in terms of build directory paths + mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, 'default')) + for (source, target) in [('shared', 'shared'), ('modules', 'modules'), ('python', 'python')]: + link_target = os.path.join(conf.env.BUILD_DIRECTORY, 'default/' + target) + if not os.path.lexists(link_target): + symlink('../' + source, link_target) + + # get perl to put the blib files in the build directory + blib_bld = os.path.join(conf.env.BUILD_DIRECTORY, 'default/pidl/blib') + blib_src = os.path.join(conf.srcnode.abspath(), 'pidl/blib') + mkdir_p(blib_bld + '/man1') + mkdir_p(blib_bld + '/man3') + if os.path.islink(blib_src): + os.unlink(blib_src) + elif os.path.exists(blib_src): + shutil.rmtree(blib_src) + + +def ADD_INIT_FUNCTION(bld, subsystem, target, init_function): + '''add an init_function to the list for a subsystem''' + if init_function is None: + return + bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function) + cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') + if not subsystem in cache: + cache[subsystem] = [] + cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } ) +Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION + + +def generate_empty_file(task): + task.outputs[0].write('') + return 0 + +################################################################# +def SAMBA_LIBRARY(bld, libname, source, + deps='', + public_deps='', + includes='', + public_headers=None, + public_headers_install=True, + private_headers=None, + header_path=None, + pc_files=None, + vnum=None, + soname=None, + cflags='', + cflags_end=None, + ldflags='', + external_library=False, + realname=None, + keep_underscore=False, + autoproto=None, + autoproto_extra_source='', + group='main', + depends_on='', + local_include=True, + global_include=True, + vars=None, + subdir=None, + install_path=None, + install=True, + pyembed=False, + pyext=False, + target_type='LIBRARY', + bundled_extension=False, + bundled_name=None, + link_name=None, + abi_directory=None, + abi_match=None, + hide_symbols=False, + manpages=None, + private_library=False, + grouping_library=False, + allow_undefined_symbols=False, + allow_warnings=False, + enabled=True): + '''define a Samba library''' + + if private_library and public_headers: + raise Errors.WafError("private library '%s' must not have public header files" % + libname) + + if LIB_MUST_BE_PRIVATE(bld, libname): + private_library = True + + if not enabled: + SET_TARGET_TYPE(bld, libname, 'DISABLED') + return + + source = bld.EXPAND_VARIABLES(source, vars=vars) + if subdir: + source = bld.SUBDIR(subdir, source) + + # remember empty libraries, so we can strip the dependencies + if ((source == '') or (source == [])): + if deps == '' and public_deps == '': + SET_TARGET_TYPE(bld, libname, 'EMPTY') + return + empty_c = libname + '.empty.c' + bld.SAMBA_GENERATOR('%s_empty_c' % libname, + rule=generate_empty_file, + target=empty_c) + source=empty_c + + if BUILTIN_LIBRARY(bld, libname): + obj_target = libname + else: + obj_target = libname + '.objlist' + + if group == 'libraries': + subsystem_group = 'main' + else: + subsystem_group = group + + # first create a target for building the object files for this library + # by separating in this way, we avoid recompiling the C files + # separately for the install library and the build library + bld.SAMBA_SUBSYSTEM(obj_target, + source = source, + deps = deps, + public_deps = public_deps, + includes = includes, + public_headers = public_headers, + public_headers_install = public_headers_install, + private_headers= private_headers, + header_path = header_path, + cflags = cflags, + cflags_end = cflags_end, + group = subsystem_group, + autoproto = autoproto, + autoproto_extra_source=autoproto_extra_source, + depends_on = depends_on, + hide_symbols = hide_symbols, + allow_warnings = allow_warnings, + pyembed = pyembed, + pyext = pyext, + local_include = local_include, + global_include = global_include) + + if BUILTIN_LIBRARY(bld, libname): + return + + if not SET_TARGET_TYPE(bld, libname, target_type): + return + + # the library itself will depend on that object target + deps += ' ' + public_deps + deps = TO_LIST(deps) + deps.append(obj_target) + + realname = bld.map_shlib_extension(realname, python=(target_type=='PYTHON')) + link_name = bld.map_shlib_extension(link_name, python=(target_type=='PYTHON')) + + # we don't want any public libraries without version numbers + if (not private_library and target_type != 'PYTHON' and not realname): + if vnum is None and soname is None: + raise Errors.WafError("public library '%s' must have a vnum" % + libname) + if pc_files is None: + raise Errors.WafError("public library '%s' must have pkg-config file" % + libname) + if public_headers is None: + raise Errors.WafError("public library '%s' must have header files" % + libname) + + if bundled_name is not None: + pass + elif target_type == 'PYTHON' or realname or not private_library: + if keep_underscore: + bundled_name = libname + else: + bundled_name = libname.replace('_', '-') + else: + assert (private_library == True and realname is None) + if abi_directory or vnum or soname: + bundled_extension=True + bundled_name = PRIVATE_NAME(bld, libname.replace('_', '-'), + bundled_extension, private_library) + + ldflags = TO_LIST(ldflags) + if bld.env['ENABLE_RELRO'] is True: + ldflags.extend(TO_LIST('-Wl,-z,relro,-z,now')) + + features = 'c cshlib symlink_lib install_lib' + if pyext: + features += ' pyext' + if pyembed: + features += ' pyembed' + + if abi_directory: + features += ' abi_check' + + if pyembed and bld.env['PYTHON_SO_ABI_FLAG']: + # For ABI checking, we don't care about the Python version. + # Remove the Python ABI tag (e.g. ".cpython-35m") + abi_flag = bld.env['PYTHON_SO_ABI_FLAG'] + replacement = '' + version_libname = libname.replace(abi_flag, replacement) + else: + version_libname = libname + + vscript = None + if bld.env.HAVE_LD_VERSION_SCRIPT: + if private_library: + version = "%s_%s" % (Context.g_module.APPNAME, Context.g_module.VERSION) + elif vnum: + version = "%s_%s" % (libname, vnum) + else: + version = None + if version: + vscript = "%s.vscript" % libname + bld.ABI_VSCRIPT(version_libname, abi_directory, version, vscript, + abi_match) + fullname = apply_pattern(bundled_name, bld.env.cshlib_PATTERN) + fullpath = bld.path.find_or_declare(fullname) + vscriptpath = bld.path.find_or_declare(vscript) + if not fullpath: + raise Errors.WafError("unable to find fullpath for %s" % fullname) + if not vscriptpath: + raise Errors.WafError("unable to find vscript path for %s" % vscript) + bld.add_manual_dependency(fullpath, vscriptpath) + if bld.is_install: + # also make the .inst file depend on the vscript + instname = apply_pattern(bundled_name + '.inst', bld.env.cshlib_PATTERN) + bld.add_manual_dependency(bld.path.find_or_declare(instname), bld.path.find_or_declare(vscript)) + vscript = os.path.join(bld.path.abspath(bld.env), vscript) + + bld.SET_BUILD_GROUP(group) + t = bld( + features = features, + source = [], + target = bundled_name, + depends_on = depends_on, + samba_ldflags = ldflags, + samba_deps = deps, + samba_includes = includes, + version_script = vscript, + version_libname = version_libname, + local_include = local_include, + global_include = global_include, + vnum = vnum, + soname = soname, + install_path = None, + samba_inst_path = install_path, + name = libname, + samba_realname = realname, + samba_install = install, + abi_directory = "%s/%s" % (bld.path.abspath(), abi_directory), + abi_match = abi_match, + private_library = private_library, + grouping_library=grouping_library, + allow_undefined_symbols=allow_undefined_symbols + ) + + if realname and not link_name: + link_name = 'shared/%s' % realname + + if link_name: + if 'waflib.extras.compat15' in sys.modules: + link_name = 'default/' + link_name + t.link_name = link_name + + if pc_files is not None and not private_library: + if pyembed: + bld.PKG_CONFIG_FILES(pc_files, vnum=vnum, extra_name=bld.env['PYTHON_SO_ABI_FLAG']) + else: + bld.PKG_CONFIG_FILES(pc_files, vnum=vnum) + + if (manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and + bld.env['XSLTPROC_MANPAGES']): + bld.MANPAGES(manpages, install) + + +Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY + + +################################################################# +def SAMBA_BINARY(bld, binname, source, + deps='', + includes='', + public_headers=None, + private_headers=None, + header_path=None, + modules=None, + ldflags=None, + cflags='', + cflags_end=None, + autoproto=None, + use_hostcc=False, + use_global_deps=True, + compiler=None, + group='main', + manpages=None, + local_include=True, + global_include=True, + subsystem_name=None, + pyembed=False, + vars=None, + subdir=None, + install=True, + install_path=None, + enabled=True): + '''define a Samba binary''' + + if not enabled: + SET_TARGET_TYPE(bld, binname, 'DISABLED') + return + + if not SET_TARGET_TYPE(bld, binname, 'BINARY'): + return + + features = 'c cprogram symlink_bin install_bin' + if pyembed: + features += ' pyembed' + + obj_target = binname + '.objlist' + + source = bld.EXPAND_VARIABLES(source, vars=vars) + if subdir: + source = bld.SUBDIR(subdir, source) + source = unique_list(TO_LIST(source)) + + if group == 'binaries': + subsystem_group = 'main' + else: + subsystem_group = group + + # only specify PIE flags for binaries + pie_cflags = cflags + pie_ldflags = TO_LIST(ldflags) + if bld.env['ENABLE_PIE'] is True: + pie_cflags += ' -fPIE' + pie_ldflags.extend(TO_LIST('-pie')) + if bld.env['ENABLE_RELRO'] is True: + pie_ldflags.extend(TO_LIST('-Wl,-z,relro,-z,now')) + + # first create a target for building the object files for this binary + # by separating in this way, we avoid recompiling the C files + # separately for the install binary and the build binary + bld.SAMBA_SUBSYSTEM(obj_target, + source = source, + deps = deps, + includes = includes, + cflags = pie_cflags, + cflags_end = cflags_end, + group = subsystem_group, + autoproto = autoproto, + subsystem_name = subsystem_name, + local_include = local_include, + global_include = global_include, + use_hostcc = use_hostcc, + pyext = pyembed, + use_global_deps= use_global_deps) + + bld.SET_BUILD_GROUP(group) + + # the binary itself will depend on that object target + deps = TO_LIST(deps) + deps.append(obj_target) + + t = bld( + features = features, + source = [], + target = binname, + samba_deps = deps, + samba_includes = includes, + local_include = local_include, + global_include = global_include, + samba_modules = modules, + top = True, + samba_subsystem= subsystem_name, + install_path = None, + samba_inst_path= install_path, + samba_install = install, + samba_ldflags = pie_ldflags + ) + + if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']: + bld.MANPAGES(manpages, install) + +Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY + + +################################################################# +def SAMBA_MODULE(bld, modname, source, + deps='', + includes='', + subsystem=None, + init_function=None, + module_init_name='samba_init_module', + autoproto=None, + autoproto_extra_source='', + cflags='', + cflags_end=None, + internal_module=True, + local_include=True, + global_include=True, + vars=None, + subdir=None, + enabled=True, + pyembed=False, + manpages=None, + allow_undefined_symbols=False, + allow_warnings=False, + install=True + ): + '''define a Samba module.''' + + bld.ASSERT(subsystem, "You must specify a subsystem for SAMBA_MODULE(%s)" % modname) + + source = bld.EXPAND_VARIABLES(source, vars=vars) + if subdir: + source = bld.SUBDIR(subdir, source) + + if internal_module or BUILTIN_LIBRARY(bld, modname): + # Do not create modules for disabled subsystems + if GET_TARGET_TYPE(bld, subsystem) == 'DISABLED': + return + bld.SAMBA_SUBSYSTEM(modname, source, + deps=deps, + includes=includes, + autoproto=autoproto, + autoproto_extra_source=autoproto_extra_source, + cflags=cflags, + cflags_end=cflags_end, + local_include=local_include, + global_include=global_include, + allow_warnings=allow_warnings, + enabled=enabled) + + bld.ADD_INIT_FUNCTION(subsystem, modname, init_function) + return + + if not enabled: + SET_TARGET_TYPE(bld, modname, 'DISABLED') + return + + # Do not create modules for disabled subsystems + if GET_TARGET_TYPE(bld, subsystem) == 'DISABLED': + return + + realname = modname + deps += ' ' + subsystem + while realname.startswith("lib"+subsystem+"_"): + realname = realname[len("lib"+subsystem+"_"):] + while realname.startswith(subsystem+"_"): + realname = realname[len(subsystem+"_"):] + + build_name = "%s_module_%s" % (subsystem, realname) + + realname = bld.make_libname(realname) + while realname.startswith("lib"): + realname = realname[len("lib"):] + + build_link_name = "modules/%s/%s" % (subsystem, realname) + + if init_function: + cflags += " -D%s=%s" % (init_function, module_init_name) + + bld.SAMBA_LIBRARY(modname, + source, + deps=deps, + includes=includes, + cflags=cflags, + cflags_end=cflags_end, + realname = realname, + autoproto = autoproto, + local_include=local_include, + global_include=global_include, + vars=vars, + bundled_name=build_name, + link_name=build_link_name, + install_path="${MODULESDIR}/%s" % subsystem, + pyembed=pyembed, + manpages=manpages, + allow_undefined_symbols=allow_undefined_symbols, + allow_warnings=allow_warnings, + install=install + ) + + +Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE + + +################################################################# +def SAMBA_SUBSYSTEM(bld, modname, source, + deps='', + public_deps='', + includes='', + public_headers=None, + public_headers_install=True, + private_headers=None, + header_path=None, + cflags='', + cflags_end=None, + group='main', + init_function_sentinel=None, + autoproto=None, + autoproto_extra_source='', + depends_on='', + local_include=True, + local_include_first=True, + global_include=True, + subsystem_name=None, + enabled=True, + use_hostcc=False, + use_global_deps=True, + vars=None, + subdir=None, + hide_symbols=False, + allow_warnings=False, + pyext=False, + pyembed=False): + '''define a Samba subsystem''' + + if not enabled: + SET_TARGET_TYPE(bld, modname, 'DISABLED') + return + + # remember empty subsystems, so we can strip the dependencies + if ((source == '') or (source == [])): + if deps == '' and public_deps == '': + SET_TARGET_TYPE(bld, modname, 'EMPTY') + return + empty_c = modname + '.empty.c' + bld.SAMBA_GENERATOR('%s_empty_c' % modname, + rule=generate_empty_file, + target=empty_c) + source=empty_c + + if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'): + return + + source = bld.EXPAND_VARIABLES(source, vars=vars) + if subdir: + source = bld.SUBDIR(subdir, source) + source = unique_list(TO_LIST(source)) + + deps += ' ' + public_deps + + bld.SET_BUILD_GROUP(group) + + features = 'c' + if pyext: + features += ' pyext' + if pyembed: + features += ' pyembed' + + t = bld( + features = features, + source = source, + target = modname, + samba_cflags = CURRENT_CFLAGS(bld, modname, cflags, + allow_warnings=allow_warnings, + hide_symbols=hide_symbols), + depends_on = depends_on, + samba_deps = TO_LIST(deps), + samba_includes = includes, + local_include = local_include, + local_include_first = local_include_first, + global_include = global_include, + samba_subsystem= subsystem_name, + samba_use_hostcc = use_hostcc, + samba_use_global_deps = use_global_deps, + ) + + if cflags_end is not None: + t.samba_cflags.extend(TO_LIST(cflags_end)) + + if autoproto is not None: + bld.SAMBA_AUTOPROTO(autoproto, source + TO_LIST(autoproto_extra_source)) + if public_headers is not None: + bld.PUBLIC_HEADERS(public_headers, header_path=header_path, + public_headers_install=public_headers_install) + return t + + +Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM + + +def SAMBA_GENERATOR(bld, name, rule, source='', target='', + group='generators', enabled=True, + public_headers=None, + public_headers_install=True, + private_headers=None, + header_path=None, + vars=None, + dep_vars=[], + always=False): + '''A generic source generator target''' + + if not SET_TARGET_TYPE(bld, name, 'GENERATOR'): + return + + if not enabled: + return + + dep_vars.append('ruledeps') + dep_vars.append('SAMBA_GENERATOR_VARS') + + bld.SET_BUILD_GROUP(group) + t = bld( + rule=rule, + source=bld.EXPAND_VARIABLES(source, vars=vars), + target=target, + shell=isinstance(rule, str), + update_outputs=True, + before='c', + ext_out='.c', + samba_type='GENERATOR', + dep_vars = dep_vars, + name=name) + + if vars is None: + vars = {} + t.env.SAMBA_GENERATOR_VARS = vars + + if always: + t.always = True + + if public_headers is not None: + bld.PUBLIC_HEADERS(public_headers, header_path=header_path, + public_headers_install=public_headers_install) + return t +Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR + + + +@Utils.run_once +def SETUP_BUILD_GROUPS(bld): + '''setup build groups used to ensure that the different build + phases happen consecutively''' + bld.p_ln = bld.srcnode # we do want to see all targets! + bld.env['USING_BUILD_GROUPS'] = True + bld.add_group('setup') + bld.add_group('build_compiler_source') + bld.add_group('vscripts') + bld.add_group('base_libraries') + bld.add_group('generators') + bld.add_group('compiler_prototypes') + bld.add_group('compiler_libraries') + bld.add_group('build_compilers') + bld.add_group('build_source') + bld.add_group('prototypes') + bld.add_group('headers') + bld.add_group('main') + bld.add_group('symbolcheck') + bld.add_group('syslibcheck') + bld.add_group('final') +Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS + + +def SET_BUILD_GROUP(bld, group): + '''set the current build group''' + if not 'USING_BUILD_GROUPS' in bld.env: + return + bld.set_group(group) +Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP + + + +def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None): + '''used to copy scripts from the source tree into the build directory + for use by selftest''' + + source = bld.path.ant_glob(pattern, flat=True) + + bld.SET_BUILD_GROUP('build_source') + for s in TO_LIST(source): + iname = s + if installname is not None: + iname = installname + target = os.path.join(installdir, iname) + tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target)) + mkdir_p(tgtdir) + link_src = os.path.normpath(os.path.join(bld.path.abspath(), s)) + link_dst = os.path.join(tgtdir, os.path.basename(iname)) + if os.path.islink(link_dst) and os.readlink(link_dst) == link_src: + continue + if os.path.islink(link_dst): + os.unlink(link_dst) + Logs.info("symlink: %s -> %s/%s" % (s, installdir, iname)) + symlink(link_src, link_dst) +Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT + + +def copy_and_fix_python_path(task): + pattern='sys.path.insert(0, "bin/python")' + if task.env["PYTHONARCHDIR"] in sys.path and task.env["PYTHONDIR"] in sys.path: + replacement = "" + elif task.env["PYTHONARCHDIR"] == task.env["PYTHONDIR"]: + replacement="""sys.path.insert(0, "%s")""" % task.env["PYTHONDIR"] + else: + replacement="""sys.path.insert(0, "%s") +sys.path.insert(1, "%s")""" % (task.env["PYTHONARCHDIR"], task.env["PYTHONDIR"]) + + if task.env["PYTHON"][0].startswith("/"): + replacement_shebang = "#!%s\n" % task.env["PYTHON"][0] + else: + replacement_shebang = "#!/usr/bin/env %s\n" % task.env["PYTHON"][0] + + installed_location=task.outputs[0].bldpath(task.env) + source_file = open(task.inputs[0].srcpath(task.env)) + installed_file = open(installed_location, 'w') + lineno = 0 + for line in source_file: + newline = line + if (lineno == 0 and + line[:2] == "#!"): + newline = replacement_shebang + elif pattern in line: + newline = line.replace(pattern, replacement) + installed_file.write(newline) + lineno = lineno + 1 + installed_file.close() + os.chmod(installed_location, 0o755) + return 0 + +def copy_and_fix_perl_path(task): + pattern='use lib "$RealBin/lib";' + + replacement = "" + if not task.env["PERL_LIB_INSTALL_DIR"] in task.env["PERL_INC"]: + replacement = 'use lib "%s";' % task.env["PERL_LIB_INSTALL_DIR"] + + if task.env["PERL"][0] == "/": + replacement_shebang = "#!%s\n" % task.env["PERL"] + else: + replacement_shebang = "#!/usr/bin/env %s\n" % task.env["PERL"] + + installed_location=task.outputs[0].bldpath(task.env) + source_file = open(task.inputs[0].srcpath(task.env)) + installed_file = open(installed_location, 'w') + lineno = 0 + for line in source_file: + newline = line + if lineno == 0 and task.env["PERL_SPECIFIED"] == True and line[:2] == "#!": + newline = replacement_shebang + elif pattern in line: + newline = line.replace(pattern, replacement) + installed_file.write(newline) + lineno = lineno + 1 + installed_file.close() + os.chmod(installed_location, 0o755) + return 0 + + +def install_file(bld, destdir, file, chmod=MODE_644, flat=False, + python_fixup=False, perl_fixup=False, + destname=None, base_name=None): + '''install a file''' + if not isinstance(file, str): + file = file.abspath() + destdir = bld.EXPAND_VARIABLES(destdir) + if not destname: + destname = file + if flat: + destname = os.path.basename(destname) + dest = os.path.join(destdir, destname) + if python_fixup: + # fix the path python will use to find Samba modules + inst_file = file + '.inst' + bld.SAMBA_GENERATOR('python_%s' % destname, + rule=copy_and_fix_python_path, + dep_vars=["PYTHON","PYTHON_SPECIFIED","PYTHONDIR","PYTHONARCHDIR"], + source=file, + target=inst_file) + file = inst_file + if perl_fixup: + # fix the path perl will use to find Samba modules + inst_file = file + '.inst' + bld.SAMBA_GENERATOR('perl_%s' % destname, + rule=copy_and_fix_perl_path, + dep_vars=["PERL","PERL_SPECIFIED","PERL_LIB_INSTALL_DIR"], + source=file, + target=inst_file) + file = inst_file + if base_name: + file = os.path.join(base_name, file) + bld.install_as(dest, file, chmod=chmod) + + +def INSTALL_FILES(bld, destdir, files, chmod=MODE_644, flat=False, + python_fixup=False, perl_fixup=False, + destname=None, base_name=None): + '''install a set of files''' + for f in TO_LIST(files): + install_file(bld, destdir, f, chmod=chmod, flat=flat, + python_fixup=python_fixup, perl_fixup=perl_fixup, + destname=destname, base_name=base_name) +Build.BuildContext.INSTALL_FILES = INSTALL_FILES + + +def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False, + python_fixup=False, exclude=None, trim_path=None): + '''install a set of files matching a wildcard pattern''' + files=TO_LIST(bld.path.ant_glob(pattern, flat=True)) + if trim_path: + files2 = [] + for f in files: + files2.append(os_path_relpath(f, trim_path)) + files = files2 + + if exclude: + for f in files[:]: + if fnmatch.fnmatch(f, exclude): + files.remove(f) + INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat, + python_fixup=python_fixup, base_name=trim_path) +Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD + +def INSTALL_DIR(bld, path, chmod=0o755, env=None): + """Install a directory if it doesn't exist, always set permissions.""" + + if not path: + return [] + + destpath = bld.EXPAND_VARIABLES(path) + if Options.options.destdir: + destpath = os.path.join(Options.options.destdir, destpath.lstrip(os.sep)) + + if bld.is_install > 0: + if not os.path.isdir(destpath): + try: + Logs.info('* create %s', destpath) + os.makedirs(destpath) + os.chmod(destpath, chmod) + except OSError as e: + if not os.path.isdir(destpath): + raise Errors.WafError("Cannot create the folder '%s' (error: %s)" % (path, e)) +Build.BuildContext.INSTALL_DIR = INSTALL_DIR + +def INSTALL_DIRS(bld, destdir, dirs, chmod=0o755, env=None): + '''install a set of directories''' + destdir = bld.EXPAND_VARIABLES(destdir) + dirs = bld.EXPAND_VARIABLES(dirs) + for d in TO_LIST(dirs): + INSTALL_DIR(bld, os.path.join(destdir, d), chmod, env) +Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS + + +def MANPAGES(bld, manpages, install): + '''build and install manual pages''' + bld.env.MAN_XSL = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl' + for m in manpages.split(): + source = m + '.xml' + bld.SAMBA_GENERATOR(m, + source=source, + target=m, + group='final', + rule='${XSLTPROC} --xinclude -o ${TGT} --nonet ${MAN_XSL} ${SRC}' + ) + if install: + bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True) +Build.BuildContext.MANPAGES = MANPAGES + +def SAMBAMANPAGES(bld, manpages, extra_source=None): + '''build and install manual pages''' + bld.env.SAMBA_EXPAND_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/expand-sambadoc.xsl' + bld.env.SAMBA_MAN_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/man.xsl' + bld.env.SAMBA_CATALOG = bld.bldnode.abspath() + '/docs-xml/build/catalog.xml' + bld.env.SAMBA_CATALOGS = 'file:///etc/xml/catalog file:///usr/local/share/xml/catalog file://' + bld.env.SAMBA_CATALOG + + for m in manpages.split(): + source = m + '.xml' + if extra_source is not None: + source = [source, extra_source] + bld.SAMBA_GENERATOR(m, + source=source, + target=m, + group='final', + dep_vars=['SAMBA_MAN_XSL', 'SAMBA_EXPAND_XSL', 'SAMBA_CATALOG'], + rule='''XML_CATALOG_FILES="${SAMBA_CATALOGS}" + export XML_CATALOG_FILES + ${XSLTPROC} --xinclude --stringparam noreference 0 -o ${TGT}.xml --nonet ${SAMBA_EXPAND_XSL} ${SRC[0].abspath(env)} + ${XSLTPROC} --nonet -o ${TGT} ${SAMBA_MAN_XSL} ${TGT}.xml''' + ) + bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True) +Build.BuildContext.SAMBAMANPAGES = SAMBAMANPAGES + +@after('apply_link') +@feature('cshlib') +def apply_bundle_remove_dynamiclib_patch(self): + if self.env['MACBUNDLE'] or getattr(self,'mac_bundle',False): + if not getattr(self,'vnum',None): + try: + self.env['LINKFLAGS'].remove('-dynamiclib') + self.env['LINKFLAGS'].remove('-single_module') + except ValueError: + pass diff --git a/ldb-2.0.8/buildtools/wafsamba/wscript b/ldb-2.0.8/buildtools/wafsamba/wscript new file mode 100644 index 0000000..8014716 --- /dev/null +++ b/ldb-2.0.8/buildtools/wafsamba/wscript @@ -0,0 +1,611 @@ +#!/usr/bin/env python + +# this is a base set of waf rules that everything else pulls in first + +import os, sys +from waflib import Configure, Logs, Options, Utils, Context, Errors +import wafsamba +from samba_utils import os_path_relpath +from optparse import SUPPRESS_HELP + +# this forces configure to be re-run if any of the configure +# sections of the build scripts change. We have to check +# for this in sys.argv as options have not yet been parsed when +# we need to set this. This is off by default until some issues +# are resolved related to WAFCACHE. It will need a lot of testing +# before it is enabled by default. +if '--enable-auto-reconfigure' in sys.argv: + Configure.autoconfig = 'clobber' + +def default_value(option, default=''): + if option in Options.options.__dict__: + return Options.options.__dict__[option] + return default + +def options(opt): + opt.load('compiler_cc') + + opt.load('gnu_dirs') + + gr = opt.option_group('library handling options') + + gr.add_option('--bundled-libraries', + help=("comma separated list of bundled libraries. May include !LIBNAME to disable bundling a library. Can be 'NONE' or 'ALL' [auto]"), + action="store", dest='BUNDLED_LIBS', default='') + + gr.add_option('--private-libraries', + help=("comma separated list of normally public libraries to build instead as private libraries. May include !LIBNAME to disable making a library private. Can be 'NONE' or 'ALL' [auto]"), + action="store", dest='PRIVATE_LIBS', default='') + + extension_default = default_value('PRIVATE_EXTENSION_DEFAULT') + gr.add_option('--private-library-extension', + help=("name extension for private libraries [%s]" % extension_default), + action="store", dest='PRIVATE_EXTENSION', default=extension_default) + + extension_exception = default_value('PRIVATE_EXTENSION_EXCEPTION') + gr.add_option('--private-extension-exception', + help=("comma separated list of libraries to not apply extension to [%s]" % extension_exception), + action="store", dest='PRIVATE_EXTENSION_EXCEPTION', default=extension_exception) + + builtin_default = default_value('BUILTIN_LIBRARIES_DEFAULT') + gr.add_option('--builtin-libraries', + help=("command separated list of libraries to build directly into binaries [%s]" % builtin_default), + action="store", dest='BUILTIN_LIBRARIES', default=builtin_default) + + gr.add_option('--minimum-library-version', + help=("list of minimum system library versions (LIBNAME1:version,LIBNAME2:version)"), + action="store", dest='MINIMUM_LIBRARY_VERSION', default='') + + gr.add_option('--disable-rpath', + help=("Disable use of rpath for build binaries"), + action="store_true", dest='disable_rpath_build', default=False) + gr.add_option('--disable-rpath-install', + help=("Disable use of rpath for library path in installed files"), + action="store_true", dest='disable_rpath_install', default=False) + gr.add_option('--disable-rpath-private-install', + help=("Disable use of rpath for private library path in installed files"), + action="store_true", dest='disable_rpath_private_install', default=False) + gr.add_option('--nonshared-binary', + help=("Disable use of shared libs for the listed binaries"), + action="store", dest='NONSHARED_BINARIES', default='') + gr.add_option('--disable-symbol-versions', + help=("Disable use of the --version-script linker option"), + action="store_true", dest='disable_symbol_versions', default=False) + + opt.add_option('--with-modulesdir', + help=("modules directory [PREFIX/modules]"), + action="store", dest='MODULESDIR', default='${PREFIX}/modules') + + opt.add_option('--with-privatelibdir', + help=("private library directory [PREFIX/lib/%s]" % Context.g_module.APPNAME), + action="store", dest='PRIVATELIBDIR', default=None) + + opt.add_option('--with-libiconv', + help='additional directory to search for libiconv', + action='store', dest='iconv_open', default='/usr/local', + match = ['Checking for library iconv', 'Checking for iconv_open', 'Checking for header iconv.h']) + opt.add_option('--without-gettext', + help=("Disable use of gettext"), + action="store_true", dest='disable_gettext', default=False) + + gr = opt.option_group('developer options') + + gr.add_option('-C', + help='enable configure cacheing', + action='store_true', dest='enable_configure_cache') + gr.add_option('--enable-auto-reconfigure', + help='enable automatic reconfigure on build', + action='store_true', dest='enable_auto_reconfigure') + gr.add_option('--enable-debug', + help=("Turn on debugging symbols"), + action="store_true", dest='debug', default=False) + gr.add_option('--enable-developer', + help=("Turn on developer warnings and debugging"), + action="store_true", dest='developer', default=False) + opt.add_option('--enable-coverage', + help=("enable options necessary for code coverage " + "reporting on selftest (default=no)"), + action="store_true", dest='enable_coverage', default=False) + def picky_developer_callback(option, opt_str, value, parser): + parser.values.developer = True + parser.values.picky_developer = True + gr.add_option('--picky-developer', + help=("Treat all warnings as errors (enable -Werror)"), + action="callback", callback=picky_developer_callback, + dest='picky_developer', default=False) + gr.add_option('--fatal-errors', + help=("Stop compilation on first error (enable -Wfatal-errors)"), + action="store_true", dest='fatal_errors', default=False) + gr.add_option('--enable-gccdeps', + help=("Enable use of gcc -MD dependency module"), + action="store_true", dest='enable_gccdeps', default=True) + gr.add_option('--pedantic', + help=("Enable even more compiler warnings"), + action='store_true', dest='pedantic', default=False) + gr.add_option('--git-local-changes', + help=("mark version with + if local git changes"), + action='store_true', dest='GIT_LOCAL_CHANGES', default=False) + gr.add_option('--address-sanitizer', + help=("Enable address sanitizer compile and linker flags"), + action="store_true", dest='address_sanitizer', default=False) + gr.add_option('--undefined-sanitizer', + help=("Enable undefined behaviour sanitizer compile and linker flags"), + action="store_true", + dest='undefined_sanitizer', + default=False) + + gr.add_option('--abi-check', + help=("Check ABI signatures for libraries"), + action='store_true', dest='ABI_CHECK', default=False) + gr.add_option('--abi-check-disable', + help=("Disable ABI checking (used with --enable-developer)"), + action='store_true', dest='ABI_CHECK_DISABLE', default=False) + gr.add_option('--abi-update', + help=("Update ABI signature files for libraries"), + action='store_true', dest='ABI_UPDATE', default=False) + + gr.add_option('--show-deps', + help=("Show dependency tree for the given target"), + dest='SHOWDEPS', default='') + + gr.add_option('--symbol-check', + help=("check symbols in object files against project rules"), + action='store_true', dest='SYMBOLCHECK', default=False) + + gr.add_option('--dup-symbol-check', + help=("check for duplicate symbols in object files and system libs (must be configured with --enable-developer)"), + action='store_true', dest='DUP_SYMBOLCHECK', default=False) + + gr.add_option('--why-needed', + help=("TARGET:DEPENDENCY check why TARGET needs DEPENDENCY"), + action='store', type='str', dest='WHYNEEDED', default=None) + + gr.add_option('--show-duplicates', + help=("Show objects which are included in multiple binaries or libraries"), + action='store_true', dest='SHOW_DUPLICATES', default=False) + + gr = opt.add_option_group('cross compilation options') + + gr.add_option('--cross-compile', + help=("configure for cross-compilation"), + action='store_true', dest='CROSS_COMPILE', default=False) + gr.add_option('--cross-execute', + help=("command prefix to use for cross-execution in configure"), + action='store', dest='CROSS_EXECUTE', default='') + gr.add_option('--cross-answers', + help=("answers to cross-compilation configuration (auto modified)"), + action='store', dest='CROSS_ANSWERS', default='') + gr.add_option('--hostcc', + help=("set host compiler when cross compiling"), + action='store', dest='HOSTCC', default=False) + + # we use SUPPRESS_HELP for these, as they are ignored, and are there only + # to allow existing RPM spec files to work + opt.add_option('--build', + help=SUPPRESS_HELP, + action='store', dest='AUTOCONF_BUILD', default='') + opt.add_option('--host', + help=SUPPRESS_HELP, + action='store', dest='AUTOCONF_HOST', default='') + opt.add_option('--target', + help=SUPPRESS_HELP, + action='store', dest='AUTOCONF_TARGET', default='') + opt.add_option('--program-prefix', + help=SUPPRESS_HELP, + action='store', dest='AUTOCONF_PROGRAM_PREFIX', default='') + opt.add_option('--disable-dependency-tracking', + help=SUPPRESS_HELP, + action='store_true', dest='AUTOCONF_DISABLE_DEPENDENCY_TRACKING', default=False) + opt.add_option('--disable-silent-rules', + help=SUPPRESS_HELP, + action='store_true', dest='AUTOCONF_DISABLE_SILENT_RULES', default=False) + + gr = opt.option_group('dist options') + gr.add_option('--sign-release', + help='sign the release tarball created by waf dist', + action='store_true', dest='SIGN_RELEASE') + gr.add_option('--tag', + help='tag release in git at the same time', + type='string', action='store', dest='TAG_RELEASE') + + opt.add_option('--disable-python', + help='do not generate python modules', + action='store_true', dest='disable_python', default=False) + + +@Utils.run_once +def configure(conf): + conf.env.hlist = [] + conf.env.srcdir = conf.srcnode.abspath() + + conf.define('SRCDIR', conf.env['srcdir']) + + conf.SETUP_CONFIGURE_CACHE(Options.options.enable_configure_cache) + + # load our local waf extensions + conf.load('gnu_dirs') + conf.load('wafsamba') + + conf.CHECK_CC_ENV() + + conf.load('compiler_c') + + conf.CHECK_STANDARD_LIBPATH() + + # we need git for 'waf dist' + conf.find_program('git', var='GIT') + + # older gcc versions (< 4.4) does not work with gccdeps, so we have to see if the .d file is generated + if Options.options.enable_gccdeps: + # stale file removal - the configuration may pick up the old .pyc file + p = os.path.join(conf.env.srcdir, 'buildtools/wafsamba/gccdeps.pyc') + if os.path.exists(p): + os.remove(p) + conf.load('gccdeps') + + # make the install paths available in environment + conf.env.LIBDIR = Options.options.LIBDIR or '${PREFIX}/lib' + conf.env.BINDIR = Options.options.BINDIR or '${PREFIX}/bin' + conf.env.SBINDIR = Options.options.SBINDIR or '${PREFIX}/sbin' + conf.env.MODULESDIR = Options.options.MODULESDIR + conf.env.PRIVATELIBDIR = Options.options.PRIVATELIBDIR + conf.env.BUNDLED_LIBS = Options.options.BUNDLED_LIBS.split(',') + conf.env.SYSTEM_LIBS = () + conf.env.PRIVATE_LIBS = Options.options.PRIVATE_LIBS.split(',') + conf.env.BUILTIN_LIBRARIES = Options.options.BUILTIN_LIBRARIES.split(',') + conf.env.NONSHARED_BINARIES = Options.options.NONSHARED_BINARIES.split(',') + + conf.env.PRIVATE_EXTENSION = Options.options.PRIVATE_EXTENSION + conf.env.PRIVATE_EXTENSION_EXCEPTION = Options.options.PRIVATE_EXTENSION_EXCEPTION.split(',') + + conf.env.CROSS_COMPILE = Options.options.CROSS_COMPILE + conf.env.CROSS_EXECUTE = Options.options.CROSS_EXECUTE + conf.env.CROSS_ANSWERS = Options.options.CROSS_ANSWERS + conf.env.HOSTCC = Options.options.HOSTCC + + conf.env.AUTOCONF_BUILD = Options.options.AUTOCONF_BUILD + conf.env.AUTOCONF_HOST = Options.options.AUTOCONF_HOST + conf.env.AUTOCONF_PROGRAM_PREFIX = Options.options.AUTOCONF_PROGRAM_PREFIX + + conf.env.disable_python = Options.options.disable_python + + if (conf.env.AUTOCONF_HOST and + conf.env.AUTOCONF_BUILD and + conf.env.AUTOCONF_BUILD != conf.env.AUTOCONF_HOST): + Logs.error('ERROR: Mismatch between --build and --host. Please use --cross-compile instead') + sys.exit(1) + if conf.env.AUTOCONF_PROGRAM_PREFIX: + Logs.error('ERROR: --program-prefix not supported') + sys.exit(1) + + # enable ABI checking for developers + conf.env.ABI_CHECK = Options.options.ABI_CHECK or Options.options.developer + if Options.options.ABI_CHECK_DISABLE: + conf.env.ABI_CHECK = False + try: + conf.find_program('gdb', mandatory=True) + except: + conf.env.ABI_CHECK = False + + conf.env.enable_coverage = Options.options.enable_coverage + if conf.env.enable_coverage: + conf.ADD_LDFLAGS('-lgcov', testflags=True) + conf.ADD_CFLAGS('--coverage', testflags=True) + # disable abi check for coverage, otherwise ld will fail + conf.env.ABI_CHECK = False + + conf.env.GIT_LOCAL_CHANGES = Options.options.GIT_LOCAL_CHANGES + + conf.CHECK_UNAME() + + # see if we can compile and run a simple C program + conf.CHECK_CODE('printf("hello world")', + define='HAVE_SIMPLE_C_PROG', + mandatory=True, + execute=True, + headers='stdio.h', + msg='Checking simple C program') + + # Try to find the right extra flags for -Werror behaviour + for f in ["-Werror", # GCC + "-errwarn=%all", # Sun Studio + "-qhalt=w", # IBM xlc + "-w2", # Tru64 + ]: + if conf.CHECK_CFLAGS([f]): + if not 'WERROR_CFLAGS' in conf.env: + conf.env['WERROR_CFLAGS'] = [] + conf.env['WERROR_CFLAGS'].extend([f]) + break + + # check which compiler/linker flags are needed for rpath support + if conf.CHECK_LDFLAGS(['-Wl,-rpath,.']): + conf.env['RPATH_ST'] = '-Wl,-rpath,%s' + elif conf.CHECK_LDFLAGS(['-Wl,-R,.']): + conf.env['RPATH_ST'] = '-Wl,-R,%s' + + # check for rpath + if conf.CHECK_LIBRARY_SUPPORT(rpath=True): + support_rpath = True + conf.env.RPATH_ON_BUILD = not Options.options.disable_rpath_build + conf.env.RPATH_ON_INSTALL = (conf.env.RPATH_ON_BUILD and + not Options.options.disable_rpath_install) + if not conf.env.PRIVATELIBDIR: + conf.env.PRIVATELIBDIR = '%s/%s' % (conf.env.LIBDIR, Context.g_module.APPNAME) + conf.env.RPATH_ON_INSTALL_PRIVATE = ( + not Options.options.disable_rpath_private_install) + else: + support_rpath = False + conf.env.RPATH_ON_INSTALL = False + conf.env.RPATH_ON_BUILD = False + conf.env.RPATH_ON_INSTALL_PRIVATE = False + if not conf.env.PRIVATELIBDIR: + # rpath is not possible so there is no sense in having a + # private library directory by default. + # the user can of course always override it. + conf.env.PRIVATELIBDIR = conf.env.LIBDIR + + if (not Options.options.disable_symbol_versions and + conf.CHECK_LIBRARY_SUPPORT(rpath=support_rpath, + version_script=True, + msg='-Wl,--version-script support')): + conf.env.HAVE_LD_VERSION_SCRIPT = True + else: + conf.env.HAVE_LD_VERSION_SCRIPT = False + + if conf.CHECK_CFLAGS(['-fvisibility=hidden']): + conf.env.VISIBILITY_CFLAGS = '-fvisibility=hidden' + conf.CHECK_CODE('''int main(void) { return 0; } + __attribute__((visibility("default"))) void vis_foo2(void) {}\n''', + cflags=conf.env.VISIBILITY_CFLAGS, + strict=True, + define='HAVE_VISIBILITY_ATTR', addmain=False) + + # check HAVE_CONSTRUCTOR_ATTRIBUTE + conf.CHECK_CODE(''' + void test_constructor_attribute(void) __attribute__ ((constructor)); + + void test_constructor_attribute(void) + { + return; + } + + int main(void) { + return 0; + } + ''', + 'HAVE_CONSTRUCTOR_ATTRIBUTE', + addmain=False, + strict=True, + msg='Checking for library constructor support') + + # check HAVE_DESTRUCTOR_ATTRIBUTE + conf.CHECK_CODE(''' + void test_destructor_attribute(void) __attribute__ ((destructor)); + + void test_destructor_attribute(void) + { + return; + } + + int main(void) { + return 0; + } + ''', + 'HAVE_DESTRUCTOR_ATTRIBUTE', + addmain=False, + strict=True, + 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, + strict=True, + 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 + # conf.DEFINE('_XOPEN_SOURCE', 600, add_to_cflags=True) + + # we should use the PIC options in waf instead + # Some compilo didn't support -fPIC but just print a warning + if conf.env['COMPILER_CC'] == "suncc": + conf.ADD_CFLAGS('-KPIC', testflags=True) + # we really want define here as we need to have this + # define even during the tests otherwise detection of + # boolean is broken + conf.DEFINE('_STDC_C99', 1, add_to_cflags=True) + conf.DEFINE('_XPG6', 1, add_to_cflags=True) + else: + conf.ADD_CFLAGS('-fPIC', testflags=True) + + # On Solaris 8 with suncc (at least) the flags for the linker to define the name of the + # library are not always working (if the command line is very very long and with a lot + # files) + + if conf.env['COMPILER_CC'] == "suncc": + save = conf.env['SONAME_ST'] + conf.env['SONAME_ST'] = '-Wl,-h,%s' + if not conf.CHECK_SHLIB_INTRASINC_NAME_FLAGS("Checking if flags %s are ok" % conf.env['SONAME_ST']): + conf.env['SONAME_ST'] = save + + conf.CHECK_INLINE() + + # check for pkgconfig + conf.CHECK_CFG(atleast_pkgconfig_version='0.0.0') + + conf.DEFINE('_GNU_SOURCE', 1, add_to_cflags=True) + conf.DEFINE('_XOPEN_SOURCE_EXTENDED', 1, add_to_cflags=True) + + # + # Needs to be defined before std*.h and string*.h are included + # As Python.h already brings string.h we need it in CFLAGS. + # See memset_s() details here: + # https://en.cppreference.com/w/c/string/byte/memset + # + if conf.CHECK_CFLAGS(['-D__STDC_WANT_LIB_EXT1__=1']): + conf.ADD_CFLAGS('-D__STDC_WANT_LIB_EXT1__=1') + + # on Tru64 certain features are only available with _OSF_SOURCE set to 1 + # and _XOPEN_SOURCE set to 600 + if conf.env['SYSTEM_UNAME_SYSNAME'] == 'OSF1': + conf.DEFINE('_OSF_SOURCE', 1, add_to_cflags=True) + conf.DEFINE('_XOPEN_SOURCE', 600, add_to_cflags=True) + + # SCM_RIGHTS is only avail if _XOPEN_SOURCE iѕ defined on IRIX + if conf.env['SYSTEM_UNAME_SYSNAME'] == 'IRIX': + conf.DEFINE('_XOPEN_SOURCE', 600, add_to_cflags=True) + conf.DEFINE('_BSD_TYPES', 1, add_to_cflags=True) + + # Try to find the right extra flags for C99 initialisers + for f in ["", "-AC99", "-qlanglvl=extc99", "-qlanglvl=stdc99", "-c99"]: + if conf.CHECK_CFLAGS([f], ''' +struct foo {int x;char y;}; +struct foo bar = { .y = 'X', .x = 1 }; +'''): + if f != "": + conf.ADD_CFLAGS(f) + break + + # get the base headers we'll use for the rest of the tests + conf.CHECK_HEADERS('stdio.h sys/types.h sys/stat.h stdlib.h stddef.h memory.h string.h', + add_headers=True) + conf.CHECK_HEADERS('strings.h inttypes.h stdint.h unistd.h minix/config.h', add_headers=True) + conf.CHECK_HEADERS('ctype.h', add_headers=True) + + if sys.platform != 'darwin': + conf.CHECK_HEADERS('standards.h', add_headers=True) + + conf.CHECK_HEADERS('stdbool.h stdint.h stdarg.h vararg.h', add_headers=True) + conf.CHECK_HEADERS('limits.h assert.h') + + # see if we need special largefile flags + if not conf.CHECK_LARGEFILE(): + raise Errors.WafError('Samba requires large file support support, but not available on this platform: sizeof(off_t) < 8') + + if conf.env.HAVE_STDDEF_H and conf.env.HAVE_STDLIB_H: + conf.DEFINE('STDC_HEADERS', 1) + + conf.CHECK_HEADERS('sys/time.h time.h', together=True) + + if conf.env.HAVE_SYS_TIME_H and conf.env.HAVE_TIME_H: + conf.DEFINE('TIME_WITH_SYS_TIME', 1) + + # cope with different extensions for libraries + (root, ext) = os.path.splitext(conf.env.cshlib_PATTERN) + if ext[0] == '.': + conf.define('SHLIBEXT', ext[1:], quote=True) + else: + conf.define('SHLIBEXT', "so", quote=True) + + # First try a header check for cross-compile friendlyness + conf.CHECK_CODE(code = """#ifdef __BYTE_ORDER + #define B __BYTE_ORDER + #elif defined(BYTE_ORDER) + #define B BYTE_ORDER + #endif + + #ifdef __LITTLE_ENDIAN + #define LITTLE __LITTLE_ENDIAN + #elif defined(LITTLE_ENDIAN) + #define LITTLE LITTLE_ENDIAN + #endif + + #if !defined(LITTLE) || !defined(B) || LITTLE != B + #error Not little endian. + #endif + int main(void) { return 0; }\n""", + addmain=False, + headers="endian.h sys/endian.h", + define="HAVE_LITTLE_ENDIAN") + conf.CHECK_CODE(code = """#ifdef __BYTE_ORDER + #define B __BYTE_ORDER + #elif defined(BYTE_ORDER) + #define B BYTE_ORDER + #endif + + #ifdef __BIG_ENDIAN + #define BIG __BIG_ENDIAN + #elif defined(BIG_ENDIAN) + #define BIG BIG_ENDIAN + #endif + + #if !defined(BIG) || !defined(B) || BIG != B + #error Not big endian. + #endif + int main(void) { return 0; }\n""", + addmain=False, + headers="endian.h sys/endian.h", + define="HAVE_BIG_ENDIAN") + + if not conf.CONFIG_SET("HAVE_BIG_ENDIAN") and not conf.CONFIG_SET("HAVE_LITTLE_ENDIAN"): + # That didn't work! Do runtime test. + conf.CHECK_CODE("""union { int i; char c[sizeof(int)]; } u; + u.i = 0x01020304; + return u.c[0] == 0x04 && u.c[1] == 0x03 && u.c[2] == 0x02 && u.c[3] == 0x01 ? 0 : 1;""", + addmain=True, execute=True, + define='HAVE_LITTLE_ENDIAN', + msg="Checking for HAVE_LITTLE_ENDIAN - runtime") + conf.CHECK_CODE("""union { int i; char c[sizeof(int)]; } u; + u.i = 0x01020304; + return u.c[0] == 0x01 && u.c[1] == 0x02 && u.c[2] == 0x03 && u.c[3] == 0x04 ? 0 : 1;""", + addmain=True, execute=True, + define='HAVE_BIG_ENDIAN', + msg="Checking for HAVE_BIG_ENDIAN - runtime") + + # Extra sanity check. + if conf.CONFIG_SET("HAVE_BIG_ENDIAN") == conf.CONFIG_SET("HAVE_LITTLE_ENDIAN"): + Logs.error("Failed endian determination. The PDP-11 is back?") + sys.exit(1) + else: + if conf.CONFIG_SET("HAVE_BIG_ENDIAN"): + conf.DEFINE('WORDS_BIGENDIAN', 1) + + # check if signal() takes a void function + if conf.CHECK_CODE('return *(signal (0, 0)) (0) == 1', + define='RETSIGTYPE_INT', + execute=False, + headers='signal.h', + msg='Checking if signal handlers return int'): + conf.DEFINE('RETSIGTYPE', 'int') + else: + conf.DEFINE('RETSIGTYPE', 'void') + + conf.CHECK_VARIABLE('__FUNCTION__', define='HAVE_FUNCTION_MACRO') + + conf.CHECK_CODE('va_list ap1,ap2; va_copy(ap1,ap2)', + define="HAVE_VA_COPY", + msg="Checking for va_copy") + + conf.CHECK_CODE(''' + #define eprintf(...) fprintf(stderr, __VA_ARGS__) + eprintf("bla", "bar") + ''', define='HAVE__VA_ARGS__MACRO') + + conf.SAMBA_BUILD_ENV() + + +def build(bld): + # give a more useful message if the source directory has moved + curdir = bld.path.abspath() + srcdir = bld.srcnode.abspath() + relpath = os_path_relpath(curdir, srcdir) + if relpath.find('../') != -1: + Logs.error('bld.path %s is not a child of %s' % (curdir, srcdir)) + raise Errors.WafError('''The top source directory has moved. Please run distclean and reconfigure''') + + bld.SETUP_BUILD_GROUPS() + bld.ENFORCE_GROUP_ORDERING() + bld.CHECK_PROJECT_RULES() diff --git a/ldb-2.0.8/common/attrib_handlers.c b/ldb-2.0.8/common/attrib_handlers.c new file mode 100644 index 0000000..b5212b7 --- /dev/null +++ b/ldb-2.0.8/common/attrib_handlers.c @@ -0,0 +1,639 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Andrew Bartlett 2006-2009 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ +/* + attribute handlers for well known attribute types, selected by syntax OID + see rfc2252 +*/ + +#include "ldb_private.h" +#include "system/locale.h" +#include "ldb_handlers.h" + +/* + default handler that just copies a ldb_val. +*/ +int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + *out = ldb_val_dup(mem_ctx, in); + if (in->length > 0 && out->data == NULL) { + ldb_oom(ldb); + return -1; + } + return 0; +} + +/* + a case folding copy handler, removing leading and trailing spaces and + multiple internal spaces + + We exploit the fact that utf8 never uses the space octet except for + the space itself +*/ +int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + char *s, *t; + size_t l; + + if (!in || !out || !(in->data)) { + return -1; + } + + out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length); + if (out->data == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%.*s]", (int)in->length, (const char *)in->data); + return -1; + } + + s = (char *)(out->data); + + /* remove trailing spaces if any */ + l = strlen(s); + while (l > 0 && s[l - 1] == ' ') l--; + s[l] = '\0'; + + /* remove leading spaces if any */ + if (*s == ' ') { + for (t = s; *s == ' '; s++) ; + + /* remove leading spaces by moving down the string */ + memmove(t, s, l); + + s = t; + } + + /* check middle spaces */ + while ((t = strchr(s, ' ')) != NULL) { + for (s = t; *s == ' '; s++) ; + + if ((s - t) > 1) { + l = strlen(s); + + /* remove all spaces but one by moving down the string */ + memmove(t + 1, s, l); + } + } + + out->length = strlen((char *)out->data); + return 0; +} + +/* length limited conversion of a ldb_val to a int32_t */ +static int val_to_int64(const struct ldb_val *in, int64_t *v) +{ + char *end; + char buf[64]; + + /* make sure we don't read past the end of the data */ + if (in->length > sizeof(buf)-1) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + strncpy(buf, (char *)in->data, in->length); + buf[in->length] = 0; + + /* We've to use "strtoll" here to have the intended overflows. + * Otherwise we may get "LONG_MAX" and the conversion is wrong. */ + *v = (int64_t) strtoll(buf, &end, 0); + if (*end != 0) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + return LDB_SUCCESS; +} + + +/* + canonicalise a ldap Integer + rfc2252 specifies it should be in decimal form +*/ +static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + int64_t i; + int ret; + + ret = val_to_int64(in, &i); + if (ret != LDB_SUCCESS) { + return ret; + } + out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i); + if (out->data == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + out->length = strlen((char *)out->data); + return 0; +} + +/* + * Lexicographically ordered format for a ldap Integer + * + * [ INT64_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT64_MAX ] + * n o p + * + * For human readability sake, we continue to format the key as a string + * (like the canonicalize) rather than store as a fixed binary representation. + * + * In order to sort the integers in the correct string order, there are three + * techniques we use: + * + * 1. Zero padding + * 2. Negative integer inversion + * 3. 1-byte prefixes: 'n' < 'o' < 'p' + * + * 1. To have a fixed-width representation so that 10 sorts after 2 rather than + * after 1, we zero pad, like this 4-byte width example: + * + * 0001, 0002, 0010 + * + * INT64_MAX = 2^63 - 1 = 9223372036854775807 (19 characters long) + * + * Meaning we need to pad to 19 characters. + * + * 2. This works for positive integers, but negative integers will still be + * sorted backwards, for example: + * + * -9223372036854775808 ..., -0000000000000000002, -0000000000000000001 + * INT64_MIN -2 -1 + * + * gets sorted based on string as: + * + * -0000000000000000001, -0000000000000000002, ... -9223372036854775808 + * + * In order to fix this, we invert the negative integer range, so that they + * get sorted the same way as positive numbers. INT64_MIN becomes the lowest + * possible non-negative number (zero), and -1 becomes the highest (INT64_MAX). + * + * The actual conversion applied to negative number 'x' is: + * INT64_MAX - abs(x) + 1 + * (The +1 is needed because abs(INT64_MIN) is one greater than INT64_MAX) + * + * 3. Finally, we now have two different numbers that map to the same key, e.g. + * INT64_MIN maps to -0000000000000000000 and zero maps to 0000000000000000000. + * In order to avoid confusion, we give every number a prefix representing its + * sign: 'n' for negative numbers, 'o' for zero, and 'p' for positive. (Note + * that '+' and '-' weren't used because they sort the wrong way). + * + * The result is a range of key values that look like this: + * + * n0000000000000000000, ... n9223372036854775807, + * INT64_MIN -1 + * + * o0000000000000000000, + * ZERO + * + * p0000000000000000001, ... p9223372036854775807 + * +1 INT64_MAX + */ +static int ldb_index_format_Integer(struct ldb_context *ldb, + void *mem_ctx, + const struct ldb_val *in, + struct ldb_val *out) +{ + int64_t i; + int ret; + char prefix; + size_t len; + + ret = val_to_int64(in, &i); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (i < 0) { + /* + * i is negative, so this is subtraction rather than + * wrap-around. + */ + prefix = 'n'; + i = INT64_MAX + i + 1; + } else if (i > 0) { + prefix = 'p'; + } else { + prefix = 'o'; + } + + out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%019lld", prefix, (long long)i); + if (out->data == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + len = talloc_array_length(out->data) - 1; + if (len != 20) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + __location__ ": expected index format str %s to" + " have length 20 but got %zu", + (char*)out->data, len); + return LDB_ERR_OPERATIONS_ERROR; + } + + out->length = 20; + return 0; +} + +/* + compare two Integers +*/ +static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + int64_t i1=0, i2=0; + val_to_int64(v1, &i1); + val_to_int64(v2, &i2); + if (i1 == i2) return 0; + return i1 > i2? 1 : -1; +} + +/* + canonicalise a ldap Boolean + rfc2252 specifies it should be either "TRUE" or "FALSE" +*/ +static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + if (in->length >= 4 && strncasecmp((char *)in->data, "TRUE", in->length) == 0) { + out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE"); + out->length = 4; + } else if (in->length >= 5 && strncasecmp((char *)in->data, "FALSE", in->length) == 0) { + out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE"); + out->length = 5; + } else { + return -1; + } + return 0; +} + +/* + compare two Booleans +*/ +static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) { + return v1->length - v2->length; + } + return strncasecmp((char *)v1->data, (char *)v2->data, v1->length); +} + + +/* + compare two binary blobs +*/ +int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) { + return v1->length - v2->length; + } + return memcmp(v1->data, v2->data, v1->length); +} + +/* + compare two case insensitive strings, ignoring multiple whitespaces + and leading and trailing whitespaces + see rfc2252 section 8.1 + + try to optimize for the ascii case, + but if we find out an utf8 codepoint revert to slower but correct function +*/ +int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + const char *s1=(const char *)v1->data, *s2=(const char *)v2->data; + size_t n1 = v1->length, n2 = v2->length; + char *b1, *b2; + const char *u1, *u2; + int ret; + while (n1 && *s1 == ' ') { s1++; n1--; }; + while (n2 && *s2 == ' ') { s2++; n2--; }; + + while (n1 && n2 && *s1 && *s2) { + /* the first 127 (0x7F) chars are ascii and utf8 guarantes they + * never appear in multibyte sequences */ + if (((unsigned char)s1[0]) & 0x80) goto utf8str; + if (((unsigned char)s2[0]) & 0x80) goto utf8str; + if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2)) + break; + if (*s1 == ' ') { + while (n1 && s1[0] == s1[1]) { s1++; n1--; } + while (n2 && s2[0] == s2[1]) { s2++; n2--; } + } + s1++; s2++; + n1--; n2--; + } + + /* check for trailing spaces only if the other pointers has + * reached the end of the strings otherwise we can + * mistakenly match. ex. "domain users" <-> + * "domainUpdates" + */ + if (n1 && *s1 == ' ' && (!n2 || !*s2)) { + while (n1 && *s1 == ' ') { s1++; n1--; } + } + if (n2 && *s2 == ' ' && (!n1 || !*s1)) { + while (n2 && *s2 == ' ') { s2++; n2--; } + } + if (n1 == 0 && n2 != 0) { + return -(int)toupper(*s2); + } + if (n2 == 0 && n1 != 0) { + return (int)toupper(*s1); + } + if (n1 == 0 && n2 == 0) { + return 0; + } + return (int)toupper(*s1) - (int)toupper(*s2); + +utf8str: + /* no need to recheck from the start, just from the first utf8 char found */ + b1 = ldb_casefold(ldb, mem_ctx, s1, n1); + b2 = ldb_casefold(ldb, mem_ctx, s2, n2); + + if (!b1 || !b2) { + /* One of the strings was not UTF8, so we have no + * options but to do a binary compare */ + talloc_free(b1); + talloc_free(b2); + ret = memcmp(s1, s2, MIN(n1, n2)); + if (ret == 0) { + if (n1 == n2) return 0; + if (n1 > n2) { + return (int)toupper(s1[n2]); + } else { + return -(int)toupper(s2[n1]); + } + } + return ret; + } + + u1 = b1; + u2 = b2; + + while (*u1 & *u2) { + if (*u1 != *u2) + break; + if (*u1 == ' ') { + while (u1[0] == u1[1]) u1++; + while (u2[0] == u2[1]) u2++; + } + u1++; u2++; + } + if (! (*u1 && *u2)) { + while (*u1 == ' ') u1++; + while (*u2 == ' ') u2++; + } + ret = (int)(*u1 - *u2); + + talloc_free(b1); + talloc_free(b2); + + return ret; +} + + +/* + canonicalise a attribute in DN format +*/ +static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + struct ldb_dn *dn; + int ret = -1; + + out->length = 0; + out->data = NULL; + + dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in); + if ( ! ldb_dn_validate(dn)) { + return LDB_ERR_INVALID_DN_SYNTAX; + } + + out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn); + if (out->data == NULL) { + goto done; + } + out->length = strlen((char *)out->data); + + ret = 0; + +done: + talloc_free(dn); + + return ret; +} + +/* + compare two dns +*/ +static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + struct ldb_dn *dn1 = NULL, *dn2 = NULL; + int ret; + + dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1); + if ( ! ldb_dn_validate(dn1)) return -1; + + dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2); + if ( ! ldb_dn_validate(dn2)) { + talloc_free(dn1); + return -1; + } + + ret = ldb_dn_compare(dn1, dn2); + + talloc_free(dn1); + talloc_free(dn2); + return ret; +} + +/* + compare two utc time values. 1 second resolution +*/ +static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + time_t t1=0, t2=0; + ldb_val_to_time(v1, &t1); + ldb_val_to_time(v2, &t2); + if (t1 == t2) return 0; + return t1 > t2? 1 : -1; +} + +/* + canonicalise a utc time +*/ +static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + time_t t; + int ret; + ret = ldb_val_to_time(in, &t); + if (ret != LDB_SUCCESS) { + return ret; + } + out->data = (uint8_t *)ldb_timestring_utc(mem_ctx, t); + if (out->data == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + out->length = strlen((char *)out->data); + return 0; +} + +/* + canonicalise a generalized time +*/ +static int ldb_canonicalise_generalizedtime(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + time_t t; + int ret; + ret = ldb_val_to_time(in, &t); + if (ret != LDB_SUCCESS) { + return ret; + } + out->data = (uint8_t *)ldb_timestring(mem_ctx, t); + if (out->data == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + out->length = strlen((char *)out->data); + return 0; +} + +/* + table of standard attribute handlers +*/ +static const struct ldb_schema_syntax ldb_standard_syntaxes[] = { + { + .name = LDB_SYNTAX_INTEGER, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_Integer, + .comparison_fn = ldb_comparison_Integer + }, + { + .name = LDB_SYNTAX_ORDERED_INTEGER, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_Integer, + .index_format_fn = ldb_index_format_Integer, + .comparison_fn = ldb_comparison_Integer + }, + { + .name = LDB_SYNTAX_OCTET_STRING, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_copy, + .comparison_fn = ldb_comparison_binary + }, + { + .name = LDB_SYNTAX_DIRECTORY_STRING, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_fold, + .comparison_fn = ldb_comparison_fold + }, + { + .name = LDB_SYNTAX_DN, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_dn, + .comparison_fn = ldb_comparison_dn + }, + { + .name = LDB_SYNTAX_OBJECTCLASS, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_fold, + .comparison_fn = ldb_comparison_fold + }, + { + .name = LDB_SYNTAX_UTC_TIME, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_utctime, + .comparison_fn = ldb_comparison_utctime + }, + { + .name = LDB_SYNTAX_GENERALIZED_TIME, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_generalizedtime, + .comparison_fn = ldb_comparison_utctime + }, + { + .name = LDB_SYNTAX_BOOLEAN, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_Boolean, + .comparison_fn = ldb_comparison_Boolean + }, +}; + + +/* + return the attribute handlers for a given syntax name +*/ +const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb, + const char *syntax) +{ + unsigned int i; + unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]); + /* TODO: should be replaced with a binary search */ + for (i=0;i. +*/ + +/* + * Name: ldb + * + * Component: ldb core API + * + * Description: core API routines interfacing to ldb backends + * + * Author: Andrew Tridgell + */ + +#define TEVENT_DEPRECATED 1 +#include "ldb_private.h" +#include "ldb.h" + +static int ldb_context_destructor(void *ptr) +{ + struct ldb_context *ldb = talloc_get_type(ptr, struct ldb_context); + + if (ldb->transaction_active) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "A transaction is still active in ldb context [%p] on %s", + ldb, (const char *)ldb_get_opaque(ldb, "ldb_url")); + } + + return 0; +} + +/* + this is used to catch debug messages from events +*/ +static void ldb_tevent_debug(void *context, enum tevent_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + +static void ldb_tevent_debug(void *context, enum tevent_debug_level level, + const char *fmt, va_list ap) +{ + struct ldb_context *ldb = talloc_get_type(context, struct ldb_context); + enum ldb_debug_level ldb_level = LDB_DEBUG_FATAL; + + switch (level) { + case TEVENT_DEBUG_FATAL: + ldb_level = LDB_DEBUG_FATAL; + break; + case TEVENT_DEBUG_ERROR: + ldb_level = LDB_DEBUG_ERROR; + break; + case TEVENT_DEBUG_WARNING: + ldb_level = LDB_DEBUG_WARNING; + break; + case TEVENT_DEBUG_TRACE: + ldb_level = LDB_DEBUG_TRACE; + break; + }; + + /* There isn't a tevent: prefix here because to add it means + * actually printing the string, and most of the time we don't + * want to show it */ + ldb_vdebug(ldb, ldb_level, fmt, ap); +} + +/* + initialise a ldb context + The mem_ctx is required + The event_ctx is required +*/ +struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx) +{ + struct ldb_context *ldb; + int ret; + const char *modules_path = getenv("LDB_MODULES_PATH"); + + if (modules_path == NULL) { + modules_path = LDB_MODULESDIR; + } + + ret = ldb_modules_load(modules_path, LDB_VERSION); + if (ret != LDB_SUCCESS) { + return NULL; + } + + ldb = talloc_zero(mem_ctx, struct ldb_context); + if (ldb == NULL) { + return NULL; + } + + /* A new event context so that callers who don't want ldb + * operating on their global event context can work without + * having to provide their own private one explicitly */ + if (ev_ctx == NULL) { + ev_ctx = tevent_context_init(ldb); + if (ev_ctx == NULL) { + talloc_free(ldb); + return NULL; + } + tevent_set_debug(ev_ctx, ldb_tevent_debug, ldb); + tevent_loop_allow_nesting(ev_ctx); + } + + ret = ldb_setup_wellknown_attributes(ldb); + if (ret != LDB_SUCCESS) { + talloc_free(ldb); + return NULL; + } + + ldb_set_utf8_default(ldb); + ldb_set_create_perms(ldb, 0666); + ldb_set_modules_dir(ldb, LDB_MODULESDIR); + ldb_set_event_context(ldb, ev_ctx); + ret = ldb_register_extended_match_rules(ldb); + if (ret != LDB_SUCCESS) { + talloc_free(ldb); + return NULL; + } + + /* TODO: get timeout from options if available there */ + ldb->default_timeout = 300; /* set default to 5 minutes */ + + talloc_set_destructor((TALLOC_CTX *)ldb, ldb_context_destructor); + + return ldb; +} + +/* + try to autodetect a basedn if none specified. This fixes one of my + pet hates about ldapsearch, which is that you have to get a long, + complex basedn right to make any use of it. +*/ +void ldb_set_default_dns(struct ldb_context *ldb) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_result *res; + struct ldb_dn *tmp_dn=NULL; + static const char *attrs[] = { + "rootDomainNamingContext", + "configurationNamingContext", + "schemaNamingContext", + "defaultNamingContext", + NULL + }; + + tmp_ctx = talloc_new(ldb); + ret = ldb_search(ldb, tmp_ctx, &res, ldb_dn_new(tmp_ctx, ldb, NULL), + LDB_SCOPE_BASE, attrs, "(objectClass=*)"); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return; + } + + if (res->count != 1) { + talloc_free(tmp_ctx); + return; + } + + if (!ldb_get_opaque(ldb, "rootDomainNamingContext")) { + tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], + "rootDomainNamingContext"); + ldb_set_opaque(ldb, "rootDomainNamingContext", tmp_dn); + } + + if (!ldb_get_opaque(ldb, "configurationNamingContext")) { + tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], + "configurationNamingContext"); + ldb_set_opaque(ldb, "configurationNamingContext", tmp_dn); + } + + if (!ldb_get_opaque(ldb, "schemaNamingContext")) { + tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], + "schemaNamingContext"); + ldb_set_opaque(ldb, "schemaNamingContext", tmp_dn); + } + + if (!ldb_get_opaque(ldb, "defaultNamingContext")) { + tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], + "defaultNamingContext"); + ldb_set_opaque(ldb, "defaultNamingContext", tmp_dn); + } + + talloc_free(tmp_ctx); +} + +struct ldb_dn *ldb_get_root_basedn(struct ldb_context *ldb) +{ + void *opaque = ldb_get_opaque(ldb, "rootDomainNamingContext"); + return talloc_get_type(opaque, struct ldb_dn); +} + +struct ldb_dn *ldb_get_config_basedn(struct ldb_context *ldb) +{ + void *opaque = ldb_get_opaque(ldb, "configurationNamingContext"); + return talloc_get_type(opaque, struct ldb_dn); +} + +struct ldb_dn *ldb_get_schema_basedn(struct ldb_context *ldb) +{ + void *opaque = ldb_get_opaque(ldb, "schemaNamingContext"); + return talloc_get_type(opaque, struct ldb_dn); +} + +struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb) +{ + void *opaque = ldb_get_opaque(ldb, "defaultNamingContext"); + return talloc_get_type(opaque, struct ldb_dn); +} + +/* + connect to a database. The URL can either be one of the following forms + ldb://path + ldapi://path + + flags is made up of LDB_FLG_* + + the options are passed uninterpreted to the backend, and are + backend specific +*/ +int ldb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, const char *options[]) +{ + int ret; + char *url2; + /* We seem to need to do this here, or else some utilities don't + * get ldb backends */ + + ldb->flags = flags; + + url2 = talloc_strdup(ldb, url); + if (!url2) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_set_opaque(ldb, "ldb_url", url2); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* + * Take a copy of the options. + */ + ldb->options = ldb_options_copy(ldb, options); + if (ldb->options == NULL && options != NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_module_connect_backend(ldb, url, options, &ldb->modules); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_load_modules(ldb, options); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "Unable to load modules for %s: %s", + url, ldb_errstring(ldb)); + return ret; + } + + /* set the default base dn */ + ldb_set_default_dns(ldb); + + return LDB_SUCCESS; +} + +void ldb_set_errstring(struct ldb_context *ldb, const char *err_string) +{ + ldb_asprintf_errstring(ldb, "%s", 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) { + 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); + } +} + +void ldb_reset_err_string(struct ldb_context *ldb) +{ + if (ldb->err_string) { + talloc_free(ldb->err_string); + ldb->err_string = NULL; + } +} + + + +/* + set an ldb error based on file:line +*/ +int ldb_error_at(struct ldb_context *ldb, int ecode, + const char *reason, const char *file, int line) +{ + if (reason == NULL) { + reason = ldb_strerror(ecode); + } + ldb_asprintf_errstring(ldb, "%s at %s:%d", reason, file, line); + return ecode; +} + + +#define FIRST_OP_NOERR(ldb, op) do { \ + next_module = ldb->modules; \ + while (next_module && next_module->ops->op == NULL) { \ + next_module = next_module->next; \ + }; \ + if ((ldb->flags & LDB_FLG_ENABLE_TRACING) && next_module) { \ + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_trace_request: (%s)->" #op, \ + next_module->ops->name); \ + } \ +} while (0) + +#define FIRST_OP(ldb, op) do { \ + FIRST_OP_NOERR(ldb, op); \ + if (next_module == NULL) { \ + ldb_asprintf_errstring(ldb, "unable to find module or backend to handle operation: " #op); \ + return LDB_ERR_OPERATIONS_ERROR; \ + } \ +} while (0) + + +/* + start a transaction +*/ +int ldb_transaction_start(struct ldb_context *ldb) +{ + struct ldb_module *next_module; + int status; + + ldb_debug(ldb, LDB_DEBUG_TRACE, + "start ldb transaction (nesting: %d)", + ldb->transaction_active); + + /* explicit transaction active, count nested requests */ + if (ldb->transaction_active) { + ldb->transaction_active++; + return LDB_SUCCESS; + } + + /* start a new transaction */ + ldb->transaction_active++; + ldb->prepare_commit_done = false; + + FIRST_OP(ldb, start_transaction); + + ldb_reset_err_string(ldb); + + status = next_module->ops->start_transaction(next_module); + if (status != LDB_SUCCESS) { + if (ldb->err_string == NULL) { + /* no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, + "ldb transaction start: %s (%d)", + ldb_strerror(status), + status); + ldb->transaction_active--; + } + if ((next_module && next_module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(next_module->ldb, LDB_DEBUG_TRACE, "start ldb transaction error: %s", + ldb_errstring(next_module->ldb)); + } + } else { + if ((next_module && next_module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(next_module->ldb, LDB_DEBUG_TRACE, "start ldb transaction success"); + } + } + return status; +} + +/* + prepare for transaction commit (first phase of two phase commit) +*/ +int ldb_transaction_prepare_commit(struct ldb_context *ldb) +{ + struct ldb_module *next_module; + int status; + + if (ldb->prepare_commit_done) { + return LDB_SUCCESS; + } + + /* commit only when all nested transactions are complete */ + if (ldb->transaction_active > 1) { + return LDB_SUCCESS; + } + + ldb->prepare_commit_done = true; + + if (ldb->transaction_active < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "prepare commit called but no ldb transactions are active!"); + ldb->transaction_active = 0; + return LDB_ERR_OPERATIONS_ERROR; + } + + /* call prepare transaction if available */ + FIRST_OP_NOERR(ldb, prepare_commit); + if (next_module == NULL) { + return LDB_SUCCESS; + } + + ldb_reset_err_string(ldb); + + status = next_module->ops->prepare_commit(next_module); + if (status != LDB_SUCCESS) { + ldb->transaction_active--; + /* if a next_module fails the prepare then we need + to call the end transaction for everyone */ + FIRST_OP(ldb, del_transaction); + next_module->ops->del_transaction(next_module); + if (ldb->err_string == NULL) { + /* no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, + "ldb transaction prepare commit: %s (%d)", + ldb_strerror(status), + status); + } + if ((next_module && next_module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(next_module->ldb, LDB_DEBUG_TRACE, "prepare commit transaction error: %s", + ldb_errstring(next_module->ldb)); + } + } + + return status; +} + + +/* + commit a transaction +*/ +int ldb_transaction_commit(struct ldb_context *ldb) +{ + struct ldb_module *next_module; + int status; + + status = ldb_transaction_prepare_commit(ldb); + if (status != LDB_SUCCESS) { + return status; + } + + ldb->transaction_active--; + + ldb_debug(ldb, LDB_DEBUG_TRACE, + "commit ldb transaction (nesting: %d)", + ldb->transaction_active); + + /* commit only when all nested transactions are complete */ + if (ldb->transaction_active > 0) { + return LDB_SUCCESS; + } + + if (ldb->transaction_active < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "commit called but no ldb transactions are active!"); + ldb->transaction_active = 0; + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_reset_err_string(ldb); + + FIRST_OP(ldb, end_transaction); + status = next_module->ops->end_transaction(next_module); + if (status != LDB_SUCCESS) { + if (ldb->err_string == NULL) { + /* no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, + "ldb transaction commit: %s (%d)", + ldb_strerror(status), + status); + } + if ((next_module && next_module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(next_module->ldb, LDB_DEBUG_TRACE, "commit ldb transaction error: %s", + ldb_errstring(next_module->ldb)); + } + } + return status; +} + + +/* + cancel a transaction +*/ +int ldb_transaction_cancel(struct ldb_context *ldb) +{ + struct ldb_module *next_module; + int status; + + ldb->transaction_active--; + + ldb_debug(ldb, LDB_DEBUG_TRACE, + "cancel ldb transaction (nesting: %d)", + ldb->transaction_active); + + /* really cancel only if all nested transactions are complete */ + if (ldb->transaction_active > 0) { + return LDB_SUCCESS; + } + + if (ldb->transaction_active < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "cancel called but no ldb transactions are active!"); + ldb->transaction_active = 0; + return LDB_ERR_OPERATIONS_ERROR; + } + + FIRST_OP(ldb, del_transaction); + + status = next_module->ops->del_transaction(next_module); + if (status != LDB_SUCCESS) { + if (ldb->err_string == NULL) { + /* no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, + "ldb transaction cancel: %s (%d)", + ldb_strerror(status), + status); + } + if ((next_module && next_module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(next_module->ldb, LDB_DEBUG_TRACE, "cancel ldb transaction error: %s", + ldb_errstring(next_module->ldb)); + } + } + return status; +} + +/* + cancel a transaction with no error if no transaction is pending + used when we fork() to clear any parent transactions +*/ +int ldb_transaction_cancel_noerr(struct ldb_context *ldb) +{ + if (ldb->transaction_active > 0) { + return ldb_transaction_cancel(ldb); + } + return LDB_SUCCESS; +} + + +/* autostarts a transaction if none active */ +static int ldb_autotransaction_request(struct ldb_context *ldb, + struct ldb_request *req) +{ + int ret; + + ret = ldb_transaction_start(ldb); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_request(ldb, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret == LDB_SUCCESS) { + return ldb_transaction_commit(ldb); + } + ldb_transaction_cancel(ldb); + + return ret; +} + +int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type) +{ + struct tevent_context *ev; + int ret; + + if (handle == NULL) { + return LDB_ERR_UNAVAILABLE; + } + + if (handle->state == LDB_ASYNC_DONE) { + 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 from %s with LDB_ASYNC_DONE: %s (%d)", + handle->location, + ldb_strerror(handle->status), + handle->status); + } + return handle->status; + } + + ev = ldb_handle_get_event_context(handle); + if (NULL == ev) { + return ldb_oom(handle->ldb); + } + + switch (type) { + case LDB_WAIT_NONE: + ret = tevent_loop_once(ev); + if (ret != 0) { + return ldb_operr(handle->ldb); + } + if (handle->status == LDB_SUCCESS) { + return LDB_SUCCESS; + } + if (handle->ldb->err_string != NULL) { + return handle->status; + } + /* + * 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) { + ret = tevent_loop_once(ev); + if (ret != 0) { + return ldb_operr(handle->ldb); + } + if (handle->status != LDB_SUCCESS) { + if (handle->ldb->err_string != NULL) { + return handle->status; + } + /* + * if no error string was setup by the + * backend + */ + ldb_asprintf_errstring(handle->ldb, + "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; + } + /* + * 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; +} + +/* set the specified timeout or, if timeout is 0 set the default timeout */ +int ldb_set_timeout(struct ldb_context *ldb, + struct ldb_request *req, + int timeout) +{ + if (req == NULL) return LDB_ERR_OPERATIONS_ERROR; + + if (timeout != 0) { + req->timeout = timeout; + } else { + req->timeout = ldb->default_timeout; + } + req->starttime = time(NULL); + + return LDB_SUCCESS; +} + +/* calculates the new timeout based on the previous starttime and timeout */ +int ldb_set_timeout_from_prev_req(struct ldb_context *ldb, + struct ldb_request *oldreq, + struct ldb_request *newreq) +{ + if (newreq == NULL) return LDB_ERR_OPERATIONS_ERROR; + + if (oldreq == NULL) { + return ldb_set_timeout(ldb, newreq, 0); + } + + newreq->starttime = oldreq->starttime; + newreq->timeout = oldreq->timeout; + + return LDB_SUCCESS; +} + + +struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb) +{ + struct ldb_handle *h; + + h = talloc_zero(mem_ctx, struct ldb_handle); + if (h == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return NULL; + } + + h->status = LDB_SUCCESS; + h->state = LDB_ASYNC_INIT; + h->ldb = ldb; + h->flags = 0; + h->location = NULL; + h->parent = NULL; + + if (h->ldb->require_private_event_context == true) { + h->event_context = tevent_context_init(h); + if (h->event_context == NULL) { + ldb_set_errstring(ldb, + "Out of Memory allocating " + "event context for new handle"); + return NULL; + } + tevent_set_debug(h->event_context, ldb_tevent_debug, ldb); + tevent_loop_allow_nesting(h->event_context); + } + + return h; +} + +static struct ldb_handle *ldb_handle_new_child(TALLOC_CTX *mem_ctx, + struct ldb_request *parent_req) +{ + struct ldb_handle *h; + + h = talloc_zero(mem_ctx, struct ldb_handle); + if (h == NULL) { + ldb_set_errstring(parent_req->handle->ldb, + "Out of Memory"); + return NULL; + } + + h->status = LDB_SUCCESS; + h->state = LDB_ASYNC_INIT; + h->ldb = parent_req->handle->ldb; + h->parent = parent_req; + h->nesting = parent_req->handle->nesting + 1; + h->flags = parent_req->handle->flags; + h->custom_flags = parent_req->handle->custom_flags; + h->event_context = parent_req->handle->event_context; + + return h; +} + +/* + set the permissions for new files to be passed to open() in + backends that use local files + */ +void ldb_set_create_perms(struct ldb_context *ldb, unsigned int perms) +{ + ldb->create_perms = perms; +} + +unsigned int ldb_get_create_perms(struct ldb_context *ldb) +{ + return ldb->create_perms; +} + +void ldb_set_event_context(struct ldb_context *ldb, struct tevent_context *ev) +{ + ldb->ev_ctx = ev; +} + +struct tevent_context * ldb_get_event_context(struct ldb_context *ldb) +{ + return ldb->ev_ctx; +} + +void ldb_request_set_state(struct ldb_request *req, int state) +{ + req->handle->state = state; +} + +int ldb_request_get_status(struct ldb_request *req) +{ + return req->handle->status; +} + +/* + * This function obtains the private event context for the handle, + * which may have been created to avoid nested event loops during + * ldb_tdb with the locks held + */ +struct tevent_context *ldb_handle_get_event_context(struct ldb_handle *handle) +{ + if (handle->event_context != NULL) { + return handle->event_context; + } + return ldb_get_event_context(handle->ldb); +} + +/* + * This function forces a specific ldb handle to use the global event + * context. This allows a nested event loop to operate, so any open + * transaction also needs to be aborted. + * + * Any events on this event context will be lost + * + * This is used in Samba when sending an IRPC to another part of the + * same process instead of making a local DB modification. + */ +void ldb_handle_use_global_event_context(struct ldb_handle *handle) +{ + TALLOC_FREE(handle->event_context); +} + +void ldb_set_require_private_event_context(struct ldb_context *ldb) +{ + ldb->require_private_event_context = true; +} + +/* + trace a ldb request +*/ +static void ldb_trace_request(struct ldb_context *ldb, struct ldb_request *req) +{ + TALLOC_CTX *tmp_ctx = talloc_new(req); + unsigned int i; + struct ldb_ldif ldif; + + switch (req->operation) { + case LDB_SEARCH: + ldb_debug_add(ldb, "ldb_trace_request: SEARCH\n"); + ldb_debug_add(ldb, " dn: %s\n", + ldb_dn_is_null(req->op.search.base)?"": + ldb_dn_get_linearized(req->op.search.base)); + ldb_debug_add(ldb, " scope: %s\n", + req->op.search.scope==LDB_SCOPE_BASE?"base": + req->op.search.scope==LDB_SCOPE_ONELEVEL?"one": + req->op.search.scope==LDB_SCOPE_SUBTREE?"sub":"UNKNOWN"); + ldb_debug_add(ldb, " expr: %s\n", + ldb_filter_from_tree(tmp_ctx, req->op.search.tree)); + if (req->op.search.attrs == NULL) { + ldb_debug_add(ldb, " attr: \n"); + } else { + for (i=0; req->op.search.attrs[i]; i++) { + ldb_debug_add(ldb, " attr: %s\n", req->op.search.attrs[i]); + } + } + break; + case LDB_DELETE: + ldb_debug_add(ldb, "ldb_trace_request: DELETE\n"); + ldb_debug_add(ldb, " dn: %s\n", + ldb_dn_get_linearized(req->op.del.dn)); + break; + case LDB_RENAME: + ldb_debug_add(ldb, "ldb_trace_request: RENAME\n"); + ldb_debug_add(ldb, " olddn: %s\n", + ldb_dn_get_linearized(req->op.rename.olddn)); + ldb_debug_add(ldb, " newdn: %s\n", + ldb_dn_get_linearized(req->op.rename.newdn)); + break; + case LDB_EXTENDED: + ldb_debug_add(ldb, "ldb_trace_request: EXTENDED\n"); + ldb_debug_add(ldb, " oid: %s\n", req->op.extended.oid); + ldb_debug_add(ldb, " data: %s\n", req->op.extended.data?"yes":"no"); + break; + case LDB_ADD: + ldif.changetype = LDB_CHANGETYPE_ADD; + ldif.msg = discard_const_p(struct ldb_message, req->op.add.message); + + ldb_debug_add(ldb, "ldb_trace_request: ADD\n"); + + /* + * The choice to call + * ldb_ldif_write_redacted_trace_string() is CRITICAL + * for security. It ensures that we do not output + * passwords into debug logs + */ + + ldb_debug_add(req->handle->ldb, "%s\n", + ldb_ldif_write_redacted_trace_string(req->handle->ldb, tmp_ctx, &ldif)); + break; + case LDB_MODIFY: + ldif.changetype = LDB_CHANGETYPE_MODIFY; + ldif.msg = discard_const_p(struct ldb_message, req->op.mod.message); + + ldb_debug_add(ldb, "ldb_trace_request: MODIFY\n"); + + /* + * The choice to call + * ldb_ldif_write_redacted_trace_string() is CRITICAL + * for security. It ensures that we do not output + * passwords into debug logs + */ + + ldb_debug_add(req->handle->ldb, "%s\n", + ldb_ldif_write_redacted_trace_string(req->handle->ldb, tmp_ctx, &ldif)); + break; + case LDB_REQ_REGISTER_CONTROL: + ldb_debug_add(ldb, "ldb_trace_request: REGISTER_CONTROL\n"); + ldb_debug_add(req->handle->ldb, "%s\n", + req->op.reg_control.oid); + break; + case LDB_REQ_REGISTER_PARTITION: + ldb_debug_add(ldb, "ldb_trace_request: REGISTER_PARTITION\n"); + ldb_debug_add(req->handle->ldb, "%s\n", + ldb_dn_get_linearized(req->op.reg_partition.dn)); + break; + default: + ldb_debug_add(ldb, "ldb_trace_request: UNKNOWN(%u)\n", + req->operation); + break; + } + + if (req->controls == NULL) { + ldb_debug_add(ldb, " control: \n"); + } else { + for (i=0; req->controls && req->controls[i]; i++) { + if (req->controls[i]->oid) { + ldb_debug_add(ldb, " control: %s crit:%u data:%s\n", + req->controls[i]->oid, + req->controls[i]->critical, + req->controls[i]->data?"yes":"no"); + } + } + } + + ldb_debug_end(ldb, LDB_DEBUG_TRACE); + + talloc_free(tmp_ctx); +} + +/* + check that the element flags don't have any internal bits set + */ +static int ldb_msg_check_element_flags(struct ldb_context *ldb, + const struct ldb_message *message) +{ + unsigned i; + for (i=0; inum_elements; i++) { + if (message->elements[i].flags & LDB_FLAG_INTERNAL_MASK) { + ldb_asprintf_errstring(ldb, "Invalid element flags 0x%08x on element %s in %s\n", + message->elements[i].flags, message->elements[i].name, + ldb_dn_get_linearized(message->dn)); + return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; + } + } + return LDB_SUCCESS; +} + +/* + * This context allows us to make the unlock be a talloc destructor + * + * This ensures that a request started, but not waited on, will still + * unlock. + */ +struct ldb_db_lock_context { + struct ldb_request *req; + struct ldb_context *ldb; +}; + +/* + * We have to have a the unlock on a destructor so that we unlock the + * DB if a caller calls talloc_free(req). We trust that the ldb + * context has not already gone away. + */ +static int ldb_db_lock_destructor(struct ldb_db_lock_context *lock_context) +{ + int ret; + struct ldb_module *next_module; + FIRST_OP_NOERR(lock_context->ldb, read_unlock); + if (next_module != NULL) { + ret = next_module->ops->read_unlock(next_module); + } else { + ret = LDB_SUCCESS; + } + + if (ret != LDB_SUCCESS) { + ldb_debug(lock_context->ldb, + LDB_DEBUG_FATAL, + "Failed to unlock db: %s / %s", + ldb_errstring(lock_context->ldb), + ldb_strerror(ret)); + } + return 0; +} + +static int ldb_lock_backend_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_db_lock_context *lock_context; + int ret; + + lock_context = talloc_get_type(req->context, + struct ldb_db_lock_context); + + if (!ares) { + return ldb_module_done(lock_context->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) { + ret = ldb_module_done(lock_context->req, ares->controls, + ares->response, ares->error); + /* + * If this is a LDB_REPLY_DONE or an error, unlock the + * DB by calling the destructor on this context + */ + talloc_free(lock_context); + return ret; + } + + /* Otherwise pass on the callback */ + switch (ares->type) { + case LDB_REPLY_ENTRY: + return ldb_module_send_entry(lock_context->req, ares->message, + ares->controls); + + case LDB_REPLY_REFERRAL: + return ldb_module_send_referral(lock_context->req, + ares->referral); + default: + /* Can't happen */ + return LDB_ERR_OPERATIONS_ERROR; + } +} + +/* + * Do an ldb_search() with a lock held, but release it if the request + * is freed with talloc_free() + */ +static int lock_search(struct ldb_module *lock_module, struct ldb_request *req) +{ + /* Used in FIRST_OP_NOERR to find where to send the lock request */ + struct ldb_module *next_module = NULL; + struct ldb_request *down_req = NULL; + struct ldb_db_lock_context *lock_context; + struct ldb_context *ldb = ldb_module_get_ctx(lock_module); + int ret; + + lock_context = talloc(req, struct ldb_db_lock_context); + if (lock_context == NULL) { + return ldb_oom(ldb); + } + + lock_context->ldb = ldb; + lock_context->req = req; + + ret = ldb_build_search_req_ex(&down_req, ldb, req, + req->op.search.base, + req->op.search.scope, + req->op.search.tree, + req->op.search.attrs, + req->controls, + lock_context, + ldb_lock_backend_callback, + req); + LDB_REQ_SET_LOCATION(down_req); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* call DB lock */ + FIRST_OP_NOERR(ldb, read_lock); + if (next_module != NULL) { + ret = next_module->ops->read_lock(next_module); + } else { + ret = LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; + } + + if (ret == LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION) { + /* We might be talking LDAP */ + ldb_reset_err_string(ldb); + TALLOC_FREE(lock_context); + + return ldb_next_request(lock_module, req); + } else if ((ret != LDB_SUCCESS) && (ldb->err_string == NULL)) { + /* if no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, "Failed to get DB lock: %s (%d)", + ldb_strerror(ret), ret); + } else { + talloc_set_destructor(lock_context, ldb_db_lock_destructor); + } + + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_next_request(lock_module, down_req); +} + +/* + start an ldb request + NOTE: the request must be a talloc context. + returns LDB_ERR_* on errors. +*/ +int ldb_request(struct ldb_context *ldb, struct ldb_request *req) +{ + struct ldb_module *next_module; + int ret; + + if (req->callback == NULL) { + ldb_set_errstring(ldb, "Requests MUST define callbacks"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + ldb_reset_err_string(ldb); + + if (ldb->flags & LDB_FLG_ENABLE_TRACING) { + ldb_trace_request(ldb, req); + } + + /* call the first module in the chain */ + switch (req->operation) { + case LDB_SEARCH: + { + /* + * A fake module to allow ldb_next_request() to be + * re-used and to keep the locking out of this function. + */ + static const struct ldb_module_ops lock_module_ops = { + .name = "lock_searches", + .search = lock_search + }; + struct ldb_module lock_module = { + .ldb = ldb, + .next = ldb->modules, + .ops = &lock_module_ops + }; + next_module = &lock_module; + + /* due to "ldb_build_search_req" base DN always != NULL */ + if (!ldb_dn_validate(req->op.search.base)) { + ldb_asprintf_errstring(ldb, "ldb_search: invalid basedn '%s'", + ldb_dn_get_linearized(req->op.search.base)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + + ret = next_module->ops->search(next_module, req); + break; + } + case LDB_ADD: + if (!ldb_dn_validate(req->op.add.message->dn)) { + ldb_asprintf_errstring(ldb, "ldb_add: invalid dn '%s'", + ldb_dn_get_linearized(req->op.add.message->dn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + /* + * we have to normalize here, as so many places + * in modules and backends assume we don't have two + * elements with the same name + */ + ret = ldb_msg_normalize(ldb, req, req->op.add.message, + discard_const(&req->op.add.message)); + if (ret != LDB_SUCCESS) { + ldb_oom(ldb); + return ret; + } + FIRST_OP(ldb, add); + ret = ldb_msg_check_element_flags(ldb, req->op.add.message); + if (ret != LDB_SUCCESS) { + /* + * "ldb_msg_check_element_flags" generates an error + * string + */ + return ret; + } + ret = next_module->ops->add(next_module, req); + break; + case LDB_MODIFY: + if (!ldb_dn_validate(req->op.mod.message->dn)) { + ldb_asprintf_errstring(ldb, "ldb_modify: invalid dn '%s'", + ldb_dn_get_linearized(req->op.mod.message->dn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + FIRST_OP(ldb, modify); + ret = ldb_msg_check_element_flags(ldb, req->op.mod.message); + if (ret != LDB_SUCCESS) { + /* + * "ldb_msg_check_element_flags" generates an error + * string + */ + return ret; + } + ret = next_module->ops->modify(next_module, req); + break; + case LDB_DELETE: + if (!ldb_dn_validate(req->op.del.dn)) { + ldb_asprintf_errstring(ldb, "ldb_delete: invalid dn '%s'", + ldb_dn_get_linearized(req->op.del.dn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + FIRST_OP(ldb, del); + ret = next_module->ops->del(next_module, req); + break; + case LDB_RENAME: + if (!ldb_dn_validate(req->op.rename.olddn)) { + ldb_asprintf_errstring(ldb, "ldb_rename: invalid olddn '%s'", + ldb_dn_get_linearized(req->op.rename.olddn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + if (!ldb_dn_validate(req->op.rename.newdn)) { + ldb_asprintf_errstring(ldb, "ldb_rename: invalid newdn '%s'", + ldb_dn_get_linearized(req->op.rename.newdn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + FIRST_OP(ldb, rename); + ret = next_module->ops->rename(next_module, req); + break; + case LDB_EXTENDED: + FIRST_OP(ldb, extended); + ret = next_module->ops->extended(next_module, req); + break; + default: + FIRST_OP(ldb, request); + ret = next_module->ops->request(next_module, req); + break; + } + + if ((ret != LDB_SUCCESS) && (ldb->err_string == NULL)) { + /* if no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, "ldb_request: %s (%d)", + ldb_strerror(ret), ret); + } + + return ret; +} + +int ldb_request_done(struct ldb_request *req, int status) +{ + req->handle->state = LDB_ASYNC_DONE; + req->handle->status = status; + return status; +} + +/* + search the database given a LDAP-like search expression + + returns an LDB error code + + Use talloc_free to free the ldb_message returned in 'res', if successful + +*/ +int ldb_search_default_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_result *res; + unsigned int n; + + res = talloc_get_type(req->context, struct ldb_result); + + if (!ares) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_request_done(req, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + res->msgs = talloc_realloc(res, res->msgs, + struct ldb_message *, res->count + 2); + if (! res->msgs) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + res->msgs[res->count + 1] = NULL; + + res->msgs[res->count] = talloc_move(res->msgs, &ares->message); + res->count++; + break; + + case LDB_REPLY_REFERRAL: + if (res->refs) { + for (n = 0; res->refs[n]; n++) /*noop*/ ; + } else { + n = 0; + } + + res->refs = talloc_realloc(res, res->refs, char *, n + 2); + if (! res->refs) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + res->refs[n] = talloc_move(res->refs, &ares->referral); + res->refs[n + 1] = NULL; + break; + + case LDB_REPLY_DONE: + /* TODO: we should really support controls on entries + * and referrals too! */ + res->controls = talloc_move(res, &ares->controls); + + /* this is the last message, and means the request is done */ + /* we have to signal and eventual ldb_wait() waiting that the + * async request operation was completed */ + talloc_free(ares); + return ldb_request_done(req, LDB_SUCCESS); + } + + talloc_free(ares); + + return LDB_SUCCESS; +} + +int ldb_modify_default_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_result *res; + unsigned int n; + int ret; + + res = talloc_get_type(req->context, struct ldb_result); + + if (!ares) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->error != LDB_SUCCESS) { + ret = ares->error; + talloc_free(ares); + return ldb_request_done(req, ret); + } + + switch (ares->type) { + case LDB_REPLY_REFERRAL: + if (res->refs) { + for (n = 0; res->refs[n]; n++) /*noop*/ ; + } else { + n = 0; + } + + res->refs = talloc_realloc(res, res->refs, char *, n + 2); + if (! res->refs) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + res->refs[n] = talloc_move(res->refs, &ares->referral); + res->refs[n + 1] = NULL; + break; + + case LDB_REPLY_DONE: + talloc_free(ares); + return ldb_request_done(req, LDB_SUCCESS); + default: + talloc_free(ares); + ldb_asprintf_errstring(req->handle->ldb, "Invalid LDB reply type %d", ares->type); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + talloc_free(ares); + return ldb_request_done(req, LDB_SUCCESS); +} + +int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + int ret; + + if (!ares) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->error != LDB_SUCCESS) { + ret = ares->error; + talloc_free(ares); + return ldb_request_done(req, ret); + } + + if (ares->type != LDB_REPLY_DONE) { + talloc_free(ares); + ldb_asprintf_errstring(req->handle->ldb, "Invalid LDB reply type %d", ares->type); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + talloc_free(ares); + return ldb_request_done(req, LDB_SUCCESS); +} + +static struct ldb_request *ldb_build_req_common(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_request *req = NULL; + + req = talloc_zero(mem_ctx, struct ldb_request); + if (req == NULL) { + return NULL; + } + req->controls = controls; + req->context = context; + req->callback = callback; + + ldb_set_timeout_from_prev_req(ldb, parent, req); + + if (parent != NULL) { + req->handle = ldb_handle_new_child(req, parent); + if (req->handle == NULL) { + TALLOC_FREE(req); + return NULL; + } + } else { + req->handle = ldb_handle_new(req, ldb); + if (req->handle == NULL) { + TALLOC_FREE(req); + return NULL; + } + } + + return req; +} + +int ldb_build_search_req_ex(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const *attrs, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_request *req; + + *ret_req = NULL; + + req = ldb_build_req_common(mem_ctx, ldb, controls, + context, callback, parent); + if (req == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_SEARCH; + if (base == NULL) { + req->op.search.base = ldb_dn_new(req, ldb, NULL); + } else { + req->op.search.base = base; + } + req->op.search.scope = scope; + + req->op.search.tree = tree; + if (req->op.search.tree == NULL) { + ldb_set_errstring(ldb, "'tree' can't be NULL"); + talloc_free(req); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->op.search.attrs = attrs; + *ret_req = req; + return LDB_SUCCESS; +} + +int ldb_build_search_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *base, + enum ldb_scope scope, + const char *expression, + const char * const *attrs, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_parse_tree *tree; + int ret; + + tree = ldb_parse_tree(mem_ctx, expression); + if (tree == NULL) { + ldb_set_errstring(ldb, "Unable to parse search expression"); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_build_search_req_ex(ret_req, ldb, mem_ctx, base, + scope, tree, attrs, controls, + context, callback, parent); + if (ret == LDB_SUCCESS) { + talloc_steal(*ret_req, tree); + } + return ret; +} + +int ldb_build_add_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *message, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_request *req; + + *ret_req = NULL; + + req = ldb_build_req_common(mem_ctx, ldb, controls, + context, callback, parent); + if (req == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_ADD; + req->op.add.message = message; + *ret_req = req; + return LDB_SUCCESS; +} + +int ldb_build_mod_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *message, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_request *req; + + *ret_req = NULL; + + req = ldb_build_req_common(mem_ctx, ldb, controls, + context, callback, parent); + if (req == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_MODIFY; + req->op.mod.message = message; + + *ret_req = req; + return LDB_SUCCESS; +} + +int ldb_build_del_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_request *req; + + *ret_req = NULL; + + req = ldb_build_req_common(mem_ctx, ldb, controls, + context, callback, parent); + if (req == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_DELETE; + req->op.del.dn = dn; + *ret_req = req; + return LDB_SUCCESS; +} + +int ldb_build_rename_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *olddn, + struct ldb_dn *newdn, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_request *req; + + *ret_req = NULL; + + req = ldb_build_req_common(mem_ctx, ldb, controls, + context, callback, parent); + if (req == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_RENAME; + req->op.rename.olddn = olddn; + req->op.rename.newdn = newdn; + *ret_req = req; + return LDB_SUCCESS; +} + +int ldb_extended_default_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_result *res; + + res = talloc_get_type(req->context, struct ldb_result); + + if (!ares) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_request_done(req, ares->error); + } + + if (ares->type == LDB_REPLY_DONE) { + + /* TODO: we should really support controls on entries and referrals too! */ + res->extended = talloc_move(res, &ares->response); + res->controls = talloc_move(res, &ares->controls); + + talloc_free(ares); + return ldb_request_done(req, LDB_SUCCESS); + } + + talloc_free(ares); + ldb_asprintf_errstring(req->handle->ldb, "Invalid LDB reply type %d", ares->type); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); +} + +int ldb_build_extended_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *oid, + void *data, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent) +{ + struct ldb_request *req; + + *ret_req = NULL; + + req = ldb_build_req_common(mem_ctx, ldb, controls, + context, callback, parent); + if (req == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_EXTENDED; + req->op.extended.oid = oid; + req->op.extended.data = data; + *ret_req = req; + return LDB_SUCCESS; +} + +int ldb_extended(struct ldb_context *ldb, + const char *oid, + void *data, + struct ldb_result **_res) +{ + struct ldb_request *req; + int ret; + struct ldb_result *res; + + *_res = NULL; + req = NULL; + + res = talloc_zero(ldb, struct ldb_result); + if (!res) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_build_extended_req(&req, ldb, ldb, + oid, data, NULL, + res, ldb_extended_default_callback, + NULL); + ldb_req_set_location(req, "ldb_extended"); + + if (ret != LDB_SUCCESS) goto done; + + ldb_set_timeout(ldb, req, 0); /* use default timeout */ + + ret = ldb_request(ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + +done: + if (ret != LDB_SUCCESS) { + talloc_free(res); + res = NULL; + } + + talloc_free(req); + + *_res = res; + return ret; +} + +/* + note that ldb_search() will automatically replace a NULL 'base' value + with the defaultNamingContext from the rootDSE if available. +*/ +int ldb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + struct ldb_result **result, struct ldb_dn *base, + enum ldb_scope scope, const char * const *attrs, + const char *exp_fmt, ...) +{ + struct ldb_request *req; + struct ldb_result *res; + char *expression; + va_list ap; + int ret; + + expression = NULL; + *result = NULL; + req = NULL; + + res = talloc_zero(mem_ctx, struct ldb_result); + if (!res) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (exp_fmt) { + va_start(ap, exp_fmt); + expression = talloc_vasprintf(mem_ctx, exp_fmt, ap); + va_end(ap); + + if (!expression) { + talloc_free(res); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + ret = ldb_build_search_req(&req, ldb, mem_ctx, + base?base:ldb_get_default_basedn(ldb), + scope, + expression, + attrs, + NULL, + res, + ldb_search_default_callback, + NULL); + ldb_req_set_location(req, "ldb_search"); + + if (ret != LDB_SUCCESS) goto done; + + ret = ldb_request(ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + +done: + if (ret != LDB_SUCCESS) { + talloc_free(res); + res = NULL; + } + + talloc_free(expression); + talloc_free(req); + + *result = res; + return ret; +} + +/* + add a record to the database. Will fail if a record with the given class + and key already exists +*/ +int ldb_add(struct ldb_context *ldb, + const struct ldb_message *message) +{ + struct ldb_request *req; + int ret; + + ret = ldb_msg_sanity_check(ldb, message); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_add_req(&req, ldb, ldb, + message, + NULL, + NULL, + ldb_op_default_callback, + NULL); + ldb_req_set_location(req, "ldb_add"); + + if (ret != LDB_SUCCESS) return ret; + + /* do request and autostart a transaction */ + ret = ldb_autotransaction_request(ldb, req); + + talloc_free(req); + return ret; +} + +/* + modify the specified attributes of a record +*/ +int ldb_modify(struct ldb_context *ldb, + const struct ldb_message *message) +{ + struct ldb_request *req; + int ret; + + ret = ldb_msg_sanity_check(ldb, message); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_mod_req(&req, ldb, ldb, + message, + NULL, + NULL, + ldb_op_default_callback, + NULL); + ldb_req_set_location(req, "ldb_modify"); + + if (ret != LDB_SUCCESS) return ret; + + /* do request and autostart a transaction */ + ret = ldb_autotransaction_request(ldb, req); + + talloc_free(req); + return ret; +} + + +/* + delete a record from the database +*/ +int ldb_delete(struct ldb_context *ldb, struct ldb_dn *dn) +{ + struct ldb_request *req; + int ret; + + ret = ldb_build_del_req(&req, ldb, ldb, + dn, + NULL, + NULL, + ldb_op_default_callback, + NULL); + ldb_req_set_location(req, "ldb_delete"); + + if (ret != LDB_SUCCESS) return ret; + + /* do request and autostart a transaction */ + ret = ldb_autotransaction_request(ldb, req); + + talloc_free(req); + return ret; +} + +/* + rename a record in the database +*/ +int ldb_rename(struct ldb_context *ldb, + struct ldb_dn *olddn, struct ldb_dn *newdn) +{ + struct ldb_request *req; + int ret; + + ret = ldb_build_rename_req(&req, ldb, ldb, + olddn, + newdn, + NULL, + NULL, + ldb_op_default_callback, + NULL); + ldb_req_set_location(req, "ldb_rename"); + + if (ret != LDB_SUCCESS) return ret; + + /* do request and autostart a transaction */ + ret = ldb_autotransaction_request(ldb, req); + + talloc_free(req); + return ret; +} + + +/* + return the global sequence number +*/ +int ldb_sequence_number(struct ldb_context *ldb, + enum ldb_sequence_type type, uint64_t *seq_num) +{ + struct ldb_seqnum_request *seq; + struct ldb_seqnum_result *seqr; + struct ldb_result *res; + TALLOC_CTX *tmp_ctx; + int ret; + + *seq_num = 0; + + tmp_ctx = talloc_zero(ldb, struct ldb_request); + if (tmp_ctx == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + seq = talloc_zero(tmp_ctx, struct ldb_seqnum_request); + if (seq == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + seq->type = type; + + ret = ldb_extended(ldb, LDB_EXTENDED_SEQUENCE_NUMBER, seq, &res); + if (ret != LDB_SUCCESS) { + goto done; + } + talloc_steal(tmp_ctx, res); + + if (strcmp(LDB_EXTENDED_SEQUENCE_NUMBER, res->extended->oid) != 0) { + ldb_set_errstring(ldb, "Invalid OID in reply"); + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + seqr = talloc_get_type(res->extended->data, + struct ldb_seqnum_result); + *seq_num = seqr->seq_num; + +done: + talloc_free(tmp_ctx); + return ret; +} + +/* + return extended error information +*/ +const char *ldb_errstring(struct ldb_context *ldb) +{ + if (ldb->err_string) { + return ldb->err_string; + } + + return NULL; +} + +/* + return a string explaining what a ldb error constant meancs +*/ +const char *ldb_strerror(int ldb_err) +{ + switch (ldb_err) { + case LDB_SUCCESS: + return "Success"; + case LDB_ERR_OPERATIONS_ERROR: + return "Operations error"; + case LDB_ERR_PROTOCOL_ERROR: + return "Protocol error"; + case LDB_ERR_TIME_LIMIT_EXCEEDED: + return "Time limit exceeded"; + case LDB_ERR_SIZE_LIMIT_EXCEEDED: + return "Size limit exceeded"; + case LDB_ERR_COMPARE_FALSE: + return "Compare false"; + case LDB_ERR_COMPARE_TRUE: + return "Compare true"; + case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED: + return "Auth method not supported"; + case LDB_ERR_STRONG_AUTH_REQUIRED: + return "Strong auth required"; +/* 9 RESERVED */ + case LDB_ERR_REFERRAL: + return "Referral error"; + case LDB_ERR_ADMIN_LIMIT_EXCEEDED: + return "Admin limit exceeded"; + case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION: + return "Unsupported critical extension"; + case LDB_ERR_CONFIDENTIALITY_REQUIRED: + return "Confidentiality required"; + case LDB_ERR_SASL_BIND_IN_PROGRESS: + return "SASL bind in progress"; + case LDB_ERR_NO_SUCH_ATTRIBUTE: + return "No such attribute"; + case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE: + return "Undefined attribute type"; + case LDB_ERR_INAPPROPRIATE_MATCHING: + return "Inappropriate matching"; + case LDB_ERR_CONSTRAINT_VIOLATION: + return "Constraint violation"; + case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS: + return "Attribute or value exists"; + case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX: + return "Invalid attribute syntax"; +/* 22-31 unused */ + case LDB_ERR_NO_SUCH_OBJECT: + return "No such object"; + case LDB_ERR_ALIAS_PROBLEM: + return "Alias problem"; + case LDB_ERR_INVALID_DN_SYNTAX: + return "Invalid DN syntax"; +/* 35 RESERVED */ + case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM: + return "Alias dereferencing problem"; +/* 37-47 unused */ + case LDB_ERR_INAPPROPRIATE_AUTHENTICATION: + return "Inappropriate authentication"; + case LDB_ERR_INVALID_CREDENTIALS: + return "Invalid credentials"; + case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: + return "insufficient access rights"; + case LDB_ERR_BUSY: + return "Busy"; + case LDB_ERR_UNAVAILABLE: + return "Unavailable"; + case LDB_ERR_UNWILLING_TO_PERFORM: + return "Unwilling to perform"; + case LDB_ERR_LOOP_DETECT: + return "Loop detect"; +/* 55-63 unused */ + case LDB_ERR_NAMING_VIOLATION: + return "Naming violation"; + case LDB_ERR_OBJECT_CLASS_VIOLATION: + return "Object class violation"; + case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF: + return "Not allowed on non-leaf"; + case LDB_ERR_NOT_ALLOWED_ON_RDN: + return "Not allowed on RDN"; + case LDB_ERR_ENTRY_ALREADY_EXISTS: + return "Entry already exists"; + case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED: + return "Object class mods prohibited"; +/* 70 RESERVED FOR CLDAP */ + case LDB_ERR_AFFECTS_MULTIPLE_DSAS: + return "Affects multiple DSAs"; +/* 72-79 unused */ + case LDB_ERR_OTHER: + return "Other"; + } + + return "Unknown error"; +} + +/* + set backend specific opaque parameters +*/ +int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value) +{ + struct ldb_opaque *o; + + /* allow updating an existing value */ + for (o=ldb->opaque;o;o=o->next) { + if (strcmp(o->name, name) == 0) { + o->value = value; + return LDB_SUCCESS; + } + } + + o = talloc(ldb, struct ldb_opaque); + if (o == NULL) { + ldb_oom(ldb); + return LDB_ERR_OTHER; + } + o->next = ldb->opaque; + o->name = name; + o->value = value; + ldb->opaque = o; + return LDB_SUCCESS; +} + +/* + get a previously set opaque value +*/ +void *ldb_get_opaque(struct ldb_context *ldb, const char *name) +{ + struct ldb_opaque *o; + for (o=ldb->opaque;o;o=o->next) { + if (strcmp(o->name, name) == 0) { + return o->value; + } + } + return NULL; +} + +int ldb_global_init(void) +{ + /* Provided for compatibility with some older versions of ldb */ + return 0; +} + +/* return the ldb flags */ +unsigned int ldb_get_flags(struct ldb_context *ldb) +{ + return ldb->flags; +} + +/* set the ldb flags */ +void ldb_set_flags(struct ldb_context *ldb, unsigned flags) +{ + ldb->flags = flags; +} + + +/* + set the location in a ldb request. Used for debugging + */ +void ldb_req_set_location(struct ldb_request *req, const char *location) +{ + if (req && req->handle) { + req->handle->location = location; + } +} + +/* + return the location set with dsdb_req_set_location + */ +const char *ldb_req_location(struct ldb_request *req) +{ + return req->handle->location; +} + +/** + mark a request as untrusted. This tells the rootdse module to remove + unregistered controls + */ +void ldb_req_mark_untrusted(struct ldb_request *req) +{ + req->handle->flags |= LDB_HANDLE_FLAG_UNTRUSTED; +} + +/** + mark a request as trusted. + */ +void ldb_req_mark_trusted(struct ldb_request *req) +{ + req->handle->flags &= ~LDB_HANDLE_FLAG_UNTRUSTED; +} + +/** + set custom flags. Those flags are set by applications using ldb, + they are application dependent and the same bit can have different + meaning in different application. + */ +void ldb_req_set_custom_flags(struct ldb_request *req, uint32_t flags) +{ + if (req != NULL && req->handle != NULL) { + req->handle->custom_flags = flags; + } +} + + +/** + get custom flags. Those flags are set by applications using ldb, + they are application dependent and the same bit can have different + meaning in different application. + */ +uint32_t ldb_req_get_custom_flags(struct ldb_request *req) +{ + if (req != NULL && req->handle != NULL) { + return req->handle->custom_flags; + } + + /* + * 0 is not something any better or worse than + * anything else as req or the handle is NULL + */ + return 0; +} + + +/** + * return true if a request is untrusted + */ +bool ldb_req_is_untrusted(struct ldb_request *req) +{ + return (req->handle->flags & LDB_HANDLE_FLAG_UNTRUSTED) != 0; +} diff --git a/ldb-2.0.8/common/ldb_attributes.c b/ldb-2.0.8/common/ldb_attributes.c new file mode 100644 index 0000000..32f25fd --- /dev/null +++ b/ldb-2.0.8/common/ldb_attributes.c @@ -0,0 +1,411 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ +/* + register handlers for specific attributes and objectclass relationships + + this allows a backend to store its schema information in any format + it likes (or to not have any schema information at all) while keeping the + message matching logic generic +*/ + +#include "ldb_private.h" +#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 + 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_add_with_syntax(struct ldb_context *ldb, + const char *attribute, + unsigned flags, + const struct ldb_schema_syntax *syntax) +{ + unsigned int i, n; + struct ldb_schema_attribute *a; + + if (!syntax) { + return LDB_ERR_OPERATIONS_ERROR; + } + + n = ldb->schema.num_attributes + 1; + + a = talloc_realloc(ldb, ldb->schema.attributes, + struct ldb_schema_attribute, n); + if (a == NULL) { + ldb_oom(ldb); + return -1; + } + ldb->schema.attributes = a; + + for (i = 0; i < ldb->schema.num_attributes; i++) { + int cmp = ldb_attr_cmp(attribute, a[i].name); + if (cmp == 0) { + /* silently ignore attempts to overwrite fixed attributes */ + if (a[i].flags & LDB_ATTR_FLAG_FIXED) { + return 0; + } + if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) { + talloc_free(discard_const_p(char, a[i].name)); + } + /* To cancel out increment below */ + ldb->schema.num_attributes--; + break; + } else if (cmp < 0) { + memmove(a+i+1, a+i, sizeof(*a) * (ldb->schema.num_attributes-i)); + break; + } + } + ldb->schema.num_attributes++; + + a[i].name = attribute; + a[i].flags = flags; + a[i].syntax = syntax; + + if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) { + a[i].name = talloc_strdup(a, a[i].name); + if (a[i].name == NULL) { + ldb_oom(ldb); + return -1; + } + } + + return 0; +} + +static const struct ldb_schema_syntax ldb_syntax_default = { + .name = LDB_SYNTAX_OCTET_STRING, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_copy, + .comparison_fn = ldb_comparison_binary +}; + +static const struct ldb_schema_attribute ldb_attribute_default = { + .name = NULL, + .flags = 0, + .syntax = &ldb_syntax_default +}; + +/* + * Return the attribute handlers for a given attribute + * + * @param ldb ldb context + * @param name attribute name to search for + * @return Always return valid pointer to schema attribute. + * In case there is no attribute with name, + * ldb_attribute_default is returned + */ +static const struct ldb_schema_attribute *ldb_schema_attribute_by_name_internal( + struct ldb_context *ldb, + const char *name) +{ + /* for binary search we need signed variables */ + unsigned int i, e, b = 0; + int r; + const struct ldb_schema_attribute *def = &ldb_attribute_default; + + /* fallback to default attribute implementation */ + if (name == NULL) { + return def; + } + + /* as handlers are sorted, '*' must be the first if present */ + if (strcmp(ldb->schema.attributes[0].name, "*") == 0) { + def = &ldb->schema.attributes[0]; + b = 1; + } + + /* do a binary search on the array */ + e = ldb->schema.num_attributes - 1; + + while ((b <= e) && (e != (unsigned int) -1)) { + i = (b + e) / 2; + + r = ldb_attr_cmp(name, ldb->schema.attributes[i].name); + if (r == 0) { + return &ldb->schema.attributes[i]; + } + if (r < 0) { + e = i - 1; + } else { + b = i + 1; + } + } + + return def; +} + +/* + return the attribute handlers for a given attribute +*/ +const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb, + const char *name) +{ + if (ldb->schema.attribute_handler_override) { + const struct ldb_schema_attribute *ret = + ldb->schema.attribute_handler_override(ldb, + ldb->schema.attribute_handler_override_private, + name); + if (ret) { + return ret; + } + } + + return ldb_schema_attribute_by_name_internal(ldb, name); +} + + +/* + add to the list of ldif handlers for this ldb context +*/ +void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name) +{ + const struct ldb_schema_attribute *a; + ptrdiff_t i; + + a = ldb_schema_attribute_by_name_internal(ldb, name); + if (a == NULL || a->name == NULL) { + return; + } + + /* FIXED attributes are never removed */ + if (a->flags & LDB_ATTR_FLAG_FIXED) { + return; + } + + if (a->flags & LDB_ATTR_FLAG_ALLOCATED) { + talloc_free(discard_const_p(char, a->name)); + } + + i = a - ldb->schema.attributes; + 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--; +} + +/* + 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, + const char *attribute, + unsigned flags, + const char *syntax) +{ + const struct ldb_schema_syntax *s = ldb_standard_syntax_by_name(ldb, syntax); + return ldb_schema_attribute_add_with_syntax(ldb, attribute, flags, s); +} + +/* + setup the attribute handles for well known attributes +*/ +int ldb_setup_wellknown_attributes(struct ldb_context *ldb) +{ + const struct { + const char *attr; + const char *syntax; + } wellknown[] = { + { "dn", LDB_SYNTAX_DN }, + { "distinguishedName", LDB_SYNTAX_DN }, + { "cn", LDB_SYNTAX_DIRECTORY_STRING }, + { "dc", LDB_SYNTAX_DIRECTORY_STRING }, + { "ou", LDB_SYNTAX_DIRECTORY_STRING }, + { "objectClass", LDB_SYNTAX_OBJECTCLASS } + }; + unsigned int i; + int ret; + + for (i=0;ischema.num_dn_extended_syntax + 1; + + a = talloc_realloc(ldb, ldb->schema.dn_extended_syntax, + struct ldb_dn_extended_syntax, n); + + if (!a) { + return LDB_ERR_OPERATIONS_ERROR; + } + + a[ldb->schema.num_dn_extended_syntax] = *syntax; + ldb->schema.dn_extended_syntax = a; + + ldb->schema.num_dn_extended_syntax = n; + + return LDB_SUCCESS; +} + +/* + return the extended dn syntax for a given name +*/ +const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_context *ldb, + const char *name) +{ + unsigned int i; + for (i=0; i < ldb->schema.num_dn_extended_syntax; i++) { + if (ldb_attr_cmp(ldb->schema.dn_extended_syntax[i].name, name) == 0) { + return &ldb->schema.dn_extended_syntax[i]; + } + } + return NULL; +} + +/* + set an attribute handler override function - used to delegate schema handling + to external code + */ +void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb, + ldb_attribute_handler_override_fn_t override, + void *private_data) +{ + ldb->schema.attribute_handler_override_private = private_data; + ldb->schema.attribute_handler_override = override; +} + +/* + set that the attribute handler override function - used to delegate + schema handling to external code, is handling setting + LDB_ATTR_FLAG_INDEXED + */ +void ldb_schema_set_override_indexlist(struct ldb_context *ldb, + bool one_level_indexes) +{ + ldb->schema.index_handler_override = true; + ldb->schema.one_level_indexes = one_level_indexes; +} + +/* + * set that the GUID index mode is in operation + * + * The caller must ensure the supplied strings do not go out of + * scope (they are typically constant memory). + */ +void ldb_schema_set_override_GUID_index(struct ldb_context *ldb, + const char *GUID_index_attribute, + const char *GUID_index_dn_component) +{ + ldb->schema.GUID_index_attribute = GUID_index_attribute; + ldb->schema.GUID_index_dn_component = GUID_index_dn_component; +} diff --git a/ldb-2.0.8/common/ldb_controls.c b/ldb-2.0.8/common/ldb_controls.c new file mode 100644 index 0000000..e0f0eb4 --- /dev/null +++ b/ldb-2.0.8/common/ldb_controls.c @@ -0,0 +1,1319 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb_controls.c + * + * Component: ldb controls utility functions + * + * Description: helper functions for control modules + * + * Author: Simo Sorce + */ + +#include "ldb_private.h" + +/* check if a control with the specified "oid" exist and return it */ +/* returns NULL if not found */ +struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid) +{ + unsigned int i; + + if (req->controls != NULL) { + for (i = 0; req->controls[i]; i++) { + if (req->controls[i]->oid && strcmp(oid, req->controls[i]->oid) == 0) { + break; + } + } + + return req->controls[i]; + } + + return NULL; +} + +/* check if a control with the specified "oid" exist and return it */ +/* returns NULL if not found */ +struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid) +{ + unsigned int i; + + if (rep->controls != NULL) { + for (i = 0; rep->controls[i]; i++) { + if (rep->controls[i]->oid && strcmp(oid, rep->controls[i]->oid) == 0) { + break; + } + } + + return rep->controls[i]; + } + + return NULL; +} + +/* + * Saves the current controls list into the "saver" (can also be NULL) and + * replace the one in "req" with a new one excluding the "exclude" control + * (if it is NULL then the list remains the same) + * + * Returns 0 on error. + */ +int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver) +{ + struct ldb_control **lcs, **lcs_old; + unsigned int i, j; + + lcs_old = req->controls; + if (saver != NULL) { + *saver = lcs_old; + } + + for (i = 0; req->controls && req->controls[i]; i++); + if (i == 0) { + req->controls = NULL; + return 1; + } + + lcs = talloc_array(req, struct ldb_control *, i + 1); + if (!lcs) { + return 0; + } + + for (i = 0, j = 0; lcs_old[i]; i++) { + if (exclude == lcs_old[i]) continue; + lcs[j] = lcs_old[i]; + j++; + } + lcs[j] = NULL; + + req->controls = talloc_realloc(req, lcs, struct ldb_control *, j + 1); + if (req->controls == NULL) { + return 0; + } + return 1; +} + +/* + * Returns a list of controls, except the one specified with "exclude" (can + * also be NULL). Included controls become a child of returned list if they + * were children of "controls_in". + * + * Returns NULL on error (OOM) or an empty control list. + */ +struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in, + TALLOC_CTX *mem_ctx, + struct ldb_control *exclude) +{ + struct ldb_control **lcs = NULL; + unsigned int i, j, n; + + for (i = 0; controls_in && controls_in[i]; i++); + if (i == 0) { + return NULL; + } + n = i; + + for (i = 0, j = 0; controls_in && controls_in[i]; i++) { + if (exclude == controls_in[i]) continue; + + if (!lcs) { + /* Allocate here so if we remove the only + * control, or there were no controls, we + * don't allocate at all, and just return + * NULL */ + lcs = talloc_array(mem_ctx, struct ldb_control *, + n + 1); + if (!lcs) { + return NULL; + } + } + + lcs[j] = controls_in[i]; + talloc_reparent(controls_in, lcs, lcs[j]); + j++; + } + if (lcs) { + lcs[j] = NULL; + + lcs = talloc_realloc(mem_ctx, lcs, struct ldb_control *, j + 1); + } + + return lcs; +} + +/* check if there's any control marked as critical in the list */ +/* return True if any, False if none */ +int ldb_check_critical_controls(struct ldb_control **controls) +{ + unsigned int i; + + if (controls == NULL) { + return 0; + } + + for (i = 0; controls[i]; i++) { + if (controls[i]->critical) { + return 1; + } + } + + return 0; +} + +int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data) +{ + unsigned int i, n; + struct ldb_control **ctrls; + struct ldb_control *ctrl; + + for (n=0; req->controls && req->controls[n];n++) { + /* having two controls of the same OID makes no sense */ + if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) { + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + } + + ctrls = talloc_array(req, + struct ldb_control *, + n + 2); + if (!ctrls) return LDB_ERR_OPERATIONS_ERROR; + + for (i=0; icontrols[i]; + } + + req->controls = ctrls; + ctrls[n] = NULL; + ctrls[n+1] = NULL; + + ctrl = talloc(ctrls, struct ldb_control); + if (!ctrl) return LDB_ERR_OPERATIONS_ERROR; + + ctrl->oid = talloc_strdup(ctrl, oid); + if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR; + ctrl->critical = critical; + ctrl->data = data; + + ctrls[n] = ctrl; + return LDB_SUCCESS; +} + +int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data) +{ + unsigned n; + struct ldb_control **ctrls; + struct ldb_control *ctrl; + + for (n=0; ares->controls && ares->controls[n];) { + /* having two controls of the same OID makes no sense */ + if (ares->controls[n]->oid && strcmp(oid, ares->controls[n]->oid) == 0) { + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + n++; + } + + ctrls = talloc_realloc(ares, ares->controls, + struct ldb_control *, + n + 2); + if (!ctrls) return LDB_ERR_OPERATIONS_ERROR; + ares->controls = ctrls; + ctrls[n] = NULL; + ctrls[n+1] = NULL; + + ctrl = talloc(ctrls, struct ldb_control); + if (!ctrl) return LDB_ERR_OPERATIONS_ERROR; + + ctrl->oid = talloc_strdup(ctrl, oid); + if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR; + ctrl->critical = critical; + ctrl->data = data; + + ctrls[n] = ctrl; + return LDB_SUCCESS; +} + +/* Add a control to the request, replacing the old one if it is already in the request */ +int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data) +{ + unsigned int n; + int ret; + + ret = ldb_request_add_control(req, oid, critical, data); + if (ret != LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) { + return ret; + } + + for (n=0; req->controls[n];n++) { + if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) { + req->controls[n]->critical = critical; + req->controls[n]->data = data; + return LDB_SUCCESS; + } + } + + return LDB_ERR_OPERATIONS_ERROR; +} + +/* + * Return a control as string + * the project (ie. name:value1:value2:...:valuen + * The string didn't include the criticity of the critical flag + */ +char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control) +{ + char *res = NULL; + + if (strcmp(control->oid, LDB_CONTROL_PAGED_RESULTS_OID) == 0) { + struct ldb_paged_control *rep_control = talloc_get_type(control->data, struct ldb_paged_control); + char *cookie; + + cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len); + if (cookie == NULL) { + return NULL; + } + if (cookie[0] != '\0') { + res = talloc_asprintf(mem_ctx, "%s:%d:%s", + LDB_CONTROL_PAGED_RESULTS_NAME, + control->critical, + cookie); + + talloc_free(cookie); + } else { + res = talloc_asprintf(mem_ctx, "%s:%d", + LDB_CONTROL_PAGED_RESULTS_NAME, + control->critical); + } + return res; + } + + if (strcmp(control->oid, LDB_CONTROL_VLV_RESP_OID) == 0) { + struct ldb_vlv_resp_control *rep_control = talloc_get_type(control->data, + struct ldb_vlv_resp_control); + + 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, + cookie); + + return res; + } + + if (strcmp(control->oid, LDB_CONTROL_SORT_RESP_OID) == 0) { + struct ldb_sort_resp_control *rep_control = talloc_get_type(control->data, + struct ldb_sort_resp_control); + + res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s", + LDB_CONTROL_SORT_RESP_NAME, + control->critical, + rep_control->result, + rep_control->attr_desc); + + return res; + } + + if (strcmp(control->oid, LDB_CONTROL_ASQ_OID) == 0) { + struct ldb_asq_control *rep_control = talloc_get_type(control->data, + struct ldb_asq_control); + + res = talloc_asprintf(mem_ctx, "%s:%d:%d", + LDB_CONTROL_SORT_RESP_NAME, + control->critical, + rep_control->result); + + return res; + } + + if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_OID) == 0) { + char *cookie; + struct ldb_dirsync_control *rep_control = talloc_get_type(control->data, + struct ldb_dirsync_control); + + cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, + rep_control->cookie_len); + if (cookie == NULL) { + return NULL; + } + res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s", + LDB_CONTROL_DIRSYNC_NAME, + control->critical, + rep_control->flags, + rep_control->max_attributes, + cookie); + + talloc_free(cookie); + return res; + } + if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_EX_OID) == 0) { + char *cookie; + struct ldb_dirsync_control *rep_control = talloc_get_type(control->data, + struct ldb_dirsync_control); + + cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, + rep_control->cookie_len); + if (cookie == NULL) { + return NULL; + } + res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s", + LDB_CONTROL_DIRSYNC_EX_NAME, + control->critical, + rep_control->flags, + rep_control->max_attributes, + cookie); + + talloc_free(cookie); + return res; + } + + if (strcmp(control->oid, LDB_CONTROL_VERIFY_NAME_OID) == 0) { + struct ldb_verify_name_control *rep_control = talloc_get_type(control->data, struct ldb_verify_name_control); + + if (rep_control->gc != NULL) { + res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s", + LDB_CONTROL_VERIFY_NAME_NAME, + control->critical, + rep_control->flags, + rep_control->gc); + + } else { + res = talloc_asprintf(mem_ctx, "%s:%d:%d", + LDB_CONTROL_VERIFY_NAME_NAME, + control->critical, + rep_control->flags); + } + return res; + } + + /* + * From here we don't know the control + */ + if (control->data == NULL) { + /* + * We don't know the control but there is no real data attached + * to it so we can represent it with local_oid:oid:criticity. + */ + res = talloc_asprintf(mem_ctx, "local_oid:%s:%d", + control->oid, + control->critical); + } else { + res = talloc_asprintf(mem_ctx, "unknown oid:%s", + control->oid); + } + return res; +} + + +/* + * A little trick to allow one to use constants defined in headers rather than + * hardwritten in the file. + * "sizeof" will return the \0 char as well so it will take the place of ":" + * in the length of the string. + */ +#define LDB_CONTROL_CMP(control, NAME) strncmp(control, NAME ":", sizeof(NAME)) + +/* Parse one string and return associated control if parsing is successful*/ +struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings) +{ + struct ldb_control *ctrl; + + if (!(ctrl = talloc(mem_ctx, struct ldb_control))) { + ldb_oom(ldb); + return NULL; + } + + if (LDB_CONTROL_CMP(control_strings, + LDB_CONTROL_VLV_REQ_NAME) == 0) { + struct ldb_vlv_req_control *control; + const char *p; + char attr[1024]; + char ctxid[1024]; + int crit, bc, ac, os, cc, ret; + + attr[0] = '\0'; + 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); + /* 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)) { + 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; + } + ctrl->oid = LDB_CONTROL_VLV_REQ_OID; + ctrl->critical = crit; + if (!(control = talloc(ctrl, + struct ldb_vlv_req_control))) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + control->beforeCount = bc; + control->afterCount = ac; + if (attr[0]) { + control->type = 1; + control->match.gtOrEq.value = talloc_strdup(control, attr); + control->match.gtOrEq.value_len = strlen(attr); + } else { + control->type = 0; + control->match.byOffset.offset = os; + control->match.byOffset.contentCount = cc; + } + if (ctxid[0]) { + 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); + talloc_free(ctrl); + return NULL; + } + } else { + control->ctxid_len = 0; + control->contextId = NULL; + } + ctrl->data = control; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_NAME) == 0) { + struct ldb_dirsync_control *control; + const char *p; + char *cookie = NULL; + int crit, max_attrs, ret; + uint32_t flags; + + cookie = talloc_zero_array(ctrl, char, + strlen(control_strings) + 1); + if (cookie == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_NAME)]); + ret = sscanf(p, "%d:%u:%d:%[^$]", &crit, &flags, &max_attrs, cookie); + + if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) { + 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; + } + + /* w2k3 seems to ignore the parameter, + * but w2k sends a wrong cookie when this value is to small + * this would cause looping forever, while getting + * the same data and same cookie forever + */ + if (max_attrs == 0) max_attrs = 0x0FFFFFFF; + + ctrl->oid = LDB_CONTROL_DIRSYNC_OID; + ctrl->critical = crit; + control = talloc(ctrl, struct ldb_dirsync_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + control->flags = flags; + control->max_attributes = max_attrs; + if (*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); + talloc_free(ctrl); + return NULL; + } + } else { + control->cookie = NULL; + control->cookie_len = 0; + } + ctrl->data = control; + TALLOC_FREE(cookie); + + return ctrl; + } + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_EX_NAME) == 0) { + struct ldb_dirsync_control *control; + const char *p; + char *cookie = NULL; + int crit, max_attrs, ret; + uint32_t flags; + + cookie = talloc_zero_array(ctrl, char, + strlen(control_strings) + 1); + if (cookie == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_EX_NAME)]); + ret = sscanf(p, "%d:%u:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie); + + if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) { + 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; + } + + /* w2k3 seems to ignore the parameter, + * but w2k sends a wrong cookie when this value is to small + * this would cause looping forever, while getting + * the same data and same cookie forever + */ + if (max_attrs == 0) max_attrs = 0x0FFFFFFF; + + ctrl->oid = LDB_CONTROL_DIRSYNC_EX_OID; + ctrl->critical = crit; + control = talloc(ctrl, struct ldb_dirsync_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + control->flags = flags; + control->max_attributes = max_attrs; + if (*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); + talloc_free(ctrl); + return NULL; + } + } else { + control->cookie = NULL; + control->cookie_len = 0; + } + ctrl->data = control; + TALLOC_FREE(cookie); + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_ASQ_NAME) == 0) { + struct ldb_asq_control *control; + const char *p; + char attr[256]; + int crit, ret; + + attr[0] = '\0'; + 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')) { + 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; + } + + ctrl->oid = LDB_CONTROL_ASQ_OID; + ctrl->critical = crit; + control = talloc(ctrl, struct ldb_asq_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + control->request = 1; + control->source_attribute = talloc_strdup(control, attr); + control->src_attr_len = strlen(attr); + ctrl->data = control; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_EXTENDED_DN_NAME) == 0) { + struct ldb_extended_dn_control *control; + const char *p; + int crit, type, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_EXTENDED_DN_NAME)]); + ret = sscanf(p, "%d:%d", &crit, &type); + if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) { + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + 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; + } + control = NULL; + } else { + control = talloc(ctrl, struct ldb_extended_dn_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + control->type = type; + } + + ctrl->oid = LDB_CONTROL_EXTENDED_DN_OID; + ctrl->critical = crit; + ctrl->data = talloc_steal(ctrl, control); + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SD_FLAGS_NAME) == 0) { + struct ldb_sd_flags_control *control; + const char *p; + int crit, ret; + unsigned secinfo_flags; + + 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)) { + 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; + } + + ctrl->oid = LDB_CONTROL_SD_FLAGS_OID; + ctrl->critical = crit; + control = talloc(ctrl, struct ldb_sd_flags_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + control->secinfo_flags = secinfo_flags; + ctrl->data = control; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SEARCH_OPTIONS_NAME) == 0) { + struct ldb_search_options_control *control; + const char *p; + int crit, ret; + unsigned search_options; + + 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)) { + 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; + } + + ctrl->oid = LDB_CONTROL_SEARCH_OPTIONS_OID; + ctrl->critical = crit; + control = talloc(ctrl, struct ldb_search_options_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + control->search_options = search_options; + ctrl->data = control; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_BYPASS_OPERATIONAL_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_BYPASS_OPERATIONAL_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid bypassopreational control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_BYPASS_OPERATIONAL_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RELAX_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_RELAX_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid relax control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_RELAX_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RECALCULATE_SD_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_RECALCULATE_SD_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid recalculate_sd control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_RECALCULATE_SD_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DOMAIN_SCOPE_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_DOMAIN_SCOPE_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid domain_scope control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_DOMAIN_SCOPE_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + 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:%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; + } + + ctrl->oid = LDB_CONTROL_PAGED_RESULTS_OID; + ctrl->critical = crit; + control = talloc(ctrl, struct ldb_paged_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + control->size = size; + 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); + talloc_free(ctrl); + return NULL; + } + } else { + control->cookie = NULL; + control->cookie_len = 0; + } + ctrl->data = control; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SERVER_SORT_NAME) == 0) { + struct ldb_server_sort_control **control; + const char *p; + char attr[256]; + char rule[128]; + int crit, rev, ret; + + attr[0] = '\0'; + rule[0] = '\0'; + 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') { + 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; + } + ctrl->oid = LDB_CONTROL_SERVER_SORT_OID; + ctrl->critical = crit; + control = talloc_array(ctrl, struct ldb_server_sort_control *, 2); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + control[0] = talloc(control, struct ldb_server_sort_control); + if (control[0] == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + control[0]->attributeName = talloc_strdup(control, attr); + if (control[0]->attributeName == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + if (rule[0]) { + control[0]->orderingRule = talloc_strdup(control, rule); + if (control[0]->orderingRule == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + } else { + control[0]->orderingRule = NULL; + } + control[0]->reverse = rev; + control[1] = NULL; + ctrl->data = control; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_NOTIFICATION_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_NOTIFICATION_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid notification control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_NOTIFICATION_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_TREE_DELETE_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_TREE_DELETE_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid tree_delete control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_TREE_DELETE_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DELETED_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DELETED_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid show_deleted control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_SHOW_DELETED_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid show_deactivated_link control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_RECYCLED_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_SHOW_RECYCLED_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid show_recycled control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_SHOW_RECYCLED_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PERMISSIVE_MODIFY_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_PERMISSIVE_MODIFY_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid permissive_modify control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_REVEAL_INTERNALS_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_REVEAL_INTERNALS_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid reveal_internals control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_REVEAL_INTERNALS; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (strncmp(control_strings, "local_oid:", 10) == 0) { + const char *p; + int crit = 0, ret = 0; + char oid[256]; + + oid[0] = '\0'; + p = &(control_strings[10]); + ret = sscanf(p, "%255[^:]:%d", oid, &crit); + + if ((ret != 2) || strlen(oid) == 0 || (crit < 0) || (crit > 1)) { + 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; + } + + ctrl->oid = talloc_strdup(ctrl, oid); + if (!ctrl->oid) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RODC_DCPROMO_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_RODC_DCPROMO_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid rodc_join control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_RODC_DCPROMO_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PROVISION_NAME) == 0) { + const char *p; + int crit, ret; + + p = &(control_strings[sizeof(LDB_CONTROL_PROVISION_NAME)]); + ret = sscanf(p, "%d", &crit); + if ((ret != 1) || (crit < 0) || (crit > 1)) { + ldb_set_errstring(ldb, + "invalid provision control syntax\n" + " syntax: crit(b)\n" + " note: b = boolean"); + talloc_free(ctrl); + return NULL; + } + + ctrl->oid = LDB_CONTROL_PROVISION_OID; + ctrl->critical = crit; + ctrl->data = NULL; + + return ctrl; + } + if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_VERIFY_NAME_NAME) == 0) { + const char *p; + char gc[1024]; + int crit, flags, ret; + struct ldb_verify_name_control *control; + + gc[0] = '\0'; + + p = &(control_strings[sizeof(LDB_CONTROL_VERIFY_NAME_NAME)]); + ret = sscanf(p, "%d:%d:%1023[^$]", &crit, &flags, gc); + if ((ret != 3) || (crit < 0) || (crit > 1)) { + ret = sscanf(p, "%d:%d", &crit, &flags); + if ((ret != 2) || (crit < 0) || (crit > 1)) { + 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; + } + } + + ctrl->oid = LDB_CONTROL_VERIFY_NAME_OID; + ctrl->critical = crit; + control = talloc(ctrl, struct ldb_verify_name_control); + if (control == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + control->gc = talloc_strdup(control, gc); + if (control->gc == NULL) { + ldb_oom(ldb); + talloc_free(ctrl); + return NULL; + } + + control->gc_len = strlen(gc); + control->flags = flags; + ctrl->data = control; + return ctrl; + } + /* + * When no matching control has been found. + */ + return NULL; +} + +/* Parse controls from the format used on the command line and in ejs */ +struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings) +{ + unsigned int i; + struct ldb_control **ctrl; + + if (control_strings == NULL || control_strings[0] == NULL) + return NULL; + + for (i = 0; control_strings[i]; i++); + + ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1); + + ldb_reset_err_string(ldb); + for (i = 0; control_strings[i]; i++) { + ctrl[i] = ldb_parse_control_from_string(ldb, ctrl, control_strings[i]); + if (ctrl[i] == NULL) { + if (ldb_errstring(ldb) == NULL) { + /* no controls matched, throw an error */ + ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]); + } + talloc_free(ctrl); + return NULL; + } + } + + ctrl[i] = NULL; + + return ctrl; +} + + diff --git a/ldb-2.0.8/common/ldb_debug.c b/ldb-2.0.8/common/ldb_debug.c new file mode 100644 index 0000000..d5e9e7a --- /dev/null +++ b/ldb-2.0.8/common/ldb_debug.c @@ -0,0 +1,150 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb debug + * + * Description: functions for printing debug messages + * + * Author: Andrew Tridgell + */ + +#include "ldb_private.h" + +/* + this allows the user to choose their own debug function +*/ +int ldb_set_debug(struct ldb_context *ldb, + void (*debug)(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap), + void *context) +{ + ldb->debug_ops.debug = debug; + ldb->debug_ops.context = context; + return 0; +} + +/* + debug function for ldb_set_debug_stderr +*/ +static void ldb_debug_stderr(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); +static void ldb_debug_stderr(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) +{ + if (level <= LDB_DEBUG_WARNING) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } +} + +static void ldb_debug_stderr_all(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); +static void ldb_debug_stderr_all(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) +{ + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); +} + +/* + convenience function to setup debug messages on stderr + messages of level LDB_DEBUG_WARNING and higher are printed +*/ +int ldb_set_debug_stderr(struct ldb_context *ldb) +{ + return ldb_set_debug(ldb, ldb_debug_stderr, ldb); +} + +/* + log a message (va_list helper for ldb_tevent_debug) +*/ +void ldb_vdebug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, va_list ap) +{ + if (ldb->debug_ops.debug == NULL) { + if (ldb->flags & LDB_FLG_ENABLE_TRACING) { + ldb_set_debug(ldb, ldb_debug_stderr_all, ldb); + } else { + ldb_set_debug_stderr(ldb); + } + } + ldb->debug_ops.debug(ldb->debug_ops.context, level, fmt, ap); +} + +/* + log a message +*/ +void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + ldb_vdebug(ldb, level, fmt, ap); + va_end(ap); +} + +/* + add to an accumulated log message + */ +void ldb_debug_add(struct ldb_context *ldb, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (ldb->partial_debug == NULL) { + ldb->partial_debug = talloc_vasprintf(ldb, fmt, ap); + } else { + ldb->partial_debug = talloc_vasprintf_append(ldb->partial_debug, + fmt, ap); + } + va_end(ap); +} + +/* + send the accumulated log message, and free it + */ +void ldb_debug_end(struct ldb_context *ldb, enum ldb_debug_level level) +{ + ldb_debug(ldb, level, "%s", ldb->partial_debug); + talloc_free(ldb->partial_debug); + ldb->partial_debug = NULL; +} + +/* + log a message, and set the ldb error string to the same message +*/ +void ldb_debug_set(struct ldb_context *ldb, enum ldb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + char *msg; + va_start(ap, fmt); + msg = talloc_vasprintf(ldb, fmt, ap); + va_end(ap); + if (msg != NULL) { + ldb_set_errstring(ldb, msg); + ldb_debug(ldb, level, "%s", msg); + } + talloc_free(msg); +} + diff --git a/ldb-2.0.8/common/ldb_dn.c b/ldb-2.0.8/common/ldb_dn.c new file mode 100644 index 0000000..83f94e3 --- /dev/null +++ b/ldb-2.0.8/common/ldb_dn.c @@ -0,0 +1,2240 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb dn creation and manipulation utility functions + * + * Description: - explode a dn into it's own basic elements + * and put them in a structure (only if necessary) + * - manipulate ldb_dn structures + * + * Author: Simo Sorce + */ + +#include "ldb_private.h" +#include + +#define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed + +#define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0) + +/** + internal ldb exploded dn structures +*/ +struct ldb_dn_component { + + char *name; + struct ldb_val value; + + char *cf_name; + struct ldb_val cf_value; +}; + +struct ldb_dn_ext_component { + + const char *name; + struct ldb_val value; +}; + +struct ldb_dn { + + struct ldb_context *ldb; + + /* Special DNs are always linearized */ + bool special; + bool invalid; + + bool valid_case; + + char *linearized; + char *ext_linearized; + char *casefold; + + unsigned int comp_num; + struct ldb_dn_component *components; + + unsigned int ext_comp_num; + struct ldb_dn_ext_component *ext_components; +}; + +/* it is helpful to be able to break on this in gdb */ +static void ldb_dn_mark_invalid(struct ldb_dn *dn) +{ + dn->invalid = true; +} + +/* strdn may be NULL */ +struct ldb_dn *ldb_dn_from_ldb_val(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + const struct ldb_val *strdn) +{ + struct ldb_dn *dn; + + if (ldb == NULL || strdn == NULL) { + return NULL; + } + if (strdn->data + && (strnlen((const char*)strdn->data, strdn->length) != strdn->length)) { + /* The RDN must not contain a character with value 0x0 */ + return NULL; + } + + dn = talloc_zero(mem_ctx, struct ldb_dn); + LDB_DN_NULL_FAILED(dn); + + dn->ldb = talloc_get_type(ldb, struct ldb_context); + if (dn->ldb == NULL) { + /* the caller probably got the arguments to + ldb_dn_new() mixed up */ + talloc_free(dn); + return NULL; + } + + if (strdn->data && strdn->length) { + const char *data = (const char *)strdn->data; + size_t length = strdn->length; + + if (data[0] == '@') { + dn->special = true; + } + dn->ext_linearized = talloc_strndup(dn, data, length); + LDB_DN_NULL_FAILED(dn->ext_linearized); + + if (data[0] == '<') { + const char *p_save, *p = dn->ext_linearized; + do { + p_save = p; + p = strstr(p, ">;"); + if (p) { + p = p + 2; + } + } while (p); + + if (p_save == dn->ext_linearized) { + dn->linearized = talloc_strdup(dn, ""); + } else { + dn->linearized = talloc_strdup(dn, p_save); + } + LDB_DN_NULL_FAILED(dn->linearized); + } else { + dn->linearized = dn->ext_linearized; + dn->ext_linearized = NULL; + } + } else { + dn->linearized = talloc_strdup(dn, ""); + LDB_DN_NULL_FAILED(dn->linearized); + } + + return dn; + +failed: + talloc_free(dn); + return NULL; +} + +/* strdn may be NULL */ +struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + const char *strdn) +{ + struct ldb_val blob; + blob.data = discard_const_p(uint8_t, strdn); + blob.length = strdn ? strlen(strdn) : 0; + return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob); +} + +struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + const char *new_fmt, ...) +{ + char *strdn; + va_list ap; + + if (! ldb) return NULL; + + va_start(ap, new_fmt); + strdn = talloc_vasprintf(mem_ctx, new_fmt, ap); + va_end(ap); + + if (strdn) { + struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, strdn); + talloc_free(strdn); + return dn; + } + + return NULL; +} + +/* see RFC2253 section 2.4 */ +static int ldb_dn_escape_internal(char *dst, const char *src, int len) +{ + char c; + char *d; + int i; + d = dst; + + for (i = 0; i < len; i++){ + c = src[i]; + switch (c) { + case ' ': + if (i == 0 || i == len - 1) { + /* if at the beginning or end + * of the string then escape */ + *d++ = '\\'; + *d++ = c; + } else { + /* otherwise don't escape */ + *d++ = c; + } + break; + + case '#': + /* despite the RFC, windows escapes a # + anywhere in the string */ + case ',': + case '+': + case '"': + case '\\': + case '<': + case '>': + case '?': + /* these must be escaped using \c form */ + *d++ = '\\'; + *d++ = c; + break; + + case ';': + case '\r': + case '\n': + case '=': + case '\0': { + /* any others get \XX form */ + unsigned char v; + const char *hexbytes = "0123456789ABCDEF"; + v = (const unsigned char)c; + *d++ = '\\'; + *d++ = hexbytes[v>>4]; + *d++ = hexbytes[v&0xF]; + break; + } + default: + *d++ = c; + } + } + + /* return the length of the resulting string */ + return (d - dst); +} + +char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value) +{ + char *dst; + size_t len; + if (!value.length) + return NULL; + + /* allocate destination string, it will be at most 3 times the source */ + dst = talloc_array(mem_ctx, char, value.length * 3 + 1); + if ( ! dst) { + talloc_free(dst); + return NULL; + } + + len = ldb_dn_escape_internal(dst, (const char *)value.data, value.length); + + dst = talloc_realloc(mem_ctx, dst, char, len + 1); + if ( ! dst) { + talloc_free(dst); + return NULL; + } + dst[len] = '\0'; + return dst; +} + +/* + explode a DN string into a ldb_dn structure + based on RFC4514 except that we don't support multiple valued RDNs + + TODO: according to MS-ADTS:3.1.1.5.2 Naming Constraints + DN must be compliant with RFC2253 +*/ +static bool ldb_dn_explode(struct ldb_dn *dn) +{ + char *p, *ex_name = NULL, *ex_value = NULL, *data, *d, *dt, *t; + bool trim = true; + bool in_extended = true; + bool in_ex_name = false; + bool in_ex_value = false; + bool in_attr = false; + bool in_value = false; + bool in_quote = false; + bool is_oid = false; + bool escape = false; + unsigned int x; + size_t l = 0; + int ret; + char *parse_dn; + bool is_index; + + if (dn == NULL || dn->invalid == true) { + return false; + } + + if (dn->components != NULL) { + return true; + } + + if (dn->ext_linearized != NULL) { + parse_dn = dn->ext_linearized; + } else { + parse_dn = dn->linearized; + } + + if (parse_dn == NULL) { + return false; + } + + is_index = (strncmp(parse_dn, "DN=@INDEX:", 10) == 0); + + /* Empty DNs */ + if (parse_dn[0] == '\0') { + return true; + } + + /* Special DNs case */ + if (dn->special == true) { + return true; + } + + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; + dn->comp_num = 0; + + /* in the common case we have 3 or more components */ + /* make sure all components are zeroed, other functions depend on it */ + dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3); + if (dn->components == NULL) { + return false; + } + + /* Components data space is allocated here once */ + data = talloc_array(dn->components, char, strlen(parse_dn) + 1); + if (data == NULL) { + goto failed; + } + + p = parse_dn; + t = NULL; + d = dt = data; + + while (*p) { + if (in_extended == true) { + + if (!in_ex_name && !in_ex_value) { + + if (p[0] == '<') { + p++; + ex_name = d; + in_ex_name = true; + continue; + } else { + in_extended = false; + in_attr = true; + dt = d; + + continue; + } + } + + if (in_ex_name && *p == '=') { + *d++ = '\0'; + p++; + ex_value = d; + in_ex_name = false; + in_ex_value = true; + continue; + } + + if (in_ex_value && *p == '>') { + struct ldb_dn_ext_component *ext_comp = NULL; + const struct ldb_dn_extended_syntax *ext_syntax; + struct ldb_val ex_val = { + .data = (uint8_t *)ex_value, + .length = d - ex_value + }; + + *d++ = '\0'; + p++; + in_ex_value = false; + + /* Process name and ex_value */ + + ext_comp = talloc_realloc( + dn, + dn->ext_components, + struct ldb_dn_ext_component, + dn->ext_comp_num + 1); + + if (ext_comp == NULL) { + /* ouch ! */ + goto failed; + } + + dn->ext_components = ext_comp; + + ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name); + if (ext_syntax == NULL) { + /* We don't know about this type of extended DN */ + 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) { + ldb_dn_mark_invalid(dn); + goto failed; + } + + dn->ext_comp_num++; + + if (*p == '\0') { + /* We have reached the end (extended component only)! */ + talloc_free(data); + return true; + + } else if (*p == ';') { + p++; + continue; + } else { + ldb_dn_mark_invalid(dn); + goto failed; + } + } + + *d++ = *p++; + continue; + } + if (in_attr == true) { + if (trim == true) { + if (*p == ' ') { + p++; + continue; + } + + /* first char */ + trim = false; + + if (!isascii(*p)) { + /* attr names must be ascii only */ + ldb_dn_mark_invalid(dn); + goto failed; + } + + if (isdigit(*p)) { + is_oid = true; + } else + if ( ! isalpha(*p)) { + /* not a digit nor an alpha, + * invalid attribute name */ + ldb_dn_mark_invalid(dn); + goto failed; + } + + /* Copy this character across from parse_dn, + * now we have trimmed out spaces */ + *d++ = *p++; + continue; + } + + if (*p == ' ') { + p++; + /* valid only if we are at the end */ + trim = true; + continue; + } + + if (*p == '=') { + /* attribute terminated */ + in_attr = false; + in_value = true; + trim = true; + l = 0; + + /* Terminate this string in d + * (which is a copy of parse_dn + * with spaces trimmed) */ + *d++ = '\0'; + dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt); + if (dn->components[dn->comp_num].name == NULL) { + /* ouch */ + goto failed; + } + + dt = d; + + p++; + continue; + } + + if (!isascii(*p)) { + /* attr names must be ascii only */ + ldb_dn_mark_invalid(dn); + goto failed; + } + + if (is_oid == true && ( ! (isdigit(*p) || (*p == '.')))) { + /* not a digit nor a dot, + * invalid attribute oid */ + ldb_dn_mark_invalid(dn); + goto failed; + } else + if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) { + /* not ALPHA, DIGIT or HYPHEN */ + ldb_dn_mark_invalid(dn); + goto failed; + } + + *d++ = *p++; + continue; + } + + if (in_value == true) { + if (in_quote == true) { + if (*p == '\"') { + if (p[-1] != '\\') { + p++; + in_quote = false; + continue; + } + } + *d++ = *p++; + l++; + continue; + } + + if (trim == true) { + if (*p == ' ') { + p++; + continue; + } + + /* first char */ + trim = false; + + if (*p == '\"') { + in_quote = true; + p++; + continue; + } + } + + switch (*p) { + + /* TODO: support ber encoded values + case '#': + */ + + case ',': + if (escape == true) { + *d++ = *p++; + l++; + escape = false; + continue; + } + /* ok found value terminator */ + + if (t != NULL) { + /* trim back */ + d -= (p - t); + l -= (p - t); + } + + in_attr = true; + in_value = false; + trim = true; + + p++; + *d++ = '\0'; + + /* + * This talloc_memdup() is OK with the + * +1 because *d has been set to '\0' + * just above + */ + dn->components[dn->comp_num].value.data = \ + (uint8_t *)talloc_memdup(dn->components, dt, l + 1); + dn->components[dn->comp_num].value.length = l; + if (dn->components[dn->comp_num].value.data == NULL) { + /* ouch ! */ + goto failed; + } + talloc_set_name_const(dn->components[dn->comp_num].value.data, + (const char *)dn->components[dn->comp_num].value.data); + + dt = d; + + dn->comp_num++; + if (dn->comp_num > 2) { + dn->components = talloc_realloc(dn, + dn->components, + struct ldb_dn_component, + dn->comp_num + 1); + if (dn->components == NULL) { + /* ouch ! */ + goto failed; + } + /* make sure all components are zeroed, other functions depend on this */ + memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component)); + } + + continue; + + case '+': + case '=': + /* to main compatibility with earlier + versions of ldb indexing, we have to + accept the base64 encoded binary index + values, which contain a '+' or '=' + which should normally be escaped */ + if (is_index == true) { + if (t != NULL) { + t = NULL; + } + *d++ = *p++; + l++; + break; + } + + FALL_THROUGH; + case '\"': + case '<': + case '>': + case ';': + /* a string with not escaped specials is invalid (tested) */ + if (escape == false) { + ldb_dn_mark_invalid(dn); + goto failed; + } + escape = false; + + *d++ = *p++; + l++; + + if (t != NULL) { + t = NULL; + } + break; + + case '\\': + if (escape == false) { + escape = true; + p++; + continue; + } + escape = false; + + *d++ = *p++; + l++; + + if (t != NULL) { + t = NULL; + } + break; + + default: + if (escape == true) { + if (isxdigit(p[0]) && isxdigit(p[1])) { + if (sscanf(p, "%02x", &x) != 1) { + /* invalid escaping sequence */ + ldb_dn_mark_invalid(dn); + goto failed; + } + p += 2; + *d++ = (unsigned char)x; + } else { + *d++ = *p++; + } + + escape = false; + l++; + if (t != NULL) { + t = NULL; + } + break; + } + + if (*p == ' ') { + if (t == NULL) { + t = p; + } + } else { + if (t != NULL) { + t = NULL; + } + } + + *d++ = *p++; + l++; + + break; + } + + } + } + + if (in_attr == true || in_quote == true) { + /* invalid dn */ + ldb_dn_mark_invalid(dn); + goto failed; + } + + if (in_value == true) { + /* save last element */ + if (t != NULL) { + /* trim back */ + d -= (p - t); + l -= (p - t); + } + + *d++ = '\0'; + /* + * This talloc_memdup() is OK with the + * +1 because *d has been set to '\0' + * just above. + */ + dn->components[dn->comp_num].value.length = l; + dn->components[dn->comp_num].value.data = + (uint8_t *)talloc_memdup(dn->components, dt, l + 1); + if (dn->components[dn->comp_num].value.data == NULL) { + /* ouch */ + goto failed; + } + talloc_set_name_const(dn->components[dn->comp_num].value.data, + (const char *)dn->components[dn->comp_num].value.data); + + dn->comp_num++; + } + talloc_free(data); + return true; + +failed: + LDB_FREE(dn->components); /* "data" is implicitly free'd */ + dn->comp_num = 0; + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; + + return false; +} + +bool ldb_dn_validate(struct ldb_dn *dn) +{ + return ldb_dn_explode(dn); +} + +const char *ldb_dn_get_linearized(struct ldb_dn *dn) +{ + unsigned int i; + size_t len; + char *d, *n; + + if ( ! dn || ( dn->invalid)) return NULL; + + if (dn->linearized) return dn->linearized; + + if ( ! dn->components) { + ldb_dn_mark_invalid(dn); + return NULL; + } + + if (dn->comp_num == 0) { + dn->linearized = talloc_strdup(dn, ""); + if ( ! dn->linearized) return NULL; + return dn->linearized; + } + + /* calculate maximum possible length of DN */ + for (len = 0, i = 0; i < dn->comp_num; i++) { + /* name len */ + len += strlen(dn->components[i].name); + /* max escaped data len */ + len += (dn->components[i].value.length * 3); + len += 2; /* '=' and ',' */ + } + dn->linearized = talloc_array(dn, char, len); + if ( ! dn->linearized) return NULL; + + d = dn->linearized; + + for (i = 0; i < dn->comp_num; i++) { + + /* copy the name */ + n = dn->components[i].name; + while (*n) *d++ = *n++; + + *d++ = '='; + + /* and the value */ + d += ldb_dn_escape_internal( d, + (char *)dn->components[i].value.data, + dn->components[i].value.length); + *d++ = ','; + } + + *(--d) = '\0'; + + /* don't waste more memory than necessary */ + dn->linearized = talloc_realloc(dn, dn->linearized, + char, (d - dn->linearized + 1)); + + return dn->linearized; +} + +static int ldb_dn_extended_component_compare(const void *p1, const void *p2) +{ + const struct ldb_dn_ext_component *ec1 = (const struct ldb_dn_ext_component *)p1; + const struct ldb_dn_ext_component *ec2 = (const struct ldb_dn_ext_component *)p2; + return strcmp(ec1->name, ec2->name); +} + +char *ldb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int mode) +{ + const char *linearized = ldb_dn_get_linearized(dn); + char *p = NULL; + unsigned int i; + + if (!linearized) { + return NULL; + } + + if (!ldb_dn_has_extended(dn)) { + return talloc_strdup(mem_ctx, linearized); + } + + if (!ldb_dn_validate(dn)) { + return NULL; + } + + /* sort the extended components by name. The idea is to make + * the resulting DNs consistent, plus to ensure that we put + * 'DELETED' first, so it can be very quickly recognised + */ + TYPESAFE_QSORT(dn->ext_components, dn->ext_comp_num, + ldb_dn_extended_component_compare); + + for (i = 0; i < dn->ext_comp_num; i++) { + const struct ldb_dn_extended_syntax *ext_syntax; + const char *name = dn->ext_components[i].name; + struct ldb_val ec_val = dn->ext_components[i].value; + struct ldb_val val; + int ret; + + ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name); + if (!ext_syntax) { + return NULL; + } + + if (mode == 1) { + ret = ext_syntax->write_clear_fn(dn->ldb, mem_ctx, + &ec_val, &val); + } else if (mode == 0) { + ret = ext_syntax->write_hex_fn(dn->ldb, mem_ctx, + &ec_val, &val); + } else { + ret = -1; + } + + if (ret != LDB_SUCCESS) { + return NULL; + } + + if (i == 0) { + p = talloc_asprintf(mem_ctx, "<%s=%.*s>", + name, + (int)val.length, + val.data); + } else { + p = talloc_asprintf_append_buffer(p, ";<%s=%.*s>", + name, + (int)val.length, + val.data); + } + + talloc_free(val.data); + + if (!p) { + return NULL; + } + } + + if (dn->ext_comp_num && *linearized) { + p = talloc_asprintf_append_buffer(p, ";%s", linearized); + } + + if (!p) { + return NULL; + } + + return p; +} + +/* + filter out all but an acceptable list of extended DN components + */ +void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept_list) +{ + unsigned int i; + for (i=0; iext_comp_num; i++) { + if (!ldb_attr_in_list(accept_list, dn->ext_components[i].name)) { + memmove(&dn->ext_components[i], + &dn->ext_components[i+1], + (dn->ext_comp_num-(i+1))*sizeof(dn->ext_components[0])); + dn->ext_comp_num--; + i--; + } + } + LDB_FREE(dn->ext_linearized); +} + + +char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) +{ + return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn)); +} + +/* + casefold a dn. We need to casefold the attribute names, and canonicalize + attribute values of case insensitive attributes. +*/ + +static bool ldb_dn_casefold_internal(struct ldb_dn *dn) +{ + unsigned int i; + int ret; + + if ( ! dn || dn->invalid) return false; + + if (dn->valid_case) return true; + + if (( ! dn->components) && ( ! ldb_dn_explode(dn))) { + return false; + } + + for (i = 0; i < dn->comp_num; i++) { + const struct ldb_schema_attribute *a; + + dn->components[i].cf_name = + ldb_attr_casefold(dn->components, + dn->components[i].name); + if (!dn->components[i].cf_name) { + goto failed; + } + + a = ldb_schema_attribute_by_name(dn->ldb, + dn->components[i].cf_name); + + ret = a->syntax->canonicalise_fn(dn->ldb, dn->components, + &(dn->components[i].value), + &(dn->components[i].cf_value)); + if (ret != 0) { + goto failed; + } + } + + dn->valid_case = true; + + return true; + +failed: + for (i = 0; i < dn->comp_num; i++) { + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + return false; +} + +const char *ldb_dn_get_casefold(struct ldb_dn *dn) +{ + unsigned int i; + size_t len; + char *d, *n; + + if (dn->casefold) return dn->casefold; + + if (dn->special) { + dn->casefold = talloc_strdup(dn, dn->linearized); + if (!dn->casefold) return NULL; + dn->valid_case = true; + return dn->casefold; + } + + if ( ! ldb_dn_casefold_internal(dn)) { + return NULL; + } + + if (dn->comp_num == 0) { + dn->casefold = talloc_strdup(dn, ""); + return dn->casefold; + } + + /* calculate maximum possible length of DN */ + for (len = 0, i = 0; i < dn->comp_num; i++) { + /* name len */ + len += strlen(dn->components[i].cf_name); + /* max escaped data len */ + len += (dn->components[i].cf_value.length * 3); + len += 2; /* '=' and ',' */ + } + dn->casefold = talloc_array(dn, char, len); + if ( ! dn->casefold) return NULL; + + d = dn->casefold; + + for (i = 0; i < dn->comp_num; i++) { + + /* copy the name */ + n = dn->components[i].cf_name; + while (*n) *d++ = *n++; + + *d++ = '='; + + /* and the value */ + d += ldb_dn_escape_internal( d, + (char *)dn->components[i].cf_value.data, + dn->components[i].cf_value.length); + *d++ = ','; + } + *(--d) = '\0'; + + /* don't waste more memory than necessary */ + dn->casefold = talloc_realloc(dn, dn->casefold, + char, strlen(dn->casefold) + 1); + + return dn->casefold; +} + +char *ldb_dn_alloc_casefold(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) +{ + return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn)); +} + +/* Determine if dn is below base, in the ldap tree. Used for + * evaluating a subtree search. + * 0 if they match, otherwise non-zero + */ + +int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn) +{ + int ret; + unsigned int n_base, n_dn; + + if ( ! base || base->invalid) return 1; + if ( ! dn || dn->invalid) return -1; + + if (( ! base->valid_case) || ( ! dn->valid_case)) { + if (base->linearized && dn->linearized && dn->special == base->special) { + /* try with a normal compare first, if we are lucky + * we will avoid exploding and casfolding */ + int dif; + dif = strlen(dn->linearized) - strlen(base->linearized); + if (dif < 0) { + return dif; + } + if (strcmp(base->linearized, + &dn->linearized[dif]) == 0) { + return 0; + } + } + + if ( ! ldb_dn_casefold_internal(base)) { + return 1; + } + + if ( ! ldb_dn_casefold_internal(dn)) { + return -1; + } + + } + + /* if base has more components, + * they don't have the same base */ + if (base->comp_num > dn->comp_num) { + return (dn->comp_num - base->comp_num); + } + + if ((dn->comp_num == 0) || (base->comp_num == 0)) { + if (dn->special && base->special) { + return strcmp(base->linearized, dn->linearized); + } else if (dn->special) { + return -1; + } else if (base->special) { + return 1; + } else { + return 0; + } + } + + n_base = base->comp_num - 1; + n_dn = dn->comp_num - 1; + + while (n_base != (unsigned int) -1) { + char *b_name = base->components[n_base].cf_name; + char *dn_name = dn->components[n_dn].cf_name; + + char *b_vdata = (char *)base->components[n_base].cf_value.data; + char *dn_vdata = (char *)dn->components[n_dn].cf_value.data; + + size_t b_vlen = base->components[n_base].cf_value.length; + size_t dn_vlen = dn->components[n_dn].cf_value.length; + + /* compare attr names */ + ret = strcmp(b_name, dn_name); + if (ret != 0) return ret; + + /* compare attr.cf_value. */ + if (b_vlen != dn_vlen) { + return b_vlen - dn_vlen; + } + ret = strncmp(b_vdata, dn_vdata, b_vlen); + if (ret != 0) return ret; + + n_base--; + n_dn--; + } + + return 0; +} + +/* compare DNs using casefolding compare functions. + + If they match, then return 0 + */ + +int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1) +{ + unsigned int i; + int ret; + + if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) { + return -1; + } + + if (( ! dn0->valid_case) || ( ! dn1->valid_case)) { + if (dn0->linearized && dn1->linearized) { + /* try with a normal compare first, if we are lucky + * we will avoid exploding and casfolding */ + if (strcmp(dn0->linearized, dn1->linearized) == 0) { + return 0; + } + } + + if ( ! ldb_dn_casefold_internal(dn0)) { + return 1; + } + + if ( ! ldb_dn_casefold_internal(dn1)) { + return -1; + } + + } + + if (dn0->comp_num != dn1->comp_num) { + return (dn1->comp_num - dn0->comp_num); + } + + if (dn0->comp_num == 0) { + if (dn0->special && dn1->special) { + return strcmp(dn0->linearized, dn1->linearized); + } else if (dn0->special) { + return 1; + } else if (dn1->special) { + return -1; + } else { + return 0; + } + } + + for (i = 0; i < dn0->comp_num; i++) { + char *dn0_name = dn0->components[i].cf_name; + char *dn1_name = dn1->components[i].cf_name; + + char *dn0_vdata = (char *)dn0->components[i].cf_value.data; + char *dn1_vdata = (char *)dn1->components[i].cf_value.data; + + size_t dn0_vlen = dn0->components[i].cf_value.length; + size_t dn1_vlen = dn1->components[i].cf_value.length; + + /* compare attr names */ + ret = strcmp(dn0_name, dn1_name); + if (ret != 0) { + return ret; + } + + /* compare attr.cf_value. */ + if (dn0_vlen != dn1_vlen) { + return dn0_vlen - dn1_vlen; + } + ret = strncmp(dn0_vdata, dn1_vdata, dn0_vlen); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +static struct ldb_dn_component ldb_dn_copy_component( + TALLOC_CTX *mem_ctx, + struct ldb_dn_component *src) +{ + struct ldb_dn_component dst; + + memset(&dst, 0, sizeof(dst)); + + if (src == NULL) { + return dst; + } + + dst.value = ldb_val_dup(mem_ctx, &(src->value)); + if (dst.value.data == NULL) { + return dst; + } + + dst.name = talloc_strdup(mem_ctx, src->name); + if (dst.name == NULL) { + LDB_FREE(dst.value.data); + return dst; + } + + if (src->cf_value.data) { + dst.cf_value = ldb_val_dup(mem_ctx, &(src->cf_value)); + if (dst.cf_value.data == NULL) { + LDB_FREE(dst.value.data); + LDB_FREE(dst.name); + return dst; + } + + dst.cf_name = talloc_strdup(mem_ctx, src->cf_name); + if (dst.cf_name == NULL) { + LDB_FREE(dst.cf_name); + LDB_FREE(dst.value.data); + LDB_FREE(dst.name); + return dst; + } + } else { + dst.cf_value.data = NULL; + dst.cf_name = NULL; + } + + return dst; +} + +static struct ldb_dn_ext_component ldb_dn_ext_copy_component( + TALLOC_CTX *mem_ctx, + struct ldb_dn_ext_component *src) +{ + struct ldb_dn_ext_component dst; + + memset(&dst, 0, sizeof(dst)); + + if (src == NULL) { + return dst; + } + + dst.value = ldb_val_dup(mem_ctx, &(src->value)); + if (dst.value.data == NULL) { + return dst; + } + + dst.name = talloc_strdup(mem_ctx, src->name); + if (dst.name == NULL) { + LDB_FREE(dst.value.data); + return dst; + } + + return dst; +} + +struct ldb_dn *ldb_dn_copy(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) +{ + struct ldb_dn *new_dn; + + if (!dn || dn->invalid) { + return NULL; + } + + new_dn = talloc_zero(mem_ctx, struct ldb_dn); + if ( !new_dn) { + return NULL; + } + + *new_dn = *dn; + + if (dn->components) { + unsigned int i; + + new_dn->components = + talloc_zero_array(new_dn, + struct ldb_dn_component, + dn->comp_num); + if ( ! new_dn->components) { + talloc_free(new_dn); + return NULL; + } + + for (i = 0; i < dn->comp_num; i++) { + new_dn->components[i] = + ldb_dn_copy_component(new_dn->components, + &dn->components[i]); + if ( ! new_dn->components[i].value.data) { + talloc_free(new_dn); + return NULL; + } + } + } + + if (dn->ext_components) { + unsigned int i; + + new_dn->ext_components = + talloc_zero_array(new_dn, + struct ldb_dn_ext_component, + dn->ext_comp_num); + if ( ! new_dn->ext_components) { + talloc_free(new_dn); + return NULL; + } + + for (i = 0; i < dn->ext_comp_num; i++) { + new_dn->ext_components[i] = + ldb_dn_ext_copy_component( + new_dn->ext_components, + &dn->ext_components[i]); + if ( ! new_dn->ext_components[i].value.data) { + talloc_free(new_dn); + return NULL; + } + } + } + + if (dn->casefold) { + new_dn->casefold = talloc_strdup(new_dn, dn->casefold); + if ( ! new_dn->casefold) { + talloc_free(new_dn); + return NULL; + } + } + + if (dn->linearized) { + new_dn->linearized = talloc_strdup(new_dn, dn->linearized); + if ( ! new_dn->linearized) { + talloc_free(new_dn); + return NULL; + } + } + + if (dn->ext_linearized) { + new_dn->ext_linearized = talloc_strdup(new_dn, + dn->ext_linearized); + if ( ! new_dn->ext_linearized) { + talloc_free(new_dn); + return NULL; + } + } + + return new_dn; +} + +/* modify the given dn by adding a base. + * + * return true if successful and false if not + * if false is returned the dn may be marked invalid + */ +bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base) +{ + const char *s; + char *t; + + if ( !base || base->invalid || !dn || dn->invalid) { + return false; + } + + if (dn == base) { + return false; /* or we will visit infinity */ + } + + if (dn->components) { + unsigned int i; + + if ( ! ldb_dn_validate(base)) { + return false; + } + + s = NULL; + if (dn->valid_case) { + if ( ! (s = ldb_dn_get_casefold(base))) { + return false; + } + } + + dn->components = talloc_realloc(dn, + dn->components, + struct ldb_dn_component, + dn->comp_num + base->comp_num); + if ( ! dn->components) { + ldb_dn_mark_invalid(dn); + return false; + } + + for (i = 0; i < base->comp_num; dn->comp_num++, i++) { + dn->components[dn->comp_num] = + ldb_dn_copy_component(dn->components, + &base->components[i]); + if (dn->components[dn->comp_num].value.data == NULL) { + ldb_dn_mark_invalid(dn); + return false; + } + } + + if (dn->casefold && s) { + if (*dn->casefold) { + t = talloc_asprintf(dn, "%s,%s", + dn->casefold, s); + } else { + t = talloc_strdup(dn, s); + } + LDB_FREE(dn->casefold); + dn->casefold = t; + } + } + + if (dn->linearized) { + + s = ldb_dn_get_linearized(base); + if ( ! s) { + return false; + } + + if (*dn->linearized) { + t = talloc_asprintf(dn, "%s,%s", + dn->linearized, s); + } else { + t = talloc_strdup(dn, s); + } + if ( ! t) { + ldb_dn_mark_invalid(dn); + return false; + } + LDB_FREE(dn->linearized); + dn->linearized = t; + } + + /* Wipe the ext_linearized DN, + * the GUID and SID are almost certainly no longer valid */ + LDB_FREE(dn->ext_linearized); + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; + + return true; +} + +/* modify the given dn by adding a base. + * + * return true if successful and false if not + * if false is returned the dn may be marked invalid + */ +bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...) +{ + struct ldb_dn *base; + char *base_str; + va_list ap; + bool ret; + + if ( !dn || dn->invalid) { + return false; + } + + va_start(ap, base_fmt); + base_str = talloc_vasprintf(dn, base_fmt, ap); + va_end(ap); + + if (base_str == NULL) { + return false; + } + + base = ldb_dn_new(base_str, dn->ldb, base_str); + + ret = ldb_dn_add_base(dn, base); + + talloc_free(base_str); + + return ret; +} + +/* modify the given dn by adding children elements. + * + * return true if successful and false if not + * if false is returned the dn may be marked invalid + */ +bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child) +{ + const char *s; + char *t; + + if ( !child || child->invalid || !dn || dn->invalid) { + return false; + } + + if (dn->components) { + unsigned int n; + unsigned int i, j; + + if (dn->comp_num == 0) { + return false; + } + + if ( ! ldb_dn_validate(child)) { + return false; + } + + s = NULL; + if (dn->valid_case) { + if ( ! (s = ldb_dn_get_casefold(child))) { + return false; + } + } + + n = dn->comp_num + child->comp_num; + + dn->components = talloc_realloc(dn, + dn->components, + struct ldb_dn_component, + n); + if ( ! dn->components) { + ldb_dn_mark_invalid(dn); + return false; + } + + for (i = dn->comp_num - 1, j = n - 1; i != (unsigned int) -1; + i--, j--) { + dn->components[j] = dn->components[i]; + } + + for (i = 0; i < child->comp_num; i++) { + dn->components[i] = + ldb_dn_copy_component(dn->components, + &child->components[i]); + if (dn->components[i].value.data == NULL) { + ldb_dn_mark_invalid(dn); + return false; + } + } + + dn->comp_num = n; + + if (dn->casefold && s) { + t = talloc_asprintf(dn, "%s,%s", s, dn->casefold); + LDB_FREE(dn->casefold); + dn->casefold = t; + } + } + + if (dn->linearized) { + if (dn->linearized[0] == '\0') { + return false; + } + + s = ldb_dn_get_linearized(child); + if ( ! s) { + return false; + } + + t = talloc_asprintf(dn, "%s,%s", s, dn->linearized); + if ( ! t) { + ldb_dn_mark_invalid(dn); + return false; + } + LDB_FREE(dn->linearized); + dn->linearized = t; + } + + /* Wipe the ext_linearized DN, + * the GUID and SID are almost certainly no longer valid */ + LDB_FREE(dn->ext_linearized); + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; + + return true; +} + +/* modify the given dn by adding children elements. + * + * return true if successful and false if not + * if false is returned the dn may be marked invalid + */ +bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...) +{ + struct ldb_dn *child; + char *child_str; + va_list ap; + bool ret; + + if ( !dn || dn->invalid) { + return false; + } + + va_start(ap, child_fmt); + child_str = talloc_vasprintf(dn, child_fmt, ap); + va_end(ap); + + if (child_str == NULL) { + return false; + } + + child = ldb_dn_new(child_str, dn->ldb, child_str); + + ret = ldb_dn_add_child(dn, child); + + talloc_free(child_str); + + return ret; +} + +/* modify the given dn by adding a single child element. + * + * return true if successful and false if not + * if false is returned the dn may be marked invalid + */ +bool ldb_dn_add_child_val(struct ldb_dn *dn, + const char *rdn, + struct ldb_val value) +{ + bool ret; + int ldb_ret; + struct ldb_dn *child = NULL; + + if ( !dn || dn->invalid) { + return false; + } + + child = ldb_dn_new(dn, dn->ldb, "X=Y"); + ret = ldb_dn_add_child(dn, child); + + if (ret == false) { + return false; + } + + ldb_ret = ldb_dn_set_component(dn, + 0, + rdn, + value); + if (ldb_ret != LDB_SUCCESS) { + return false; + } + + return true; +} + +bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num) +{ + unsigned int i; + + if ( ! ldb_dn_validate(dn)) { + return false; + } + + if (dn->comp_num < num) { + return false; + } + + /* free components */ + for (i = dn->comp_num - num; i < dn->comp_num; i++) { + LDB_FREE(dn->components[i].name); + LDB_FREE(dn->components[i].value.data); + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + + dn->comp_num -= num; + + if (dn->valid_case) { + for (i = 0; i < dn->comp_num; i++) { + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + dn->valid_case = false; + } + + LDB_FREE(dn->casefold); + LDB_FREE(dn->linearized); + + /* Wipe the ext_linearized DN, + * the GUID and SID are almost certainly no longer valid */ + LDB_FREE(dn->ext_linearized); + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; + + return true; +} + +bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num) +{ + unsigned int i, j; + + if ( ! ldb_dn_validate(dn)) { + return false; + } + + if (dn->comp_num < num) { + return false; + } + + for (i = 0, j = num; j < dn->comp_num; i++, j++) { + if (i < num) { + LDB_FREE(dn->components[i].name); + LDB_FREE(dn->components[i].value.data); + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + dn->components[i] = dn->components[j]; + } + + dn->comp_num -= num; + + if (dn->valid_case) { + for (i = 0; i < dn->comp_num; i++) { + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + dn->valid_case = false; + } + + LDB_FREE(dn->casefold); + LDB_FREE(dn->linearized); + + /* Wipe the ext_linearized DN, + * the GUID and SID are almost certainly no longer valid */ + LDB_FREE(dn->ext_linearized); + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; + + return true; +} + + +/* replace the components of a DN with those from another DN, without + * touching the extended components + * + * return true if successful and false if not + * if false is returned the dn may be marked invalid + */ +bool ldb_dn_replace_components(struct ldb_dn *dn, struct ldb_dn *new_dn) +{ + unsigned int i; + + if ( ! ldb_dn_validate(dn) || ! ldb_dn_validate(new_dn)) { + return false; + } + + /* free components */ + for (i = 0; i < dn->comp_num; i++) { + LDB_FREE(dn->components[i].name); + LDB_FREE(dn->components[i].value.data); + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + + dn->components = talloc_realloc(dn, + dn->components, + struct ldb_dn_component, + new_dn->comp_num); + if (dn->components == NULL) { + ldb_dn_mark_invalid(dn); + return false; + } + + dn->comp_num = new_dn->comp_num; + dn->valid_case = new_dn->valid_case; + + for (i = 0; i < dn->comp_num; i++) { + dn->components[i] = ldb_dn_copy_component(dn->components, &new_dn->components[i]); + if (dn->components[i].name == NULL) { + ldb_dn_mark_invalid(dn); + return false; + } + } + if (new_dn->linearized == NULL) { + dn->linearized = NULL; + } else { + dn->linearized = talloc_strdup(dn, new_dn->linearized); + if (dn->linearized == NULL) { + ldb_dn_mark_invalid(dn); + return false; + } + } + + return true; +} + + +struct ldb_dn *ldb_dn_get_parent(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) +{ + struct ldb_dn *new_dn; + + new_dn = ldb_dn_copy(mem_ctx, dn); + if ( !new_dn ) { + return NULL; + } + + if ( ! ldb_dn_remove_child_components(new_dn, 1)) { + talloc_free(new_dn); + return NULL; + } + + return new_dn; +} + +/* Create a 'canonical name' string from a DN: + + ie dc=samba,dc=org -> samba.org/ + uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator + + There are two formats, + the EX format has the last '/' replaced with a newline (\n). + +*/ +static char *ldb_dn_canonical(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int ex_format) { + unsigned int i; + TALLOC_CTX *tmpctx; + char *cracked = NULL; + const char *format = (ex_format ? "\n" : "/" ); + + if ( ! ldb_dn_validate(dn)) { + return NULL; + } + + tmpctx = talloc_new(mem_ctx); + + /* Walk backwards down the DN, grabbing 'dc' components at first */ + for (i = dn->comp_num - 1; i != (unsigned int) -1; i--) { + if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) { + break; + } + if (cracked) { + cracked = talloc_asprintf(tmpctx, "%s.%s", + ldb_dn_escape_value(tmpctx, + dn->components[i].value), + cracked); + } else { + cracked = ldb_dn_escape_value(tmpctx, + dn->components[i].value); + } + if (!cracked) { + goto done; + } + } + + /* Only domain components? Finish here */ + if (i == (unsigned int) -1) { + cracked = talloc_strdup_append_buffer(cracked, format); + talloc_steal(mem_ctx, cracked); + goto done; + } + + /* Now walk backwards appending remaining components */ + for (; i > 0; i--) { + cracked = talloc_asprintf_append_buffer(cracked, "/%s", + ldb_dn_escape_value(tmpctx, + dn->components[i].value)); + if (!cracked) { + goto done; + } + } + + /* Last one, possibly a newline for the 'ex' format */ + cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format, + ldb_dn_escape_value(tmpctx, + dn->components[i].value)); + + talloc_steal(mem_ctx, cracked); +done: + talloc_free(tmpctx); + return cracked; +} + +/* Wrapper functions for the above, for the two different string formats */ +char *ldb_dn_canonical_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { + return ldb_dn_canonical(mem_ctx, dn, 0); + +} + +char *ldb_dn_canonical_ex_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { + return ldb_dn_canonical(mem_ctx, dn, 1); +} + +int ldb_dn_get_comp_num(struct ldb_dn *dn) +{ + if ( ! ldb_dn_validate(dn)) { + return -1; + } + return dn->comp_num; +} + +int ldb_dn_get_extended_comp_num(struct ldb_dn *dn) +{ + if ( ! ldb_dn_validate(dn)) { + return -1; + } + return dn->ext_comp_num; +} + +const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num) +{ + if ( ! ldb_dn_validate(dn)) { + return NULL; + } + if (num >= dn->comp_num) return NULL; + return dn->components[num].name; +} + +const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, + unsigned int num) +{ + if ( ! ldb_dn_validate(dn)) { + return NULL; + } + if (num >= dn->comp_num) return NULL; + return &dn->components[num].value; +} + +const char *ldb_dn_get_rdn_name(struct ldb_dn *dn) +{ + if ( ! ldb_dn_validate(dn)) { + return NULL; + } + if (dn->comp_num == 0) return NULL; + return dn->components[0].name; +} + +const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn) +{ + if ( ! ldb_dn_validate(dn)) { + return NULL; + } + if (dn->comp_num == 0) return NULL; + return &dn->components[0].value; +} + +int ldb_dn_set_component(struct ldb_dn *dn, int num, + const char *name, const struct ldb_val val) +{ + char *n; + struct ldb_val v; + + if ( ! ldb_dn_validate(dn)) { + return LDB_ERR_OTHER; + } + + if (num < 0) { + return LDB_ERR_OTHER; + } + + if ((unsigned)num >= dn->comp_num) { + return LDB_ERR_OTHER; + } + + if (val.length > val.length + 1) { + return LDB_ERR_OTHER; + } + + n = talloc_strdup(dn, name); + if ( ! n) { + return LDB_ERR_OTHER; + } + + v.length = val.length; + + /* + * This is like talloc_memdup(dn, v.data, v.length + 1), but + * avoids the over-read + */ + v.data = (uint8_t *)talloc_size(dn, v.length+1); + if ( ! v.data) { + talloc_free(n); + return LDB_ERR_OTHER; + } + memcpy(v.data, val.data, val.length); + + /* + * Enforce NUL termination outside the stated length, as is + * traditional in LDB + */ + v.data[v.length] = '\0'; + + talloc_free(dn->components[num].name); + talloc_free(dn->components[num].value.data); + dn->components[num].name = n; + dn->components[num].value = v; + + if (dn->valid_case) { + unsigned int i; + for (i = 0; i < dn->comp_num; i++) { + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + dn->valid_case = false; + } + LDB_FREE(dn->casefold); + LDB_FREE(dn->linearized); + + /* Wipe the ext_linearized DN, + * the GUID and SID are almost certainly no longer valid */ + LDB_FREE(dn->ext_linearized); + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; + + return LDB_SUCCESS; +} + +const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, + const char *name) +{ + unsigned int i; + if ( ! ldb_dn_validate(dn)) { + return NULL; + } + for (i=0; i < dn->ext_comp_num; i++) { + if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) { + return &dn->ext_components[i].value; + } + } + return NULL; +} + +int ldb_dn_set_extended_component(struct ldb_dn *dn, + const char *name, const struct ldb_val *val) +{ + 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; + } + + 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; + } + + for (i=0; i < dn->ext_comp_num; i++) { + if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) { + if (val) { + dn->ext_components[i].value = + ldb_val_dup(dn->ext_components, val); + + 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; + } + } else { + if (i != (dn->ext_comp_num - 1)) { + memmove(&dn->ext_components[i], + &dn->ext_components[i+1], + ((dn->ext_comp_num-1) - i) * + sizeof(*dn->ext_components)); + } + dn->ext_comp_num--; + + dn->ext_components = talloc_realloc(dn, + dn->ext_components, + struct ldb_dn_ext_component, + dn->ext_comp_num); + if (!dn->ext_components) { + ldb_dn_mark_invalid(dn); + return LDB_ERR_OPERATIONS_ERROR; + } + } + LDB_FREE(dn->ext_linearized); + + return LDB_SUCCESS; + } + } + + if (val == NULL) { + /* removing a value that doesn't exist is not an error */ + return LDB_SUCCESS; + } + + v2 = *val; + + p = dn->ext_components + = talloc_realloc(dn, + dn->ext_components, + struct ldb_dn_ext_component, + dn->ext_comp_num + 1); + if (!dn->ext_components) { + ldb_dn_mark_invalid(dn); + return LDB_ERR_OPERATIONS_ERROR; + } + + p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, &v2); + p[dn->ext_comp_num].name = talloc_strdup(p, name); + + if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) { + ldb_dn_mark_invalid(dn); + return LDB_ERR_OPERATIONS_ERROR; + } + dn->ext_components = p; + dn->ext_comp_num++; + + LDB_FREE(dn->ext_linearized); + + return LDB_SUCCESS; +} + +void ldb_dn_remove_extended_components(struct ldb_dn *dn) +{ + LDB_FREE(dn->ext_linearized); + LDB_FREE(dn->ext_components); + dn->ext_comp_num = 0; +} + +bool ldb_dn_is_valid(struct ldb_dn *dn) +{ + if ( ! dn) return false; + return ! dn->invalid; +} + +bool ldb_dn_is_special(struct ldb_dn *dn) +{ + if ( ! dn || dn->invalid) return false; + return dn->special; +} + +bool ldb_dn_has_extended(struct ldb_dn *dn) +{ + if ( ! dn || dn->invalid) return false; + if (dn->ext_linearized && (dn->ext_linearized[0] == '<')) return true; + return dn->ext_comp_num != 0; +} + +bool ldb_dn_check_special(struct ldb_dn *dn, const char *check) +{ + if ( ! dn || dn->invalid) return false; + return ! strcmp(dn->linearized, check); +} + +bool ldb_dn_is_null(struct ldb_dn *dn) +{ + if ( ! dn || dn->invalid) return false; + if (ldb_dn_has_extended(dn)) return false; + if (dn->linearized && (dn->linearized[0] == '\0')) return true; + return false; +} + +/* + this updates dn->components, taking the components from ref_dn. + This is used by code that wants to update the DN path of a DN + while not impacting on the extended DN components + */ +int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn) +{ + dn->components = talloc_realloc(dn, dn->components, + struct ldb_dn_component, ref_dn->comp_num); + if (!dn->components) { + return LDB_ERR_OPERATIONS_ERROR; + } + memcpy(dn->components, ref_dn->components, + sizeof(struct ldb_dn_component)*ref_dn->comp_num); + dn->comp_num = ref_dn->comp_num; + + LDB_FREE(dn->casefold); + LDB_FREE(dn->linearized); + LDB_FREE(dn->ext_linearized); + + return LDB_SUCCESS; +} + +/* + minimise a DN. The caller must pass in a validated DN. + + If the DN has an extended component then only the first extended + component is kept, the DN string is stripped. + + The existing dn is modified + */ +bool ldb_dn_minimise(struct ldb_dn *dn) +{ + unsigned int i; + + if (!ldb_dn_validate(dn)) { + return false; + } + if (dn->ext_comp_num == 0) { + return true; + } + + /* free components */ + for (i = 0; i < dn->comp_num; i++) { + LDB_FREE(dn->components[i].name); + LDB_FREE(dn->components[i].value.data); + LDB_FREE(dn->components[i].cf_name); + LDB_FREE(dn->components[i].cf_value.data); + } + dn->comp_num = 0; + dn->valid_case = false; + + LDB_FREE(dn->casefold); + LDB_FREE(dn->linearized); + + /* note that we don't free dn->components as this there are + * several places in ldb_dn.c that rely on it being non-NULL + * for an exploded DN + */ + + for (i = 1; i < dn->ext_comp_num; i++) { + LDB_FREE(dn->ext_components[i].value.data); + } + dn->ext_comp_num = 1; + + dn->ext_components = talloc_realloc(dn, dn->ext_components, struct ldb_dn_ext_component, 1); + if (dn->ext_components == NULL) { + ldb_dn_mark_invalid(dn); + return false; + } + + LDB_FREE(dn->ext_linearized); + + return true; +} + +struct ldb_context *ldb_dn_get_ldb_context(struct ldb_dn *dn) +{ + return dn->ldb; +} diff --git a/ldb-2.0.8/common/ldb_ldif.c b/ldb-2.0.8/common/ldb_ldif.c new file mode 100644 index 0000000..6f7589f --- /dev/null +++ b/ldb-2.0.8/common/ldb_ldif.c @@ -0,0 +1,1108 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldif routines + * + * Description: ldif pack/unpack routines + * + * Author: Andrew Tridgell + */ + +/* + see RFC2849 for the LDIF format definition +*/ + +#include "ldb_private.h" +#include "system/locale.h" + +/* + +*/ +static int ldb_read_data_file(TALLOC_CTX *mem_ctx, struct ldb_val *value) +{ + struct stat statbuf; + char *buf; + int count, size, bytes; + int ret; + int f; + const char *fname = (const char *)value->data; + + if (strncmp(fname, "file://", 7) != 0) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + fname += 7; + + f = open(fname, O_RDONLY); + if (f == -1) { + return -1; + } + + if (fstat(f, &statbuf) != 0) { + ret = -1; + goto done; + } + + if (statbuf.st_size == 0) { + ret = -1; + goto done; + } + + value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1); + if (value->data == NULL) { + ret = -1; + goto done; + } + value->data[statbuf.st_size] = 0; + + count = 0; + size = statbuf.st_size; + buf = (char *)value->data; + while (count < statbuf.st_size) { + bytes = read(f, buf, size); + if (bytes == -1) { + talloc_free(value->data); + ret = -1; + goto done; + } + count += bytes; + buf += bytes; + size -= bytes; + } + + value->length = statbuf.st_size; + ret = statbuf.st_size; + +done: + close(f); + return ret; +} + +/* + this base64 decoder was taken from jitterbug (written by tridge). + we might need to replace it with a new version +*/ +int ldb_base64_decode(char *s) +{ + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int bit_offset=0, byte_offset, idx, i, n; + uint8_t *d = (uint8_t *)s; + char *p=NULL; + + n=i=0; + + while (*s && (p=strchr(b64,*s))) { + idx = (int)(p - b64); + byte_offset = (i*6)/8; + bit_offset = (i*6)%8; + d[byte_offset] &= ~((1<<(8-bit_offset))-1); + if (bit_offset < 3) { + d[byte_offset] |= (idx << (2-bit_offset)); + n = byte_offset+1; + } else { + d[byte_offset] |= (idx >> (bit_offset-2)); + d[byte_offset+1] = 0; + d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF; + n = byte_offset+2; + } + s++; i++; + } + if (bit_offset >= 3) { + n--; + } + + if (*s && !p) { + /* the only termination allowed */ + if (*s != '=') { + return -1; + } + } + + /* null terminate */ + d[n] = 0; + return n; +} + + +/* + encode as base64 + caller frees +*/ +char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len) +{ + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int bit_offset, byte_offset, idx, i; + const uint8_t *d = (const uint8_t *)buf; + int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0; + char *out; + + out = talloc_array(mem_ctx, char, bytes+pad_bytes+1); + if (!out) return NULL; + + for (i=0;i> (2-bit_offset)) & 0x3F; + } else { + idx = (d[byte_offset] << (bit_offset-2)) & 0x3F; + if (byte_offset+1 < len) { + idx |= (d[byte_offset+1] >> (8-(bit_offset-2))); + } + } + out[i] = b64[idx]; + } + + for (;idata; + + if (val->length == 0) { + return 0; + } + + if (p[0] == ' ' || p[0] == ':') { + return 1; + } + + for (i=0; ilength; i++) { + if (!isprint(p[i]) || p[i] == '\n') { + return 1; + } + } + return 0; +} + +/* this macro is used to handle the return checking on fprintf_fn() */ +#define CHECK_RET do { if (ret < 0) return ret; total += ret; } while (0) + +/* + write a line folded string onto a file +*/ +static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private_data, + const char *buf, size_t length, int start_pos) +{ + size_t i; + size_t total = 0; + int ret; + + for (i=0;imsg; + p = ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1); + ret = fprintf_fn(private_data, "dn: %s\n", p); + talloc_free(p); + CHECK_RET; + + if (ldif->changetype != LDB_CHANGETYPE_NONE) { + for (i=0;ldb_changetypes[i].name;i++) { + if (ldb_changetypes[i].changetype == ldif->changetype) { + break; + } + } + if (!ldb_changetypes[i].name) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d", + ldif->changetype); + talloc_free(mem_ctx); + return -1; + } + ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name); + CHECK_RET; + } + + for (i=0;inum_elements;i++) { + const struct ldb_schema_attribute *a; + size_t namelen; + + if (msg->elements[i].name == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Invalid element name (NULL) at position %d", i); + talloc_free(mem_ctx); + return -1; + } + + namelen = strlen(msg->elements[i].name); + a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name); + + if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { + switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + fprintf_fn(private_data, "add: %s\n", + msg->elements[i].name); + break; + case LDB_FLAG_MOD_DELETE: + fprintf_fn(private_data, "delete: %s\n", + msg->elements[i].name); + break; + case LDB_FLAG_MOD_REPLACE: + fprintf_fn(private_data, "replace: %s\n", + msg->elements[i].name); + break; + } + } + + if (in_trace && secret_attributes && ldb_attr_in_list(secret_attributes, msg->elements[i].name)) { + /* Deliberatly skip printing this password */ + ret = fprintf_fn(private_data, "# %s::: REDACTED SECRET ATTRIBUTE\n", + msg->elements[i].name); + CHECK_RET; + continue; + } + for (j=0;jelements[i].num_values;j++) { + struct ldb_val v; + bool use_b64_encode = false; + bool copy_raw_bytes = false; + + ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v); + if (ret != LDB_SUCCESS) { + v = msg->elements[i].values[j]; + } + + if (ldb->flags & LDB_FLG_SHOW_BINARY) { + use_b64_encode = false; + copy_raw_bytes = true; + } else if (a->flags & LDB_ATTR_FLAG_FORCE_BASE64_LDIF) { + use_b64_encode = true; + } else if (msg->elements[i].flags & + LDB_FLAG_FORCE_NO_BASE64_LDIF) { + use_b64_encode = false; + copy_raw_bytes = true; + } else { + use_b64_encode = ldb_should_b64_encode(ldb, &v); + } + + if (ret != LDB_SUCCESS || use_b64_encode) { + ret = fprintf_fn(private_data, "%s:: ", + msg->elements[i].name); + CHECK_RET; + ret = base64_encode_f(ldb, fprintf_fn, private_data, + (char *)v.data, v.length, + namelen + 3); + CHECK_RET; + ret = fprintf_fn(private_data, "\n"); + CHECK_RET; + } else { + ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name); + CHECK_RET; + if (copy_raw_bytes) { + ret = fprintf_fn(private_data, "%*.*s", + v.length, v.length, (char *)v.data); + } else { + ret = fold_string(fprintf_fn, private_data, + (char *)v.data, v.length, + namelen + 2); + } + CHECK_RET; + ret = fprintf_fn(private_data, "\n"); + CHECK_RET; + } + if (v.data != msg->elements[i].values[j].data) { + talloc_free(v.data); + } + } + if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { + fprintf_fn(private_data, "-\n"); + } + } + ret = fprintf_fn(private_data,"\n"); + CHECK_RET; + + talloc_free(mem_ctx); + + return total; +} + +#undef CHECK_RET + + +/* + write to ldif, using a caller supplied write method +*/ +int ldb_ldif_write(struct ldb_context *ldb, + int (*fprintf_fn)(void *, const char *, ...), + void *private_data, + const struct ldb_ldif *ldif) +{ + return ldb_ldif_write_trace(ldb, fprintf_fn, private_data, ldif, false); +} + + +/* + pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF + this routine removes any RFC2849 continuations and comments + + caller frees +*/ +static char *next_chunk(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + int (*fgetc_fn)(void *), void *private_data) +{ + size_t alloc_size=0, chunk_size = 0; + char *chunk = NULL; + int c; + int in_comment = 0; + + while ((c = fgetc_fn(private_data)) != EOF) { + if (chunk_size+1 >= alloc_size) { + char *c2; + alloc_size += 1024; + c2 = talloc_realloc(mem_ctx, chunk, char, alloc_size); + if (!c2) { + talloc_free(chunk); + errno = ENOMEM; + return NULL; + } + chunk = c2; + } + + if (in_comment) { + if (c == '\n') { + in_comment = 0; + } + continue; + } + + /* handle continuation lines - see RFC2849 */ + if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') { + chunk_size--; + continue; + } + + /* chunks are terminated by a double line-feed */ + if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') { + chunk[chunk_size-1] = 0; + return chunk; + } + + if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) { + in_comment = 1; + continue; + } + + /* ignore leading blank lines */ + if (chunk_size == 0 && c == '\n') { + continue; + } + + chunk[chunk_size++] = c; + } + + if (chunk) { + chunk[chunk_size] = 0; + } + + return chunk; +} + + +/* simple ldif attribute parser */ +static int next_attr(TALLOC_CTX *mem_ctx, char **s, const char **attr, struct ldb_val *value) +{ + char *p; + int base64_encoded = 0; + int binary_file = 0; + + if (strncmp(*s, "-\n", 2) == 0) { + value->length = 0; + *attr = "-"; + *s += 2; + return 0; + } + + p = strchr(*s, ':'); + if (!p) { + return -1; + } + + *p++ = 0; + + if (*p == ':') { + base64_encoded = 1; + p++; + } + + if (*p == '<') { + binary_file = 1; + p++; + } + + *attr = *s; + + while (*p == ' ' || *p == '\t') { + p++; + } + + value->data = (uint8_t *)p; + + p = strchr(p, '\n'); + + if (!p) { + value->length = strlen((char *)value->data); + *s = ((char *)value->data) + value->length; + } else { + value->length = p - (char *)value->data; + *s = p+1; + *p = 0; + } + + if (base64_encoded) { + int len = ldb_base64_decode((char *)value->data); + if (len == -1) { + /* it wasn't valid base64 data */ + return -1; + } + value->length = len; + } + + if (binary_file) { + int len = ldb_read_data_file(mem_ctx, value); + if (len == -1) { + /* an error occurred while trying to retrieve the file */ + return -1; + } + } + + return 0; +} + + +/* + free a message from a ldif_read +*/ +void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif) +{ + talloc_free(ldif); +} + +int ldb_ldif_parse_modrdn(struct ldb_context *ldb, + const struct ldb_ldif *ldif, + TALLOC_CTX *mem_ctx, + struct ldb_dn **_olddn, + struct ldb_dn **_newrdn, + bool *_deleteoldrdn, + struct ldb_dn **_newsuperior, + struct ldb_dn **_newdn) +{ + struct ldb_message *msg = ldif->msg; + struct ldb_val *newrdn_val = NULL; + struct ldb_val *deleteoldrdn_val = NULL; + struct ldb_val *newsuperior_val = NULL; + struct ldb_dn *olddn = NULL; + struct ldb_dn *newrdn = NULL; + bool deleteoldrdn = true; + struct ldb_dn *newsuperior = NULL; + struct ldb_dn *newdn = NULL; + struct ldb_val tmp_false; + struct ldb_val tmp_true; + bool ok; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + + if (tmp_ctx == NULL) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "Error: talloc_new() failed"); + goto err_op; + } + + if (ldif->changetype != LDB_CHANGETYPE_MODRDN) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: invalid changetype '%d'", + ldif->changetype); + goto err_other; + } + + if (msg->num_elements < 2) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: num_elements[%u] < 2", + msg->num_elements); + goto err_other; + } + + if (msg->num_elements > 3) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: num_elements[%u] > 3", + msg->num_elements); + goto err_other; + } + +#define CHECK_ELEMENT(i, _name, v, needed) do { \ + v = NULL; \ + if (msg->num_elements < (i + 1)) { \ + if (needed) { \ + ldb_debug(ldb, LDB_DEBUG_ERROR, \ + "Error: num_elements[%u] < (%u + 1)", \ + msg->num_elements, i); \ + goto err_other; \ + } \ + } else if (ldb_attr_cmp(msg->elements[i].name, _name) != 0) { \ + ldb_debug(ldb, LDB_DEBUG_ERROR, \ + "Error: elements[%u].name[%s] != [%s]", \ + i, msg->elements[i].name, _name); \ + goto err_other; \ + } else if (msg->elements[i].flags != 0) { \ + ldb_debug(ldb, LDB_DEBUG_ERROR, \ + "Error: elements[%u].flags[0x%X} != [0x0]", \ + i, msg->elements[i].flags); \ + goto err_other; \ + } else if (msg->elements[i].num_values != 1) { \ + ldb_debug(ldb, LDB_DEBUG_ERROR, \ + "Error: elements[%u].num_values[%u] != 1", \ + i, msg->elements[i].num_values); \ + goto err_other; \ + } else { \ + v = &msg->elements[i].values[0]; \ + } \ +} while (0) + + CHECK_ELEMENT(0, "newrdn", newrdn_val, true); + CHECK_ELEMENT(1, "deleteoldrdn", deleteoldrdn_val, true); + CHECK_ELEMENT(2, "newsuperior", newsuperior_val, false); + +#undef CHECK_ELEMENT + + olddn = ldb_dn_copy(tmp_ctx, msg->dn); + if (olddn == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: failed to copy olddn '%s'", + ldb_dn_get_linearized(msg->dn)); + goto err_op; + } + + newrdn = ldb_dn_from_ldb_val(tmp_ctx, ldb, newrdn_val); + if (!ldb_dn_validate(newrdn)) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Unable to parse dn '%s'", + (char *)newrdn_val->data); + goto err_dn; + } + + tmp_false.length = 1; + tmp_false.data = discard_const_p(uint8_t, "0"); + tmp_true.length = 1; + tmp_true.data = discard_const_p(uint8_t, "1"); + if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_false) == 1) { + deleteoldrdn = false; + } else if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_true) == 1) { + deleteoldrdn = true; + } else { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: deleteoldrdn value invalid '%s' not '0'/'1'", + (char *)deleteoldrdn_val->data); + goto err_attr; + } + + if (newsuperior_val) { + newsuperior = ldb_dn_from_ldb_val(tmp_ctx, ldb, newsuperior_val); + if (!ldb_dn_validate(newsuperior)) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Unable to parse dn '%s'", + (char *)newsuperior_val->data); + goto err_dn; + } + } else { + newsuperior = ldb_dn_get_parent(tmp_ctx, msg->dn); + if (newsuperior == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Unable to get parent dn '%s'", + ldb_dn_get_linearized(msg->dn)); + goto err_dn; + } + } + + newdn = ldb_dn_copy(tmp_ctx, newrdn); + if (newdn == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: failed to copy newrdn '%s'", + ldb_dn_get_linearized(newrdn)); + goto err_op; + } + + ok = ldb_dn_add_base(newdn, newsuperior); + if (!ok) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: failed to base '%s' to newdn '%s'", + ldb_dn_get_linearized(newsuperior), + ldb_dn_get_linearized(newdn)); + goto err_op; + } + + if (_olddn) { + *_olddn = talloc_move(mem_ctx, &olddn); + } + if (_newrdn) { + *_newrdn = talloc_move(mem_ctx, &newrdn); + } + if (_deleteoldrdn) { + *_deleteoldrdn = deleteoldrdn; + } + if (_newsuperior != NULL && _newrdn != NULL) { + if (newsuperior_val) { + *_newrdn = talloc_move(mem_ctx, &newrdn); + } else { + *_newrdn = NULL; + } + } + if (_newdn) { + *_newdn = talloc_move(mem_ctx, &newdn); + } + + talloc_free(tmp_ctx); + return LDB_SUCCESS; +err_other: + talloc_free(tmp_ctx); + return LDB_ERR_OTHER; +err_op: + talloc_free(tmp_ctx); + return LDB_ERR_OPERATIONS_ERROR; +err_attr: + talloc_free(tmp_ctx); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; +err_dn: + talloc_free(tmp_ctx); + return LDB_ERR_INVALID_DN_SYNTAX; +} + +/* + read from a LDIF source, creating a ldb_message +*/ +struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, + int (*fgetc_fn)(void *), void *private_data) +{ + struct ldb_ldif *ldif; + struct ldb_message *msg; + const char *attr=NULL; + char *chunk=NULL, *s; + struct ldb_val value; + unsigned flags = 0; + value.data = NULL; + + ldif = talloc(ldb, struct ldb_ldif); + if (!ldif) return NULL; + + ldif->msg = ldb_msg_new(ldif); + if (ldif->msg == NULL) { + talloc_free(ldif); + return NULL; + } + + ldif->changetype = LDB_CHANGETYPE_NONE; + msg = ldif->msg; + + chunk = next_chunk(ldb, ldif, fgetc_fn, private_data); + if (!chunk) { + goto failed; + } + + s = chunk; + + if (next_attr(ldif, &s, &attr, &value) != 0) { + goto failed; + } + + /* first line must be a dn */ + if (ldb_attr_cmp(attr, "dn") != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'", + attr); + goto failed; + } + + msg->dn = ldb_dn_from_ldb_val(msg, ldb, &value); + + if ( ! ldb_dn_validate(msg->dn)) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'", + (char *)value.data); + goto failed; + } + + while (next_attr(ldif, &s, &attr, &value) == 0) { + const struct ldb_schema_attribute *a; + struct ldb_message_element *el; + int ret, empty = 0; + + if (ldb_attr_cmp(attr, "changetype") == 0) { + int i; + for (i=0;ldb_changetypes[i].name;i++) { + if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) { + ldif->changetype = ldb_changetypes[i].changetype; + break; + } + } + if (!ldb_changetypes[i].name) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Bad ldif changetype '%s'",(char *)value.data); + } + flags = 0; + continue; + } + + if (ldb_attr_cmp(attr, "add") == 0) { + flags = LDB_FLAG_MOD_ADD; + empty = 1; + } + if (ldb_attr_cmp(attr, "delete") == 0) { + flags = LDB_FLAG_MOD_DELETE; + empty = 1; + } + if (ldb_attr_cmp(attr, "replace") == 0) { + flags = LDB_FLAG_MOD_REPLACE; + empty = 1; + } + if (ldb_attr_cmp(attr, "-") == 0) { + flags = 0; + continue; + } + + if (empty) { + if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) { + goto failed; + } + continue; + } + + el = &msg->elements[msg->num_elements-1]; + + a = ldb_schema_attribute_by_name(ldb, attr); + + if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 && + flags == el->flags) { + /* its a continuation */ + el->values = + talloc_realloc(msg->elements, el->values, + struct ldb_val, el->num_values+1); + if (!el->values) { + goto failed; + } + ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[el->num_values]); + if (ret != 0) { + goto failed; + } + if (value.length == 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Attribute value cannot be empty for attribute '%s'", el->name); + goto failed; + } + if (value.data != el->values[el->num_values].data) { + talloc_steal(el->values, el->values[el->num_values].data); + } + el->num_values++; + } else { + /* its a new attribute */ + msg->elements = talloc_realloc(msg, msg->elements, + struct ldb_message_element, + msg->num_elements+1); + if (!msg->elements) { + goto failed; + } + el = &msg->elements[msg->num_elements]; + el->flags = flags; + el->name = talloc_strdup(msg->elements, attr); + el->values = talloc(msg->elements, struct ldb_val); + if (!el->values || !el->name) { + goto failed; + } + el->num_values = 1; + ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[0]); + if (ret != 0) { + goto failed; + } + if (value.data != el->values[0].data) { + talloc_steal(el->values, el->values[0].data); + } + msg->num_elements++; + } + } + + if (ldif->changetype == LDB_CHANGETYPE_MODRDN) { + int ret; + + ret = ldb_ldif_parse_modrdn(ldb, ldif, ldif, + NULL, NULL, NULL, NULL, NULL); + if (ret != LDB_SUCCESS) { + goto failed; + } + } + + return ldif; + +failed: + talloc_free(ldif); + return NULL; +} + + + +/* + a wrapper around ldif_read() for reading from FILE* +*/ + +static int fgetc_file(void *private_data) +{ + int c; + struct ldif_read_file_state *state = + (struct ldif_read_file_state *)private_data; + c = fgetc(state->f); + if (c == '\n') { + state->line_no++; + } + return c; +} + +struct ldb_ldif *ldb_ldif_read_file_state(struct ldb_context *ldb, + struct ldif_read_file_state *state) +{ + return ldb_ldif_read(ldb, fgetc_file, state); +} + +struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f) +{ + struct ldif_read_file_state state; + state.f = f; + return ldb_ldif_read_file_state(ldb, &state); +} + +/* + a wrapper around ldif_read() for reading from const char* +*/ +struct ldif_read_string_state { + const char *s; +}; + +static int fgetc_string(void *private_data) +{ + struct ldif_read_string_state *state = + (struct ldif_read_string_state *)private_data; + if (state->s[0] != 0) { + return *state->s++; + } + return EOF; +} + +struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s) +{ + struct ldif_read_string_state state; + struct ldb_ldif *ldif; + state.s = *s; + ldif = ldb_ldif_read(ldb, fgetc_string, &state); + *s = state.s; + return ldif; +} + + +/* + wrapper around ldif_write() for a file +*/ +struct ldif_write_file_state { + FILE *f; +}; + +static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3); + +static int fprintf_file(void *private_data, const char *fmt, ...) +{ + struct ldif_write_file_state *state = + (struct ldif_write_file_state *)private_data; + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf(state->f, fmt, ap); + va_end(ap); + return ret; +} + +int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif) +{ + struct ldif_write_file_state state; + state.f = f; + return ldb_ldif_write(ldb, fprintf_file, &state, ldif); +} + +/* + wrapper around ldif_write() for a string +*/ +struct ldif_write_string_state { + char *string; +}; + +static int ldif_printf_string(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3); + +static int ldif_printf_string(void *private_data, const char *fmt, ...) +{ + struct ldif_write_string_state *state = + (struct ldif_write_string_state *)private_data; + va_list ap; + size_t oldlen = talloc_get_size(state->string); + va_start(ap, fmt); + + state->string = talloc_vasprintf_append(state->string, fmt, ap); + va_end(ap); + if (!state->string) { + return -1; + } + + return talloc_get_size(state->string) - oldlen; +} + +char *ldb_ldif_write_redacted_trace_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + const struct ldb_ldif *ldif) +{ + struct ldif_write_string_state state; + state.string = talloc_strdup(mem_ctx, ""); + if (!state.string) { + return NULL; + } + if (ldb_ldif_write_trace(ldb, ldif_printf_string, &state, ldif, true) == -1) { + return NULL; + } + return state.string; +} + +char *ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + const struct ldb_ldif *ldif) +{ + struct ldif_write_string_state state; + state.string = talloc_strdup(mem_ctx, ""); + if (!state.string) { + return NULL; + } + if (ldb_ldif_write(ldb, ldif_printf_string, &state, ldif) == -1) { + return NULL; + } + return state.string; +} + +/* + convenient function to turn a ldb_message into a string. Useful for + debugging + */ +char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + enum ldb_changetype changetype, + const struct ldb_message *msg) +{ + struct ldb_ldif ldif; + + ldif.changetype = changetype; + ldif.msg = discard_const_p(struct ldb_message, msg); + + return ldb_ldif_write_string(ldb, mem_ctx, &ldif); +} + +/* + * convenient function to turn a ldb_message into a string. Useful for + * debugging but also safer if some of the LDIF could be sensitive. + * + * The secret attributes are specified in a 'const char * const *' within + * the LDB_SECRET_ATTRIBUTE_LIST opaque set on the ldb + * + */ +char *ldb_ldif_message_redacted_string(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + enum ldb_changetype changetype, + const struct ldb_message *msg) +{ + struct ldb_ldif ldif; + + ldif.changetype = changetype; + ldif.msg = discard_const_p(struct ldb_message, msg); + + return ldb_ldif_write_redacted_trace_string(ldb, mem_ctx, &ldif); +} diff --git a/ldb-2.0.8/common/ldb_match.c b/ldb-2.0.8/common/ldb_match.c new file mode 100644 index 0000000..829afa7 --- /dev/null +++ b/ldb-2.0.8/common/ldb_match.c @@ -0,0 +1,755 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Simo Sorce 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb expression matching + * + * Description: ldb expression matching + * + * Author: Andrew Tridgell + */ + +#include "ldb_private.h" +#include "dlinklist.h" + +/* + check if the scope matches in a search result +*/ +static int ldb_match_scope(struct ldb_context *ldb, + struct ldb_dn *base, + struct ldb_dn *dn, + enum ldb_scope scope) +{ + int ret = 0; + + if (base == NULL || dn == NULL) { + return 1; + } + + switch (scope) { + case LDB_SCOPE_BASE: + if (ldb_dn_compare(base, dn) == 0) { + ret = 1; + } + break; + + case LDB_SCOPE_ONELEVEL: + if (ldb_dn_get_comp_num(dn) == (ldb_dn_get_comp_num(base) + 1)) { + if (ldb_dn_compare_base(base, dn) == 0) { + ret = 1; + } + } + break; + + case LDB_SCOPE_SUBTREE: + default: + if (ldb_dn_compare_base(base, dn) == 0) { + ret = 1; + } + break; + } + + return ret; +} + + +/* + match if node is present +*/ +static int ldb_match_present(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + enum ldb_scope scope, bool *matched) +{ + const struct ldb_schema_attribute *a; + struct ldb_message_element *el; + + if (ldb_attr_dn(tree->u.present.attr) == 0) { + *matched = true; + return LDB_SUCCESS; + } + + el = ldb_msg_find_element(msg, tree->u.present.attr); + if (el == NULL) { + *matched = false; + return LDB_SUCCESS; + } + + a = ldb_schema_attribute_by_name(ldb, el->name); + if (!a) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (a->syntax->operator_fn) { + unsigned int i; + for (i = 0; i < el->num_values; i++) { + int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched); + if (ret != LDB_SUCCESS) return ret; + if (*matched) return LDB_SUCCESS; + } + *matched = false; + return LDB_SUCCESS; + } + + *matched = true; + return LDB_SUCCESS; +} + +static int ldb_match_comparison(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + enum ldb_scope scope, + enum ldb_parse_op comp_op, bool *matched) +{ + unsigned int i; + struct ldb_message_element *el; + const struct ldb_schema_attribute *a; + + /* FIXME: APPROX comparison not handled yet */ + if (comp_op == LDB_OP_APPROX) { + return LDB_ERR_INAPPROPRIATE_MATCHING; + } + + el = ldb_msg_find_element(msg, tree->u.comparison.attr); + if (el == NULL) { + *matched = false; + return LDB_SUCCESS; + } + + a = ldb_schema_attribute_by_name(ldb, el->name); + if (!a) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + for (i = 0; i < el->num_values; i++) { + if (a->syntax->operator_fn) { + int ret; + ret = a->syntax->operator_fn(ldb, comp_op, a, &el->values[i], &tree->u.comparison.value, matched); + if (ret != LDB_SUCCESS) return ret; + if (*matched) return LDB_SUCCESS; + } else { + int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value); + + if (ret == 0) { + *matched = true; + return LDB_SUCCESS; + } + if (ret > 0 && comp_op == LDB_OP_GREATER) { + *matched = true; + return LDB_SUCCESS; + } + if (ret < 0 && comp_op == LDB_OP_LESS) { + *matched = true; + return LDB_SUCCESS; + } + } + } + + *matched = false; + return LDB_SUCCESS; +} + +/* + match a simple leaf node +*/ +static int ldb_match_equality(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + enum ldb_scope scope, + bool *matched) +{ + unsigned int i; + struct ldb_message_element *el; + const struct ldb_schema_attribute *a; + struct ldb_dn *valuedn; + int ret; + + if (ldb_attr_dn(tree->u.equality.attr) == 0) { + valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value); + if (valuedn == NULL) { + return LDB_ERR_INVALID_DN_SYNTAX; + } + + ret = ldb_dn_compare(msg->dn, valuedn); + + talloc_free(valuedn); + + *matched = (ret == 0); + return LDB_SUCCESS; + } + + /* TODO: handle the "*" case derived from an extended search + operation without the attibute type defined */ + el = ldb_msg_find_element(msg, tree->u.equality.attr); + if (el == NULL) { + *matched = false; + return LDB_SUCCESS; + } + + a = ldb_schema_attribute_by_name(ldb, el->name); + if (a == NULL) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + for (i=0;inum_values;i++) { + if (a->syntax->operator_fn) { + ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a, + &tree->u.equality.value, &el->values[i], matched); + if (ret != LDB_SUCCESS) return ret; + if (*matched) return LDB_SUCCESS; + } else { + if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value, + &el->values[i]) == 0) { + *matched = true; + return LDB_SUCCESS; + } + } + } + + *matched = false; + return LDB_SUCCESS; +} + +static int ldb_wildcard_compare(struct ldb_context *ldb, + const struct ldb_parse_tree *tree, + const struct ldb_val value, bool *matched) +{ + const struct ldb_schema_attribute *a; + struct ldb_val val; + struct ldb_val cnk; + struct ldb_val *chunk; + uint8_t *save_p = NULL; + unsigned int c = 0; + + if (tree->operation != LDB_OP_SUBSTRING) { + *matched = false; + return LDB_ERR_INAPPROPRIATE_MATCHING; + } + + a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr); + if (!a) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (tree->u.substring.chunks == NULL) { + *matched = false; + return LDB_SUCCESS; + } + + if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + save_p = val.data; + cnk.data = NULL; + + if ( ! tree->u.substring.start_with_wildcard ) { + + chunk = tree->u.substring.chunks[c]; + if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch; + + /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */ + if (cnk.length > val.length) { + goto mismatch; + } + /* + * Empty strings are returned as length 0. Ensure + * we can cope with this. + */ + if (cnk.length == 0) { + goto mismatch; + } + + if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch; + val.length -= cnk.length; + val.data += cnk.length; + c++; + talloc_free(cnk.data); + cnk.data = NULL; + } + + while (tree->u.substring.chunks[c]) { + uint8_t *p; + + chunk = tree->u.substring.chunks[c]; + if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch; + + /* + * Empty strings are returned as length 0. Ensure + * we can cope with this. + */ + if (cnk.length == 0) { + goto mismatch; + } + /* + * Values might be binary blobs. Don't use string + * search, but memory search instead. + */ + p = memmem((const void *)val.data,val.length, + (const void *)cnk.data, cnk.length); + if (p == NULL) goto mismatch; + + /* + * At this point we know cnk.length <= val.length as + * otherwise there could be no match + */ + + if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) { + uint8_t *g; + uint8_t *end = val.data + val.length; + do { /* greedy */ + + /* + * haystack is a valid pointer in val + * because the memmem() can only + * succeed if the needle (cnk.length) + * is <= haystacklen + * + * p will be a pointer at least + * cnk.length from the end of haystack + */ + uint8_t *haystack + = p + cnk.length; + size_t haystacklen + = end - (haystack); + + g = memmem(haystack, + haystacklen, + (const uint8_t *)cnk.data, + cnk.length); + if (g) { + p = g; + } + } while(g); + } + val.length = val.length - (p - (uint8_t *)(val.data)) - cnk.length; + val.data = (uint8_t *)(p + cnk.length); + c++; + talloc_free(cnk.data); + cnk.data = NULL; + } + + /* last chunk may not have reached end of string */ + if ( (! tree->u.substring.end_with_wildcard) && (val.length != 0) ) goto mismatch; + talloc_free(save_p); + *matched = true; + return LDB_SUCCESS; + +mismatch: + *matched = false; + talloc_free(save_p); + talloc_free(cnk.data); + return LDB_SUCCESS; +} + +/* + match a simple leaf node +*/ +static int ldb_match_substring(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + enum ldb_scope scope, bool *matched) +{ + unsigned int i; + struct ldb_message_element *el; + + el = ldb_msg_find_element(msg, tree->u.substring.attr); + if (el == NULL) { + *matched = false; + return LDB_SUCCESS; + } + + for (i = 0; i < el->num_values; i++) { + int ret; + ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched); + if (ret != LDB_SUCCESS) return ret; + if (*matched) return LDB_SUCCESS; + } + + *matched = false; + return LDB_SUCCESS; +} + + +/* + bitwise and/or comparator depending on oid +*/ +static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2, + bool *matched) +{ + uint64_t i1, i2; + char ibuf[100]; + char *endptr = NULL; + + if (v1->length >= sizeof(ibuf)-1) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + memcpy(ibuf, (char *)v1->data, v1->length); + ibuf[v1->length] = 0; + i1 = strtoull(ibuf, &endptr, 0); + if (endptr != NULL) { + if (endptr == ibuf || *endptr != 0) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + } + + if (v2->length >= sizeof(ibuf)-1) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + endptr = NULL; + memcpy(ibuf, (char *)v2->data, v2->length); + ibuf[v2->length] = 0; + i2 = strtoull(ibuf, &endptr, 0); + if (endptr != NULL) { + if (endptr == ibuf || *endptr != 0) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + } + if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) { + *matched = ((i1 & i2) == i2); + } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) { + *matched = ((i1 & i2) != 0); + } else { + return LDB_ERR_INAPPROPRIATE_MATCHING; + } + return LDB_SUCCESS; +} + +static int ldb_match_bitmask(struct ldb_context *ldb, + const char *oid, + const struct ldb_message *msg, + const char *attribute_to_match, + const struct ldb_val *value_to_match, + bool *matched) +{ + unsigned int i; + struct ldb_message_element *el; + + /* find the message element */ + el = ldb_msg_find_element(msg, attribute_to_match); + if (el == NULL) { + *matched = false; + return LDB_SUCCESS; + } + + for (i=0;inum_values;i++) { + int ret; + struct ldb_val *v = &el->values[i]; + + ret = ldb_comparator_bitmask(oid, v, value_to_match, matched); + if (ret != LDB_SUCCESS) { + return ret; + } + if (*matched) { + return LDB_SUCCESS; + } + } + + *matched = false; + return LDB_SUCCESS; +} + +/* + always return false +*/ +static int ldb_comparator_false(struct ldb_context *ldb, + const char *oid, + const struct ldb_message *msg, + const char *attribute_to_match, + const struct ldb_val *value_to_match, + bool *matched) +{ + *matched = false; + return LDB_SUCCESS; +} + + +static const struct ldb_extended_match_rule *ldb_find_extended_match_rule(struct ldb_context *ldb, + const char *oid) +{ + struct ldb_extended_match_entry *extended_match_rule; + + for (extended_match_rule = ldb->extended_match_rules; + extended_match_rule; + extended_match_rule = extended_match_rule->next) { + if (strcmp(extended_match_rule->rule->oid, oid) == 0) { + return extended_match_rule->rule; + } + } + + return NULL; +} + + +/* + extended match, handles things like bitops +*/ +static int ldb_match_extended(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + enum ldb_scope scope, bool *matched) +{ + const struct ldb_extended_match_rule *rule; + + if (tree->u.extended.dnAttributes) { + /* FIXME: We really need to find out what this ":dn" part in + * an extended match means and how to handle it. For now print + * only a warning to have s3 winbind and other tools working + * against us. - Matthias */ + ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb: dnAttributes extended match not supported yet"); + } + if (tree->u.extended.rule_id == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet"); + return LDB_ERR_INAPPROPRIATE_MATCHING; + } + if (tree->u.extended.attr == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet"); + return LDB_ERR_INAPPROPRIATE_MATCHING; + } + + rule = ldb_find_extended_match_rule(ldb, tree->u.extended.rule_id); + if (rule == NULL) { + *matched = false; + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s", + tree->u.extended.rule_id); + return LDB_SUCCESS; + } + + return rule->callback(ldb, rule->oid, msg, + tree->u.extended.attr, + &tree->u.extended.value, matched); +} + +/* + Check if a particular message will match the given filter + + set *matched to true if it matches, false otherwise + + returns LDB_SUCCESS or an error + + this is a recursive function, and does short-circuit evaluation + */ +int ldb_match_message(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + enum ldb_scope scope, bool *matched) +{ + unsigned int i; + int ret; + + *matched = false; + + if (scope != LDB_SCOPE_BASE && ldb_dn_is_special(msg->dn)) { + /* don't match special records except on base searches */ + return LDB_SUCCESS; + } + + switch (tree->operation) { + case LDB_OP_AND: + for (i=0;iu.list.num_elements;i++) { + ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched); + if (ret != LDB_SUCCESS) return ret; + if (!*matched) return LDB_SUCCESS; + } + *matched = true; + return LDB_SUCCESS; + + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched); + if (ret != LDB_SUCCESS) return ret; + if (*matched) return LDB_SUCCESS; + } + *matched = false; + return LDB_SUCCESS; + + case LDB_OP_NOT: + ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched); + if (ret != LDB_SUCCESS) return ret; + *matched = ! *matched; + return LDB_SUCCESS; + + case LDB_OP_EQUALITY: + return ldb_match_equality(ldb, msg, tree, scope, matched); + + case LDB_OP_SUBSTRING: + return ldb_match_substring(ldb, msg, tree, scope, matched); + + case LDB_OP_GREATER: + return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched); + + case LDB_OP_LESS: + return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched); + + case LDB_OP_PRESENT: + return ldb_match_present(ldb, msg, tree, scope, matched); + + case LDB_OP_APPROX: + return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX, matched); + + case LDB_OP_EXTENDED: + return ldb_match_extended(ldb, msg, tree, scope, matched); + } + + return LDB_ERR_INAPPROPRIATE_MATCHING; +} + +/* + return 0 if the given parse tree matches the given message. Assumes + the message is in sorted order + + return 1 if it matches, and 0 if it doesn't match +*/ + +int ldb_match_msg(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + struct ldb_dn *base, + enum ldb_scope scope) +{ + bool matched; + int ret; + + if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) { + return 0; + } + + ret = ldb_match_message(ldb, msg, tree, scope, &matched); + if (ret != LDB_SUCCESS) { + /* to match the old API, we need to consider this a + failure to match */ + return 0; + } + return matched?1:0; +} + +int ldb_match_msg_error(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + struct ldb_dn *base, + enum ldb_scope scope, + bool *matched) +{ + if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) { + *matched = false; + return LDB_SUCCESS; + } + + return ldb_match_message(ldb, msg, tree, scope, matched); +} + +int ldb_match_msg_objectclass(const struct ldb_message *msg, + const char *objectclass) +{ + unsigned int i; + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + if (!el) { + return 0; + } + for (i=0; i < el->num_values; i++) { + if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) { + return 1; + } + } + return 0; +} + +_PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb) +{ + struct ldb_extended_match_rule *bitmask_and; + struct ldb_extended_match_rule *bitmask_or; + struct ldb_extended_match_rule *always_false; + int ret; + + /* Register bitmask-and match */ + bitmask_and = talloc_zero(ldb, struct ldb_extended_match_rule); + if (bitmask_and == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + bitmask_and->oid = LDB_OID_COMPARATOR_AND; + bitmask_and->callback = ldb_match_bitmask; + + ret = ldb_register_extended_match_rule(ldb, bitmask_and); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* Register bitmask-or match */ + bitmask_or = talloc_zero(ldb, struct ldb_extended_match_rule); + if (bitmask_or == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + bitmask_or->oid = LDB_OID_COMPARATOR_OR; + bitmask_or->callback = ldb_match_bitmask; + + ret = ldb_register_extended_match_rule(ldb, bitmask_or); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* Register always-false match */ + always_false = talloc_zero(ldb, struct ldb_extended_match_rule); + if (always_false == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + always_false->oid = SAMBA_LDAP_MATCH_ALWAYS_FALSE; + always_false->callback = ldb_comparator_false; + + ret = ldb_register_extended_match_rule(ldb, always_false); + if (ret != LDB_SUCCESS) { + return ret; + } + + return LDB_SUCCESS; +} + +/* + register a new ldb extended matching rule +*/ +int ldb_register_extended_match_rule(struct ldb_context *ldb, + const struct ldb_extended_match_rule *rule) +{ + const struct ldb_extended_match_rule *lookup_rule; + struct ldb_extended_match_entry *entry; + + lookup_rule = ldb_find_extended_match_rule(ldb, rule->oid); + if (lookup_rule) { + return LDB_ERR_ENTRY_ALREADY_EXISTS; + } + + entry = talloc_zero(ldb, struct ldb_extended_match_entry); + if (!entry) { + return LDB_ERR_OPERATIONS_ERROR; + } + entry->rule = rule; + DLIST_ADD_END(ldb->extended_match_rules, entry); + + return LDB_SUCCESS; +} + diff --git a/ldb-2.0.8/common/ldb_modules.c b/ldb-2.0.8/common/ldb_modules.c new file mode 100644 index 0000000..cc067ab --- /dev/null +++ b/ldb-2.0.8/common/ldb_modules.c @@ -0,0 +1,1236 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004-2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb modules core + * + * Description: core modules routines + * + * Author: Simo Sorce + */ + +#include "ldb_private.h" +#include "dlinklist.h" +#include "system/dir.h" + +static char *ldb_modules_strdup_no_spaces(TALLOC_CTX *mem_ctx, const char *string) +{ + size_t i, len; + char *trimmed; + + trimmed = talloc_strdup(mem_ctx, string); + if (!trimmed) { + return NULL; + } + + len = strlen(trimmed); + for (i = 0; trimmed[i] != '\0'; i++) { + switch (trimmed[i]) { + case ' ': + case '\t': + case '\n': + memmove(&trimmed[i], &trimmed[i + 1], len -i -1); + break; + } + } + + return trimmed; +} + + +/* modules are called in inverse order on the stack. + Lets place them as an admin would think the right order is. + Modules order is important */ +const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string) +{ + char **modules = NULL; + const char **m; + char *modstr, *p; + unsigned int i; + + /* spaces not admitted */ + modstr = ldb_modules_strdup_no_spaces(mem_ctx, string); + if ( ! modstr) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_strdup_no_spaces()"); + return NULL; + } + + modules = talloc_realloc(mem_ctx, modules, char *, 2); + if ( ! modules ) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()"); + talloc_free(modstr); + return NULL; + } + talloc_steal(modules, modstr); + + if (modstr[0] == '\0') { + modules[0] = NULL; + m = discard_const_p(const char *, modules); + return m; + } + + i = 0; + /* The str*r*chr walks backwards: This is how we get the inverse order mentioned above */ + while ((p = strrchr(modstr, ',')) != NULL) { + *p = '\0'; + p++; + modules[i] = p; + + i++; + modules = talloc_realloc(mem_ctx, modules, char *, i + 2); + if ( ! modules ) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()"); + return NULL; + } + + } + modules[i] = modstr; + + modules[i + 1] = NULL; + + m = discard_const_p(const char *, modules); + + return m; +} + +static struct backends_list_entry { + struct ldb_backend_ops *ops; + struct backends_list_entry *prev, *next; +} *ldb_backends = NULL; + +static struct ops_list_entry { + const struct ldb_module_ops *ops; + struct ops_list_entry *next; +} *registered_modules = NULL; + +static struct backends_list_entry *ldb_find_backend(const char *url_prefix) +{ + struct backends_list_entry *backend; + + for (backend = ldb_backends; backend; backend = backend->next) { + if (strcmp(backend->ops->name, url_prefix) == 0) { + return backend; + } + } + + return NULL; +} + +/* + register a new ldb backend + + if override is true, then override any existing backend for this prefix +*/ +int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn, bool override) +{ + struct backends_list_entry *be; + + be = ldb_find_backend(url_prefix); + if (be) { + if (!override) { + return LDB_SUCCESS; + } + } else { + be = talloc_zero(ldb_backends, struct backends_list_entry); + if (!be) { + return LDB_ERR_OPERATIONS_ERROR; + } + be->ops = talloc_zero(be, struct ldb_backend_ops); + if (!be->ops) { + talloc_free(be); + return LDB_ERR_OPERATIONS_ERROR; + } + DLIST_ADD_END(ldb_backends, be); + } + + be->ops->name = url_prefix; + be->ops->connect_fn = connectfn; + + return LDB_SUCCESS; +} + +/* + Return the ldb module form of a database. + The URL can either be one of the following forms + ldb://path + ldapi://path + + flags is made up of LDB_FLG_* + + the options are passed uninterpreted to the backend, and are + backend specific. + + This allows modules to get at only the backend module, for example where a + module may wish to direct certain requests at a particular backend. +*/ +int ldb_module_connect_backend(struct ldb_context *ldb, + const char *url, + const char *options[], + struct ldb_module **backend_module) +{ + int ret; + char *backend; + struct backends_list_entry *be; + + if (strchr(url, ':') != NULL) { + backend = talloc_strndup(ldb, url, strchr(url, ':')-url); + } else { + /* Default to tdb */ + backend = talloc_strdup(ldb, "tdb"); + } + if (backend == NULL) { + return ldb_oom(ldb); + } + + be = ldb_find_backend(backend); + + talloc_free(backend); + + if (be == NULL) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "Unable to find backend for '%s' - do you need to set LDB_MODULES_PATH?", url); + return LDB_ERR_OTHER; + } + + ret = be->ops->connect_fn(ldb, url, ldb->flags, options, backend_module); + + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Failed to connect to '%s' with backend '%s': %s", url, be->ops->name, ldb_errstring(ldb)); + return ret; + } + return ret; +} + +static struct ldb_hooks { + struct ldb_hooks *next, *prev; + ldb_hook_fn hook_fn; +} *ldb_hooks; + +/* + register a ldb hook function + */ +int ldb_register_hook(ldb_hook_fn hook_fn) +{ + struct ldb_hooks *lc; + lc = talloc_zero(ldb_hooks, struct ldb_hooks); + if (lc == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + lc->hook_fn = hook_fn; + DLIST_ADD_END(ldb_hooks, lc); + return LDB_SUCCESS; +} + +/* + call ldb hooks of a given type + */ +int ldb_modules_hook(struct ldb_context *ldb, enum ldb_module_hook_type t) +{ + struct ldb_hooks *lc; + for (lc = ldb_hooks; lc; lc=lc->next) { + int ret = lc->hook_fn(ldb, t); + if (ret != LDB_SUCCESS) { + return ret; + } + } + return LDB_SUCCESS; +} + + +static const struct ldb_module_ops *ldb_find_module_ops(const char *name) +{ + struct ops_list_entry *e; + + for (e = registered_modules; e; e = e->next) { + if (strcmp(e->ops->name, name) == 0) + return e->ops; + } + + return NULL; +} + + +int ldb_register_module(const struct ldb_module_ops *ops) +{ + struct ops_list_entry *entry; + + if (ldb_find_module_ops(ops->name) != NULL) + return LDB_ERR_ENTRY_ALREADY_EXISTS; + + /* + * ldb modules are not (yet) unloaded and + * are only loaded once (the above check + * makes sure of this). Allocate off the NULL + * context. We never want this to be freed + * until process shutdown. If eventually we + * want to unload ldb modules we can add a + * deregister function that walks and + * frees the list. + */ + entry = talloc(NULL, struct ops_list_entry); + if (entry == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + entry->ops = ops; + entry->next = registered_modules; + registered_modules = entry; + + return LDB_SUCCESS; +} + +/* + load a list of modules + */ +int ldb_module_load_list(struct ldb_context *ldb, const char **module_list, + struct ldb_module *backend, struct ldb_module **out) +{ + struct ldb_module *module; + unsigned int i; + + module = backend; + + for (i = 0; module_list && module_list[i] != NULL; i++) { + struct ldb_module *current; + const struct ldb_module_ops *ops; + + if (strcmp(module_list[i], "") == 0) { + continue; + } + + ops = ldb_find_module_ops(module_list[i]); + + if (ops == NULL) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "WARNING: Module [%s] not found - do you need to set LDB_MODULES_PATH?", + module_list[i]); + return LDB_ERR_OPERATIONS_ERROR; + } + + current = talloc_zero(ldb, struct ldb_module); + if (current == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + talloc_set_name(current, "ldb_module: %s", module_list[i]); + + current->ldb = ldb; + current->ops = ops; + + DLIST_ADD(module, current); + } + *out = module; + return LDB_SUCCESS; +} + +/* + initialise a chain of modules + */ +int ldb_module_init_chain(struct ldb_context *ldb, struct ldb_module *module) +{ + while (module && module->ops->init_context == NULL) + module = module->next; + + /* init is different in that it is not an error if modules + * do not require initialization */ + + if (module) { + int ret = module->ops->init_context(module); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed : %s", + module->ops->name, ldb_strerror(ret)); + return ret; + } + } + + return LDB_SUCCESS; +} + +int ldb_load_modules(struct ldb_context *ldb, const char *options[]) +{ + const char *modules_string; + const char **modules = NULL; + int ret; + TALLOC_CTX *mem_ctx = talloc_new(ldb); + if (!mem_ctx) { + return ldb_oom(ldb); + } + + /* find out which modules we are requested to activate */ + + /* check if we have a custom module list passd as ldb option */ + if (options) { + modules_string = ldb_options_find(ldb, options, "modules"); + if (modules_string) { + modules = ldb_modules_list_from_string(ldb, mem_ctx, modules_string); + } + } + + /* if not overloaded by options and the backend is not ldap try to load the modules list from ldb */ + if ((modules == NULL) && (strcmp("ldap", ldb->modules->ops->name) != 0)) { + const char * const attrs[] = { "@LIST" , NULL}; + struct ldb_result *res = NULL; + struct ldb_dn *mods_dn; + + mods_dn = ldb_dn_new(mem_ctx, ldb, "@MODULES"); + if (mods_dn == NULL) { + talloc_free(mem_ctx); + return ldb_oom(ldb); + } + + ret = ldb_search(ldb, mods_dn, &res, mods_dn, LDB_SCOPE_BASE, attrs, "@LIST=*"); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db"); + } else if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out", ldb_errstring(ldb)); + talloc_free(mem_ctx); + return ret; + } else { + const char *module_list; + if (res->count == 0) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db"); + } else if (res->count > 1) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found (%u), bailing out", res->count); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } else { + module_list = ldb_msg_find_attr_as_string(res->msgs[0], "@LIST", NULL); + if (!module_list) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db"); + } + modules = ldb_modules_list_from_string(ldb, mem_ctx, + module_list); + } + } + + talloc_free(mods_dn); + } + + if (modules != NULL) { + ret = ldb_module_load_list(ldb, modules, ldb->modules, &ldb->modules); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + } else { + ldb_debug(ldb, LDB_DEBUG_TRACE, "No modules specified for this database"); + } + + ret = ldb_module_init_chain(ldb, ldb->modules); + talloc_free(mem_ctx); + return ret; +} + +/* + by using this we allow ldb modules to only implement the functions they care about, + which makes writing a module simpler, and makes it more likely to keep working + when ldb is extended +*/ +#define FIND_OP_NOERR(module, op) do { \ + module = module->next; \ + while (module && module->ops->op == NULL) module = module->next; \ + if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { \ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_trace_next_request: (%s)->" #op, \ + module->ops->name); \ + } \ +} while (0) + +#define FIND_OP(module, op) do { \ + struct ldb_context *ldb = module->ldb; \ + FIND_OP_NOERR(module, op); \ + if (module == NULL) { \ + ldb_asprintf_errstring(ldb, "Unable to find backend operation for " #op ); \ + return LDB_ERR_OPERATIONS_ERROR; \ + } \ +} while (0) + + +struct ldb_module *ldb_module_new(TALLOC_CTX *memctx, + struct ldb_context *ldb, + const char *module_name, + const struct ldb_module_ops *ops) +{ + struct ldb_module *module; + + module = talloc(memctx, struct ldb_module); + if (!module) { + ldb_oom(ldb); + return NULL; + } + talloc_set_name_const(module, module_name); + module->ldb = ldb; + module->prev = module->next = NULL; + module->ops = ops; + + return module; +} + +const char * ldb_module_get_name(struct ldb_module *module) +{ + return module->ops->name; +} + +struct ldb_context *ldb_module_get_ctx(struct ldb_module *module) +{ + return module->ldb; +} + +const struct ldb_module_ops *ldb_module_get_ops(struct ldb_module *module) +{ + return module->ops; +} + +void *ldb_module_get_private(struct ldb_module *module) +{ + return module->private_data; +} + +void ldb_module_set_private(struct ldb_module *module, void *private_data) +{ + module->private_data = private_data; +} + +/* + helper functions to call the next module in chain +*/ + +int ldb_next_request(struct ldb_module *module, struct ldb_request *request) +{ + int ret; + + if (request->callback == NULL) { + ldb_set_errstring(module->ldb, "Requests MUST define callbacks"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + request->handle->nesting++; + + switch (request->operation) { + case LDB_SEARCH: + FIND_OP(module, search); + ret = module->ops->search(module, request); + break; + case LDB_ADD: + FIND_OP(module, add); + ret = module->ops->add(module, request); + break; + case LDB_MODIFY: + FIND_OP(module, modify); + ret = module->ops->modify(module, request); + break; + case LDB_DELETE: + FIND_OP(module, del); + ret = module->ops->del(module, request); + break; + case LDB_RENAME: + FIND_OP(module, rename); + ret = module->ops->rename(module, request); + break; + case LDB_EXTENDED: + FIND_OP(module, extended); + ret = module->ops->extended(module, request); + break; + default: + FIND_OP(module, request); + ret = module->ops->request(module, request); + break; + } + + request->handle->nesting--; + + if (ret == LDB_SUCCESS) { + return ret; + } + if (!ldb_errstring(module->ldb)) { + const char *op; + switch (request->operation) { + case LDB_SEARCH: + op = "LDB_SEARCH"; + break; + case LDB_ADD: + op = "LDB_ADD"; + break; + case LDB_MODIFY: + op = "LDB_MODIFY"; + break; + case LDB_DELETE: + op = "LDB_DELETE"; + break; + case LDB_RENAME: + op = "LDB_RENAME"; + break; + case LDB_EXTENDED: + op = "LDB_EXTENDED"; + break; + default: + op = "request"; + break; + } + + /* Set a default error string, to place the blame somewhere */ + ldb_asprintf_errstring(module->ldb, "error in module %s: %s during %s (%d)", module->ops->name, ldb_strerror(ret), op, ret); + } + + if (!(request->handle->flags & LDB_HANDLE_FLAG_DONE_CALLED)) { + /* It is _extremely_ common that a module returns a + * failure without calling ldb_module_done(), but that + * guarantees we will end up hanging in + * ldb_wait(). This fixes it without having to rewrite + * all our modules, and leaves us one less sharp + * corner for module developers to cut themselves on + */ + ret = ldb_module_done(request, NULL, NULL, ret); + } + return ret; +} + +int ldb_next_init(struct ldb_module *module) +{ + module = module->next; + + return ldb_module_init_chain(module->ldb, module); +} + +int ldb_next_start_trans(struct ldb_module *module) +{ + int ret; + FIND_OP(module, start_transaction); + ret = module->ops->start_transaction(module); + if (ret == LDB_SUCCESS) { + return ret; + } + if (!ldb_errstring(module->ldb)) { + /* Set a default error string, to place the blame somewhere */ + ldb_asprintf_errstring(module->ldb, "start_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); + } + if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_start_trans error: %s", + ldb_errstring(module->ldb)); + } + return ret; +} + +int ldb_next_end_trans(struct ldb_module *module) +{ + int ret; + FIND_OP(module, end_transaction); + ret = module->ops->end_transaction(module); + if (ret == LDB_SUCCESS) { + return ret; + } + if (!ldb_errstring(module->ldb)) { + /* Set a default error string, to place the blame somewhere */ + ldb_asprintf_errstring(module->ldb, "end_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); + } + if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_end_trans error: %s", + ldb_errstring(module->ldb)); + } + return ret; +} + +int ldb_next_read_lock(struct ldb_module *module) +{ + int ret; + FIND_OP(module, read_lock); + ret = module->ops->read_lock(module); + if (ret == LDB_SUCCESS) { + return ret; + } + if (!ldb_errstring(module->ldb)) { + /* Set a default error string, to place the blame somewhere */ + ldb_asprintf_errstring(module->ldb, + "read_lock error in module %s: %s (%d)", + module->ops->name, ldb_strerror(ret), + ret); + } + if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, + "ldb_next_read_lock error: %s", + ldb_errstring(module->ldb)); + } + return ret; +} + +int ldb_next_read_unlock(struct ldb_module *module) +{ + int ret; + FIND_OP(module, read_unlock); + ret = module->ops->read_unlock(module); + if (ret == LDB_SUCCESS) { + return ret; + } + if (!ldb_errstring(module->ldb)) { + /* Set a default error string, to place the blame somewhere */ + ldb_asprintf_errstring(module->ldb, + "read_unlock error in module %s: %s (%d)", + module->ops->name, ldb_strerror(ret), + ret); + } + if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, + "ldb_next_read_unlock error: %s", + ldb_errstring(module->ldb)); + } + return ret; +} + +int ldb_next_prepare_commit(struct ldb_module *module) +{ + int ret; + FIND_OP_NOERR(module, prepare_commit); + if (module == NULL) { + /* we are allowed to have no prepare commit in + backends */ + return LDB_SUCCESS; + } + ret = module->ops->prepare_commit(module); + if (ret == LDB_SUCCESS) { + return ret; + } + if (!ldb_errstring(module->ldb)) { + /* Set a default error string, to place the blame somewhere */ + ldb_asprintf_errstring(module->ldb, "prepare_commit error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); + } + if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_prepare_commit error: %s", + ldb_errstring(module->ldb)); + } + return ret; +} + +int ldb_next_del_trans(struct ldb_module *module) +{ + int ret; + FIND_OP(module, del_transaction); + ret = module->ops->del_transaction(module); + if (ret == LDB_SUCCESS) { + return ret; + } + if (!ldb_errstring(module->ldb)) { + /* Set a default error string, to place the blame somewhere */ + ldb_asprintf_errstring(module->ldb, "del_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); + } + if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_del_trans error: %s", + ldb_errstring(module->ldb)); + } + return ret; +} + +/* calls the request callback to send an entry + * + * params: + * req: the original request passed to your module + * msg: reply message (must be a talloc pointer, and it will be stolen + * on the ldb_reply that is sent to the callback) + * ctrls: controls to send in the reply (must be a talloc pointer, and it will be stolen + * on the ldb_reply that is sent to the callback) + */ + +int ldb_module_send_entry(struct ldb_request *req, + struct ldb_message *msg, + struct ldb_control **ctrls) +{ + struct ldb_reply *ares; + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(req->handle->ldb); + req->callback(req, NULL); + return LDB_ERR_OPERATIONS_ERROR; + } + ares->type = LDB_REPLY_ENTRY; + ares->message = talloc_steal(ares, msg); + ares->controls = talloc_steal(ares, ctrls); + ares->error = LDB_SUCCESS; + + if ((req->handle->ldb->flags & LDB_FLG_ENABLE_TRACING) && + req->handle->nesting == 0) { + char *s; + struct ldb_ldif ldif; + + ldif.changetype = LDB_CHANGETYPE_NONE; + ldif.msg = discard_const_p(struct ldb_message, msg); + + ldb_debug_add(req->handle->ldb, "ldb_trace_response: ENTRY\n"); + + /* + * The choice to call + * ldb_ldif_write_redacted_trace_string() is CRITICAL + * for security. It ensures that we do not output + * passwords into debug logs + */ + + s = ldb_ldif_write_redacted_trace_string(req->handle->ldb, msg, &ldif); + ldb_debug_add(req->handle->ldb, "%s\n", s); + talloc_free(s); + ldb_debug_end(req->handle->ldb, LDB_DEBUG_TRACE); + } + + return req->callback(req, ares); +} + +/* calls the request callback to send an referrals + * + * params: + * req: the original request passed to your module + * ref: referral string (must be a talloc pointer, steal) + */ + +int ldb_module_send_referral(struct ldb_request *req, + char *ref) +{ + struct ldb_reply *ares; + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(req->handle->ldb); + req->callback(req, NULL); + return LDB_ERR_OPERATIONS_ERROR; + } + ares->type = LDB_REPLY_REFERRAL; + ares->referral = talloc_steal(ares, ref); + ares->error = LDB_SUCCESS; + + if ((req->handle->ldb->flags & LDB_FLG_ENABLE_TRACING) && + req->handle->nesting == 0) { + ldb_debug_add(req->handle->ldb, "ldb_trace_response: REFERRAL\n"); + ldb_debug_add(req->handle->ldb, "ref: %s\n", ref); + ldb_debug_end(req->handle->ldb, LDB_DEBUG_TRACE); + } + + return req->callback(req, ares); +} + +/* calls the original request callback + * + * params: + * req: the original request passed to your module + * ctrls: controls to send in the reply (must be a talloc pointer, steal) + * response: results for extended request (steal) + * error: LDB_SUCCESS for a successful return + * any other ldb error otherwise + */ +int ldb_module_done(struct ldb_request *req, + struct ldb_control **ctrls, + struct ldb_extended *response, + int error) +{ + struct ldb_reply *ares; + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(req->handle->ldb); + req->callback(req, NULL); + return LDB_ERR_OPERATIONS_ERROR; + } + ares->type = LDB_REPLY_DONE; + ares->controls = talloc_steal(ares, ctrls); + ares->response = talloc_steal(ares, response); + ares->error = error; + + req->handle->flags |= LDB_HANDLE_FLAG_DONE_CALLED; + + if ((req->handle->ldb->flags & LDB_FLG_ENABLE_TRACING) && + req->handle->nesting == 0) { + ldb_debug_add(req->handle->ldb, "ldb_trace_response: DONE\n"); + ldb_debug_add(req->handle->ldb, "error: %d\n", error); + if (ldb_errstring(req->handle->ldb)) { + ldb_debug_add(req->handle->ldb, "msg: %s\n", + ldb_errstring(req->handle->ldb)); + } + ldb_debug_end(req->handle->ldb, LDB_DEBUG_TRACE); + } + + return req->callback(req, ares); +} + +/* to be used *only* in modules init functions. + * this function is synchronous and will register + * the requested OID in the rootdse module if present + * otherwise it will return an error */ +int ldb_mod_register_control(struct ldb_module *module, const char *oid) +{ + struct ldb_request *req; + int ret; + + req = talloc_zero(module, struct ldb_request); + if (req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_REQ_REGISTER_CONTROL; + req->op.reg_control.oid = oid; + req->callback = ldb_op_default_callback; + + ldb_set_timeout(module->ldb, req, 0); + + req->handle = ldb_handle_new(req, module->ldb); + if (req->handle == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_request(module->ldb, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + talloc_free(req); + + return ret; +} + +static int ldb_modules_load_dir(const char *modules_dir, const char *version); + + +/* + load one module. A static list of loaded module inode numbers is + used to prevent a module being loaded twice + + dlopen() is used on the module, and dlsym() is then used to look for + a ldb_init_module() function. If present, that function is called + with the ldb version number as an argument. + + The ldb_init_module() function will typically call + ldb_register_module() and ldb_register_backend() to register a + module or backend, but it may also be used to register command line + handling functions, ldif handlers or any other local + modififications. + + The ldb_init_module() function does not get a ldb_context passed in, + as modules will be used for multiple ldb context handles. The call + from the first ldb_init() is just a convenient way to ensure it is + called early enough. + */ +static int ldb_modules_load_path(const char *path, const char *version) +{ + void *handle; + int (*init_fn)(const char *); + int ret; + struct stat st; + static struct loaded { + struct loaded *next, *prev; + ino_t st_ino; + dev_t st_dev; + } *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) { + fprintf(stderr, "ldb: unable to stat module %s : %s\n", path, strerror(errno)); + return LDB_ERR_UNAVAILABLE; + } + + for (le=loaded; le; le=le->next) { + if (le->st_ino == st.st_ino && + le->st_dev == st.st_dev) { + /* its already loaded */ + return LDB_SUCCESS; + } + } + + le = talloc(loaded, struct loaded); + if (le == NULL) { + fprintf(stderr, "ldb: unable to allocated loaded entry\n"); + return LDB_ERR_UNAVAILABLE; + } + + le->st_ino = st.st_ino; + le->st_dev = st.st_dev; + + DLIST_ADD_END(loaded, le); + + /* if it is a directory, recurse */ + if (S_ISDIR(st.st_mode)) { + return ldb_modules_load_dir(path, version); + } + + dlopen_flags = RTLD_NOW; +#ifdef RTLD_DEEPBIND + /* + * use deepbind if possible, to avoid issues with different + * 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 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. + * + * So in future we may remove this completely + * or at least invert the default behavior. + */ + if (deepbind_enabled) { + dlopen_flags |= RTLD_DEEPBIND; + } +#endif + + handle = dlopen(path, dlopen_flags); + if (handle == NULL) { + fprintf(stderr, "ldb: unable to dlopen %s : %s\n", path, dlerror()); + return LDB_SUCCESS; + } + + init_fn = dlsym(handle, "ldb_init_module"); + if (init_fn == NULL) { + /* ignore it, it could be an old-style + * module. Once we've converted all modules we + * could consider this an error */ + dlclose(handle); + return LDB_SUCCESS; + } + + ret = init_fn(version); + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + /* the module is already registered - ignore this, as + * it can happen if LDB_MODULES_PATH points at both + * the build and install directory + */ + ret = LDB_SUCCESS; + } + return ret; +} + +static int qsort_string(const char **s1, const char **s2) +{ + return strcmp(*s1, *s2); +} + + +/* + load all modules from the given ldb modules directory. This is run once + during the first ldb_init() call. + + Modules are loaded in alphabetical order to ensure that any module + load ordering dependencies are reproducible. Modules should avoid + relying on load order + */ +static int ldb_modules_load_dir(const char *modules_dir, const char *version) +{ + DIR *dir; + struct dirent *de; + const char **modlist = NULL; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + unsigned i, num_modules = 0; + + dir = opendir(modules_dir); + if (dir == NULL) { + if (errno == ENOENT) { + talloc_free(tmp_ctx); + /* we don't have any modules */ + return LDB_SUCCESS; + } + talloc_free(tmp_ctx); + fprintf(stderr, "ldb: unable to open modules directory '%s' - %s\n", + modules_dir, strerror(errno)); + return LDB_ERR_UNAVAILABLE; + } + + + while ((de = readdir(dir))) { + if (ISDOT(de->d_name) || ISDOTDOT(de->d_name)) + continue; + + modlist = talloc_realloc(tmp_ctx, modlist, const char *, num_modules+1); + if (modlist == NULL) { + talloc_free(tmp_ctx); + closedir(dir); + fprintf(stderr, "ldb: unable to allocate modules list\n"); + return LDB_ERR_UNAVAILABLE; + } + modlist[num_modules] = talloc_asprintf(modlist, "%s/%s", modules_dir, de->d_name); + if (modlist[num_modules] == NULL) { + talloc_free(tmp_ctx); + closedir(dir); + fprintf(stderr, "ldb: unable to allocate module list entry\n"); + return LDB_ERR_UNAVAILABLE; + } + num_modules++; + } + + closedir(dir); + + /* sort the directory, so we get consistent load ordering */ + TYPESAFE_QSORT(modlist, num_modules, qsort_string); + + for (i=0; ihandle) { + char *s = talloc_asprintf_append_buffer(ret, "req[%u] %p : %s\n", + i++, req, ldb_req_location(req)); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + ret = s; + req = req->handle->parent; + } + return ret; +} + + +/* + return the next module in the chain + */ +struct ldb_module *ldb_module_next(struct ldb_module *module) +{ + return module->next; +} + +/* + set the next module in the module chain + */ +void ldb_module_set_next(struct ldb_module *module, struct ldb_module *next) +{ + module->next = next; +} + + +/* + get the popt_options pointer in the ldb structure. This allows a ldb + module to change the command line parsing + */ +struct poptOption **ldb_module_popt_options(struct ldb_context *ldb) +{ + return &ldb->popt_options; +} + + +/* + return the current ldb flags LDB_FLG_* + */ +uint32_t ldb_module_flags(struct ldb_context *ldb) +{ + return ldb->flags; +} diff --git a/ldb-2.0.8/common/ldb_msg.c b/ldb-2.0.8/common/ldb_msg.c new file mode 100644 index 0000000..2346e66 --- /dev/null +++ b/ldb-2.0.8/common/ldb_msg.c @@ -0,0 +1,1469 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb message component utility functions + * + * Description: functions for manipulating ldb_message structures + * + * Author: Andrew Tridgell + */ + +#include "ldb_private.h" + +/* + create a new ldb_message in a given memory context (NULL for top level) +*/ +struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx) +{ + return talloc_zero(mem_ctx, struct ldb_message); +} + +/* + find an element in a message by attribute name +*/ +struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, + const char *attr_name) +{ + unsigned int i; + for (i=0;inum_elements;i++) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { + return &msg->elements[i]; + } + } + return NULL; +} + +/* + see if two ldb_val structures contain exactly the same data + return 1 for a match, 0 for a mis-match +*/ +int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) return 0; + if (v1->data == v2->data) return 1; + if (v1->length == 0) return 1; + + if (memcmp(v1->data, v2->data, v1->length) == 0) { + return 1; + } + + return 0; +} + +/* + find a value in an element + assumes case sensitive comparison +*/ +struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, + struct ldb_val *val) +{ + unsigned int i; + for (i=0;inum_values;i++) { + if (ldb_val_equal_exact(val, &el->values[i])) { + return &el->values[i]; + } + } + return NULL; +} + + +static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) { + return v1->length - v2->length; + } + return memcmp(v1->data, v2->data, v1->length); +} + + +/* + ldb_msg_find_duplicate_val() will set the **duplicate pointer to the first + duplicate value it finds. It does a case sensitive comparison (memcmp). + + LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown + options flag, otherwise LDB_SUCCESS. +*/ +#define LDB_DUP_QUADRATIC_THRESHOLD 10 + +int ldb_msg_find_duplicate_val(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message_element *el, + struct ldb_val **duplicate, + uint32_t options) +{ + unsigned int i, j; + struct ldb_val *val; + + if (options != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + *duplicate = NULL; + + /* + If there are not many values, it is best to avoid the talloc + overhead and just do a brute force search. + */ + if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) { + for (j = 0; j < el->num_values; j++) { + val = &el->values[j]; + for ( i = j + 1; i < el->num_values; i++) { + if (ldb_val_equal_exact(val, &el->values[i])) { + *duplicate = val; + return LDB_SUCCESS; + } + } + } + } else { + struct ldb_val *values; + values = talloc_array(mem_ctx, struct ldb_val, el->num_values); + if (values == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + memcpy(values, el->values, + el->num_values * sizeof(struct ldb_val)); + TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp); + for (i = 1; i < el->num_values; i++) { + if (ldb_val_equal_exact(&values[i], + &values[i - 1])) { + /* find the original location */ + for (j = 0; j < el->num_values; j++) { + if (ldb_val_equal_exact(&values[i], + &el->values[j]) + ) { + *duplicate = &el->values[j]; + break; + } + } + talloc_free(values); + if (*duplicate == NULL) { + /* how we got here, I don't know */ + return LDB_ERR_OPERATIONS_ERROR; + } + return LDB_SUCCESS; + } + } + talloc_free(values); + } + return LDB_SUCCESS; +} + + +/* + Determine whether the values in an element are also in another element. + + Without any flags, return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS if the elements + share values, or LDB_SUCCESS if they don't. In this case, the function + simply determines the set intersection and it doesn't matter in which order + the elements are provided. + + With the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, any values in common are + removed from the first element and LDB_SUCCESS is returned. + + LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown option. + LDB_ERR_INAPPROPRIATE_MATCHING is returned if the elements differ in name. +*/ + +int ldb_msg_find_common_values(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_message_element *el, + struct ldb_message_element *el2, + uint32_t options) +{ + struct ldb_val *values; + struct ldb_val *values2; + unsigned int i, j, k, n_values; + + bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES; + + if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (strcmp(el->name, el2->name) != 0) { + return LDB_ERR_INAPPROPRIATE_MATCHING; + } + if (el->num_values == 0 || el2->num_values == 0) { + return LDB_SUCCESS; + } + /* + With few values, it is better to do the brute-force search than the + clever search involving tallocs, memcpys, sorts, etc. + */ + if (MIN(el->num_values, el2->num_values) == 1 || + MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) { + for (i = 0; i < el2->num_values; i++) { + for (j = 0; j < el->num_values; j++) { + if (ldb_val_equal_exact(&el->values[j], + &el2->values[i])) { + if (! remove_duplicates) { + return \ + LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + /* + With the remove_duplicates flag, we + resolve the intersection by removing + the offending one from el. + */ + el->num_values--; + for (k = j; k < el->num_values; k++) { + el->values[k] = \ + el->values[k + 1]; + } + j--; /* rewind */ + } + } + } + return LDB_SUCCESS; + } + + values = talloc_array(mem_ctx, struct ldb_val, el->num_values); + if (values == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + values2 = talloc_array(mem_ctx, struct ldb_val, + el2->num_values); + if (values2 == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + memcpy(values, el->values, + el->num_values * sizeof(struct ldb_val)); + memcpy(values2, el2->values, + el2->num_values * sizeof(struct ldb_val)); + TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp); + TYPESAFE_QSORT(values2, el2->num_values, ldb_val_cmp); + + /* + el->n_values may diverge from the number of values in the sorted + list when the remove_duplicates flag is used. + */ + n_values = el->num_values; + i = 0; + j = 0; + while (i != n_values && j < el2->num_values) { + int ret = ldb_val_cmp(&values[i], &values2[j]); + if (ret < 0) { + i++; + } else if (ret > 0) { + j++; + } else { + /* we have a collision */ + if (! remove_duplicates) { + TALLOC_FREE(values); + TALLOC_FREE(values2); + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + /* + With the remove_duplicates flag we need to find + this in the original list and remove it, which is + inefficient but hopefully rare. + */ + for (k = 0; k < el->num_values; k++) { + if (ldb_val_equal_exact(&el->values[k], + &values[i])) { + break; + } + } + el->num_values--; + for (; k < el->num_values; k++) { + el->values[k] = el->values[k + 1]; + } + i++; + } + } + TALLOC_FREE(values); + TALLOC_FREE(values2); + + return LDB_SUCCESS; +} + +/* + duplicate a ldb_val structure +*/ +struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v) +{ + struct ldb_val v2; + v2.length = v->length; + if (v->data == NULL) { + v2.data = NULL; + return v2; + } + + /* the +1 is to cope with buggy C library routines like strndup + that look one byte beyond */ + v2.data = talloc_array(mem_ctx, uint8_t, v->length+1); + if (!v2.data) { + v2.length = 0; + return v2; + } + + memcpy(v2.data, v->data, v->length); + ((char *)v2.data)[v->length] = 0; + return v2; +} + +/** + * Adds new empty element to msg->elements + */ +static int _ldb_msg_add_el(struct ldb_message *msg, + struct ldb_message_element **return_el) +{ + struct ldb_message_element *els; + + /* + * TODO: Find out a way to assert on input parameters. + * msg and return_el must be valid + */ + + els = talloc_realloc(msg, msg->elements, + struct ldb_message_element, msg->num_elements + 1); + if (!els) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ZERO_STRUCT(els[msg->num_elements]); + + msg->elements = els; + msg->num_elements++; + + *return_el = &els[msg->num_elements-1]; + + return LDB_SUCCESS; +} + +/** + * Add an empty element with a given name to a message + */ +int ldb_msg_add_empty(struct ldb_message *msg, + const char *attr_name, + int flags, + struct ldb_message_element **return_el) +{ + int ret; + struct ldb_message_element *el; + + ret = _ldb_msg_add_el(msg, &el); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* initialize newly added element */ + el->flags = flags; + el->name = talloc_strdup(msg->elements, attr_name); + if (!el->name) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (return_el) { + *return_el = el; + } + + return LDB_SUCCESS; +} + +/** + * Adds an element to a message. + * + * NOTE: Ownership of ldb_message_element fields + * is NOT transferred. Thus, if *el pointer + * is invalidated for some reason, this will + * corrupt *msg contents also + */ +int ldb_msg_add(struct ldb_message *msg, + const struct ldb_message_element *el, + int flags) +{ + int ret; + struct ldb_message_element *el_new; + /* We have to copy this, just in case *el is a pointer into + * what ldb_msg_add_empty() is about to realloc() */ + struct ldb_message_element el_copy = *el; + + ret = _ldb_msg_add_el(msg, &el_new); + if (ret != LDB_SUCCESS) { + return ret; + } + + el_new->flags = flags; + el_new->name = el_copy.name; + el_new->num_values = el_copy.num_values; + el_new->values = el_copy.values; + + return LDB_SUCCESS; +} + +/* + add a value to a message +*/ +int ldb_msg_add_value(struct ldb_message *msg, + const char *attr_name, + const struct ldb_val *val, + struct ldb_message_element **return_el) +{ + struct ldb_message_element *el; + struct ldb_val *vals; + int ret; + + el = ldb_msg_find_element(msg, attr_name); + if (!el) { + ret = ldb_msg_add_empty(msg, attr_name, 0, &el); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + vals = talloc_realloc(msg->elements, el->values, struct ldb_val, + el->num_values+1); + if (!vals) { + return LDB_ERR_OPERATIONS_ERROR; + } + el->values = vals; + el->values[el->num_values] = *val; + el->num_values++; + + if (return_el) { + *return_el = el; + } + + return LDB_SUCCESS; +} + + +/* + add a value to a message, stealing it into the 'right' place +*/ +int ldb_msg_add_steal_value(struct ldb_message *msg, + const char *attr_name, + struct ldb_val *val) +{ + int ret; + struct ldb_message_element *el; + + ret = ldb_msg_add_value(msg, attr_name, val, &el); + if (ret == LDB_SUCCESS) { + talloc_steal(el->values, val->data); + } + return ret; +} + + +/* + add a string element to a message +*/ +int ldb_msg_add_string(struct ldb_message *msg, + const char *attr_name, const char *str) +{ + struct ldb_val val; + + val.data = discard_const_p(uint8_t, str); + val.length = strlen(str); + + if (val.length == 0) { + /* allow empty strings as non-existent attributes */ + return LDB_SUCCESS; + } + + return ldb_msg_add_value(msg, attr_name, &val, NULL); +} + +/* + add a string element to a message, stealing it into the 'right' place +*/ +int ldb_msg_add_steal_string(struct ldb_message *msg, + const char *attr_name, char *str) +{ + struct ldb_val val; + + val.data = (uint8_t *)str; + val.length = strlen(str); + + if (val.length == 0) { + /* allow empty strings as non-existent attributes */ + return LDB_SUCCESS; + } + + return ldb_msg_add_steal_value(msg, attr_name, &val); +} + +/* + add a DN element to a message + WARNING: this uses the linearized string from the dn, and does not + copy the string. +*/ +int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, + struct ldb_dn *dn) +{ + char *str = ldb_dn_alloc_linearized(msg, dn); + + if (str == NULL) { + /* we don't want to have unknown DNs added */ + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_msg_add_steal_string(msg, attr_name, str); +} + +/* + add a printf formatted element to a message +*/ +int ldb_msg_add_fmt(struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) +{ + struct ldb_val val; + va_list ap; + char *str; + + va_start(ap, fmt); + str = talloc_vasprintf(msg, fmt, ap); + va_end(ap); + + if (str == NULL) return LDB_ERR_OPERATIONS_ERROR; + + val.data = (uint8_t *)str; + val.length = strlen(str); + + return ldb_msg_add_steal_value(msg, attr_name, &val); +} + +/* + compare two ldb_message_element structures + assumes case sensitive comparison +*/ +int ldb_msg_element_compare(struct ldb_message_element *el1, + struct ldb_message_element *el2) +{ + unsigned int i; + + if (el1->num_values != el2->num_values) { + return el1->num_values - el2->num_values; + } + + for (i=0;inum_values;i++) { + if (!ldb_msg_find_val(el2, &el1->values[i])) { + return -1; + } + } + + return 0; +} + +/* + compare two ldb_message_element structures. + Different ordering is considered a mismatch +*/ +bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1, + const struct ldb_message_element *el2) +{ + unsigned i; + if (el1->num_values != el2->num_values) { + return false; + } + for (i=0;inum_values;i++) { + if (ldb_val_equal_exact(&el1->values[i], + &el2->values[i]) != 1) { + return false; + } + } + return true; +} + +/* + compare two ldb_message_element structures + comparing by element name +*/ +int ldb_msg_element_compare_name(struct ldb_message_element *el1, + struct ldb_message_element *el2) +{ + return ldb_attr_cmp(el1->name, el2->name); +} + +/* + convenience functions to return common types from a message + these return the first value if the attribute is multi-valued +*/ +const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, + const char *attr_name) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return NULL; + } + return &el->values[0]; +} + +int ldb_msg_find_attr_as_int(const struct ldb_message *msg, + const char *attr_name, + int default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-2147483648")]; + char *end = NULL; + int ret; + + if (!v || !v->data) { + return default_value; + } + + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; + } + + memcpy(buf, v->data, v->length); + errno = 0; + ret = (int) strtoll(buf, &end, 10); + if (errno != 0) { + return default_value; + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; +} + +unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg, + const char *attr_name, + unsigned int default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-2147483648")]; + char *end = NULL; + unsigned int ret; + + if (!v || !v->data) { + return default_value; + } + + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; + } + + memcpy(buf, v->data, v->length); + errno = 0; + ret = (unsigned int) strtoll(buf, &end, 10); + if (errno != 0) { + errno = 0; + ret = (unsigned int) strtoull(buf, &end, 10); + if (errno != 0) { + return default_value; + } + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; +} + +int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg, + const char *attr_name, + int64_t default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-9223372036854775808")]; + char *end = NULL; + int64_t ret; + + if (!v || !v->data) { + return default_value; + } + + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; + } + + memcpy(buf, v->data, v->length); + errno = 0; + ret = (int64_t) strtoll(buf, &end, 10); + if (errno != 0) { + return default_value; + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; +} + +uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg, + const char *attr_name, + uint64_t default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-9223372036854775808")]; + char *end = NULL; + uint64_t ret; + + if (!v || !v->data) { + return default_value; + } + + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; + } + + memcpy(buf, v->data, v->length); + errno = 0; + ret = (uint64_t) strtoll(buf, &end, 10); + if (errno != 0) { + errno = 0; + ret = (uint64_t) strtoull(buf, &end, 10); + if (errno != 0) { + return default_value; + } + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; +} + +double ldb_msg_find_attr_as_double(const struct ldb_message *msg, + const char *attr_name, + double default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char *buf; + char *end = NULL; + double ret; + + if (!v || !v->data) { + return default_value; + } + buf = talloc_strndup(msg, (const char *)v->data, v->length); + if (buf == NULL) { + return default_value; + } + + errno = 0; + ret = strtod(buf, &end); + talloc_free(buf); + if (errno != 0) { + return default_value; + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; +} + +int ldb_msg_find_attr_as_bool(const struct ldb_message *msg, + const char *attr_name, + int default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { + return default_value; + } + if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) { + return 0; + } + if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) { + return 1; + } + return default_value; +} + +const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg, + const char *attr_name, + const char *default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { + return default_value; + } + if (v->data[v->length] != '\0') { + return default_value; + } + return (const char *)v->data; +} + +struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, + const char *attr_name) +{ + struct ldb_dn *res_dn; + const struct ldb_val *v; + + v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { + return NULL; + } + res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v); + if ( ! ldb_dn_validate(res_dn)) { + talloc_free(res_dn); + return NULL; + } + return res_dn; +} + +/* + sort the elements of a message by name +*/ +void ldb_msg_sort_elements(struct ldb_message *msg) +{ + TYPESAFE_QSORT(msg->elements, msg->num_elements, + ldb_msg_element_compare_name); +} + +/* + shallow copy a message - copying only the elements array so that the caller + can safely add new elements without changing the message +*/ +struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg) +{ + struct ldb_message *msg2; + unsigned int i; + + msg2 = talloc(mem_ctx, struct ldb_message); + if (msg2 == NULL) return NULL; + + *msg2 = *msg; + + msg2->elements = talloc_array(msg2, struct ldb_message_element, + msg2->num_elements); + if (msg2->elements == NULL) goto failed; + + for (i=0;inum_elements;i++) { + msg2->elements[i] = msg->elements[i]; + } + + return msg2; + +failed: + talloc_free(msg2); + return NULL; +} + + +/* + copy a message, allocating new memory for all parts +*/ +struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg) +{ + struct ldb_message *msg2; + unsigned int i, j; + + msg2 = ldb_msg_copy_shallow(mem_ctx, msg); + if (msg2 == NULL) return NULL; + + msg2->dn = ldb_dn_copy(msg2, msg2->dn); + if (msg2->dn == NULL) goto failed; + + for (i=0;inum_elements;i++) { + struct ldb_message_element *el = &msg2->elements[i]; + struct ldb_val *values = el->values; + el->name = talloc_strdup(msg2->elements, el->name); + if (el->name == NULL) goto failed; + el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values); + if (el->values == NULL) goto failed; + for (j=0;jnum_values;j++) { + el->values[j] = ldb_val_dup(el->values, &values[j]); + if (el->values[j].data == NULL && values[j].length != 0) { + goto failed; + } + } + } + + return msg2; + +failed: + talloc_free(msg2); + return NULL; +} + + +/** + * Canonicalize a message, merging elements of the same name + */ +struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, + const struct ldb_message *msg) +{ + int ret; + struct ldb_message *msg2; + + /* + * Preserve previous behavior and allocate + * *msg2 into *ldb context + */ + ret = ldb_msg_normalize(ldb, ldb, msg, &msg2); + if (ret != LDB_SUCCESS) { + return NULL; + } + + return msg2; +} + +/** + * Canonicalize a message, merging elements of the same name + */ +int ldb_msg_normalize(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, + struct ldb_message **_msg_out) +{ + unsigned int i; + struct ldb_message *msg2; + + msg2 = ldb_msg_copy(mem_ctx, msg); + if (msg2 == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_msg_sort_elements(msg2); + + for (i=1; i < msg2->num_elements; i++) { + struct ldb_message_element *el1 = &msg2->elements[i-1]; + struct ldb_message_element *el2 = &msg2->elements[i]; + + if (ldb_msg_element_compare_name(el1, el2) == 0) { + el1->values = talloc_realloc(msg2->elements, + el1->values, struct ldb_val, + el1->num_values + el2->num_values); + if (el1->num_values + el2->num_values > 0 && el1->values == NULL) { + talloc_free(msg2); + return LDB_ERR_OPERATIONS_ERROR; + } + memcpy(el1->values + el1->num_values, + el2->values, + sizeof(struct ldb_val) * el2->num_values); + el1->num_values += el2->num_values; + talloc_free(discard_const_p(char, el2->name)); + if ((i+1) < msg2->num_elements) { + memmove(el2, el2+1, sizeof(struct ldb_message_element) * + (msg2->num_elements - (i+1))); + } + msg2->num_elements--; + i--; + } + } + + *_msg_out = msg2; + return LDB_SUCCESS; +} + + +/** + * return a ldb_message representing the differences between msg1 and msg2. + * If you then use this in a ldb_modify() call, + * it can be used to save edits to a message + */ +struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, + struct ldb_message *msg1, + struct ldb_message *msg2) +{ + int ldb_ret; + struct ldb_message *mod; + + ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod); + if (ldb_ret != LDB_SUCCESS) { + return NULL; + } + + return mod; +} + +/** + * return a ldb_message representing the differences between msg1 and msg2. + * If you then use this in a ldb_modify() call it can be used to save edits to a message + * + * Result message is constructed as follows: + * - LDB_FLAG_MOD_ADD - elements found only in msg2 + * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1 + * Value for msg2 element is used + * - LDB_FLAG_MOD_DELETE - elements found only in msg2 + * + * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR + */ +int ldb_msg_difference(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_message *msg1, + struct ldb_message *msg2, + struct ldb_message **_msg_out) +{ + int ldb_res; + unsigned int i; + struct ldb_message *mod; + struct ldb_message_element *el; + TALLOC_CTX *temp_ctx; + + temp_ctx = talloc_new(mem_ctx); + if (!temp_ctx) { + return LDB_ERR_OPERATIONS_ERROR; + } + + mod = ldb_msg_new(temp_ctx); + if (mod == NULL) { + goto failed; + } + + mod->dn = msg1->dn; + mod->num_elements = 0; + mod->elements = NULL; + + /* + * Canonicalize *msg2 so we have no repeated elements + * Resulting message is allocated in *mod's mem context, + * as we are going to move some elements from *msg2 to + * *mod object later + */ + ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2); + if (ldb_res != LDB_SUCCESS) { + goto failed; + } + + /* look in msg2 to find elements that need to be added or modified */ + for (i=0;inum_elements;i++) { + el = ldb_msg_find_element(msg1, msg2->elements[i].name); + + if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) { + continue; + } + + ldb_res = ldb_msg_add(mod, + &msg2->elements[i], + el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD); + if (ldb_res != LDB_SUCCESS) { + goto failed; + } + } + + /* look in msg1 to find elements that need to be deleted */ + for (i=0;inum_elements;i++) { + el = ldb_msg_find_element(msg2, msg1->elements[i].name); + if (el == NULL) { + ldb_res = ldb_msg_add_empty(mod, + msg1->elements[i].name, + LDB_FLAG_MOD_DELETE, NULL); + if (ldb_res != LDB_SUCCESS) { + goto failed; + } + } + } + + /* steal resulting message into supplied context */ + talloc_steal(mem_ctx, mod); + *_msg_out = mod; + + talloc_free(temp_ctx); + return LDB_SUCCESS; + +failed: + talloc_free(temp_ctx); + return LDB_ERR_OPERATIONS_ERROR; +} + + +int ldb_msg_sanity_check(struct ldb_context *ldb, + const struct ldb_message *msg) +{ + unsigned int i, j; + + /* basic check on DN */ + if (msg->dn == NULL) { + ldb_set_errstring(ldb, "ldb message lacks a DN!"); + return LDB_ERR_INVALID_DN_SYNTAX; + } + + /* basic syntax checks */ + for (i = 0; i < msg->num_elements; i++) { + for (j = 0; j < msg->elements[i].num_values; j++) { + if (msg->elements[i].values[j].length == 0) { + /* an attribute cannot be empty */ + ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!", + msg->elements[i].name, + ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + } + } + + return LDB_SUCCESS; +} + + + + +/* + copy an attribute list. This only copies the array, not the elements + (ie. the elements are left as the same pointers) +*/ +const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs) +{ + const char **ret; + unsigned int i; + + for (i=0;attrs && attrs[i];i++) /* noop */ ; + ret = talloc_array(mem_ctx, const char *, i+1); + if (ret == NULL) { + return NULL; + } + for (i=0;attrs && attrs[i];i++) { + ret[i] = attrs[i]; + } + ret[i] = attrs[i]; + return ret; +} + + +/* + copy an attribute list. This only copies the array, not the elements + (ie. the elements are left as the same pointers). The new attribute is added to the list. +*/ +const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr) +{ + const char **ret; + unsigned int i; + bool found = false; + + for (i=0;attrs && attrs[i];i++) { + if (ldb_attr_cmp(attrs[i], new_attr) == 0) { + found = true; + } + } + if (found) { + return ldb_attr_list_copy(mem_ctx, attrs); + } + ret = talloc_array(mem_ctx, const char *, i+2); + if (ret == NULL) { + return NULL; + } + for (i=0;attrs && attrs[i];i++) { + ret[i] = attrs[i]; + } + ret[i] = new_attr; + ret[i+1] = NULL; + return ret; +} + + +/* + return 1 if an attribute is in a list of attributes, or 0 otherwise +*/ +int ldb_attr_in_list(const char * const *attrs, const char *attr) +{ + unsigned int i; + for (i=0;attrs && attrs[i];i++) { + if (ldb_attr_cmp(attrs[i], attr) == 0) { + return 1; + } + } + return 0; +} + + +/* + rename the specified attribute in a search result +*/ +int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr); + if (el == NULL) { + return LDB_SUCCESS; + } + el->name = talloc_strdup(msg->elements, replace); + if (el->name == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + return LDB_SUCCESS; +} + + +/* + copy the specified attribute in a search result to a new attribute +*/ +int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr); + int ret; + + if (el == NULL) { + return LDB_SUCCESS; + } + ret = ldb_msg_add(msg, el, 0); + if (ret != LDB_SUCCESS) { + return ret; + } + return ldb_msg_rename_attr(msg, attr, replace); +} + +/* + remove the specified element in a search result +*/ +void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el) +{ + ptrdiff_t n = (el - msg->elements); + if (n >= msg->num_elements || n < 0) { + /* the element is not in the list. the caller is crazy. */ + return; + } + msg->num_elements--; + if (n != msg->num_elements) { + memmove(el, el+1, (msg->num_elements - n)*sizeof(*el)); + } +} + + +/* + remove the specified attribute in a search result +*/ +void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr) +{ + struct ldb_message_element *el; + + while ((el = ldb_msg_find_element(msg, attr)) != NULL) { + ldb_msg_remove_element(msg, el); + } +} + +/* + return a LDAP formatted GeneralizedTime string +*/ +char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t) +{ + struct tm *tm = gmtime(&t); + char *ts; + int r; + + if (!tm) { + return NULL; + } + + /* we now excatly how long this string will be */ + ts = talloc_array(mem_ctx, char, 18); + + /* formatted like: 20040408072012.0Z */ + r = snprintf(ts, 18, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + if (r != 17) { + talloc_free(ts); + return NULL; + } + + return ts; +} + +/* + convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert +*/ +time_t ldb_string_to_time(const char *s) +{ + struct tm tm; + + if (s == NULL) return 0; + + memset(&tm, 0, sizeof(tm)); + if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + return 0; + } + tm.tm_year -= 1900; + tm.tm_mon -= 1; + + return timegm(&tm); +} + +/* + convert a LDAP GeneralizedTime string in ldb_val format to a + time_t. +*/ +int ldb_val_to_time(const struct ldb_val *v, time_t *t) +{ + char val[15] = {0}; + struct tm tm = { + .tm_year = 0, + }; + + if (v == NULL) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (v->data == NULL) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (v->length < 16 && v->length != 13) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (v->data[v->length - 1] != 'Z') { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (v->length == 13) { + memcpy(val, v->data, 12); + + if (sscanf(val, "%02u%02u%02u%02u%02u%02u", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + if (tm.tm_year < 50) { + tm.tm_year += 100; + } + } else { + + /* + * anything between '.' and 'Z' is silently ignored. + */ + if (v->data[14] != '.') { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + memcpy(val, v->data, 14); + + if (sscanf(val, "%04u%02u%02u%02u%02u%02u", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + tm.tm_year -= 1900; + } + tm.tm_mon -= 1; + + *t = timegm(&tm); + + return LDB_SUCCESS; +} + +/* + return a LDAP formatted UTCTime string +*/ +char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t) +{ + struct tm *tm = gmtime(&t); + char *ts; + int r; + + if (!tm) { + return NULL; + } + + /* we now excatly how long this string will be */ + ts = talloc_array(mem_ctx, char, 14); + + /* formatted like: 20040408072012.0Z => 040408072012Z */ + r = snprintf(ts, 14, + "%02u%02u%02u%02u%02u%02uZ", + (tm->tm_year+1900)%100, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + if (r != 13) { + talloc_free(ts); + return NULL; + } + + return ts; +} + +/* + convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert +*/ +time_t ldb_string_utc_to_time(const char *s) +{ + struct tm tm; + + if (s == NULL) return 0; + + memset(&tm, 0, sizeof(tm)); + if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + return 0; + } + if (tm.tm_year < 50) { + tm.tm_year += 100; + } + tm.tm_mon -= 1; + + return timegm(&tm); +} + + +/* + dump a set of results to a file. Useful from within gdb +*/ +void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f) +{ + unsigned int i; + + for (i = 0; i < result->count; i++) { + struct ldb_ldif ldif; + fprintf(f, "# record %d\n", i+1); + ldif.changetype = LDB_CHANGETYPE_NONE; + ldif.msg = result->msgs[i]; + ldb_ldif_write_file(ldb, f, &ldif); + } +} + +/* + checks for a string attribute. Returns "1" on match and otherwise "0". +*/ +int ldb_msg_check_string_attribute(const struct ldb_message *msg, + const char *name, const char *value) +{ + struct ldb_message_element *el; + struct ldb_val val; + + el = ldb_msg_find_element(msg, name); + if (el == NULL) { + return 0; + } + + val.data = discard_const_p(uint8_t, value); + val.length = strlen(value); + + if (ldb_msg_find_val(el, &val)) { + return 1; + } + + return 0; +} + + +/* + compare a ldb_val to a string +*/ +int ldb_val_string_cmp(const struct ldb_val *v, const char *str) +{ + size_t len = strlen(str); + if (len != v->length) { + return len - v->length; + } + return strncmp((const char *)v->data, str, len); +} diff --git a/ldb-2.0.8/common/ldb_options.c b/ldb-2.0.8/common/ldb_options.c new file mode 100644 index 0000000..ee8c728 --- /dev/null +++ b/ldb-2.0.8/common/ldb_options.c @@ -0,0 +1,107 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2010 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb options[] handling + * + * Author: Andrew Tridgell + */ + +#include "ldb_private.h" + +/* + find an option within an options array + + accepts the following forms: + + NAME + NAME:value + NAME=value + + returns a pointer into an element of the options[] array, or NULL is + not found. + + For the NAME form, returns a pointer to an empty string (thus + allowing for boolean options). + */ +const char *ldb_options_find(struct ldb_context *ldb, const char *options[], + const char *option_name) +{ + size_t len = strlen(option_name); + int i; + + if (options == NULL) { + return NULL; + } + + for (i=0; options[i]; i++) { + if (strncmp(option_name, options[i], len) != 0) { + continue; + } + if (options[i][len] == ':' || options[i][len] == '=') { + return &options[i][len+1]; + } + if (options[i][len] == 0) { + return &options[i][len]; + } + } + + return NULL; +} + +const char **ldb_options_copy(TALLOC_CTX *ctx, const char *options[]) +{ + + size_t num_options = 0; + const char **copy = NULL; + size_t i = 0; + + if (options == NULL) { + return copy; + } + + for (i=0; options[i]; i++) { + num_options++; + } + + copy = talloc_zero_array(ctx, const char *, num_options + 1); + if (copy == NULL) { + return copy; + } + + for (i=0; options[i]; i++) { + copy[i] = talloc_strdup(copy, options[i]); + if (copy[i] == NULL) { + TALLOC_FREE(copy); + return copy; + } + } + return copy; +} + +const char **ldb_options_get(struct ldb_context *ldb) +{ + return ldb->options; +} diff --git a/ldb-2.0.8/common/ldb_pack.c b/ldb-2.0.8/common/ldb_pack.c new file mode 100644 index 0000000..e7dd364 --- /dev/null +++ b/ldb-2.0.8/common/ldb_pack.c @@ -0,0 +1,1261 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb pack/unpack + * + * Description: pack/unpack routines for ldb messages as key/value blobs + * + * Author: Andrew Tridgell + */ + +#include "ldb_private.h" + +/* + * These macros are from byte_array.h via libssh + * TODO: This will be replaced with use of the byte_array.h header when it + * becomes available. + * + * Macros for handling integer types in byte arrays + * + * This file is originally from the libssh.org project + * + * Copyright (c) 2018 Andreas Schneider + * + * 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 2.1 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 + * Lesser 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#define _DATA_BYTE_CONST(data, pos) \ + ((uint8_t)(((const uint8_t *)(data))[(pos)])) +#define PULL_LE_U8(data, pos) \ + (_DATA_BYTE_CONST(data, pos)) +#define PULL_LE_U16(data, pos) \ + ((uint16_t)PULL_LE_U8(data, pos) |\ + ((uint16_t)(PULL_LE_U8(data, (pos) + 1))) << 8) +#define PULL_LE_U32(data, pos) \ + ((uint32_t)(PULL_LE_U16(data, pos) |\ + ((uint32_t)PULL_LE_U16(data, (pos) + 2)) << 16)) + +#define _DATA_BYTE(data, pos) \ + (((uint8_t *)(data))[(pos)]) +#define PUSH_LE_U8(data, pos, val) \ + (_DATA_BYTE(data, pos) = ((uint8_t)(val))) +#define PUSH_LE_U16(data, pos, val) \ + (PUSH_LE_U8((data), (pos), (uint8_t)((uint16_t)(val) & 0xff)),\ + PUSH_LE_U8((data), (pos) + 1,\ + (uint8_t)((uint16_t)(val) >> 8))) +#define PUSH_LE_U32(data, pos, val) \ + (PUSH_LE_U16((data), (pos), (uint16_t)((uint32_t)(val) & 0xffff)),\ + PUSH_LE_U16((data), (pos) + 2, (uint16_t)((uint32_t)(val) >> 16))) + +#define U32_LEN 4 +#define U16_LEN 2 +#define U8_LEN 1 +#define NULL_PAD_BYTE_LEN 1 + +static int attribute_storable_values(const struct ldb_message_element *el) +{ + if (el->num_values == 0) return 0; + + if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0; + + return el->num_values; +} + +static int ldb_pack_data_v1(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_val *data) +{ + unsigned int i, j, real_elements=0; + size_t size, dn_len, attr_len, value_len; + const char *dn; + uint8_t *p; + size_t len; + + dn = ldb_dn_get_linearized(message->dn); + if (dn == NULL) { + errno = ENOMEM; + return -1; + } + + /* work out how big it needs to be */ + size = U32_LEN * 2 + NULL_PAD_BYTE_LEN; + + dn_len = strlen(dn); + if (size + dn_len < size) { + errno = ENOMEM; + return -1; + } + size += dn_len; + + /* + * First calcuate the buffer size we need, and check for + * overflows + */ + for (i=0;inum_elements;i++) { + if (attribute_storable_values(&message->elements[i]) == 0) { + continue; + } + + real_elements++; + + if (size + U32_LEN + NULL_PAD_BYTE_LEN < size) { + errno = ENOMEM; + return -1; + } + size += U32_LEN + NULL_PAD_BYTE_LEN; + + attr_len = strlen(message->elements[i].name); + if (size + attr_len < size) { + errno = ENOMEM; + return -1; + } + size += attr_len; + + for (j=0;jelements[i].num_values;j++) { + if (size + U32_LEN + NULL_PAD_BYTE_LEN < size) { + errno = ENOMEM; + return -1; + } + size += U32_LEN + NULL_PAD_BYTE_LEN; + + value_len = message->elements[i].values[j].length; + if (size + value_len < size) { + errno = ENOMEM; + return -1; + } + size += value_len; + } + } + + /* allocate it */ + data->data = talloc_array(ldb, uint8_t, size); + if (!data->data) { + errno = ENOMEM; + return -1; + } + data->length = size; + + p = data->data; + PUSH_LE_U32(p, 0, LDB_PACKING_FORMAT); + p += U32_LEN; + PUSH_LE_U32(p, 0, real_elements); + p += U32_LEN; + + /* the dn needs to be packed so we can be case preserving + while hashing on a case folded dn */ + len = dn_len; + memcpy(p, dn, len+NULL_PAD_BYTE_LEN); + p += len + NULL_PAD_BYTE_LEN; + + for (i=0;inum_elements;i++) { + if (attribute_storable_values(&message->elements[i]) == 0) { + continue; + } + len = strlen(message->elements[i].name); + memcpy(p, message->elements[i].name, len+NULL_PAD_BYTE_LEN); + p += len + NULL_PAD_BYTE_LEN; + PUSH_LE_U32(p, 0, message->elements[i].num_values); + p += U32_LEN; + for (j=0;jelements[i].num_values;j++) { + PUSH_LE_U32(p, 0, + message->elements[i].values[j].length); + p += U32_LEN; + memcpy(p, message->elements[i].values[j].data, + message->elements[i].values[j].length); + p[message->elements[i].values[j].length] = 0; + p += message->elements[i].values[j].length + + NULL_PAD_BYTE_LEN; + } + } + + return 0; +} + +/* + * New pack version designed based on performance profiling of version 1. + * The approach is to separate value data from the rest of the record's data. + * This improves performance because value data is not needed during unpacking + * or filtering of the message's attribute list. During filtering we only copy + * attributes which are present in the attribute list, however at the parse + * stage we need to point to all attributes as they may be referenced in the + * search expression. + * With this new format, we don't lose time loading data (eg via + * talloc_memdup()) that is never needed (for the vast majority of attributes + * are are never found in either the search expression or attribute list). + * Additional changes include adding a canonicalized DN (for later + * optimizations) and variable width length fields for faster unpacking. + * The pack and unpack performance improvement is tested in the torture + * test torture_ldb_pack_format_perf. + * + * Layout: + * + * Version (4 bytes) + * Number of Elements (4 bytes) + * DN length (4 bytes) + * DN with null terminator (DN length + 1 bytes) + * Canonicalized DN length (4 bytes) + * Canonicalized DN with null terminator (Canonicalized DN length + 1 bytes) + * Number of bytes from here to value data section (4 bytes) + * # For each element: + * Element name length (4 bytes) + * Element name with null terminator (Element name length + 1 bytes) + * Number of values (4 bytes) + * Width of value lengths + * # For each value: + * Value data length (#bytes given by width field above) + * # For each element: + * # For each value: + * Value data (#bytes given by corresponding length above) + */ +static int ldb_pack_data_v2(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_val *data) +{ + unsigned int i, j, real_elements=0; + size_t size, dn_len, dn_canon_len, attr_len, value_len; + const char *dn, *dn_canon; + uint8_t *p, *q; + size_t len; + size_t max_val_len; + uint8_t val_len_width; + + /* + * First half of this function will calculate required size for + * packed data. Initial size is 20 = 5 * 4. 5 fixed fields are: + * version, num elements, dn len, canon dn len, attr section len + */ + size = U32_LEN * 5; + + /* + * Get linearized and canonicalized form of the DN and add the lengths + * of each to size, plus 1 for null terminator. + */ + dn = ldb_dn_get_linearized(message->dn); + if (dn == NULL) { + errno = ENOMEM; + return -1; + } + + dn_len = strlen(dn) + NULL_PAD_BYTE_LEN; + if (size + dn_len < size) { + errno = ENOMEM; + return -1; + } + size += dn_len; + + if (ldb_dn_is_special(message->dn)) { + dn_canon_len = NULL_PAD_BYTE_LEN; + dn_canon = discard_const_p(char, "\0"); + } else { + dn_canon = ldb_dn_canonical_string(message->dn, message->dn); + if (dn_canon == NULL) { + errno = ENOMEM; + return -1; + } + + dn_canon_len = strlen(dn_canon) + NULL_PAD_BYTE_LEN; + if (size + dn_canon_len < size) { + errno = ENOMEM; + return -1; + } + } + size += dn_canon_len; + + /* Add the size required by each element */ + for (i=0;inum_elements;i++) { + if (attribute_storable_values(&message->elements[i]) == 0) { + continue; + } + + real_elements++; + + /* + * Add length of element name + 9 for: + * 1 for null terminator + * 4 for element name length field + * 4 for number of values field + */ + attr_len = strlen(message->elements[i].name); + if (size + attr_len + U32_LEN * 2 + NULL_PAD_BYTE_LEN < size) { + errno = ENOMEM; + return -1; + } + size += attr_len + U32_LEN * 2 + NULL_PAD_BYTE_LEN; + + /* + * Find the max value length, so we can calculate the width + * required for the value length fields. + */ + max_val_len = 0; + for (j=0;jelements[i].num_values;j++) { + value_len = message->elements[i].values[j].length; + if (value_len > max_val_len) { + max_val_len = value_len; + } + + if (size + value_len + NULL_PAD_BYTE_LEN < size) { + errno = ENOMEM; + return -1; + } + size += value_len + NULL_PAD_BYTE_LEN; + } + + if (max_val_len <= UCHAR_MAX) { + val_len_width = U8_LEN; + } else if (max_val_len <= USHRT_MAX) { + val_len_width = U16_LEN; + } else if (max_val_len <= UINT_MAX) { + val_len_width = U32_LEN; + } else { + errno = EMSGSIZE; + return -1; + } + + /* Total size required for val lengths (re-using variable) */ + max_val_len = (val_len_width*message->elements[i].num_values); + + /* Add one for storing the width */ + max_val_len += U8_LEN; + if (size + max_val_len < size) { + errno = ENOMEM; + return -1; + } + size += max_val_len; + } + + /* Allocate */ + data->data = talloc_array(ldb, uint8_t, size); + if (!data->data) { + errno = ENOMEM; + return -1; + } + data->length = size; + + /* Packing format version and number of element */ + p = data->data; + PUSH_LE_U32(p, 0, LDB_PACKING_FORMAT_V2); + p += U32_LEN; + PUSH_LE_U32(p, 0, real_elements); + p += U32_LEN; + + /* Pack DN and Canonicalized DN */ + PUSH_LE_U32(p, 0, dn_len-NULL_PAD_BYTE_LEN); + p += U32_LEN; + memcpy(p, dn, dn_len); + p += dn_len; + + PUSH_LE_U32(p, 0, dn_canon_len-NULL_PAD_BYTE_LEN); + p += U32_LEN; + memcpy(p, dn_canon, dn_canon_len); + p += dn_canon_len; + + /* + * Save pointer at this point and leave a U32_LEN gap for + * storing the size of the attribute names and value lengths + * section + */ + q = p; + p += U32_LEN; + + for (i=0;inum_elements;i++) { + if (attribute_storable_values(&message->elements[i]) == 0) { + continue; + } + + /* Length of el name */ + len = strlen(message->elements[i].name); + PUSH_LE_U32(p, 0, len); + p += U32_LEN; + + /* + * Even though we have the element name's length, put a null + * terminator at the end so if any code uses the name + * directly, it'll be safe to do things requiring null + * termination like strlen + */ + memcpy(p, message->elements[i].name, len+NULL_PAD_BYTE_LEN); + p += len + NULL_PAD_BYTE_LEN; + /* Num values */ + PUSH_LE_U32(p, 0, message->elements[i].num_values); + p += U32_LEN; + + /* + * Calculate value length width again. It's faster to + * calculate it again than do the array management to + * store the result during size calculation. + */ + max_val_len = 0; + for (j=0;jelements[i].num_values;j++) { + value_len = message->elements[i].values[j].length; + if (value_len > max_val_len) { + max_val_len = value_len; + } + } + + if (max_val_len <= UCHAR_MAX) { + val_len_width = U8_LEN; + } else if (max_val_len <= USHRT_MAX) { + val_len_width = U16_LEN; + } else if (max_val_len <= UINT_MAX) { + val_len_width = U32_LEN; + } else { + errno = EMSGSIZE; + return -1; + } + + /* Pack the width */ + *p = val_len_width & 0xFF; + p += U8_LEN; + + /* + * Pack each value's length using the minimum number of bytes + * required, which we just calculated. We repeat the loop + * for each case here so the compiler can inline code. + */ + if (val_len_width == U8_LEN) { + for (j=0;jelements[i].num_values;j++) { + PUSH_LE_U8(p, 0, + message->elements[i].values[j].length); + p += U8_LEN; + } + } else if (val_len_width == U16_LEN) { + for (j=0;jelements[i].num_values;j++) { + PUSH_LE_U16(p, 0, + message->elements[i].values[j].length); + p += U16_LEN; + } + } else if (val_len_width == U32_LEN) { + for (j=0;jelements[i].num_values;j++) { + PUSH_LE_U32(p, 0, + message->elements[i].values[j].length); + p += U32_LEN; + } + } + } + + /* + * We've finished packing the attr names and value lengths + * section, so store the size in the U32_LEN gap we left + * earlier + */ + PUSH_LE_U32(q, 0, p-q); + + /* Now pack the values */ + for (i=0;inum_elements;i++) { + if (attribute_storable_values(&message->elements[i]) == 0) { + continue; + } + for (j=0;jelements[i].num_values;j++) { + memcpy(p, message->elements[i].values[j].data, + message->elements[i].values[j].length); + + /* + * Even though we have the data length, put a null + * terminator at the end of each value's data so if + * any code uses the data directly, it'll be safe to + * do things requiring null termination like strlen. + */ + p[message->elements[i].values[j].length] = 0; + p += message->elements[i].values[j].length + + NULL_PAD_BYTE_LEN; + } + } + + /* + * If we didn't end up at the end of the data here, something has + * gone very wrong. + */ + if (p != data->data + size) { + errno = ENOMEM; + return -1; + } + + return 0; +} + +/* + pack a ldb message into a linear buffer in a ldb_val + + note that this routine avoids saving elements with zero values, + as these are equivalent to having no element + + caller frees the data buffer after use +*/ +int ldb_pack_data(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_val *data, + uint32_t pack_format_version) { + + if (pack_format_version == LDB_PACKING_FORMAT) { + return ldb_pack_data_v1(ldb, message, data); + } else if (pack_format_version == LDB_PACKING_FORMAT_V2) { + return ldb_pack_data_v2(ldb, message, data); + } else { + errno = EINVAL; + return -1; + } +} + +/* + * Unpack a ldb message from a linear buffer in ldb_val + */ +static int ldb_unpack_data_flags_v1(struct ldb_context *ldb, + const struct ldb_val *data, + struct ldb_message *message, + unsigned int flags, + unsigned format) +{ + uint8_t *p; + size_t remaining; + size_t dn_len; + unsigned int i, j; + unsigned int nelem = 0; + size_t len; + struct ldb_val *ldb_val_single_array = NULL; + + message->elements = NULL; + + p = data->data; + + /* Format (U32, already read) + U32 for num_elements */ + if (data->length < U32_LEN * 2) { + errno = EIO; + goto failed; + } + + /* Skip first 4 bytes, format already read */ + p += U32_LEN; + message->num_elements = PULL_LE_U32(p, 0); + p += U32_LEN; + + remaining = data->length - U32_LEN * 2; + + switch (format) { + case LDB_PACKING_FORMAT_NODN: + message->dn = NULL; + break; + + case LDB_PACKING_FORMAT: + /* + * With this check, we know that the DN at p is \0 + * terminated. + */ + dn_len = strnlen((char *)p, remaining); + if (dn_len == remaining) { + errno = EIO; + goto failed; + } + if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) { + message->dn = NULL; + } else { + struct ldb_val blob; + blob.data = discard_const_p(uint8_t, p); + blob.length = dn_len; + message->dn = ldb_dn_from_ldb_val(message, ldb, &blob); + if (message->dn == NULL) { + errno = ENOMEM; + goto failed; + } + } + /* + * Redundant: by definition, remaining must be more + * than one less than dn_len, as otherwise it would be + * == dn_len + */ + if (remaining < dn_len + NULL_PAD_BYTE_LEN) { + errno = EIO; + goto failed; + } + remaining -= dn_len + NULL_PAD_BYTE_LEN; + p += dn_len + NULL_PAD_BYTE_LEN; + break; + + default: + errno = EIO; + goto failed; + } + + if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) { + return 0; + } + + if (message->num_elements == 0) { + return 0; + } + + if (message->num_elements > remaining / 6) { + errno = EIO; + goto failed; + } + + message->elements = talloc_zero_array(message, struct ldb_message_element, + message->num_elements); + if (!message->elements) { + errno = ENOMEM; + 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 + * 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;inum_elements;i++) { + const char *attr = NULL; + size_t attr_len; + struct ldb_message_element *element = NULL; + + /* + * Sanity check: Element must be at least the size of empty + * attr name and value and NULL terms for each. + */ + if (remaining < U32_LEN * 2 + NULL_PAD_BYTE_LEN * 2) { + errno = EIO; + goto failed; + } + + /* + * With this check, we know that the attribute name at + * p is \0 terminated. + */ + attr_len = strnlen((char *)p, remaining-6); + if (attr_len == remaining-6) { + errno = EIO; + goto failed; + } + if (attr_len == 0) { + errno = EIO; + goto failed; + } + attr = (char *)p; + + element = &message->elements[nelem]; + element->name = attr; + element->flags = 0; + + if (remaining < (attr_len + NULL_PAD_BYTE_LEN)) { + errno = EIO; + goto failed; + } + remaining -= attr_len + NULL_PAD_BYTE_LEN; + p += attr_len + NULL_PAD_BYTE_LEN; + element->num_values = PULL_LE_U32(p, 0); + element->values = NULL; + 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); + if (!element->values) { + errno = ENOMEM; + goto failed; + } + } + p += U32_LEN; + if (remaining < U32_LEN) { + errno = EIO; + goto failed; + } + remaining -= U32_LEN; + for (j = 0; j < element->num_values; j++) { + /* + * Sanity check: Value must be at least the size of + * empty val and NULL terminator. + */ + if (remaining < U32_LEN + NULL_PAD_BYTE_LEN) { + errno = EIO; + goto failed; + } + remaining -= U32_LEN + NULL_PAD_BYTE_LEN; + + len = PULL_LE_U32(p, 0); + if (remaining < len) { + errno = EIO; + goto failed; + } + if (len + NULL_PAD_BYTE_LEN < len) { + errno = EIO; + goto failed; + } + + element->values[j].length = len; + element->values[j].data = p + U32_LEN; + remaining -= len; + p += len + U32_LEN + NULL_PAD_BYTE_LEN; + } + nelem++; + } + /* + * Adapt the number of elements to the real number of unpacked elements, + * it means that we overallocated elements array. + */ + message->num_elements = nelem; + + /* + * Shrink the allocated size. On current talloc behaviour + * this will help if we skipped 32 or more attributes. + */ + message->elements = talloc_realloc(message, message->elements, + struct ldb_message_element, + message->num_elements); + + if (remaining != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: %zu bytes unread in ldb_unpack_data_flags", + remaining); + } + + return 0; + +failed: + talloc_free(message->elements); + return -1; +} + +/* + * Unpack a ldb message from a linear buffer in ldb_val + */ +static int ldb_unpack_data_flags_v2(struct ldb_context *ldb, + const struct ldb_val *data, + struct ldb_message *message, + unsigned int flags) +{ + uint8_t *p, *q, *end_p, *value_section_p; + unsigned int i, j; + unsigned int nelem = 0; + size_t len; + struct ldb_val *ldb_val_single_array = NULL; + uint8_t val_len_width; + + message->elements = NULL; + + p = data->data; + end_p = p + data->length; + + /* Skip first 4 bytes, format already read */ + p += U32_LEN; + + /* First fields are fixed: num_elements, DN length */ + if (p + U32_LEN * 2 > end_p) { + errno = EIO; + goto failed; + } + + message->num_elements = PULL_LE_U32(p, 0); + p += U32_LEN; + + len = PULL_LE_U32(p, 0); + p += U32_LEN; + + if (p + len + NULL_PAD_BYTE_LEN > end_p) { + errno = EIO; + goto failed; + } + + if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) { + message->dn = NULL; + } else { + struct ldb_val blob; + blob.data = discard_const_p(uint8_t, p); + blob.length = len; + message->dn = ldb_dn_from_ldb_val(message, ldb, &blob); + if (message->dn == NULL) { + errno = ENOMEM; + goto failed; + } + } + + p += len + NULL_PAD_BYTE_LEN; + + if (*(p-NULL_PAD_BYTE_LEN) != '\0') { + errno = EINVAL; + goto failed; + } + + /* Now skip the canonicalized DN and its length */ + len = PULL_LE_U32(p, 0) + NULL_PAD_BYTE_LEN; + p += U32_LEN; + + if (p + len > end_p) { + errno = EIO; + goto failed; + } + + p += len; + + if (*(p-NULL_PAD_BYTE_LEN) != '\0') { + errno = EINVAL; + goto failed; + } + + if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) { + return 0; + } + + if (message->num_elements == 0) { + return 0; + } + + /* + * Sanity check (17 bytes is the minimum element size) + */ + if (message->num_elements > (end_p - p) / 17) { + errno = EIO; + goto failed; + } + + message->elements = talloc_zero_array(message, + struct ldb_message_element, + message->num_elements); + if (!message->elements) { + errno = ENOMEM; + 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. + * 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; + } + } + + q = p + PULL_LE_U32(p, 0); + value_section_p = q; + p += U32_LEN; + + for (i=0;inum_elements;i++) { + const char *attr = NULL; + size_t attr_len; + struct ldb_message_element *element = NULL; + + /* Sanity check: minimum element size */ + if (p + (U32_LEN * 2) + /* attr name len, num values */ + (U8_LEN * 2) + /* value length width, one val length */ + (NULL_PAD_BYTE_LEN * 2) /* null for attr name + val */ + > value_section_p) { + errno = EIO; + goto failed; + } + + attr_len = PULL_LE_U32(p, 0); + p += U32_LEN; + + if (attr_len == 0) { + errno = EIO; + goto failed; + } + attr = (char *)p; + + p += attr_len + NULL_PAD_BYTE_LEN; + /* + * num_values, val_len_width + * + * val_len_width is the width specifier + * for the variable length encoding + */ + if (p + U32_LEN + U8_LEN > value_section_p) { + errno = EIO; + goto failed; + } + + if (*(p-NULL_PAD_BYTE_LEN) != '\0') { + errno = EINVAL; + goto failed; + } + + element = &message->elements[nelem]; + element->name = attr; + element->flags = 0; + + element->num_values = PULL_LE_U32(p, 0); + element->values = NULL; + 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); + if (!element->values) { + errno = ENOMEM; + goto failed; + } + } + + p += U32_LEN; + + /* + * Here we read how wide the remaining lengths are + * which avoids storing and parsing a lot of leading + * 0s + */ + val_len_width = *p; + p += U8_LEN; + + if (p + val_len_width * element->num_values > + value_section_p) { + errno = EIO; + goto failed; + } + + /* + * This is structured weird for compiler optimization + * purposes, but we need to pull the array of widths + * with different macros depending on how wide the + * biggest one is (specified by val_len_width) + */ + if (val_len_width == U8_LEN) { + for (j = 0; j < element->num_values; j++) { + element->values[j].length = PULL_LE_U8(p, 0); + p += U8_LEN; + } + } else if (val_len_width == U16_LEN) { + for (j = 0; j < element->num_values; j++) { + element->values[j].length = PULL_LE_U16(p, 0); + p += U16_LEN; + } + } else if (val_len_width == U32_LEN) { + for (j = 0; j < element->num_values; j++) { + element->values[j].length = PULL_LE_U32(p, 0); + p += U32_LEN; + } + } else { + errno = ERANGE; + goto failed; + } + + for (j = 0; j < element->num_values; j++) { + len = element->values[j].length; + if (len + NULL_PAD_BYTE_LEN < len) { + errno = EIO; + goto failed; + } + if (q + len + NULL_PAD_BYTE_LEN > end_p) { + errno = EIO; + goto failed; + } + + element->values[j].data = q; + q += len + NULL_PAD_BYTE_LEN; + } + nelem++; + } + + /* + * If p isn't now pointing at the beginning of the value section, + * something went very wrong. + */ + if (p != value_section_p) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Data corruption in ldb_unpack_data_flags"); + errno = EIO; + goto failed; + } + + /* + * Adapt the number of elements to the real number of unpacked + * elements it means that we overallocated elements array. + */ + message->num_elements = nelem; + + /* + * Shrink the allocated size. On current talloc behaviour + * this will help if we skipped 32 or more attributes. + */ + message->elements = talloc_realloc(message, message->elements, + struct ldb_message_element, + message->num_elements); + + if (q != end_p) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: %zu bytes unread in ldb_unpack_data_flags", + end_p - q); + errno = EIO; + goto failed; + } + + return 0; + +failed: + talloc_free(message->elements); + return -1; +} + +int ldb_unpack_get_format(const struct ldb_val *data, + uint32_t *pack_format_version) +{ + if (data->length < U32_LEN) { + return LDB_ERR_OPERATIONS_ERROR; + } + *pack_format_version = PULL_LE_U32(data->data, 0); + return LDB_SUCCESS; +} + +/* + * Unpack a ldb message from a linear buffer in ldb_val + */ +int ldb_unpack_data_flags(struct ldb_context *ldb, + const struct ldb_val *data, + struct ldb_message *message, + unsigned int flags) +{ + unsigned format; + + if (data->length < U32_LEN) { + errno = EIO; + return -1; + } + + format = PULL_LE_U32(data->data, 0); + if (format == LDB_PACKING_FORMAT_V2) { + return ldb_unpack_data_flags_v2(ldb, data, message, flags); + } + + /* + * The v1 function we're about to call takes either LDB_PACKING_FORMAT + * or LDB_PACKING_FORMAT_NODN packing format versions, and will error + * if given some other version, so we don't need to do any further + * checks on 'format'. + */ + return ldb_unpack_data_flags_v1(ldb, data, message, flags, format); +} + + +/* + * Unpack a ldb message from a linear buffer in ldb_val + * + * Free with ldb_unpack_data_free() + */ +int ldb_unpack_data(struct ldb_context *ldb, + const struct ldb_val *data, + struct ldb_message *message) +{ + return ldb_unpack_data_flags(ldb, data, message, 0); +} + +/* + add the special distinguishedName element +*/ +static int msg_add_distinguished_name(struct ldb_message *msg) +{ + const char *dn_attr = "distinguishedName"; + char *dn = NULL; + + if (ldb_msg_find_element(msg, dn_attr)) { + /* + * This should not happen, but this is + * existing behaviour... + */ + return LDB_SUCCESS; + } + + dn = ldb_dn_alloc_linearized(msg, msg->dn); + if (dn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_msg_add_steal_string(msg, dn_attr, dn); +} + +/* + * filter the specified list of attributes from msg, + * adding requested attributes, and perhaps all for *, + * but not the DN to filtered_msg. + */ +int ldb_filter_attrs(struct ldb_context *ldb, + const struct ldb_message *msg, + const char *const *attrs, + struct ldb_message *filtered_msg) +{ + unsigned int i; + bool keep_all = false; + bool add_dn = false; + uint32_t num_elements; + uint32_t elements_size; + + if (attrs) { + /* check for special attrs */ + for (i = 0; attrs[i]; i++) { + int cmp = strcmp(attrs[i], "*"); + if (cmp == 0) { + keep_all = true; + break; + } + cmp = ldb_attr_cmp(attrs[i], "distinguishedName"); + if (cmp == 0) { + add_dn = true; + } + } + } else { + keep_all = true; + } + + if (keep_all) { + 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(filtered_msg) != 0) { + goto failed; + } + return 0; + } else if (i == 0) { + return 0; + + /* + * Otherwise we are copying at most as many elements as we + * have attributes + */ + } else { + elements_size = i; + } + + filtered_msg->elements = talloc_array(filtered_msg, + struct ldb_message_element, + elements_size); + if (filtered_msg->elements == NULL) goto failed; + + num_elements = 0; + + for (i = 0; i < msg->num_elements; i++) { + struct ldb_message_element *el = &msg->elements[i]; + + /* + * el2 is assigned after the Pigeonhole principle + * check below for clarity + */ + struct ldb_message_element *el2 = NULL; + unsigned int j; + + 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; + } + } + + /* + * Pigeonhole 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; + } + + el2 = &filtered_msg->elements[num_elements]; + + *el2 = *el; + el2->name = talloc_strdup(filtered_msg->elements, + el->name); + if (el2->name == NULL) { + goto failed; + } + el2->values = talloc_array(filtered_msg->elements, + struct ldb_val, el->num_values); + if (el2->values == NULL) { + goto failed; + } + for (j=0;jnum_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++; + } + + filtered_msg->num_elements = num_elements; + + if (add_dn) { + if (msg_add_distinguished_name(filtered_msg) != 0) { + goto failed; + } + } + + if (filtered_msg->num_elements > 0) { + filtered_msg->elements + = talloc_realloc(filtered_msg, + filtered_msg->elements, + struct ldb_message_element, + filtered_msg->num_elements); + if (filtered_msg->elements == NULL) { + goto failed; + } + } else { + TALLOC_FREE(filtered_msg->elements); + } + + return 0; +failed: + TALLOC_FREE(filtered_msg->elements); + return -1; +} diff --git a/ldb-2.0.8/common/ldb_parse.c b/ldb-2.0.8/common/ldb_parse.c new file mode 100644 index 0000000..452c583 --- /dev/null +++ b/ldb-2.0.8/common/ldb_parse.c @@ -0,0 +1,974 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb expression parsing + * + * Description: parse LDAP-like search expressions + * + * Author: Andrew Tridgell + */ + +/* + TODO: + - add RFC2254 binary string handling + - possibly add ~=, <= and >= handling + - expand the test suite + - add better parse error handling + +*/ + +#include "ldb_private.h" +#include "system/locale.h" + +static int ldb_parse_hex2char(const char *x) +{ + if (isxdigit(x[0]) && isxdigit(x[1])) { + const char h1 = x[0], h2 = x[1]; + int c = 0; + + if (h1 >= 'a') c = h1 - (int)'a' + 10; + else if (h1 >= 'A') c = h1 - (int)'A' + 10; + else if (h1 >= '0') c = h1 - (int)'0'; + c = c << 4; + if (h2 >= 'a') c += h2 - (int)'a' + 10; + else if (h2 >= 'A') c += h2 - (int)'A' + 10; + else if (h2 >= '0') c += h2 - (int)'0'; + + return c; + } + + return -1; +} + +/* +a filter is defined by: + ::= '(' ')' + ::= | | | + ::= '&' + ::= '|' + ::= '!' + ::= | + ::= + ::= '=' | '~=' | '<=' | '>=' +*/ + +/* + decode a RFC2254 binary string representation of a buffer. + Used in LDAP filters. +*/ +struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str) +{ + size_t i, j; + struct ldb_val ret; + size_t slen = str?strlen(str):0; + + ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1); + ret.length = 0; + if (ret.data == NULL) return ret; + + for (i=j=0;i 0x7E || strchr(" *()\\&|!\"", cval)) { + return true; + } + return false; +} + +/* + encode a blob as a RFC2254 binary string, escaping any + non-printable or '\' characters +*/ +char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val) +{ + size_t i; + char *ret; + size_t len = val.length; + unsigned char *buf = val.data; + + for (i=0;idata == NULL) return NULL; + + val++; + } + + if (ret != NULL) { + ret[val] = NULL; + } + + return ret; +} + +static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s); + + +/* + parse an extended match + + possible forms: + (attr:oid:=value) + (attr:dn:oid:=value) + (attr:dn:=value) + (:dn:oid:=value) + + the ':dn' part sets the dnAttributes boolean if present + the oid sets the rule_id string + +*/ +static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, + char *attr, char *value) +{ + char *p1, *p2; + + ret->operation = LDB_OP_EXTENDED; + ret->u.extended.value = ldb_binary_decode(ret, value); + if (ret->u.extended.value.data == NULL) goto failed; + + p1 = strchr(attr, ':'); + if (p1 == NULL) goto failed; + p2 = strchr(p1+1, ':'); + + *p1 = 0; + if (p2) *p2 = 0; + + ret->u.extended.attr = attr; + if (strcmp(p1+1, "dn") == 0) { + ret->u.extended.dnAttributes = 1; + if (p2) { + ret->u.extended.rule_id = talloc_strdup(ret, p2+1); + if (ret->u.extended.rule_id == NULL) goto failed; + } else { + ret->u.extended.rule_id = NULL; + } + } else { + ret->u.extended.dnAttributes = 0; + ret->u.extended.rule_id = talloc_strdup(ret, p1+1); + if (ret->u.extended.rule_id == NULL) goto failed; + } + + return ret; + +failed: + talloc_free(ret); + return NULL; +} + +static enum ldb_parse_op ldb_parse_filtertype(TALLOC_CTX *mem_ctx, char **type, char **value, const char **s) +{ + enum ldb_parse_op filter = 0; + char *name, *val, *k; + const char *p = *s; + const char *t, *t1; + + /* retrieve attributetype name */ + t = p; + + if (*p == '@') { /* for internal attributes the first char can be @ */ + p++; + } + + while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-') || (*p == '.')) { + /* attribute names can only be alphanums */ + p++; + } + + if (*p == ':') { /* but extended searches have : and . chars too */ + p = strstr(p, ":="); + if (p == NULL) { /* malformed attribute name */ + return 0; + } + } + + t1 = p; + + while (isspace((unsigned char)*p)) p++; + + if (!strchr("=<>~:", *p)) { + return 0; + } + + /* save name */ + name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1); + if (name == NULL) return 0; + name[t1 - t] = '\0'; + + /* retrieve filtertype */ + + if (*p == '=') { + filter = LDB_OP_EQUALITY; + } else if (*p != '\0' && *(p + 1) == '=') { + switch (*p) { + case '<': + filter = LDB_OP_LESS; + p++; + break; + case '>': + filter = LDB_OP_GREATER; + p++; + break; + case '~': + filter = LDB_OP_APPROX; + p++; + break; + case ':': + filter = LDB_OP_EXTENDED; + p++; + break; + } + } + if (!filter) { + talloc_free(name); + return 0; + } + p++; + + while (isspace((unsigned char)*p)) p++; + + /* retrieve value */ + t = p; + + while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++; + + val = (char *)talloc_memdup(mem_ctx, t, p - t + 1); + if (val == NULL) { + talloc_free(name); + return 0; + } + val[p - t] = '\0'; + + k = &(val[p - t]); + + /* remove trailing spaces from value */ + while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--; + *k = '\0'; + + *type = name; + *value = val; + *s = p; + return filter; +} + +/* + ::= +*/ +static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx, const char **s) +{ + char *attr, *value; + struct ldb_parse_tree *ret; + enum ldb_parse_op filtertype; + + ret = talloc_zero(mem_ctx, struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + filtertype = ldb_parse_filtertype(ret, &attr, &value, s); + if (!filtertype) { + talloc_free(ret); + return NULL; + } + + switch (filtertype) { + + case LDB_OP_PRESENT: + ret->operation = LDB_OP_PRESENT; + ret->u.present.attr = attr; + break; + + case LDB_OP_EQUALITY: + + if (strcmp(value, "*") == 0) { + ret->operation = LDB_OP_PRESENT; + ret->u.present.attr = attr; + break; + } + + if (ldb_parse_find_wildcard(value) != NULL) { + ret->operation = LDB_OP_SUBSTRING; + ret->u.substring.attr = attr; + ret->u.substring.start_with_wildcard = 0; + ret->u.substring.end_with_wildcard = 0; + ret->u.substring.chunks = ldb_wildcard_decode(ret, value); + if (ret->u.substring.chunks == NULL){ + talloc_free(ret); + return NULL; + } + if (value[0] == '*') + ret->u.substring.start_with_wildcard = 1; + if (value[strlen(value) - 1] == '*') + ret->u.substring.end_with_wildcard = 1; + talloc_free(value); + + break; + } + + ret->operation = LDB_OP_EQUALITY; + ret->u.equality.attr = attr; + ret->u.equality.value = ldb_binary_decode(ret, value); + if (ret->u.equality.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; + + case LDB_OP_GREATER: + ret->operation = LDB_OP_GREATER; + ret->u.comparison.attr = attr; + ret->u.comparison.value = ldb_binary_decode(ret, value); + if (ret->u.comparison.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; + + case LDB_OP_LESS: + ret->operation = LDB_OP_LESS; + ret->u.comparison.attr = attr; + ret->u.comparison.value = ldb_binary_decode(ret, value); + if (ret->u.comparison.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; + + case LDB_OP_APPROX: + ret->operation = LDB_OP_APPROX; + ret->u.comparison.attr = attr; + ret->u.comparison.value = ldb_binary_decode(ret, value); + if (ret->u.comparison.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; + + case LDB_OP_EXTENDED: + + ret = ldb_parse_extended(ret, attr, value); + break; + + default: + talloc_free(ret); + return NULL; + } + + return ret; +} + + +/* + parse a filterlist + ::= '&' + ::= '|' + ::= | +*/ +static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const char **s) +{ + struct ldb_parse_tree *ret, *next; + enum ldb_parse_op op; + const char *p = *s; + + switch (*p) { + case '&': + op = LDB_OP_AND; + break; + case '|': + op = LDB_OP_OR; + break; + default: + return NULL; + } + p++; + + while (isspace((unsigned char)*p)) p++; + + ret = talloc(mem_ctx, struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = op; + ret->u.list.num_elements = 1; + ret->u.list.elements = talloc(ret, struct ldb_parse_tree *); + if (!ret->u.list.elements) { + errno = ENOMEM; + talloc_free(ret); + return NULL; + } + + ret->u.list.elements[0] = ldb_parse_filter(ret->u.list.elements, &p); + if (!ret->u.list.elements[0]) { + talloc_free(ret); + return NULL; + } + + while (isspace((unsigned char)*p)) p++; + + while (*p) { + struct ldb_parse_tree **e; + if (*p == ')') { + break; + } + + next = ldb_parse_filter(ret->u.list.elements, &p); + if (next == NULL) { + /* an invalid filter element */ + talloc_free(ret); + return NULL; + } + e = talloc_realloc(ret, ret->u.list.elements, + struct ldb_parse_tree *, + ret->u.list.num_elements + 1); + if (!e) { + errno = ENOMEM; + talloc_free(ret); + return NULL; + } + ret->u.list.elements = e; + ret->u.list.elements[ret->u.list.num_elements] = next; + ret->u.list.num_elements++; + while (isspace((unsigned char)*p)) p++; + } + + *s = p; + + return ret; +} + + +/* + ::= '!' +*/ +static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s) +{ + struct ldb_parse_tree *ret; + const char *p = *s; + + if (*p != '!') { + return NULL; + } + p++; + + ret = talloc(mem_ctx, struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = LDB_OP_NOT; + ret->u.isnot.child = ldb_parse_filter(ret, &p); + if (!ret->u.isnot.child) { + talloc_free(ret); + return NULL; + } + + *s = p; + + return ret; +} + +/* + parse a filtercomp + ::= | | | +*/ +static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const char **s) +{ + struct ldb_parse_tree *ret; + const char *p = *s; + + while (isspace((unsigned char)*p)) p++; + + switch (*p) { + case '&': + ret = ldb_parse_filterlist(mem_ctx, &p); + break; + + case '|': + ret = ldb_parse_filterlist(mem_ctx, &p); + break; + + case '!': + ret = ldb_parse_not(mem_ctx, &p); + break; + + case '(': + case ')': + return NULL; + + default: + ret = ldb_parse_simple(mem_ctx, &p); + + } + + *s = p; + return ret; +} + + +/* + ::= '(' ')' +*/ +static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s) +{ + struct ldb_parse_tree *ret; + const char *p = *s; + + if (*p != '(') { + return NULL; + } + p++; + + ret = ldb_parse_filtercomp(mem_ctx, &p); + + if (*p != ')') { + return NULL; + } + p++; + + while (isspace((unsigned char)*p)) { + p++; + } + + *s = p; + + return ret; +} + + +/* + main parser entry point. Takes a search string and returns a parse tree + + expression ::= | +*/ +struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) +{ + while (s && isspace((unsigned char)*s)) s++; + + if (s == NULL || *s == 0) { + s = "(|(objectClass=*)(distinguishedName=*))"; + } + + if (*s == '(') { + return ldb_parse_filter(mem_ctx, &s); + } + + return ldb_parse_simple(mem_ctx, &s); +} + + +/* + construct a ldap parse filter given a parse tree +*/ +char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree) +{ + char *s, *s2, *ret; + unsigned int i; + + if (tree == NULL) { + return NULL; + } + + switch (tree->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + ret = talloc_asprintf(mem_ctx, "(%c", tree->operation==LDB_OP_AND?'&':'|'); + if (ret == NULL) return NULL; + for (i=0;iu.list.num_elements;i++) { + s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + s2 = talloc_asprintf_append(ret, "%s", s); + talloc_free(s); + if (s2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = s2; + } + s = talloc_asprintf_append(ret, ")"); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + return s; + case LDB_OP_NOT: + s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child); + if (s == NULL) return NULL; + + ret = talloc_asprintf(mem_ctx, "(!%s)", s); + talloc_free(s); + return ret; + case LDB_OP_EQUALITY: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s=%s)", + tree->u.equality.attr, s); + talloc_free(s); + return ret; + case LDB_OP_SUBSTRING: + ret = talloc_asprintf(mem_ctx, "(%s=%s", tree->u.substring.attr, + tree->u.substring.start_with_wildcard?"*":""); + if (ret == NULL) return NULL; + for (i = 0; tree->u.substring.chunks && tree->u.substring.chunks[i]; i++) { + s2 = ldb_binary_encode(mem_ctx, *(tree->u.substring.chunks[i])); + if (s2 == NULL) { + talloc_free(ret); + return NULL; + } + if (tree->u.substring.chunks[i+1] || + tree->u.substring.end_with_wildcard) { + s = talloc_asprintf_append(ret, "%s*", s2); + } else { + s = talloc_asprintf_append(ret, "%s", s2); + } + if (s == NULL) { + talloc_free(ret); + return NULL; + } + ret = s; + } + s = talloc_asprintf_append(ret, ")"); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + ret = s; + return ret; + case LDB_OP_GREATER: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s>=%s)", + tree->u.equality.attr, s); + talloc_free(s); + return ret; + case LDB_OP_LESS: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s<=%s)", + tree->u.equality.attr, s); + talloc_free(s); + return ret; + case LDB_OP_PRESENT: + ret = talloc_asprintf(mem_ctx, "(%s=*)", tree->u.present.attr); + return ret; + case LDB_OP_APPROX: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s~=%s)", + tree->u.equality.attr, s); + talloc_free(s); + return ret; + case LDB_OP_EXTENDED: + s = ldb_binary_encode(mem_ctx, tree->u.extended.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)", + tree->u.extended.attr?tree->u.extended.attr:"", + tree->u.extended.dnAttributes?":dn":"", + tree->u.extended.rule_id?":":"", + tree->u.extended.rule_id?tree->u.extended.rule_id:"", + s); + talloc_free(s); + return ret; + } + + return NULL; +} + + +/* + walk a parse tree, calling the provided callback on each node +*/ +int ldb_parse_tree_walk(struct ldb_parse_tree *tree, + int (*callback)(struct ldb_parse_tree *tree, void *), + void *private_context) +{ + unsigned int i; + int ret; + + ret = callback(tree, private_context); + if (ret != LDB_SUCCESS) { + return ret; + } + + switch (tree->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + ret = ldb_parse_tree_walk(tree->u.list.elements[i], callback, private_context); + if (ret != LDB_SUCCESS) { + return ret; + } + } + break; + case LDB_OP_NOT: + ret = ldb_parse_tree_walk(tree->u.isnot.child, callback, private_context); + if (ret != LDB_SUCCESS) { + return ret; + } + break; + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + case LDB_OP_SUBSTRING: + case LDB_OP_PRESENT: + case LDB_OP_EXTENDED: + break; + } + return LDB_SUCCESS; +} + +struct parse_tree_attr_replace_ctx { + const char *attr; + const char *replace; +}; + +/* + callback for ldb_parse_tree_attr_replace() + */ +static int parse_tree_attr_replace(struct ldb_parse_tree *tree, void *private_context) +{ + struct parse_tree_attr_replace_ctx *ctx = private_context; + switch (tree->operation) { + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + if (ldb_attr_cmp(tree->u.equality.attr, ctx->attr) == 0) { + tree->u.equality.attr = ctx->replace; + } + break; + case LDB_OP_SUBSTRING: + if (ldb_attr_cmp(tree->u.substring.attr, ctx->attr) == 0) { + tree->u.substring.attr = ctx->replace; + } + break; + case LDB_OP_PRESENT: + if (ldb_attr_cmp(tree->u.present.attr, ctx->attr) == 0) { + tree->u.present.attr = ctx->replace; + } + break; + case LDB_OP_EXTENDED: + if (tree->u.extended.attr && + ldb_attr_cmp(tree->u.extended.attr, ctx->attr) == 0) { + tree->u.extended.attr = ctx->replace; + } + break; + default: + break; + } + return LDB_SUCCESS; +} + +/* + replace any occurrences of an attribute name in the parse tree with a + new name +*/ +void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree, + const char *attr, + const char *replace) +{ + struct parse_tree_attr_replace_ctx ctx; + + ctx.attr = attr; + ctx.replace = replace; + + ldb_parse_tree_walk(tree, parse_tree_attr_replace, &ctx); +} + +/* + shallow copy a tree - copying only the elements array so that the caller + can safely add new elements without changing the message +*/ +struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx, + const struct ldb_parse_tree *ot) +{ + unsigned int i; + struct ldb_parse_tree *nt; + + nt = talloc(mem_ctx, struct ldb_parse_tree); + if (!nt) { + return NULL; + } + + *nt = *ot; + + switch (ot->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + nt->u.list.elements = talloc_array(nt, struct ldb_parse_tree *, + ot->u.list.num_elements); + if (!nt->u.list.elements) { + talloc_free(nt); + return NULL; + } + + for (i=0;iu.list.num_elements;i++) { + nt->u.list.elements[i] = + ldb_parse_tree_copy_shallow(nt->u.list.elements, + ot->u.list.elements[i]); + if (!nt->u.list.elements[i]) { + talloc_free(nt); + return NULL; + } + } + break; + case LDB_OP_NOT: + nt->u.isnot.child = ldb_parse_tree_copy_shallow(nt, + ot->u.isnot.child); + if (!nt->u.isnot.child) { + talloc_free(nt); + return NULL; + } + break; + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + case LDB_OP_SUBSTRING: + case LDB_OP_PRESENT: + case LDB_OP_EXTENDED: + break; + } + + return nt; +} diff --git a/ldb-2.0.8/common/ldb_utf8.c b/ldb-2.0.8/common/ldb_utf8.c new file mode 100644 index 0000000..55d8f90 --- /dev/null +++ b/ldb-2.0.8/common/ldb_utf8.c @@ -0,0 +1,136 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb utf8 handling + * + * Description: case folding and case comparison for UTF8 strings + * + * Author: Andrew Tridgell + */ + +#include "ldb_private.h" +#include "system/locale.h" + + +/* + this allow the user to pass in a caseless comparison + function to handle utf8 caseless comparisons + */ +void ldb_set_utf8_fns(struct ldb_context *ldb, + void *context, + char *(*casefold)(void *, void *, const char *, size_t)) +{ + if (context) + ldb->utf8_fns.context = context; + if (casefold) + ldb->utf8_fns.casefold = casefold; +} + +/* + a simple case folding function + NOTE: does not handle UTF8 +*/ +char *ldb_casefold_default(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n) +{ + size_t i; + char *ret = talloc_strndup(mem_ctx, s, n); + if (!s) { + errno = ENOMEM; + return NULL; + } + for (i=0;ret[i];i++) { + ret[i] = toupper((unsigned char)ret[i]); + } + return ret; +} + +void ldb_set_utf8_default(struct ldb_context *ldb) +{ + ldb_set_utf8_fns(ldb, NULL, ldb_casefold_default); +} + +char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n) +{ + return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n); +} + +/* + check the attribute name is valid according to rfc2251 + returns 1 if the name is ok + */ + +int ldb_valid_attr_name(const char *s) +{ + size_t i; + + if (!s || !s[0]) + return 0; + + /* handle special ldb_tdb wildcard */ + if (strcmp(s, "*") == 0) return 1; + + for (i = 0; s[i]; i++) { + if (! isascii(s[i])) { + return 0; + } + if (i == 0) { /* first char must be an alpha (or our special '@' identifier) */ + if (! (isalpha(s[i]) || (s[i] == '@'))) { + return 0; + } + } else { + if (! (isalnum(s[i]) || (s[i] == '-'))) { + return 0; + } + } + } + return 1; +} + +char *ldb_attr_casefold(TALLOC_CTX *mem_ctx, const char *s) +{ + size_t i; + char *ret = talloc_strdup(mem_ctx, s); + if (!ret) { + errno = ENOMEM; + return NULL; + } + for (i = 0; ret[i]; i++) { + ret[i] = toupper((unsigned char)ret[i]); + } + return ret; +} + +/* + we accept either 'dn' or 'distinguishedName' for a distinguishedName +*/ +int ldb_attr_dn(const char *attr) +{ + if (ldb_attr_cmp(attr, "dn") == 0 || + ldb_attr_cmp(attr, "distinguishedName") == 0) { + return 0; + } + return -1; +} diff --git a/ldb-2.0.8/common/qsort.c b/ldb-2.0.8/common/qsort.c new file mode 100644 index 0000000..012aaf3 --- /dev/null +++ b/ldb-2.0.8/common/qsort.c @@ -0,0 +1,251 @@ +/* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Douglas C. Schmidt (schmidt@ics.uci.edu). + + The GNU C 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 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see . */ + +/* If you consider tuning this algorithm, you should consult first: + Engineering a sort function; Jon Bentley and M. Douglas McIlroy; + Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */ + +/* Modified to be used in samba4 by + * Simo Sorce 2005 + */ + +#include "ldb_private.h" + +/* Byte-wise swap two items of size SIZE. */ +#define SWAP(a, b, size) \ + do \ + { \ + register size_t __size = (size); \ + register char *__a = (a), *__b = (b); \ + do \ + { \ + char __tmp = *__a; \ + *__a++ = *__b; \ + *__b++ = __tmp; \ + } while (--__size > 0); \ + } while (0) + +/* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sun 4/260. */ +#define MAX_THRESH 4 + +/* Stack node declarations used to store unfulfilled partition obligations. */ +typedef struct + { + char *lo; + char *hi; + } stack_node; + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +/* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type size_t, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(size_t). */ +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif +#define STACK_SIZE (CHAR_BIT * sizeof(size_t)) +#define PUSH(low, high) ((void) ((stack[i].lo = (low)), (stack[i].hi = (high)), i++)) +#define POP(low, high) ((void) (i--, (low = stack[i].lo), (high = stack[i].hi))) + + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + +void ldb_qsort (void *const pbase, size_t total_elems, size_t size, + void *opaque, ldb_qsort_cmp_fn_t cmp) +{ + register char *base_ptr = (char *) pbase; + + const size_t max_thresh = MAX_THRESH * size; + + if (total_elems == 0) + /* Avoid lossage with unsigned arithmetic below. */ + return; + + if (total_elems > MAX_THRESH) + { + char *lo = base_ptr; + char *hi = &lo[size * (total_elems - 1)]; + stack_node stack[STACK_SIZE]; + size_t i = 0; + + PUSH (NULL, NULL); + + do + { + char *left_ptr; + char *right_ptr; + + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR in + the while loops. */ + + char *mid = lo + size * ((hi - lo) / size >> 1); + + if ((*cmp) ((void *) mid, (void *) lo, opaque) < 0) + SWAP (mid, lo, size); + if ((*cmp) ((void *) hi, (void *) mid, opaque) < 0) + SWAP (mid, hi, size); + else + goto jump_over; + if ((*cmp) ((void *) mid, (void *) lo, opaque) < 0) + SWAP (mid, lo, size); + jump_over:; + + left_ptr = lo + size; + right_ptr = hi - size; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do + { + while ((*cmp) ((void *) left_ptr, (void *) mid, opaque) < 0) + left_ptr += size; + + while ((*cmp) ((void *) mid, (void *) right_ptr, opaque) < 0) + right_ptr -= size; + + if (left_ptr < right_ptr) + { + SWAP (left_ptr, right_ptr, size); + if (mid == left_ptr) + mid = right_ptr; + else if (mid == right_ptr) + mid = left_ptr; + left_ptr += size; + right_ptr -= size; + } + else if (left_ptr == right_ptr) + { + left_ptr += size; + right_ptr -= size; + break; + } + } + while (left_ptr <= right_ptr); + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if ((size_t) (right_ptr - lo) <= max_thresh) + { + if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore both small partitions. */ + POP (lo, hi); + else + /* Ignore small left partition. */ + lo = left_ptr; + } + else if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore small right partition. */ + hi = right_ptr; + else if ((right_ptr - lo) > (hi - left_ptr)) + { + /* Push larger left partition indices. */ + PUSH (lo, right_ptr); + lo = left_ptr; + } + else + { + /* Push larger right partition indices. */ + PUSH (left_ptr, hi); + hi = right_ptr; + } + } + while (i > 0 && i < STACK_SIZE); + } + + /* Once the BASE_PTR array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE_PTR points to the beginning + of the array to sort, and END_PTR points at the very last element in + the array (*not* one beyond it!). */ + +#define min(x, y) ((x) < (y) ? (x) : (y)) + + { + char *const end_ptr = &base_ptr[size * (total_elems - 1)]; + char *tmp_ptr = base_ptr; + char *thresh = min(end_ptr, base_ptr + max_thresh); + register char *run_ptr; + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size) + if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0) + tmp_ptr = run_ptr; + + if (tmp_ptr != base_ptr) + SWAP (tmp_ptr, base_ptr, size); + + /* Insertion sort, running from left-hand-side up to right-hand-side. */ + + run_ptr = base_ptr + size; + while ((run_ptr += size) <= end_ptr) + { + tmp_ptr = run_ptr - size; + while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0) + tmp_ptr -= size; + + tmp_ptr += size; + if (tmp_ptr != run_ptr) + { + char *trav; + + trav = run_ptr + size; + while (--trav >= run_ptr) + { + char c = *trav; + char *hi, *lo; + + for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo) + *hi = *lo; + *hi = c; + } + } + } + } +} diff --git a/ldb-2.0.8/configure b/ldb-2.0.8/configure new file mode 100755 index 0000000..6c931bf --- /dev/null +++ b/ldb-2.0.8/configure @@ -0,0 +1,21 @@ +#!/bin/sh + +PREVPATH=`dirname $0` + +if [ -f $PREVPATH/../../buildtools/bin/waf ]; then + WAF=../../buildtools/bin/waf +elif [ -f $PREVPATH/buildtools/bin/waf ]; then + WAF=./buildtools/bin/waf +else + echo "ldb: Unable to find waf" + exit 1 +fi + +# using JOBS=1 gives maximum compatibility with +# systems like AIX which have broken threading in python +JOBS=1 +export JOBS + +cd . || exit 1 +$PYTHON $WAF configure "$@" || exit 1 +cd $PREVPATH diff --git a/ldb-2.0.8/docs/builddocs.sh b/ldb-2.0.8/docs/builddocs.sh new file mode 100755 index 0000000..449dcb2 --- /dev/null +++ b/ldb-2.0.8/docs/builddocs.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# build ldb docs +# tridge@samba.org August 2006 + +XSLTPROC="$1" +SRCDIR="$2" + +if [ -z "$XSLTPROC" ] || [ ! -x "$XSLTPROC" ]; then + echo "xsltproc not installed" + exit 0 +fi + +MANXSL="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl" +HTMLXSL="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl" + +mkdir -p man + +for f in $SRCDIR/man/*.xml; do + base=`basename $f .xml` + out=man/"`basename $base`" + if [ ! -f "$out" ] || [ "$f" -nt "$out" ]; then + echo Processing manpage $f + $XSLTPROC --nonet -o "$out" "$MANXSL" $f + ret=$? + if [ "$ret" = "4" ]; then + echo "ignoring stylesheet error 4 for $MANXSL" + exit 0 + fi + if [ "$ret" != "0" ]; then + echo "xsltproc failed with error $ret" + exit $ret + fi + fi +done + +for f in $SRCDIR/man/*.xml; do + base=`basename $f .xml` + out=man/"`basename $base`".html + if [ ! -f "$out" ] || [ "$f" -nt "$out" ]; then + echo Processing html $f + $XSLTPROC --nonet -o "$out" "$HTMLXSL" $f + ret=$? + if [ "$ret" = "4" ]; then + echo "ignoring stylesheet error 4 for $HTMLXSL" + exit 0 + fi + if [ "$ret" != "0" ]; then + echo "xsltproc failed with error $ret" + exit $ret + fi + fi +done diff --git a/ldb-2.0.8/docs/design.txt b/ldb-2.0.8/docs/design.txt new file mode 100644 index 0000000..0bb278b --- /dev/null +++ b/ldb-2.0.8/docs/design.txt @@ -0,0 +1,41 @@ +The list of indexed fields +-------------------------- + +dn=@INDEXLIST + list of field names that are indexed + + contains fields of type @IDXATTR which contain attriute names + of indexed fields + + +Data records +------------ + +for each user record in the db there is: + main record + key: DN=dn + data: packed attribute/value list + + a index record for each indexed field in the record + + +Index Records +------------- + +The index records contain the list of dn's that contain records +matching the index key + +All index records are of the form: + dn=@INDEX:field:value + +and contain fields of type @IDX which are the dns of the records +that have that value for some attribute + + +Search Expressions +------------------ + +Very similar to LDAP search expressions, but does not allow ~=, <= or >= + + attrib0 := (field=value) + attrib := attrib0 | (attrib&&attrib) | (attrib||attrib) | !attrib diff --git a/ldb-2.0.8/docs/installdocs.sh b/ldb-2.0.8/docs/installdocs.sh new file mode 100755 index 0000000..6cc7b74 --- /dev/null +++ b/ldb-2.0.8/docs/installdocs.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# install ldb docs +# tridge@samba.org August 2006 + +MANDIR="$1" + +MAN1="`/bin/ls man/*.1`" +MAN3="`/bin/ls man/*.3`" + +if [ -z "$MAN1" ] && [ -z "$MAN3" ]; then + echo "No manpages have been built" + exit 0 +fi + +mkdir -p "$MANDIR/man1" "$MANDIR/man3" +cp $MAN1 "$MANDIR/man1/" || exit 1 +cp $MAN3 "$MANDIR/man3/" || exit 1 diff --git a/ldb-2.0.8/examples.dox b/ldb-2.0.8/examples.dox new file mode 100644 index 0000000..ef4b4f0 --- /dev/null +++ b/ldb-2.0.8/examples.dox @@ -0,0 +1,16 @@ +/** \example ldbreader.c + +The code below shows a simple LDB application. + +It lists / dumps the records in a LDB database to standard output. + +*/ + + +/** \example ldifreader.c + +The code below shows a simple LDB application. + +It lists / dumps the entries in an LDIF file to standard output. + +*/ diff --git a/ldb-2.0.8/examples/ldbreader.c b/ldb-2.0.8/examples/ldbreader.c new file mode 100644 index 0000000..3496baf --- /dev/null +++ b/ldb-2.0.8/examples/ldbreader.c @@ -0,0 +1,122 @@ +/* + example code for the ldb database library + + Copyright (C) Brad Hards (bradh@frogmouth.net) 2005-2006 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/** \example ldbreader.c + +The code below shows a simple LDB application. + +It lists / dumps the records in a LDB database to standard output. + +*/ + +#include "ldb.h" + +/* + ldb_ldif_write takes a function pointer to a custom output + function. This version is about as simple as the output function can + be. In a more complex example, you'd likely be doing something with + the private data function (e.g. holding a file handle). +*/ +static int vprintf_fn(void *private_data, const char *fmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, fmt); + /* We just write to standard output */ + retval = vprintf(fmt, ap); + va_end(ap); + /* Note that the function should return the number of + bytes written, or a negative error code */ + return retval; +} + +int main(int argc, const char **argv) +{ + struct ldb_context *ldb; + const char *expression = "(dn=*)"; + struct ldb_result *resultMsg; + int i; + + /* + This is the always the first thing you want to do in an LDB + application - initialise up the context structure. + + Note that you can use the context structure as a parent + for talloc allocations as well + */ + ldb = ldb_init(NULL, NULL); + + /* + We now open the database. In this example we just hard code the connection path. + + Also note that the database is being opened read-only. This means that the + call will fail unless the database already exists. + */ + if (LDB_SUCCESS != ldb_connect(ldb, "tdb://tdbtest.ldb", LDB_FLG_RDONLY, NULL) ){ + printf("Problem on connection\n"); + exit(-1); + } + + /* + At this stage we have an open database, and can start using it. It is opened + read-only, so a query is possible. + + We construct a search that just returns all the (sensible) contents. You can do + quite fine grained results with the LDAP search syntax, however it is a bit + confusing to start with. See RFC2254. + */ + if (LDB_SUCCESS != ldb_search(ldb, ldb, &resultMsg, + NULL, LDB_SCOPE_DEFAULT, NULL, + "%s", expression)) { + printf("Problem in search\n"); + exit(-1); + } + + printf("%i records returned\n", resultMsg->count); + + /* + We can now iterate through the results, writing them out + (to standard output) with our custom output routine as defined + at the top of this file + */ + for (i = 0; i < resultMsg->count; ++i) { + struct ldb_ldif ldifMsg; + + printf("Message: %i\n", i+1); + + ldifMsg.changetype = LDB_CHANGETYPE_NONE; + ldifMsg.msg = resultMsg->msgs[i]; + ldb_ldif_write(ldb, vprintf_fn, NULL, &ldifMsg); + } + + /* + There are two objects to clean up - the result from the + ldb_search() query, and the original ldb context. + */ + talloc_free(resultMsg); + + talloc_free(ldb); + + return 0; +} diff --git a/ldb-2.0.8/examples/ldifreader.c b/ldb-2.0.8/examples/ldifreader.c new file mode 100644 index 0000000..dcd9daf --- /dev/null +++ b/ldb-2.0.8/examples/ldifreader.c @@ -0,0 +1,125 @@ +/* + example code for the ldb database library + + Copyright (C) Brad Hards (bradh@frogmouth.net) 2005-2006 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/** \example ldifreader.c + +The code below shows a simple LDB application. + +It lists / dumps the entries in an LDIF file to standard output. + +*/ + +#include "ldb.h" + +/* + ldb_ldif_write takes a function pointer to a custom output + function. This version is about as simple as the output function can + be. In a more complex example, you'd likely be doing something with + the private data function (e.g. holding a file handle). +*/ +static int vprintf_fn(void *private_data, const char *fmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, fmt); + /* We just write to standard output */ + retval = vprintf(fmt, ap); + va_end(ap); + /* Note that the function should return the number of + bytes written, or a negative error code */ + return retval; +} + +int main(int argc, const char **argv) +{ + struct ldb_context *ldb; + FILE *fileStream; + struct ldb_ldif *ldifMsg; + + if (argc != 2) { + printf("Usage %s filename.ldif\n", argv[0]); + exit(1); + } + + /* + This is the always the first thing you want to do in an LDB + application - initialise up the context structure. + + Note that you can use the context structure as a parent + for talloc allocations as well + */ + ldb = ldb_init(NULL, NULL); + + fileStream = fopen(argv[1], "r"); + if (0 == fileStream) { + perror(argv[1]); + exit(1); + } + + /* + We now work through the filestream to get each entry. + */ + while ( (ldifMsg = ldb_ldif_read_file(ldb, fileStream)) ) { + /* + Each message has a particular change type. For Add, + Modify and Delete, this will also appear in the + output listing (as changetype: add, changetype: + modify or changetype:delete, respectively). + */ + switch (ldifMsg->changetype) { + case LDB_CHANGETYPE_NONE: + printf("ChangeType: None\n"); + break; + case LDB_CHANGETYPE_ADD: + printf("ChangeType: Add\n"); + break; + case LDB_CHANGETYPE_MODIFY: + printf("ChangeType: Modify\n"); + break; + case LDB_CHANGETYPE_DELETE: + printf("ChangeType: Delete\n"); + break; + default: + printf("ChangeType: Unknown\n"); + } + + /* + We can now write out the results, using our custom + output routine as defined at the top of this file. + */ + ldb_ldif_write(ldb, vprintf_fn, NULL, ldifMsg); + + /* + Clean up the message + */ + ldb_ldif_read_free(ldb, ldifMsg); + } + + /* + Clean up the context + */ + talloc_free(ldb); + + return 0; +} diff --git a/ldb-2.0.8/include/dlinklist.h b/ldb-2.0.8/include/dlinklist.h new file mode 100644 index 0000000..822a826 --- /dev/null +++ b/ldb-2.0.8/include/dlinklist.h @@ -0,0 +1,178 @@ +/* + Unix SMB/CIFS implementation. + some simple double linked list macros + + Copyright (C) Andrew Tridgell 1998-2010 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* To use these macros you must have a structure containing a next and + prev pointer */ + +#ifndef _DLINKLIST_H +#define _DLINKLIST_H + +/* + February 2010 - changed list format to have a prev pointer from the + list head. This makes DLIST_ADD_END() O(1) even though we only have + one list pointer. + + The scheme is as follows: + + 1) with no entries in the list: + list_head == NULL + + 2) with 1 entry in the list: + list_head->next == NULL + list_head->prev == list_head + + 3) with 2 entries in the list: + list_head->next == element2 + list_head->prev == element2 + element2->prev == list_head + element2->next == NULL + + 4) with N entries in the list: + list_head->next == element2 + list_head->prev == elementN + elementN->prev == element{N-1} + elementN->next == NULL + + This allows us to find the tail of the list by using + list_head->prev, which means we can add to the end of the list in + O(1) time + */ + + +/* + add an element at the front of a list +*/ +#define DLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (p)->prev = (list) = (p); \ + (p)->next = NULL; \ + } else { \ + (p)->prev = (list)->prev; \ + (list)->prev = (p); \ + (p)->next = (list); \ + (list) = (p); \ + } \ +} while (0) + +/* + remove an element from a list + Note that the element doesn't have to be in the list. If it + isn't then this is a no-op +*/ +#define DLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + (list) = (p)->next; \ + } else if ((p)->prev && (list) && (p) == (list)->prev) { \ + (p)->prev->next = NULL; \ + (list)->prev = (p)->prev; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) != (list)) (p)->next = (p)->prev = NULL; \ +} while (0) + +/* + find the head of the list given any element in it. + Note that this costs O(N), so you should avoid this macro + if at all possible! +*/ +#define DLIST_HEAD(p, result_head) \ +do { \ + (result_head) = (p); \ + while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ +} while(0) + +/* return the last element in the list */ +#define DLIST_TAIL(list) ((list)?(list)->prev:NULL) + +/* return the previous element in the list. */ +#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) + +/* insert 'p' after the given element 'el' in a list. If el is NULL then + this is the same as a DLIST_ADD() */ +#define DLIST_ADD_AFTER(list, p, el) \ +do { \ + if (!(list) || !(el)) { \ + DLIST_ADD(list, p); \ + } else { \ + (p)->prev = (el); \ + (p)->next = (el)->next; \ + (el)->next = (p); \ + if ((p)->next) (p)->next->prev = (p); \ + if ((list)->prev == (el)) (list)->prev = (p); \ + }\ +} while (0) + + +/* + add to the end of a list. +*/ +#define DLIST_ADD_END(list, p) \ +do { \ + if (!(list)) { \ + DLIST_ADD(list, p); \ + } else { \ + DLIST_ADD_AFTER(list, p, (list)->prev); \ + } \ +} while (0) + +/* promote an element to the front of a list */ +#define DLIST_PROMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD(list, p); \ +} while (0) + +/* + demote an element to the end of a list. +*/ +#define DLIST_DEMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD_END(list, p); \ +} while (0) + +/* + concatenate two lists - putting all elements of the 2nd list at the + end of the first list. +*/ +#define DLIST_CONCATENATE(list1, list2) \ +do { \ + if (!(list1)) { \ + (list1) = (list2); \ + } else { \ + (list1)->prev->next = (list2); \ + if (list2) { \ + void *_tmplist = (void *)(list1)->prev; \ + (list1)->prev = (list2)->prev; \ + (list2)->prev = _tmplist; \ + } \ + } \ +} while (0) + +#endif /* _DLINKLIST_H */ diff --git a/ldb-2.0.8/include/ldb.h b/ldb-2.0.8/include/ldb.h new file mode 100644 index 0000000..3cba0f4 --- /dev/null +++ b/ldb-2.0.8/include/ldb.h @@ -0,0 +1,2365 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2005-2006 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb header + * + * Description: defines for base ldb API + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + */ + +/** + \file ldb.h Samba's ldb database + + This header file provides the main API for ldb. +*/ + +#ifndef _LDB_H_ + +/*! \cond DOXYGEN_IGNORE */ +#define _LDB_H_ 1 +/*! \endcond */ + +#include +#include +#include +#include +#include + +/* + major restrictions as compared to normal LDAP: + + - each record must have a unique key field + - the key must be representable as a NULL terminated C string and may not + contain a comma or braces + + major restrictions as compared to tdb: + + - no explicit locking calls, but we have transactions when using ldb_tdb + +*/ + +#ifndef ldb_val +/** + Result value + + An individual lump of data in a result comes in this format. The + pointer will usually be to a UTF-8 string if the application is + sensible, but it can be to anything you like, including binary data + blobs of arbitrary size. + + \note the data is null (0x00) terminated, but the length does not + include the terminator. +*/ +struct ldb_val { + uint8_t *data; /*!< result data */ + size_t length; /*!< length of data */ +}; +#endif + +/*! \cond DOXYGEN_IGNORE */ +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(a,b) +#endif + +#ifndef _DEPRECATED_ +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif +/*! \endcond */ + +/* opaque ldb_dn structures, see ldb_dn.c for internals */ +struct ldb_dn_component; +struct ldb_dn; + +/** + There are a number of flags that are used with ldap_modify() in + ldb_message_element.flags fields. The LDB_FLAG_MOD_ADD, + LDB_FLAG_MOD_DELETE and LDB_FLAG_MOD_REPLACE are better thought of as + an enumeration, not flags, and are used in ldap_modify() calls to + specify whether attributes are being added, deleted or modified + respectively. +*/ +#define LDB_FLAG_MOD_MASK 0x3 + +/** + use this to extract the mod type (enum) from the operation + */ +#define LDB_FLAG_MOD_TYPE(flags) ((flags) & LDB_FLAG_MOD_MASK) + +/** + Value used in ldap_modify() to indicate that attributes are + being added. + + \sa LDB_FLAG_MOD_MASK +*/ +#define LDB_FLAG_MOD_ADD 1 + +/** + Value used in ldap_modify() to indicate that attributes are + being replaced. + + \sa LDB_FLAG_MOD_MASK +*/ +#define LDB_FLAG_MOD_REPLACE 2 + +/** + Value used in ldap_modify() to indicate that attributes are + being deleted. + + \sa LDB_FLAG_MOD_MASK +*/ +#define LDB_FLAG_MOD_DELETE 3 + +/** + Flag value used in ldb_ldif_write_trace() to enforce binary encoded + attribute values per attribute. + + This is a genuine flag, being outside LDB_FLAG_MOD_MASK and also + outside LDB_FLAG_INTERNAL_MASK +*/ +#define LDB_FLAG_FORCE_NO_BASE64_LDIF 4 + +/** + flag bits on an element usable only by the internal implementation +*/ +#define LDB_FLAG_INTERNAL_MASK 0xFFFFFFF0 + +/** + OID for logic AND comaprison. + + This is the well known object ID for a logical AND comparitor. +*/ +#define LDB_OID_COMPARATOR_AND "1.2.840.113556.1.4.803" + +/** + OID for logic OR comparison. + + This is the well known object ID for a logical OR comparitor. +*/ +#define LDB_OID_COMPARATOR_OR "1.2.840.113556.1.4.804" + +/** + results are given back as arrays of ldb_message_element +*/ +struct ldb_message_element { + unsigned int flags; + const char *name; + unsigned int num_values; + struct ldb_val *values; +}; + + +/** + a ldb_message represents all or part of a record. It can contain an arbitrary + number of elements. +*/ +struct ldb_message { + struct ldb_dn *dn; + unsigned int num_elements; + struct ldb_message_element *elements; +}; + +enum ldb_changetype { + LDB_CHANGETYPE_NONE=0, + LDB_CHANGETYPE_ADD, + LDB_CHANGETYPE_DELETE, + LDB_CHANGETYPE_MODIFY, + LDB_CHANGETYPE_MODRDN +}; + +/** + LDIF record + + This structure contains a LDIF record, as returned from ldif_read() + and equivalent functions. +*/ +struct ldb_ldif { + enum ldb_changetype changetype; /*!< The type of change */ + struct ldb_message *msg; /*!< The changes */ +}; + +enum ldb_scope {LDB_SCOPE_DEFAULT=-1, + LDB_SCOPE_BASE=0, + LDB_SCOPE_ONELEVEL=1, + LDB_SCOPE_SUBTREE=2}; + +struct ldb_context; +struct tevent_context; + +/* debugging uses one of the following levels */ +enum ldb_debug_level {LDB_DEBUG_FATAL, LDB_DEBUG_ERROR, + LDB_DEBUG_WARNING, LDB_DEBUG_TRACE}; + +/* alias for something that's not a fatal error but we really want to log */ +#define LDB_DEBUG_ALWAYS_LOG LDB_DEBUG_FATAL + +/** + the user can optionally supply a debug function. The function + is based on the vfprintf() style of interface, but with the addition + of a severity level +*/ +struct ldb_debug_ops { + void (*debug)(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + void *context; +}; + +/** + The user can optionally supply a custom utf8 functions, + to handle comparisons and casefolding. +*/ +struct ldb_utf8_fns { + void *context; + char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n); +}; + +/** + Flag value for database connection mode. + + If LDB_FLG_RDONLY is used in ldb_connect, then the database will be + opened read-only, if possible. +*/ +#define LDB_FLG_RDONLY 1 + +/** + Flag value for database connection mode. + + If LDB_FLG_NOSYNC is used in ldb_connect, then the database will be + opened without synchronous operations, if possible. +*/ +#define LDB_FLG_NOSYNC 2 + +/** + Flag value to specify autoreconnect mode. + + If LDB_FLG_RECONNECT is used in ldb_connect, then the backend will + be opened in a way that makes it try to auto reconnect if the + connection is dropped (actually make sense only with ldap). +*/ +#define LDB_FLG_RECONNECT 4 + +/** + Flag to tell backends not to use mmap +*/ +#define LDB_FLG_NOMMAP 8 + +/** + Flag to tell ldif handlers not to force encoding of binary + structures in base64 +*/ +#define LDB_FLG_SHOW_BINARY 16 + +/** + Flags to enable ldb tracing +*/ +#define LDB_FLG_ENABLE_TRACING 32 + +/** + Flags to tell LDB not to create a new database file: + + Without this flag ldb_tdb (for example) will create a blank file + during an invocation of ldb_connect(), even when the caller only + wanted read operations, for example in ldbsearch. +*/ +#define LDB_FLG_DONT_CREATE_DB 64 + +/* + structures for ldb_parse_tree handling code +*/ +enum ldb_parse_op { LDB_OP_AND=1, LDB_OP_OR=2, LDB_OP_NOT=3, + LDB_OP_EQUALITY=4, LDB_OP_SUBSTRING=5, + LDB_OP_GREATER=6, LDB_OP_LESS=7, LDB_OP_PRESENT=8, + LDB_OP_APPROX=9, LDB_OP_EXTENDED=10 }; + +struct ldb_parse_tree { + enum ldb_parse_op operation; + union { + struct { + struct ldb_parse_tree *child; + } isnot; + struct { + const char *attr; + struct ldb_val value; + } equality; + struct { + const char *attr; + int start_with_wildcard; + int end_with_wildcard; + struct ldb_val **chunks; + } substring; + struct { + const char *attr; + } present; + struct { + const char *attr; + struct ldb_val value; + } comparison; + struct { + const char *attr; + int dnAttributes; + const char *rule_id; + struct ldb_val value; + } extended; + struct { + unsigned int num_elements; + struct ldb_parse_tree **elements; + } list; + } u; +}; + +struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s); +char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree); + +/** + Encode a binary blob + + This function encodes a binary blob using the encoding rules in RFC + 2254 (Section 4). This function also escapes any non-printable + characters. + + \param mem_ctx the memory context to allocate the return string in. + \param val the (potentially) binary data to be encoded + + \return the encoded data as a null terminated string + + \sa RFC 2252. +*/ +char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val); + +/** + Encode a string + + This function encodes a string using the encoding rules in RFC 2254 + (Section 4). This function also escapes any non-printable + characters. + + \param mem_ctx the memory context to allocate the return string in. + \param string the string to be encoded + + \return the encoded data as a null terminated string + + \sa RFC 2252. +*/ +char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string); + +/* + functions for controlling attribute handling +*/ +typedef int (*ldb_attr_handler_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, struct ldb_val *); +typedef int (*ldb_attr_comparison_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, const struct ldb_val *); +struct ldb_schema_attribute; +typedef int (*ldb_attr_operator_t)(struct ldb_context *, enum ldb_parse_op operation, + const struct ldb_schema_attribute *a, + const struct ldb_val *, const struct ldb_val *, bool *matched); + +/* + attribute handler structure + + attr -> The attribute name + ldif_read_fn -> convert from ldif to binary format + ldif_write_fn -> convert from binary to ldif format + canonicalise_fn -> canonicalise a value, for use by indexing and dn construction + index_form_fn -> get lexicographically sorted format for index + comparison_fn -> compare two values + operator_fn -> override function for optimizing out unnecessary + calls to canonicalise_fn and comparison_fn +*/ + +struct ldb_schema_syntax { + const char *name; + ldb_attr_handler_t ldif_read_fn; + ldb_attr_handler_t ldif_write_fn; + ldb_attr_handler_t canonicalise_fn; + ldb_attr_handler_t index_format_fn; + ldb_attr_comparison_t comparison_fn; + ldb_attr_operator_t operator_fn; +}; + +struct ldb_schema_attribute { + const char *name; + unsigned flags; + const struct ldb_schema_syntax *syntax; +}; + +const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb, + const char *name); + +struct ldb_dn_extended_syntax { + const char *name; + ldb_attr_handler_t read_fn; + ldb_attr_handler_t write_clear_fn; + ldb_attr_handler_t write_hex_fn; +}; + +const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_context *ldb, + const char *name); + +/** + The attribute is not returned by default +*/ +#define LDB_ATTR_FLAG_HIDDEN (1<<0) + +/* the attribute handler name should be freed when released */ +#define LDB_ATTR_FLAG_ALLOCATED (1<<1) + +/** + The attribute is supplied by the application and should not be removed +*/ +#define LDB_ATTR_FLAG_FIXED (1<<2) + +/* + when this is set, attempts to create two records which have the same + value for this attribute will return LDB_ERR_ENTRY_ALREADY_EXISTS + */ +#define LDB_ATTR_FLAG_UNIQUE_INDEX (1<<3) + +/* + when this is set, attempts to create two attribute values for this attribute on a single DN will return LDB_ERR_CONSTRAINT_VIOLATION + */ +#define LDB_ATTR_FLAG_SINGLE_VALUE (1<<4) + +/* + * The values should always be base64 encoded + */ +#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) + +/* + * The attribute is indexed + */ +#define LDB_ATTR_FLAG_INDEXED (1<<7) + +/** + LDAP attribute syntax for a DN + + This is the well-known LDAP attribute syntax for a DN. + + See RFC 2252, Section 4.3.2 +*/ +#define LDB_SYNTAX_DN "1.3.6.1.4.1.1466.115.121.1.12" + +/** + LDAP attribute syntax for a Directory String + + This is the well-known LDAP attribute syntax for a Directory String. + + \sa RFC 2252, Section 4.3.2 +*/ +#define LDB_SYNTAX_DIRECTORY_STRING "1.3.6.1.4.1.1466.115.121.1.15" + +/** + LDAP attribute syntax for an integer + + This is the well-known LDAP attribute syntax for an integer. + + See RFC 2252, Section 4.3.2 +*/ +#define LDB_SYNTAX_INTEGER "1.3.6.1.4.1.1466.115.121.1.27" + +/** + Custom attribute syntax for an integer whose index is lexicographically + ordered by attribute value in the database. +*/ +#define LDB_SYNTAX_ORDERED_INTEGER "LDB_SYNTAX_ORDERED_INTEGER" + +/** + LDAP attribute syntax for a boolean + + This is the well-known LDAP attribute syntax for a boolean. + + See RFC 2252, Section 4.3.2 +*/ +#define LDB_SYNTAX_BOOLEAN "1.3.6.1.4.1.1466.115.121.1.7" + +/** + LDAP attribute syntax for an octet string + + This is the well-known LDAP attribute syntax for an octet string. + + See RFC 2252, Section 4.3.2 +*/ +#define LDB_SYNTAX_OCTET_STRING "1.3.6.1.4.1.1466.115.121.1.40" + +/** + LDAP attribute syntax for UTC time. + + This is the well-known LDAP attribute syntax for a UTC time. + + See RFC 2252, Section 4.3.2 +*/ +#define LDB_SYNTAX_UTC_TIME "1.3.6.1.4.1.1466.115.121.1.53" +#define LDB_SYNTAX_GENERALIZED_TIME "1.3.6.1.4.1.1466.115.121.1.24" + +#define LDB_SYNTAX_OBJECTCLASS "LDB_SYNTAX_OBJECTCLASS" + +/* sorting helpers */ +typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque); + +/* Individual controls */ + +/** + OID for getting and manipulating attributes from the ldb + without interception in the operational module. + It can be used to access attribute that used to be stored in the sam + and that are now calculated. +*/ +#define LDB_CONTROL_BYPASS_OPERATIONAL_OID "1.3.6.1.4.1.7165.4.3.13" +#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. + +*/ +#define LDB_CONTROL_RECALCULATE_SD_OID "1.3.6.1.4.1.7165.4.3.5" +#define LDB_CONTROL_RECALCULATE_SD_NAME "recalculate_sd" + +/** + REVEAL_INTERNALS is used to reveal internal attributes and DN + components which are not normally shown to the user +*/ +#define LDB_CONTROL_REVEAL_INTERNALS "1.3.6.1.4.1.7165.4.3.6" +#define LDB_CONTROL_REVEAL_INTERNALS_NAME "reveal_internals" + +/** + LDB_CONTROL_AS_SYSTEM is used to skip access checks on operations + that are performed by the system, but with a user's credentials, e.g. + updating prefix map +*/ +#define LDB_CONTROL_AS_SYSTEM_OID "1.3.6.1.4.1.7165.4.3.7" + +/** + LDB_CONTROL_PROVISION_OID is used to skip some constraint checks. It's is + mainly thought to be used for the provisioning. +*/ +#define LDB_CONTROL_PROVISION_OID "1.3.6.1.4.1.7165.4.3.16" +#define LDB_CONTROL_PROVISION_NAME "provision" + +/* AD controls */ + +/** + OID for the paged results control. This control is included in the + searchRequest and searchResultDone messages as part of the controls + field of the LDAPMessage, as defined in Section 4.1.12 of + LDAP v3. + + \sa RFC 2696. +*/ +#define LDB_CONTROL_PAGED_RESULTS_OID "1.2.840.113556.1.4.319" +#define LDB_CONTROL_PAGED_RESULTS_NAME "paged_results" + +/** + OID for specifying the returned elements of the ntSecurityDescriptor + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_SD_FLAGS_OID "1.2.840.113556.1.4.801" +#define LDB_CONTROL_SD_FLAGS_NAME "sd_flags" + +/** + OID for specifying an advanced scope for the search (one partition) + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_DOMAIN_SCOPE_OID "1.2.840.113556.1.4.1339" +#define LDB_CONTROL_DOMAIN_SCOPE_NAME "domain_scope" + +/** + OID for specifying an advanced scope for a search + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_SEARCH_OPTIONS_OID "1.2.840.113556.1.4.1340" +#define LDB_CONTROL_SEARCH_OPTIONS_NAME "search_options" + +/** + OID for notification + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_NOTIFICATION_OID "1.2.840.113556.1.4.528" +#define LDB_CONTROL_NOTIFICATION_NAME "notification" + +/** + OID for performing subtree deletes + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_TREE_DELETE_OID "1.2.840.113556.1.4.805" +#define LDB_CONTROL_TREE_DELETE_NAME "tree_delete" + +/** + OID for getting deleted objects + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_SHOW_DELETED_OID "1.2.840.113556.1.4.417" +#define LDB_CONTROL_SHOW_DELETED_NAME "show_deleted" + +/** + OID for getting recycled objects + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_SHOW_RECYCLED_OID "1.2.840.113556.1.4.2064" +#define LDB_CONTROL_SHOW_RECYCLED_NAME "show_recycled" + +/** + OID for getting deactivated linked attributes + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID "1.2.840.113556.1.4.2065" +#define LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME "show_deactivated_link" + +/** + OID for extended DN + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_EXTENDED_DN_OID "1.2.840.113556.1.4.529" +#define LDB_CONTROL_EXTENDED_DN_NAME "extended_dn" + +/** + OID for LDAP server sort result extension. + + This control is included in the searchRequest message as part of + the controls field of the LDAPMessage, as defined in Section 4.1.12 + of LDAP v3. The controlType is set to + "1.2.840.113556.1.4.473". The criticality MAY be either TRUE or + FALSE (where absent is also equivalent to FALSE) at the client's + option. + + \sa RFC 2891. +*/ +#define LDB_CONTROL_SERVER_SORT_OID "1.2.840.113556.1.4.473" +#define LDB_CONTROL_SERVER_SORT_NAME "server_sort" + +/** + OID for LDAP server sort result response extension. + + This control is included in the searchResultDone message as part of + the controls field of the LDAPMessage, as defined in Section 4.1.12 of + LDAP v3. + + \sa RFC 2891. +*/ +#define LDB_CONTROL_SORT_RESP_OID "1.2.840.113556.1.4.474" +#define LDB_CONTROL_SORT_RESP_NAME "server_sort_resp" + +/** + OID for LDAP Attribute Scoped Query extension. + + This control is included in SearchRequest or SearchResponse + messages as part of the controls field of the LDAPMessage. +*/ +#define LDB_CONTROL_ASQ_OID "1.2.840.113556.1.4.1504" +#define LDB_CONTROL_ASQ_NAME "asq" + +/** + OID for LDAP Directory Sync extension. + + This control is included in SearchRequest or SearchResponse + messages as part of the controls field of the LDAPMessage. +*/ +#define LDB_CONTROL_DIRSYNC_OID "1.2.840.113556.1.4.841" +#define LDB_CONTROL_DIRSYNC_NAME "dirsync" +#define LDB_CONTROL_DIRSYNC_EX_OID "1.2.840.113556.1.4.2090" +#define LDB_CONTROL_DIRSYNC_EX_NAME "dirsync_ex" + + +/** + OID for LDAP Virtual List View Request extension. + + This control is included in SearchRequest messages + as part of the controls field of the LDAPMessage. +*/ +#define LDB_CONTROL_VLV_REQ_OID "2.16.840.1.113730.3.4.9" +#define LDB_CONTROL_VLV_REQ_NAME "vlv" + +/** + OID for LDAP Virtual List View Response extension. + + This control is included in SearchResponse messages + as part of the controls field of the LDAPMessage. +*/ +#define LDB_CONTROL_VLV_RESP_OID "2.16.840.1.113730.3.4.10" +#define LDB_CONTROL_VLV_RESP_NAME "vlv_resp" + +/** + OID to let modifies don't give an error when adding an existing + attribute with the same value or deleting an nonexisting one attribute + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_PERMISSIVE_MODIFY_OID "1.2.840.113556.1.4.1413" +#define LDB_CONTROL_PERMISSIVE_MODIFY_NAME "permissive_modify" + +/** + OID to allow the server to be more 'fast and loose' with the data being added. + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_SERVER_LAZY_COMMIT "1.2.840.113556.1.4.619" + +/** + Control for RODC join -see [MS-ADTS] section 3.1.1.3.4.1.23 + + \sa Microsoft documentation of this OID +*/ +#define LDB_CONTROL_RODC_DCPROMO_OID "1.2.840.113556.1.4.1341" +#define LDB_CONTROL_RODC_DCPROMO_NAME "rodc_join" + +/* Other standardised controls */ + +/** + OID for the allowing client to request temporary relaxed + enforcement of constraints of the x.500 model. + + Mainly used for the OpenLDAP backend. + + \sa draft managedit. +*/ +#define LDB_CONTROL_RELAX_OID "1.3.6.1.4.1.4203.666.5.12" +#define LDB_CONTROL_RELAX_NAME "relax" + +/** + OID for the allowing some kind of relax check for attributes with DNs + + + \sa 3.1.1.3.4.1.16 in [MS-ADTS].pdf +*/ +#define LDB_CONTROL_VERIFY_NAME_OID "1.2.840.113556.1.4.1338" +#define LDB_CONTROL_VERIFY_NAME_NAME "verify_name" + +/* Extended operations */ + +/** + OID for LDAP Extended Operation SEQUENCE_NUMBER + + This extended operation is used to retrieve the extended sequence number. +*/ +#define LDB_EXTENDED_SEQUENCE_NUMBER "1.3.6.1.4.1.7165.4.4.3" + +/** + OID for LDAP Extended Operation PASSWORD_CHANGE. + + This Extended operation is used to allow user password changes by the user + itself. +*/ +#define LDB_EXTENDED_PASSWORD_CHANGE_OID "1.3.6.1.4.1.4203.1.11.1" + + +/** + OID for LDAP Extended Operation FAST_BIND + + This Extended operations is used to perform a fast bind. +*/ +#define LDB_EXTENDED_FAST_BIND_OID "1.2.840.113556.1.4.1781" + +/** + OID for LDAP Extended Operation START_TLS. + + This Extended operation is used to start a new TLS channel on top of a clear + text channel. +*/ +#define LDB_EXTENDED_START_TLS_OID "1.3.6.1.4.1.1466.20037" + +/** + OID for LDAP Extended Operation DYNAMIC_REFRESH. + + This Extended operation is used to create and maintain objects which exist + only a specific time, e.g. when a certain client or a certain person is + logged in. Data refreshes have to be periodically sent in a specific + interval. Otherwise the entry is going to be removed. +*/ +#define LDB_EXTENDED_DYNAMIC_OID "1.3.6.1.4.1.1466.101.119.1" + +struct ldb_sd_flags_control { + /* + * request the owner 0x00000001 + * request the group 0x00000002 + * request the DACL 0x00000004 + * request the SACL 0x00000008 + */ + unsigned secinfo_flags; +}; + +/* + * DOMAIN_SCOPE 0x00000001 + * this limits the search to one partition, + * and no referrals will be returned. + * (Note this doesn't limit the entries by there + * objectSid belonging to a domain! Builtin and Foreign Sids + * are still returned) + * + * PHANTOM_ROOT 0x00000002 + * this search on the whole tree on a domain controller + * over multiple partitions without referrals. + * (This is the default behavior on the Global Catalog Port) + */ + +#define LDB_SEARCH_OPTION_DOMAIN_SCOPE 0x00000001 +#define LDB_SEARCH_OPTION_PHANTOM_ROOT 0x00000002 + +struct ldb_search_options_control { + unsigned search_options; +}; + +struct ldb_paged_control { + int size; + int cookie_len; + char *cookie; +}; + +struct ldb_extended_dn_control { + int type; +}; + +struct ldb_server_sort_control { + const char *attributeName; + const char *orderingRule; + int reverse; +}; + +struct ldb_sort_resp_control { + int result; + char *attr_desc; +}; + +struct ldb_asq_control { + int request; + char *source_attribute; + int src_attr_len; + int result; +}; + +struct ldb_dirsync_control { + int flags; + int max_attributes; + int cookie_len; + char *cookie; +}; + +struct ldb_vlv_req_control { + int beforeCount; + int afterCount; + int type; + union { + struct { + int offset; + int contentCount; + } byOffset; + struct { + int value_len; + char *value; + } gtOrEq; + } match; + int ctxid_len; + uint8_t *contextId; +}; + +struct ldb_vlv_resp_control { + int targetPosition; + int contentCount; + int vlv_result; + int ctxid_len; + uint8_t *contextId; +}; + +struct ldb_verify_name_control { + int flags; + size_t gc_len; + char *gc; +}; + +struct ldb_control { + const char *oid; + int critical; + void *data; +}; + +enum ldb_request_type { + LDB_SEARCH, + LDB_ADD, + LDB_MODIFY, + LDB_DELETE, + LDB_RENAME, + LDB_EXTENDED, + LDB_REQ_REGISTER_CONTROL, + LDB_REQ_REGISTER_PARTITION +}; + +enum ldb_reply_type { + LDB_REPLY_ENTRY, + LDB_REPLY_REFERRAL, + LDB_REPLY_DONE +}; + +enum ldb_wait_type { + LDB_WAIT_ALL, + LDB_WAIT_NONE +}; + +enum ldb_state { + LDB_ASYNC_INIT, + LDB_ASYNC_PENDING, + LDB_ASYNC_DONE +}; + +struct ldb_extended { + const char *oid; + void *data; /* NULL or a valid talloc pointer! talloc_get_type() will be used on it */ +}; + +enum ldb_sequence_type { + LDB_SEQ_HIGHEST_SEQ, + LDB_SEQ_HIGHEST_TIMESTAMP, + LDB_SEQ_NEXT +}; + +#define LDB_SEQ_GLOBAL_SEQUENCE 0x01 +#define LDB_SEQ_TIMESTAMP_SEQUENCE 0x02 + +struct ldb_seqnum_request { + enum ldb_sequence_type type; +}; + +struct ldb_seqnum_result { + uint64_t seq_num; + uint32_t flags; +}; + +struct ldb_result { + unsigned int count; + struct ldb_message **msgs; + struct ldb_extended *extended; + struct ldb_control **controls; + char **refs; +}; + +struct ldb_reply { + int error; + enum ldb_reply_type type; + struct ldb_message *message; + struct ldb_extended *response; + struct ldb_control **controls; + char *referral; +}; + +struct ldb_request; +struct ldb_handle; + +struct ldb_search { + struct ldb_dn *base; + enum ldb_scope scope; + struct ldb_parse_tree *tree; + const char * const *attrs; + struct ldb_result *res; +}; + +struct ldb_add { + const struct ldb_message *message; +}; + +struct ldb_modify { + const struct ldb_message *message; +}; + +struct ldb_delete { + struct ldb_dn *dn; +}; + +struct ldb_rename { + struct ldb_dn *olddn; + struct ldb_dn *newdn; +}; + +struct ldb_register_control { + const char *oid; +}; + +struct ldb_register_partition { + struct ldb_dn *dn; +}; + +typedef int (*ldb_request_callback_t)(struct ldb_request *, struct ldb_reply *); + +struct ldb_request { + + enum ldb_request_type operation; + + union { + struct ldb_search search; + struct ldb_add add; + struct ldb_modify mod; + struct ldb_delete del; + struct ldb_rename rename; + struct ldb_extended extended; + struct ldb_register_control reg_control; + struct ldb_register_partition reg_partition; + } op; + + struct ldb_control **controls; + + void *context; + ldb_request_callback_t callback; + + int timeout; + time_t starttime; + struct ldb_handle *handle; +}; + +int ldb_request(struct ldb_context *ldb, struct ldb_request *request); +int ldb_request_done(struct ldb_request *req, int status); +bool ldb_request_is_done(struct ldb_request *req); + +int ldb_modules_wait(struct ldb_handle *handle); +int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type); + +int ldb_set_timeout(struct ldb_context *ldb, struct ldb_request *req, int timeout); +int ldb_set_timeout_from_prev_req(struct ldb_context *ldb, struct ldb_request *oldreq, struct ldb_request *newreq); +void ldb_set_create_perms(struct ldb_context *ldb, unsigned int perms); +void ldb_set_modules_dir(struct ldb_context *ldb, const char *path); +struct tevent_context; +void ldb_set_event_context(struct ldb_context *ldb, struct tevent_context *ev); +struct tevent_context * ldb_get_event_context(struct ldb_context *ldb); + +/** + Initialise ldbs' global information + + This is required before any other LDB call + + \return 0 if initialisation succeeded, -1 otherwise +*/ +int ldb_global_init(void); + +/** + Initialise an ldb context + + This is required before any other LDB call. + + \param mem_ctx pointer to a talloc memory context. Pass NULL if there is + no suitable context available. + + \note The LDB modules will be loaded from directory specified by the environment + variable LDB_MODULES_PATH. If the variable is not specified, the compiled-in default + is used. + + \return pointer to ldb_context that should be free'd (using talloc_free()) + at the end of the program. +*/ +struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx); + +typedef void (*ldb_async_timeout_fn) (void *); +typedef bool (*ldb_async_callback_fn) (void *); +typedef int (*ldb_async_ctx_add_op_fn)(void *, time_t, void *, ldb_async_timeout_fn, ldb_async_callback_fn); +typedef int (*ldb_async_ctx_wait_op_fn)(void *); + +void ldb_async_ctx_set_private_data(struct ldb_context *ldb, + void *private_data); +void ldb_async_ctx_set_add_op(struct ldb_context *ldb, + ldb_async_ctx_add_op_fn add_op); +void ldb_async_ctx_set_wait_op(struct ldb_context *ldb, + ldb_async_ctx_wait_op_fn wait_op); + +/** + Connect to a database. + + This is typically called soon after ldb_init(), and is required prior to + any search or database modification operations. + + The URL can be one of the following forms: + - tdb://path + - ldapi://path + - ldap://host + - sqlite://path + + \param ldb the context associated with the database (from ldb_init()) + \param url the URL of the database to connect to, as noted above + \param flags a combination of LDB_FLG_* to modify the connection behaviour + \param options backend specific options - passed uninterpreted to the backend + + \return result code (LDB_SUCCESS on success, or a failure code) + + \note It is an error to connect to a database that does not exist in readonly mode + (that is, with LDB_FLG_RDONLY). However in read-write mode, the database will be + created if it does not exist. +*/ +int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]); + +/* + return an automatic basedn from the rootDomainNamingContext of the rootDSE + This value have been set in an opaque pointer at connection time +*/ +struct ldb_dn *ldb_get_root_basedn(struct ldb_context *ldb); + +/* + return an automatic basedn from the configurationNamingContext of the rootDSE + This value have been set in an opaque pointer at connection time +*/ +struct ldb_dn *ldb_get_config_basedn(struct ldb_context *ldb); + +/* + return an automatic basedn from the schemaNamingContext of the rootDSE + This value have been set in an opaque pointer at connection time +*/ +struct ldb_dn *ldb_get_schema_basedn(struct ldb_context *ldb); + +/* + return an automatic baseDN from the defaultNamingContext of the rootDSE + This value have been set in an opaque pointer at connection time +*/ +struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb); + +/** + The default async search callback function + + \param req the request we are callback of + \param ares a single reply from the async core + + \return result code (LDB_SUCCESS on success, or a failure code) + + \note this function expects req->context to always be an struct ldb_result pointer + AND a talloc context, this function will steal on the context each message + from the ares reply passed on by the async core so that in the end all the + messages will be in the context (ldb_result) memory tree. + Freeing the passed context (ldb_result tree) will free all the resources + (the request need to be freed separately and the result doe not depend on the + request that can be freed as sson as the search request is finished) +*/ + +int ldb_search_default_callback(struct ldb_request *req, struct ldb_reply *ares); + +/** + The default async extended operation callback function + + \param req the request we are callback of + \param ares a single reply from the async core + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ +int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares); + +int ldb_modify_default_callback(struct ldb_request *req, struct ldb_reply *ares); + +/** + Helper function to build a search request + + \param ret_req the request structure is returned here (talloced on mem_ctx) + \param ldb the context associated with the database (from ldb_init()) + \param mem_ctx a talloc memory context (used as parent of ret_req) + \param base the Base Distinguished Name for the query (use ldb_dn_new() for an empty one) + \param scope the search scope for the query + \param expression the search expression to use for this query + \param attrs the search attributes for the query (pass NULL if none required) + \param controls an array of controls + \param context the callback function context + \param the callback function to handle the async replies + \param the parent request if any + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ + +int ldb_build_search_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *base, + enum ldb_scope scope, + const char *expression, + const char * const *attrs, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent); + +int ldb_build_search_req_ex(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const *attrs, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent); + +/** + Helper function to build an add request + + \param ret_req the request structure is returned here (talloced on mem_ctx) + \param ldb the context associated with the database (from ldb_init()) + \param mem_ctx a talloc memory context (used as parent of ret_req) + \param message contains the entry to be added + \param controls an array of controls + \param context the callback function context + \param the callback function to handle the async replies + \param the parent request if any + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ + +int ldb_build_add_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *message, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent); + +/** + Helper function to build a modify request + + \param ret_req the request structure is returned here (talloced on mem_ctx) + \param ldb the context associated with the database (from ldb_init()) + \param mem_ctx a talloc memory context (used as parent of ret_req) + \param message contains the entry to be modified + \param controls an array of controls + \param context the callback function context + \param the callback function to handle the async replies + \param the parent request if any + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ + +int ldb_build_mod_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *message, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent); + +/** + Helper function to build a delete request + + \param ret_req the request structure is returned here (talloced on mem_ctx) + \param ldb the context associated with the database (from ldb_init()) + \param mem_ctx a talloc memory context (used as parent of ret_req) + \param dn the DN to be deleted + \param controls an array of controls + \param context the callback function context + \param the callback function to handle the async replies + \param the parent request if any + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ + +int ldb_build_del_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent); + +/** + Helper function to build a rename request + + \param ret_req the request structure is returned here (talloced on mem_ctx) + \param ldb the context associated with the database (from ldb_init()) + \param mem_ctx a talloc memory context (used as parent of ret_req) + \param olddn the old DN + \param newdn the new DN + \param controls an array of controls + \param context the callback function context + \param the callback function to handle the async replies + \param the parent request if any + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ + +int ldb_build_rename_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *olddn, + struct ldb_dn *newdn, + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent); + +/** + Add a ldb_control to a ldb_request + + \param req the request struct where to add the control + \param oid the object identifier of the control as string + \param critical whether the control should be critical or not + \param data a talloc pointer to the control specific data + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ +int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data); + +/** + replace a ldb_control in a ldb_request + + \param req the request struct where to add the control + \param oid the object identifier of the control as string + \param critical whether the control should be critical or not + \param data a talloc pointer to the control specific data + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ +int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data); + +/** + check if a control with the specified "oid" exist and return it + \param req the request struct where to add the control + \param oid the object identifier of the control as string + + \return the control, NULL if not found +*/ +struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid); + +/** + check if a control with the specified "oid" exist and return it + \param rep the reply struct where to add the control + \param oid the object identifier of the control as string + + \return the control, NULL if not found +*/ +struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid); + +/** + Search the database + + This function searches the database, and returns + records that match an LDAP-like search expression + + \param ldb the context associated with the database (from ldb_init()) + \param mem_ctx the memory context to use for the request and the results + \param result the return result + \param base the Base Distinguished Name for the query (use ldb_dn_new() for an empty one) + \param scope the search scope for the query + \param attrs the search attributes for the query (pass NULL if none required) + \param exp_fmt the search expression to use for this query (printf like) + + \return result code (LDB_SUCCESS on success, or a failure code) + + \note use talloc_free() to free the ldb_result returned +*/ +int ldb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + struct ldb_result **result, struct ldb_dn *base, + enum ldb_scope scope, const char * const *attrs, + const char *exp_fmt, ...) PRINTF_ATTRIBUTE(7,8); + +/** + Add a record to the database. + + This function adds a record to the database. This function will fail + if a record with the specified class and key already exists in the + database. + + \param ldb the context associated with the database (from + ldb_init()) + \param message the message containing the record to add. + + \return result code (LDB_SUCCESS if the record was added, otherwise + a failure code) +*/ +int ldb_add(struct ldb_context *ldb, + const struct ldb_message *message); + +/** + Modify the specified attributes of a record + + This function modifies a record that is in the database. + + \param ldb the context associated with the database (from + ldb_init()) + \param message the message containing the changes required. + + \return result code (LDB_SUCCESS if the record was modified as + requested, otherwise a failure code) +*/ +int ldb_modify(struct ldb_context *ldb, + const struct ldb_message *message); + +/** + Rename a record in the database + + This function renames a record in the database. + + \param ldb the context associated with the database (from + ldb_init()) + \param olddn the DN for the record to be renamed. + \param newdn the new DN + + \return result code (LDB_SUCCESS if the record was renamed as + requested, otherwise a failure code) +*/ +int ldb_rename(struct ldb_context *ldb, struct ldb_dn *olddn, struct ldb_dn *newdn); + +/** + Delete a record from the database + + This function deletes a record from the database. + + \param ldb the context associated with the database (from + ldb_init()) + \param dn the DN for the record to be deleted. + + \return result code (LDB_SUCCESS if the record was deleted, + otherwise a failure code) +*/ +int ldb_delete(struct ldb_context *ldb, struct ldb_dn *dn); + +/** + The default async extended operation callback function + + \param req the request we are callback of + \param ares a single reply from the async core + + \return result code (LDB_SUCCESS on success, or a failure code) + + \note this function expects req->context to always be an struct ldb_result pointer + AND a talloc context, this function will steal on the context each message + from the ares reply passed on by the async core so that in the end all the + messages will be in the context (ldb_result) memory tree. + Freeing the passed context (ldb_result tree) will free all the resources + (the request need to be freed separately and the result doe not depend on the + request that can be freed as sson as the search request is finished) +*/ + +int ldb_extended_default_callback(struct ldb_request *req, struct ldb_reply *ares); + + +/** + Helper function to build a extended request + + \param ret_req the request structure is returned here (talloced on mem_ctx) + \param ldb the context associated with the database (from ldb_init()) + \param mem_ctx a talloc memory context (used as parent of ret_req) + \param oid the OID of the extended operation. + \param data a void pointer a the extended operation specific parameters, + it needs to be NULL or a valid talloc pointer! talloc_get_type() will be used on it + \param controls an array of controls + \param context the callback function context + \param the callback function to handle the async replies + \param the parent request if any + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ +int ldb_build_extended_req(struct ldb_request **ret_req, + struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *oid, + void *data,/* NULL or a valid talloc pointer! talloc_get_type() will be used on it */ + struct ldb_control **controls, + void *context, + ldb_request_callback_t callback, + struct ldb_request *parent); + +/** + call an extended operation + + \param ldb the context associated with the database (from ldb_init()) + \param oid the OID of the extended operation. + \param data a void pointer a the extended operation specific parameters, + it needs to be NULL or a valid talloc pointer! talloc_get_type() will be used on it + \param res the result of the extended operation + + \return result code (LDB_SUCCESS if the extended operation returned fine, + otherwise a failure code) +*/ +int ldb_extended(struct ldb_context *ldb, + const char *oid, + void *data,/* NULL or a valid talloc pointer! talloc_get_type() will be used on it */ + struct ldb_result **res); + +/** + Obtain current/next database sequence number +*/ +int ldb_sequence_number(struct ldb_context *ldb, enum ldb_sequence_type type, uint64_t *seq_num); + +/** + start a transaction +*/ +int ldb_transaction_start(struct ldb_context *ldb); + +/** + first phase of two phase commit + */ +int ldb_transaction_prepare_commit(struct ldb_context *ldb); + +/** + commit a transaction +*/ +int ldb_transaction_commit(struct ldb_context *ldb); + +/** + cancel a transaction +*/ +int ldb_transaction_cancel(struct ldb_context *ldb); + +/* + cancel a transaction with no error if no transaction is pending + used when we fork() to clear any parent transactions +*/ +int ldb_transaction_cancel_noerr(struct ldb_context *ldb); + + +/** + return extended error information from the last call +*/ +const char *ldb_errstring(struct ldb_context *ldb); + +/** + return a string explaining what a ldb error constant means +*/ +const char *ldb_strerror(int ldb_err); + +/** + setup the default utf8 functions + FIXME: these functions do not yet handle utf8 +*/ +void ldb_set_utf8_default(struct ldb_context *ldb); + +/** + Casefold a string + + \param ldb the ldb context + \param mem_ctx the memory context to allocate the result string + memory from. + \param s the string that is to be folded + \return a copy of the string, converted to upper case + + \note The default function is not yet UTF8 aware. Provide your own + set of functions through ldb_set_utf8_fns() +*/ +char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n); + +/** + Check the attribute name is valid according to rfc2251 + \param s the string to check + + \return 1 if the name is ok +*/ +int ldb_valid_attr_name(const char *s); + +/* + ldif manipulation functions +*/ + +/** + Write an LDIF message + + This function writes an LDIF message using a caller supplied write + function. + + \param ldb the ldb context (from ldb_init()) + \param fprintf_fn a function pointer for the write function. This must take + a private data pointer, followed by a format string, and then a variable argument + list. + \param private_data pointer that will be provided back to the write + function. This is useful for maintaining state or context. + \param ldif the message to write out + + \return the total number of bytes written, or an error code as returned + from the write function. + + \sa ldb_ldif_write_file for a more convenient way to write to a + file stream. + + \sa ldb_ldif_read for the reader equivalent to this function. +*/ +int ldb_ldif_write(struct ldb_context *ldb, + int (*fprintf_fn)(void *, const char *, ...) PRINTF_ATTRIBUTE(2,3), + void *private_data, + const struct ldb_ldif *ldif); + +/** + Clean up an LDIF message + + This function cleans up a LDIF message read using ldb_ldif_read() + or related functions (such as ldb_ldif_read_string() and + ldb_ldif_read_file(). + + \param ldb the ldb context (from ldb_init()) + \param msg the message to clean up and free + +*/ +void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *msg); + +/** + Read an LDIF message + + This function creates an LDIF message using a caller supplied read + function. + + \param ldb the ldb context (from ldb_init()) + \param fgetc_fn a function pointer for the read function. This must + take a private data pointer, and must return a pointer to an + integer corresponding to the next byte read (or EOF if there is no + more data to be read). + \param private_data pointer that will be provided back to the read + function. This is udeful for maintaining state or context. + + \return the LDIF message that has been read in + + \note You must free the LDIF message when no longer required, using + ldb_ldif_read_free(). + + \sa ldb_ldif_read_file for a more convenient way to read from a + file stream. + + \sa ldb_ldif_read_string for a more convenient way to read from a + string (char array). + + \sa ldb_ldif_write for the writer equivalent to this function. +*/ +struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, + int (*fgetc_fn)(void *), void *private_data); + +/** + Read an LDIF message from a file + + This function reads the next LDIF message from the contents of a + file stream. If you want to get all of the LDIF messages, you will + need to repeatedly call this function, until it returns NULL. + + \param ldb the ldb context (from ldb_init()) + \param f the file stream to read from (typically from fdopen()) + + \sa ldb_ldif_read_string for an equivalent function that will read + from a string (char array). + + \sa ldb_ldif_write_file for the writer equivalent to this function. + +*/ +struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f); + +/** + Read an LDIF message from a string + + This function reads the next LDIF message from the contents of a char + array. If you want to get all of the LDIF messages, you will need + to repeatedly call this function, until it returns NULL. + + \param ldb the ldb context (from ldb_init()) + \param s pointer to the char array to read from + + \sa ldb_ldif_read_file for an equivalent function that will read + from a file stream. + + \sa ldb_ldif_write for a more general (arbitrary read function) + version of this function. +*/ +struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s); + +/** + Parse a modrdn LDIF message from a struct ldb_message + + \param ldb the ldb context (from ldb_init()) + \param ldif the preparsed LDIF chunk (from ldb_ldif_read()) + + \param mem_ctx the memory context that's used for return values + + \param olddn the old dn as struct ldb_dn, if not needed pass NULL + \param newrdn the new rdn as struct ldb_dn, if not needed pass NULL + \param deleteoldrdn the deleteoldrdn value as bool, if not needed pass NULL + \param newsuperior the newsuperior dn as struct ldb_dn, if not needed pass NULL + *newsuperior can be NULL as it is optional in the LDIF + \param newdn the full constructed new dn as struct ldb_dn, if not needed pass NULL + +*/ +int ldb_ldif_parse_modrdn(struct ldb_context *ldb, + const struct ldb_ldif *ldif, + TALLOC_CTX *mem_ctx, + struct ldb_dn **olddn, + struct ldb_dn **newrdn, + bool *deleteoldrdn, + struct ldb_dn **newsuperior, + struct ldb_dn **newdn); + +/** + Write an LDIF message to a file + + \param ldb the ldb context (from ldb_init()) + \param f the file stream to write to (typically from fdopen()) + \param msg the message to write out + + \return the total number of bytes written, or a negative error code + + \sa ldb_ldif_read_file for the reader equivalent to this function. +*/ +int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); + +/** + Write an LDIF message to a string + + \param ldb the ldb context (from ldb_init()) + \param mem_ctx the talloc context on which to attach the string) + \param msg the message to write out + + \return the string containing the LDIF, or NULL on error + + \sa ldb_ldif_read_string for the reader equivalent to this function. +*/ +char * ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + const struct ldb_ldif *msg); + + +/** + Write an LDB message to a string + + \param ldb the ldb context (from ldb_init()) + \param mem_ctx the talloc context on which to attach the string) + \param changetype LDB_CHANGETYPE_ADD or LDB_CHANGETYPE_MODIFY + \param msg the message to write out + + \return the string containing the LDIF, or NULL on error + + \sa ldb_ldif_message_redacted_string for a safer version of this + function +*/ +char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + enum ldb_changetype changetype, + const struct ldb_message *msg); + +/** + Write an LDB message to a string + + \param ldb the ldb context (from ldb_init()) + \param mem_ctx the talloc context on which to attach the string) + \param changetype LDB_CHANGETYPE_ADD or LDB_CHANGETYPE_MODIFY + \param msg the message to write out + + \return the string containing the LDIF, or NULL on error, but + with secret attributes redacted + + \note The secret attributes are specified in a + 'const char * const *' within the LDB_SECRET_ATTRIBUTE_LIST + opaque set on the ldb + + \sa ldb_ldif_message_string for an exact representiation of the + message as LDIF +*/ +char *ldb_ldif_message_redacted_string(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + enum ldb_changetype changetype, + const struct ldb_message *msg); + + +/** + Base64 encode a buffer + + \param mem_ctx the memory context that the result is allocated + from. + \param buf pointer to the array that is to be encoded + \param len the number of elements in the array to be encoded + + \return pointer to an array containing the encoded data + + \note The caller is responsible for freeing the result +*/ +char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len); + +/** + Base64 decode a buffer + + This function decodes a base64 encoded string in place. + + \param s the string to decode. + + \return the length of the returned (decoded) string. + + \note the string is null terminated, but the null terminator is not + included in the length. +*/ +int ldb_base64_decode(char *s); + +/* The following definitions come from lib/ldb/common/ldb_dn.c */ + +/** + Get the linear form of a DN (without any extended components) + + \param dn The DN to linearize +*/ + +const char *ldb_dn_get_linearized(struct ldb_dn *dn); + +/** + Allocate a copy of the linear form of a DN (without any extended components) onto the supplied memory context + + \param dn The DN to linearize + \param mem_ctx TALLOC context to return result on +*/ + +char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn); + +/** + Get the linear form of a DN (with any extended components) + + \param mem_ctx TALLOC context to return result on + \param dn The DN to linearize + \param mode Style of extended DN to return (0 is HEX representation of binary form, 1 is a string form) +*/ +char *ldb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int mode); +const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name); +int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val); +void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept_list); +void ldb_dn_remove_extended_components(struct ldb_dn *dn); +bool ldb_dn_has_extended(struct ldb_dn *dn); + +int ldb_dn_extended_add_syntax(struct ldb_context *ldb, + unsigned flags, + const struct ldb_dn_extended_syntax *syntax); + +/** + Allocate a new DN from a string + + \param mem_ctx TALLOC context to return resulting ldb_dn structure on + \param dn The new DN + + \note The DN will not be parsed at this time. Use ldb_dn_validate to tell if the DN is syntacticly correct +*/ + +struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *dn); +/** + Allocate a new DN from a printf style format string and arguments + + \param mem_ctx TALLOC context to return resulting ldb_dn structure on + \param new_fms The new DN as a format string (plus arguments) + + \note The DN will not be parsed at this time. Use ldb_dn_validate to tell if the DN is syntacticly correct +*/ + +struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...) PRINTF_ATTRIBUTE(3,4); +/** + Allocate a new DN from a struct ldb_val (useful to avoid buffer overrun) + + \param mem_ctx TALLOC context to return resulting ldb_dn structure on + \param dn The new DN + + \note The DN will not be parsed at this time. Use ldb_dn_validate to tell if the DN is syntacticly correct +*/ + +struct ldb_dn *ldb_dn_from_ldb_val(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn); + +/** + Determine if this DN is syntactically valid + + \param dn The DN to validate +*/ + +bool ldb_dn_validate(struct ldb_dn *dn); + +char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value); +const char *ldb_dn_get_casefold(struct ldb_dn *dn); +char *ldb_dn_alloc_casefold(TALLOC_CTX *mem_ctx, struct ldb_dn *dn); + +int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn); +int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1); + +bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base); +bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...) PRINTF_ATTRIBUTE(2,3); +bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child); +bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...) PRINTF_ATTRIBUTE(2,3); +bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num); +bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num); +bool ldb_dn_add_child_val(struct ldb_dn *dn, + const char *rdn, + struct ldb_val value); + +struct ldb_dn *ldb_dn_copy(TALLOC_CTX *mem_ctx, struct ldb_dn *dn); +struct ldb_dn *ldb_dn_get_parent(TALLOC_CTX *mem_ctx, struct ldb_dn *dn); +char *ldb_dn_canonical_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn); +char *ldb_dn_canonical_ex_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn); +int ldb_dn_get_comp_num(struct ldb_dn *dn); +int ldb_dn_get_extended_comp_num(struct ldb_dn *dn); +const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num); +const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num); +const char *ldb_dn_get_rdn_name(struct ldb_dn *dn); +const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn); +int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val); + +bool ldb_dn_is_valid(struct ldb_dn *dn); +bool ldb_dn_is_special(struct ldb_dn *dn); +bool ldb_dn_check_special(struct ldb_dn *dn, const char *check); +bool ldb_dn_is_null(struct ldb_dn *dn); +int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn); + + +/** + Compare two attributes + + This function compares to attribute names. Note that this is a + case-insensitive comparison. + + \param a the first attribute name to compare + \param b the second attribute name to compare + + \return 0 if the attribute names are the same, or only differ in + case; non-zero if there are any differences + + attribute names are restricted by rfc2251 so using + strcasecmp and toupper here is ok. + return 0 for match +*/ +#define ldb_attr_cmp(a, b) strcasecmp(a, b) +char *ldb_attr_casefold(TALLOC_CTX *mem_ctx, const char *s); +int ldb_attr_dn(const char *attr); + +/** + Create an empty message + + \param mem_ctx the memory context to create in. You can pass NULL + to get the top level context, however the ldb context (from + ldb_init()) may be a better choice +*/ +struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx); + +/** + Find an element within an message +*/ +struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, + const char *attr_name); + +/** + Compare two ldb_val values + + \param v1 first ldb_val structure to be tested + \param v2 second ldb_val structure to be tested + + \return 1 for a match, 0 if there is any difference +*/ +int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2); + +/** + find a value within an ldb_message_element + + \param el the element to search + \param val the value to search for + + \note This search is case sensitive +*/ +struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, + struct ldb_val *val); + +/** + add a new empty element to a ldb_message +*/ +int ldb_msg_add_empty(struct ldb_message *msg, + const char *attr_name, + int flags, + struct ldb_message_element **return_el); + +/** + add a element to a ldb_message +*/ +int ldb_msg_add(struct ldb_message *msg, + const struct ldb_message_element *el, + int flags); +int ldb_msg_add_value(struct ldb_message *msg, + const char *attr_name, + const struct ldb_val *val, + struct ldb_message_element **return_el); +int ldb_msg_add_steal_value(struct ldb_message *msg, + const char *attr_name, + struct ldb_val *val); +int ldb_msg_add_steal_string(struct ldb_message *msg, + const char *attr_name, char *str); +int ldb_msg_add_string(struct ldb_message *msg, + const char *attr_name, const char *str); +int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, + struct ldb_dn *dn); +int ldb_msg_add_fmt(struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); + +/** + compare two message elements - return 0 on match +*/ +int ldb_msg_element_compare(struct ldb_message_element *el1, + struct ldb_message_element *el2); +int ldb_msg_element_compare_name(struct ldb_message_element *el1, + struct ldb_message_element *el2); + +/** + Find elements in a message. + + This function finds elements and converts to a specific type, with + a give default value if not found. Assumes that elements are + single valued. +*/ +const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name); +int ldb_msg_find_attr_as_int(const struct ldb_message *msg, + const char *attr_name, + int default_value); +unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg, + const char *attr_name, + unsigned int default_value); +int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg, + const char *attr_name, + int64_t default_value); +uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg, + const char *attr_name, + uint64_t default_value); +double ldb_msg_find_attr_as_double(const struct ldb_message *msg, + const char *attr_name, + double default_value); +int ldb_msg_find_attr_as_bool(const struct ldb_message *msg, + const char *attr_name, + int default_value); +const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg, + const char *attr_name, + const char *default_value); + +struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, + const char *attr_name); + +void ldb_msg_sort_elements(struct ldb_message *msg); + +struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg); +struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg); + +/* + * ldb_msg_canonicalize() is now depreciated + * Please use ldb_msg_normalize() instead + * + * NOTE: Returned ldb_message object is allocated + * into *ldb's context. Callers are recommended + * to steal the returned object into a TALLOC_CTX + * with short lifetime. + */ +struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, + const struct ldb_message *msg) _DEPRECATED_; + +int ldb_msg_normalize(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, + struct ldb_message **_msg_out); + + +/* + * ldb_msg_diff() is now depreciated + * Please use ldb_msg_difference() instead + * + * NOTE: Returned ldb_message object is allocated + * into *ldb's context. Callers are recommended + * to steal the returned object into a TALLOC_CTX + * with short lifetime. + */ +struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, + struct ldb_message *msg1, + struct ldb_message *msg2) _DEPRECATED_; + +/** + * return a ldb_message representing the differences between msg1 and msg2. + * If you then use this in a ldb_modify() call, + * it can be used to save edits to a message + * + * Result message is constructed as follows: + * - LDB_FLAG_MOD_ADD - elements found only in msg2 + * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have + * different value in msg1 + * Value for msg2 element is used + * - LDB_FLAG_MOD_DELETE - elements found only in msg2 + * + * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR + */ +int ldb_msg_difference(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_message *msg1, + struct ldb_message *msg2, + struct ldb_message **_msg_out); + +/** + Tries to find a certain string attribute in a message + + \param msg the message to check + \param name attribute name + \param value attribute value + + \return 1 on match and 0 otherwise. +*/ +int ldb_msg_check_string_attribute(const struct ldb_message *msg, + const char *name, + const char *value); + +/** + Integrity check an ldb_message + + This function performs basic sanity / integrity checks on an + ldb_message. + + \param ldb context in which to perform the checks + \param msg the message to check + + \return LDB_SUCCESS if the message is OK, or a non-zero error code + (one of LDB_ERR_INVALID_DN_SYNTAX, LDB_ERR_ENTRY_ALREADY_EXISTS or + LDB_ERR_INVALID_ATTRIBUTE_SYNTAX) if there is a problem with a + message. +*/ +int ldb_msg_sanity_check(struct ldb_context *ldb, + const struct ldb_message *msg); + +/** + Duplicate an ldb_val structure + + This function copies an ldb value structure. + + \param mem_ctx the memory context that the duplicated value will be + allocated from + \param v the ldb_val to be duplicated. + + \return the duplicated ldb_val structure. +*/ +struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v); + +/** + this allows the user to set a debug function for error reporting +*/ +int ldb_set_debug(struct ldb_context *ldb, + void (*debug)(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0), + void *context); + +/** + this allows the user to set custom utf8 function for error reporting +*/ +void ldb_set_utf8_fns(struct ldb_context *ldb, + void *context, + char *(*casefold)(void *, void *, const char *, size_t n)); + +/** + this sets up debug to print messages on stderr +*/ +int ldb_set_debug_stderr(struct ldb_context *ldb); + +/* control backend specific opaque values */ +int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value); +void *ldb_get_opaque(struct ldb_context *ldb, const char *name); + +const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs); +const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr); +int ldb_attr_in_list(const char * const *attrs, const char *attr); + +int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace); +int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace); +void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr); +void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el); + + +void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree, + const char *attr, + const char *replace); + +/* + shallow copy a tree - copying only the elements array so that the caller + can safely add new elements without changing the message +*/ +struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx, + const struct ldb_parse_tree *ot); + +/** + Convert a time structure to a string + + This function converts a time_t structure to an LDAP formatted + GeneralizedTime string. + + \param mem_ctx the memory context to allocate the return string in + \param t the time structure to convert + + \return the formatted string, or NULL if the time structure could + not be converted +*/ +char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t); + +/** + Convert a string to a time structure + + This function converts an LDAP formatted GeneralizedTime string + to a time_t structure. + + \param s the string to convert + + \return the time structure, or 0 if the string cannot be converted +*/ +time_t ldb_string_to_time(const char *s); + +/** + convert a LDAP GeneralizedTime string in ldb_val format to a + time_t. +*/ +int ldb_val_to_time(const struct ldb_val *v, time_t *t); + +/** + Convert a time structure to a string + + This function converts a time_t structure to an LDAP formatted + UTCTime string. + + \param mem_ctx the memory context to allocate the return string in + \param t the time structure to convert + + \return the formatted string, or NULL if the time structure could + not be converted +*/ +char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t); + +/** + Convert a string to a time structure + + This function converts an LDAP formatted UTCTime string + to a time_t structure. + + \param s the string to convert + + \return the time structure, or 0 if the string cannot be converted +*/ +time_t ldb_string_utc_to_time(const char *s); + + +void ldb_qsort (void *const pbase, size_t total_elems, size_t size, void *opaque, ldb_qsort_cmp_fn_t cmp); + +#ifndef discard_const +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) +#endif + +/* + a wrapper around ldb_qsort() that ensures the comparison function is + type safe. This will produce a compilation warning if the types + don't match + */ +#define LDB_TYPESAFE_QSORT(base, numel, opaque, comparison) \ +do { \ + if (numel > 1) { \ + ldb_qsort(base, numel, sizeof((base)[0]), discard_const(opaque), (ldb_qsort_cmp_fn_t)comparison); \ + comparison(&((base)[0]), &((base)[1]), opaque); \ + } \ +} while (0) + +/* allow ldb to also call TYPESAFE_QSORT() */ +#ifndef TYPESAFE_QSORT +#define TYPESAFE_QSORT(base, numel, comparison) \ +do { \ + if (numel > 1) { \ + qsort(base, numel, sizeof((base)[0]), (int (*)(const void *, const void *))comparison); \ + comparison(&((base)[0]), &((base)[1])); \ + } \ +} while (0) +#endif + + + +/** + Convert a control into its string representation. + + \param mem_ctx TALLOC context to return result on, and to allocate error_string on + \param control A struct ldb_control to convert + + \return string representation of the control +*/ +char* ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control); +/** + Convert a string representing a control into a ldb_control structure + + \param ldb LDB context + \param mem_ctx TALLOC context to return result on, and to allocate error_string on + \param control_strings A string-formatted control + + \return a ldb_control element +*/ +struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings); +/** + Convert an array of string represention of a control into an array of ldb_control structures + + \param ldb LDB context + \param mem_ctx TALLOC context to return result on, and to allocate error_string on + \param control_strings Array of string-formatted controls + + \return array of ldb_control elements +*/ +struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings); + +/** + return the ldb flags +*/ +unsigned int ldb_get_flags(struct ldb_context *ldb); + +/* set the ldb flags */ +void ldb_set_flags(struct ldb_context *ldb, unsigned flags); + + +struct ldb_dn *ldb_dn_binary_from_ldb_val(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + const struct ldb_val *strdn); + +int ldb_dn_get_binary(struct ldb_dn *dn, struct ldb_val *val); +int ldb_dn_set_binary(struct ldb_dn *dn, struct ldb_val *val); + +/* debugging functions for ldb requests */ +void ldb_req_set_location(struct ldb_request *req, const char *location); +const char *ldb_req_location(struct ldb_request *req); + +/* set the location marker on a request handle - used for debugging */ +#define LDB_REQ_SET_LOCATION(req) ldb_req_set_location(req, __location__) + +/* + minimise a DN. The caller must pass in a validated DN. + + If the DN has an extended component then only the first extended + component is kept, the DN string is stripped. + + The existing dn is modified + */ +bool ldb_dn_minimise(struct ldb_dn *dn); + +/* + compare a ldb_val to a string +*/ +int ldb_val_string_cmp(const struct ldb_val *v, const char *str); + +#endif diff --git a/ldb-2.0.8/include/ldb_errors.h b/ldb-2.0.8/include/ldb_errors.h new file mode 100644 index 0000000..b247fbe --- /dev/null +++ b/ldb-2.0.8/include/ldb_errors.h @@ -0,0 +1,312 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb header + * + * Description: defines error codes following RFC 2251 ldap error codes + * + * Author: Simo Sorce + */ + +#ifndef _LDB_ERRORS_H_ + +/*! \cond DOXYGEN_IGNORE */ +#define _LDB_ERRORS_H_ 1 +/*! \endcond */ + +/** + \file ldb_errors.h + + This header provides a set of result codes for LDB function calls. + + Many LDB function calls return an integer value (int). As shown in + the function documentation, those return values may indicate + whether the function call worked correctly (in which case it + returns LDB_SUCCESS) or some problem occurred (in which case some + other value will be returned). As a special case, + LDB_ERR_COMPARE_FALSE or LDB_ERR_COMPARE_TRUE may be returned, + which does not indicate an error. + + \note Not all error codes make sense for LDB, however they are + based on the LDAP error codes, and are kept for reference and to + avoid overlap. + + \note Some of this documentation is based on information in + the OpenLDAP documentation, as developed and maintained by the + The OpenLDAP Project. + */ + +/** + The function call succeeded. + + If a function returns LDB_SUCCESS, then that function, and the + underlying transactions that may have been required, completed + successfully. +*/ +#define LDB_SUCCESS 0 + +/** + The function call failed for some non-specific reason. +*/ +#define LDB_ERR_OPERATIONS_ERROR 1 + +/** + The function call failed because of a protocol violation. +*/ +#define LDB_ERR_PROTOCOL_ERROR 2 + +/** + The function call failed because a time limit was exceeded. +*/ +#define LDB_ERR_TIME_LIMIT_EXCEEDED 3 + +/** + The function call failed because a size limit was exceeded. +*/ +#define LDB_ERR_SIZE_LIMIT_EXCEEDED 4 + +/** + The function was for value comparison, and the comparison operation + returned false. + + \note This is a status value, and doesn't normally indicate an + error. +*/ +#define LDB_ERR_COMPARE_FALSE 5 + +/** + The function was for value comparison, and the comparison operation + returned true. + + \note This is a status value, and doesn't normally indicate an + error. +*/ +#define LDB_ERR_COMPARE_TRUE 6 + +/** + The function used an authentication method that is not supported by + the database. +*/ +#define LDB_ERR_AUTH_METHOD_NOT_SUPPORTED 7 + +/** + The function call required a underlying operation that required + strong authentication. + + This will normally only occur if you are using LDB with a LDAP + backend. +*/ +#define LDB_ERR_STRONG_AUTH_REQUIRED 8 + +/* 9 RESERVED */ + +/** + The function resulted in a referral to another server. +*/ +#define LDB_ERR_REFERRAL 10 + +/** + The function failed because an administrative / policy limit was + exceeded. +*/ +#define LDB_ERR_ADMIN_LIMIT_EXCEEDED 11 + +/** + The function required an extension or capability that the + database cannot provide. +*/ +#define LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION 12 + +/** + The function involved a transaction or database operation that + could not be performed without a secure link. +*/ +#define LDB_ERR_CONFIDENTIALITY_REQUIRED 13 + +/** + This is an intermediate result code for SASL bind operations that + have more than one step. + + \note This is a result code that does not normally indicate an + error has occurred. +*/ +#define LDB_ERR_SASL_BIND_IN_PROGRESS 14 + +/** + The function referred to an attribute type that is not present in + the entry. +*/ +#define LDB_ERR_NO_SUCH_ATTRIBUTE 16 + +/** + The function referred to an attribute type that is invalid +*/ +#define LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE 17 + +/** + The function required a filter type that is not available for the + specified attribute. +*/ +#define LDB_ERR_INAPPROPRIATE_MATCHING 18 + +/** + The function would have violated an attribute constraint. +*/ +#define LDB_ERR_CONSTRAINT_VIOLATION 19 + +/** + The function involved an attribute type or attribute value that + already exists in the entry. +*/ +#define LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS 20 + +/** + The function used an invalid (incorrect syntax) attribute value. +*/ +#define LDB_ERR_INVALID_ATTRIBUTE_SYNTAX 21 + +/* 22-31 unused */ + +/** + The function referred to an object that does not exist in the + database. +*/ +#define LDB_ERR_NO_SUCH_OBJECT 32 + +/** + The function referred to an alias which points to a non-existent + object in the database. +*/ +#define LDB_ERR_ALIAS_PROBLEM 33 + +/** + The function used a DN which was invalid (incorrect syntax). +*/ +#define LDB_ERR_INVALID_DN_SYNTAX 34 + +/* 35 RESERVED */ + +/** + The function required dereferencing of an alias, and something went + wrong during the dereferencing process. +*/ +#define LDB_ERR_ALIAS_DEREFERENCING_PROBLEM 36 + +/* 37-47 unused */ + +/** + The function passed in the wrong authentication method. +*/ +#define LDB_ERR_INAPPROPRIATE_AUTHENTICATION 48 + +/** + The function passed in or referenced incorrect credentials during + authentication. +*/ +#define LDB_ERR_INVALID_CREDENTIALS 49 + +/** + The function required access permissions that the user does not + possess. +*/ +#define LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS 50 + +/** + The function required a transaction or call that the database could + not perform because it is busy. +*/ +#define LDB_ERR_BUSY 51 + +/** + The function required a transaction or call to a database that is + not available. +*/ +#define LDB_ERR_UNAVAILABLE 52 + +/** + The function required a transaction or call to a database that the + database declined to perform. +*/ +#define LDB_ERR_UNWILLING_TO_PERFORM 53 + +/** + The function failed because it resulted in a loop being detected. +*/ +#define LDB_ERR_LOOP_DETECT 54 + +/* 55-63 unused */ + +/** + The function failed because it would have violated a naming rule. +*/ +#define LDB_ERR_NAMING_VIOLATION 64 + +/** + The function failed because it would have violated the schema. +*/ +#define LDB_ERR_OBJECT_CLASS_VIOLATION 65 + +/** + The function required an operation that is only allowed on leaf + objects, but the object is not a leaf. +*/ +#define LDB_ERR_NOT_ALLOWED_ON_NON_LEAF 66 + +/** + The function required an operation that cannot be performed on a + Relative DN, but the object is a Relative DN. +*/ +#define LDB_ERR_NOT_ALLOWED_ON_RDN 67 + +/** + The function failed because the entry already exists. +*/ +#define LDB_ERR_ENTRY_ALREADY_EXISTS 68 + +/** + The function failed because modifications to an object class are + not allowable. +*/ +#define LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED 69 + +/* 70 RESERVED FOR CLDAP */ + +/** + The function failed because it needed to be applied to multiple + databases. +*/ +#define LDB_ERR_AFFECTS_MULTIPLE_DSAS 71 + +/* 72-79 unused */ + +/** + The function failed for unknown reasons. +*/ +#define LDB_ERR_OTHER 80 + +/* 81-90 RESERVED for APIs */ + +#endif /* _LDB_ERRORS_H_ */ diff --git a/ldb-2.0.8/include/ldb_handlers.h b/ldb-2.0.8/include/ldb_handlers.h new file mode 100644 index 0000000..79d8bb6 --- /dev/null +++ b/ldb-2.0.8/include/ldb_handlers.h @@ -0,0 +1,45 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb header + * + * Description: defines attribute handlers + * + * Author: Simo Sorce + */ +#ifndef __LDB_HANDLERS_H__ +#define __LDB_HANDLERS_H__ + +int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out); +int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out); +int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2); +int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2); + +#endif /* __LDB_HANDLERS_H__ */ diff --git a/ldb-2.0.8/include/ldb_module.h b/ldb-2.0.8/include/ldb_module.h new file mode 100644 index 0000000..8c1e5ee --- /dev/null +++ b/ldb-2.0.8/include/ldb_module.h @@ -0,0 +1,595 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb module header + * + * Description: defines ldb modules structures and helpers + * + */ + +#ifndef _LDB_MODULE_H_ +#define _LDB_MODULE_H_ + +#include + +#if defined(_SAMBA_BUILD_) && defined(USING_SYSTEM_LDB) + +/* + * Versions before 1.2.0 doesn't define these values + * so we assime 1.1.29 (which was used in Samba 4.6) + * + * See https://bugzilla.samba.org/show_bug.cgi?id=12859 + */ +#ifndef EXPECTED_SYSTEM_LDB_VERSION_MAJOR +#define EXPECTED_SYSTEM_LDB_VERSION_MAJOR 1 +#endif +#ifndef EXPECTED_SYSTEM_LDB_VERSION_MINOR +#define EXPECTED_SYSTEM_LDB_VERSION_MINOR 1 +#endif +#ifndef EXPECTED_SYSTEM_LDB_VERSION_MINOR +#define EXPECTED_SYSTEM_LDB_VERSION_MINOR 29 +#endif + +/* + * Only Samba versions which expect ldb >= 1.4.0 + * reopen the ldb after each fork(). + * + * See https://bugzilla.samba.org/show_bug.cgi?id=13519 + */ +#if EXPECTED_SYSTEM_LDB_VERSION_MAJOR > 1 +#define __LDB_FORK_COMPATIBLE__ 1 +#elif EXPECTED_SYSTEM_LDB_VERSION_MINOR > 3 +#define __LDB_FORK_COMPATIBLE__ 1 +#endif +#ifndef __LDB_FORK_COMPATIBLE__ +#error "Samba < 4.9 is not compatible with this version of ldb due to assumptions around fork() behaviour" +#endif + +#endif /* defined(_SAMBA_BUILD_) && defined(USING_SYSTEM_LDB) */ + +struct ldb_context; +struct ldb_module; + +/** + internal flag bits on message elements. Must be within LDB_FLAG_INTERNAL_MASK + */ +#define LDB_FLAG_INTERNAL_DISABLE_VALIDATION 0x10 + +/* disable any single value checking on this attribute */ +#define LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK 0x20 + +/* attribute has failed access check and must not be exposed */ +#define LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE 0x40 + +/* force single value checking on this attribute */ +#define LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK 0x80 + +/* + * ensure that this value is unique on an index + * (despite the index not otherwise being configured as UNIQUE). + * For example, all words starting with 'a' must be unique, but duplicates of + * words starting with b are allowed. This is specifically for Samba's + * objectSid index which is unique in the primary domain only. + */ +#define LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX 0x100 + +/* an extended match rule that always fails to match */ +#define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1" + +/* The const char * const * pointer to a list of secret (password) + * attributes, not to be printed in trace messages */ +#define LDB_SECRET_ATTRIBUTE_LIST_OPAQUE "LDB_SECRET_ATTRIBUTE_LIST" + +/* + * The scheme to be used for referral entries, i.e. ldap or ldaps + */ +#define LDAP_REFERRAL_SCHEME_OPAQUE "LDAP_REFERRAL_SCHEME" + +/* + these function pointers define the operations that a ldb module can intercept +*/ +struct ldb_module_ops { + const char *name; + int (*init_context) (struct ldb_module *); + int (*search)(struct ldb_module *, struct ldb_request *); /* search */ + int (*add)(struct ldb_module *, struct ldb_request *); /* add */ + int (*modify)(struct ldb_module *, struct ldb_request *); /* modify */ + int (*del)(struct ldb_module *, struct ldb_request *); /* delete */ + int (*rename)(struct ldb_module *, struct ldb_request *); /* rename */ + int (*request)(struct ldb_module *, struct ldb_request *); /* match any other operation */ + int (*extended)(struct ldb_module *, struct ldb_request *); /* extended operations */ + int (*start_transaction)(struct ldb_module *); + int (*prepare_commit)(struct ldb_module *); + int (*end_transaction)(struct ldb_module *); + int (*del_transaction)(struct ldb_module *); + int (*sequence_number)(struct ldb_module *, struct ldb_request *); + int (*read_lock)(struct ldb_module *); + int (*read_unlock)(struct ldb_module *); + void *private_data; +}; + + +/* The following definitions come from lib/ldb/common/ldb_debug.c */ +void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +void ldb_debug_set(struct ldb_context *ldb, enum ldb_debug_level level, + const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +void ldb_debug_add(struct ldb_context *ldb, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3); +void ldb_debug_end(struct ldb_context *ldb, enum ldb_debug_level level); +void ldb_vdebug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0); + +#define ldb_error(ldb, ecode, reason) ldb_error_at(ldb, ecode, reason, __FILE__, __LINE__) +#define ldb_module_error(module, ecode, reason) ldb_error_at(ldb_module_get_ctx(module), ecode, reason, __FILE__, __LINE__) + +#define ldb_oom(ldb) ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "ldb out of memory") +#define ldb_module_oom(module) ldb_oom(ldb_module_get_ctx(module)) +#define ldb_operr(ldb) ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "operations error") +#define ldb_module_operr(module) ldb_error(ldb_module_get_ctx(module), LDB_ERR_OPERATIONS_ERROR, "operations error") + +/* The following definitions come from lib/ldb/common/ldb.c */ + +void ldb_request_set_state(struct ldb_request *req, int state); +int ldb_request_get_status(struct ldb_request *req); + +unsigned int ldb_get_create_perms(struct ldb_context *ldb); + +const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb, + const char *syntax); + +/* The following definitions come from lib/ldb/common/ldb_attributes.c */ + +int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb, + const char *name, + unsigned flags, + const struct ldb_schema_syntax *syntax); +int ldb_schema_attribute_add(struct ldb_context *ldb, + const char *name, + unsigned flags, + const char *syntax); +void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name); + +/* we allow external code to override the name -> schema_attribute function */ +typedef const struct ldb_schema_attribute *(*ldb_attribute_handler_override_fn_t)(struct ldb_context *, void *, const char *); + +/** + Allow the caller to define a callback for the attribute handler + + \param ldb The ldb context + \param override The callback to be used for attribute lookups + \param private_data Private data for the callback + +*/ +void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb, + ldb_attribute_handler_override_fn_t override, + void *private_data); + +/** + Allow the caller to define that the callback for the attribute handler + also overrides the index list + + \param ldb The ldb context + \param one_level_indexes Indicates that the index for SCOPE_ONELEVEL + should also be maintained + +*/ +void ldb_schema_set_override_indexlist(struct ldb_context *ldb, + bool one_level_indexes); + +/** + + \param ldb The ldb context + \param GUID_index_attribute The globally attribute (eg objectGUID) + on each entry + \param GUID_index_attribute The DN component matching the + globally attribute on each entry (eg GUID) + + The caller must ensure the supplied strings do not go out of + scope (they are typically constant memory). + +*/ +void ldb_schema_set_override_GUID_index(struct ldb_context *ldb, + const char *GUID_index_attribute, + const char *GUID_index_dn_component); + +/* A useful function to build comparison functions with */ +int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx, + ldb_attr_handler_t canonicalise_fn, + const struct ldb_val *v1, + const struct ldb_val *v2); + +/* The following definitions come from lib/ldb/common/ldb_controls.c */ +int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver); +/* Returns a list of controls, except the one specified. Included + * controls become a child of returned list if they were children of + * controls_in */ +struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in, + TALLOC_CTX *mem_ctx, + struct ldb_control *exclude); +int ldb_check_critical_controls(struct ldb_control **controls); + +/* The following definitions come from lib/ldb/common/ldb_ldif.c */ +int ldb_should_b64_encode(struct ldb_context *ldb, const struct ldb_val *val); + +/* The following definitions come from lib/ldb/common/ldb_match.c */ +int ldb_match_msg(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + struct ldb_dn *base, + enum ldb_scope scope); + +int ldb_match_msg_error(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + struct ldb_dn *base, + enum ldb_scope scope, + bool *matched); + +int ldb_match_msg_objectclass(const struct ldb_message *msg, + const char *objectclass); + +int ldb_register_extended_match_rules(struct ldb_context *ldb); + +/* The following definitions come from lib/ldb/common/ldb_modules.c */ + +struct ldb_module *ldb_module_new(TALLOC_CTX *memctx, + struct ldb_context *ldb, + const char *module_name, + const struct ldb_module_ops *ops); + +const char * ldb_module_get_name(struct ldb_module *module); +struct ldb_context *ldb_module_get_ctx(struct ldb_module *module); +void *ldb_module_get_private(struct ldb_module *module); +void ldb_module_set_private(struct ldb_module *module, void *private_data); +const struct ldb_module_ops *ldb_module_get_ops(struct ldb_module *module); + +int ldb_next_request(struct ldb_module *module, struct ldb_request *request); +int ldb_next_start_trans(struct ldb_module *module); +int ldb_next_end_trans(struct ldb_module *module); +int ldb_next_del_trans(struct ldb_module *module); +int ldb_next_prepare_commit(struct ldb_module *module); +int ldb_next_init(struct ldb_module *module); +int ldb_next_read_lock(struct ldb_module *module); +int ldb_next_read_unlock(struct ldb_module *module); + +void ldb_set_errstring(struct ldb_context *ldb, const char *err_string); +void ldb_asprintf_errstring(struct ldb_context *ldb, const char *format, ...) PRINTF_ATTRIBUTE(2,3); +void ldb_reset_err_string(struct ldb_context *ldb); +int ldb_error_at(struct ldb_context *ldb, int ecode, const char *reason, const char *file, int line); + +const char *ldb_default_modules_dir(void); + +int ldb_register_module(const struct ldb_module_ops *); + +typedef int (*ldb_connect_fn)(struct ldb_context *ldb, const char *url, + unsigned int flags, const char *options[], + struct ldb_module **module); + +/** + Require that LDB use a private event context for each request + + A private event context may need to be created to avoid nested event + loops during ldb_tdb with the locks held. This indicates that a + backend is in use that requires this to hold locks safely. + + \param handle The ldb handle to set the flag on + */ +void ldb_set_require_private_event_context(struct ldb_context *ldb); + +struct ldb_backend_ops { + const char *name; + ldb_connect_fn connect_fn; +}; + +const char *ldb_default_modules_dir(void); + +int ldb_register_backend(const char *url_prefix, ldb_connect_fn, bool); + +struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb); + +/** + Obtains the private event context for the handle, + + A private event context may have been created to avoid nested event + loops during ldb_tdb with the locks held. Otherwise return the + global one. + + \param handle The ldb handle to obtain the event context for + \return the tevent event context for this handle (private or global) + */ +struct tevent_context *ldb_handle_get_event_context(struct ldb_handle *handle); + +int ldb_module_send_entry(struct ldb_request *req, + struct ldb_message *msg, + struct ldb_control **ctrls); + +int ldb_module_send_referral(struct ldb_request *req, + char *ref); + +int ldb_module_done(struct ldb_request *req, + struct ldb_control **ctrls, + struct ldb_extended *response, + int error); + +int ldb_mod_register_control(struct ldb_module *module, const char *oid); + +void ldb_set_default_dns(struct ldb_context *ldb); +/** + Add a ldb_control to a ldb_reply + + \param ares the reply struct where to add the control + \param oid the object identifier of the control as string + \param critical whether the control should be critical or not + \param data a talloc pointer to the control specific data + + \return result code (LDB_SUCCESS on success, or a failure code) +*/ +int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data); + +/** + mark a request as untrusted. + + This tells the rootdse module to remove unregistered controls + + \param req the request to mark as untrusted +*/ +void ldb_req_mark_untrusted(struct ldb_request *req); + +/** + mark a request as trusted. + + This tells the rootdse module to allow unregistered controls + + \param req the request to mark as trusted +*/ +void ldb_req_mark_trusted(struct ldb_request *req); + +/** + return true is a request is untrusted + + This indicates the request came across a trust boundary + for example over LDAP + + \param req the request check + \return is req trusted +*/ +bool ldb_req_is_untrusted(struct ldb_request *req); + +/** + set custom flags. Those flags are set by applications using ldb, + they are application dependent and the same bit can have different + meaning in different application. + */ +void ldb_req_set_custom_flags(struct ldb_request *req, uint32_t flags); + +/** + get custom flags. Those flags are set by applications using ldb, + they are application dependent and the same bit can have different + meaning in different application. + */ +uint32_t ldb_req_get_custom_flags(struct ldb_request *req); + +/* load all modules from the given directory */ +int ldb_modules_load(const char *modules_path, const char *version); + +/* init functions prototype */ +typedef int (*ldb_module_init_fn)(const char *); + +/* + general ldb hook function + */ +enum ldb_module_hook_type { LDB_MODULE_HOOK_CMDLINE_OPTIONS = 1, + LDB_MODULE_HOOK_CMDLINE_PRECONNECT = 2, + LDB_MODULE_HOOK_CMDLINE_POSTCONNECT = 3 }; + +typedef int (*ldb_hook_fn)(struct ldb_context *, enum ldb_module_hook_type ); + +/* + register a ldb hook function + */ +int ldb_register_hook(ldb_hook_fn hook_fn); + +/* + call ldb hooks of a given type + */ +int ldb_modules_hook(struct ldb_context *ldb, enum ldb_module_hook_type t); + +#define LDB_MODULE_CHECK_VERSION(version) do { \ + if (strcmp(version, LDB_VERSION) != 0) { \ + fprintf(stderr, "ldb: module version mismatch in %s : ldb_version=%s module_version=%s\n", \ + __FILE__, version, LDB_VERSION); \ + return LDB_ERR_UNAVAILABLE; \ + }} while (0) + + +/* + return a string representation of the calling chain for the given + ldb request + */ +char *ldb_module_call_chain(struct ldb_request *req, TALLOC_CTX *mem_ctx); + +/* + return the next module in the chain + */ +struct ldb_module *ldb_module_next(struct ldb_module *module); + +/* + set the next module in the module chain + */ +void ldb_module_set_next(struct ldb_module *module, struct ldb_module *next); + +/* + load a list of modules + */ +int ldb_module_load_list(struct ldb_context *ldb, const char **module_list, + struct ldb_module *backend, struct ldb_module **out); + +/* + get the popt_options pointer in the ldb structure. This allows a ldb + module to change the command line parsing + */ +struct poptOption **ldb_module_popt_options(struct ldb_context *ldb); + +/* modules are called in inverse order on the stack. + Lets place them as an admin would think the right order is. + Modules order is important */ +const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string); + +/* + return the current ldb flags LDB_FLG_* + */ +uint32_t ldb_module_flags(struct ldb_context *ldb); + +int ldb_module_connect_backend(struct ldb_context *ldb, + const char *url, + const char *options[], + struct ldb_module **backend_module); + +/* + initialise a chain of modules + */ +int ldb_module_init_chain(struct ldb_context *ldb, struct ldb_module *module); + +/* + * prototype for the init function defined by dynamically loaded modules + */ +int ldb_init_module(const char *version); + +/* replace the components of a DN with those from another DN, without + * touching the extended components + * + * return true if successful and false if not + * if false is returned the dn may be marked invalid + */ +bool ldb_dn_replace_components(struct ldb_dn *dn, struct ldb_dn *new_dn); + +/* + walk a parse tree, calling the provided callback on each node +*/ +int ldb_parse_tree_walk(struct ldb_parse_tree *tree, + int (*callback)(struct ldb_parse_tree *tree, void *), + void *private_context); + +/* compare two message elements with ordering - used by modify */ +bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1, + const struct ldb_message_element *el2); + + +struct ldb_extended_match_rule +{ + const char *oid; + int (*callback)(struct ldb_context *, const char *oid, + const struct ldb_message *, const char *, + const struct ldb_val *, bool *); +}; + +int ldb_register_extended_match_rule(struct ldb_context *ldb, + const struct ldb_extended_match_rule *rule); + +/* + * these pack/unpack functions are exposed in the library for use by + * ldb tools like ldbdump and for use in tests, + * but are not part of the public API + */ +int ldb_pack_data(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_val *data, + uint32_t pack_format_version); +/* + * Unpack a ldb message from a linear buffer in ldb_val + */ +int ldb_unpack_data(struct ldb_context *ldb, + const struct ldb_val *data, + struct ldb_message *message); + +/* + * filter the specified list of attributes from msg, + * adding requested attributes, and perhaps all for *, + * but not the DN to filtered_msg. + */ +int ldb_filter_attrs(struct ldb_context *ldb, + const struct ldb_message *msg, + const char *const *attrs, + struct ldb_message *filtered_msg); +/* + * Unpack a ldb message from a linear buffer in ldb_val + * + * 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. + * + * Likewise if LDB_UNPACK_DATA_FLAG_NO_DN is specified, the DN is omitted. + * + * If LDB_UNPACK_DATA_FLAG_NO_ATTRS is specified, then no attributes + * are unpacked or returned. + * + */ +int ldb_unpack_data_flags(struct ldb_context *ldb, + const struct ldb_val *data, + struct ldb_message *message, + unsigned int flags); + +int ldb_unpack_get_format(const struct ldb_val *data, + uint32_t *pack_format_version); + +/* currently unused (was NO_DATA_ALLOC) 0x0001 */ +#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002 +#define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004 +#define LDB_UNPACK_DATA_FLAG_NO_ATTRS 0x0008 +#define LDB_UNPACK_DATA_FLAG_READ_LOCKED 0x0010 + +enum ldb_pack_format { + + /* Old packing format (based on a somewhat arbitrary date) */ + LDB_PACKING_FORMAT_NODN = 0x26011966, + + /* In-use packing formats */ + LDB_PACKING_FORMAT, + LDB_PACKING_FORMAT_V2 +}; + +/** + Forces a specific ldb handle to use the global event context. + + This allows a nested event loop to operate, so any open + transaction also needs to be aborted. + + Any events on this event context will be lost. + + This is used in Samba when sending an IRPC to another part of the + same process instead of making a local DB modification. + + \param handle The ldb handle to force to use the global context + + */ +void ldb_handle_use_global_event_context(struct ldb_handle *handle); + +/** + * Get the options passed to ldb_connect. + * + * This allows the options to be inspected by elements in the module stack + * + */ +const char **ldb_options_get(struct ldb_context *ldb); +#endif diff --git a/ldb-2.0.8/include/ldb_private.h b/ldb-2.0.8/include/ldb_private.h new file mode 100644 index 0000000..4deb246 --- /dev/null +++ b/ldb-2.0.8/include/ldb_private.h @@ -0,0 +1,320 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2004-2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb private header + * + * Description: defines internal ldb structures used by the subsystem and modules + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + */ + +#ifndef _LDB_PRIVATE_H_ +#define _LDB_PRIVATE_H_ 1 + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb.h" +#include "ldb_module.h" + +struct ldb_context; + +struct ldb_module_ops; + +struct ldb_backend_ops; + +#define LDB_HANDLE_FLAG_DONE_CALLED 1 +/* call is from an untrusted source - eg. over ldap:// */ +#define LDB_HANDLE_FLAG_UNTRUSTED 2 + +struct ldb_handle { + int status; + enum ldb_state state; + struct ldb_context *ldb; + unsigned flags; + /* flags dedicated to be set by application using ldb */ + uint32_t custom_flags; + unsigned nesting; + + /* Private event context (if not NULL) */ + struct tevent_context *event_context; + + /* used for debugging */ + struct ldb_request *parent; + const char *location; +}; + +/* basic module structure */ +struct ldb_module { + struct ldb_module *prev, *next; + struct ldb_context *ldb; + void *private_data; + const struct ldb_module_ops *ops; +}; + +/* + schema related information needed for matching rules +*/ +struct ldb_schema { + void *attribute_handler_override_private; + ldb_attribute_handler_override_fn_t attribute_handler_override; + + /* attribute handling table */ + unsigned num_attributes; + struct ldb_schema_attribute *attributes; + + unsigned num_dn_extended_syntax; + struct ldb_dn_extended_syntax *dn_extended_syntax; + + /* + * If set, the attribute_handler_override has the details of + * what attributes have an index + */ + bool index_handler_override; + bool one_level_indexes; + + const char *GUID_index_attribute; + const char *GUID_index_dn_component; +}; + +/* + every ldb connection is started by establishing a ldb_context +*/ +struct ldb_context { + /* the operations provided by the backend */ + struct ldb_module *modules; + + /* debugging operations */ + struct ldb_debug_ops debug_ops; + + /* extended matching rules */ + struct ldb_extended_match_entry { + const struct ldb_extended_match_rule *rule; + struct ldb_extended_match_entry *prev, *next; + } *extended_match_rules; + + /* custom utf8 functions */ + struct ldb_utf8_fns utf8_fns; + + /* backend specific opaque parameters */ + struct ldb_opaque { + struct ldb_opaque *next; + const char *name; + void *value; + } *opaque; + + struct ldb_schema schema; + + char *err_string; + + int transaction_active; + + int default_timeout; + + unsigned int flags; + + unsigned int create_perms; + + struct tevent_context *ev_ctx; + + /* + * If the backend holds locks, we must not use a global event + * context, so this flag will be set and ldb_handle_new() will + * build a new event context + */ + bool require_private_event_context; + + bool prepare_commit_done; + + char *partial_debug; + + struct poptOption *popt_options; + + /* + * The ldb options passed to ldb_connect + * A NULL terminated array of zero terminated strings + */ + const char **options; +}; + +/* The following definitions come from lib/ldb/common/ldb.c */ + +extern const struct ldb_module_ops ldb_objectclass_module_ops; +extern const struct ldb_module_ops ldb_paged_results_module_ops; +extern const struct ldb_module_ops ldb_rdn_name_module_ops; +extern const struct ldb_module_ops ldb_schema_module_ops; +extern const struct ldb_module_ops ldb_asq_module_ops; +extern const struct ldb_module_ops ldb_server_sort_module_ops; +extern const struct ldb_module_ops ldb_ldap_module_ops; +extern const struct ldb_module_ops ldb_ildap_module_ops; +extern const struct ldb_module_ops ldb_paged_searches_module_ops; +extern const struct ldb_module_ops ldb_tdb_module_ops; +extern const struct ldb_module_ops ldb_skel_module_ops; +extern const struct ldb_module_ops ldb_subtree_rename_module_ops; +extern const struct ldb_module_ops ldb_subtree_delete_module_ops; +extern const struct ldb_module_ops ldb_sqlite3_module_ops; +extern const struct ldb_module_ops ldb_wins_ldb_module_ops; +extern const struct ldb_module_ops ldb_ranged_results_module_ops; + +extern const struct ldb_backend_ops ldb_tdb_backend_ops; +extern const struct ldb_backend_ops ldb_sqlite3_backend_ops; +extern const struct ldb_backend_ops ldb_ldap_backend_ops; +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); +int ldb_subclass_add(struct ldb_context *ldb, const char *classname, const char *subclass); + +/* The following definitions come from lib/ldb/common/ldb_utf8.c */ +char *ldb_casefold_default(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n); + +void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f); + + +/* The following definitions come from lib/ldb/common/ldb_modules.c */ + +const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string); +int ldb_load_modules(struct ldb_context *ldb, const char *options[]); + +struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str); + + +/* The following definitions come from lib/ldb/common/ldb_options.c */ + +const char *ldb_options_find(struct ldb_context *ldb, const char *options[], + const char *option_name); +const char **ldb_options_copy(TALLOC_CTX *ctx, const char *options[]); + +/* The following definitions come from lib/ldb/common/ldb_ldif.c */ + +struct ldif_read_file_state { + FILE *f; + size_t line_no; +}; + +struct ldb_ldif *ldb_ldif_read_file_state(struct ldb_context *ldb, + struct ldif_read_file_state *state); + +char *ldb_ldif_write_redacted_trace_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + const struct ldb_ldif *ldif); + +/* + * Get the LDB context in use on an LDB DN. + * + * This is helpful to the python LDB code, which may use as part of + * adding base and child components to an existing DN. + */ +struct ldb_context *ldb_dn_get_ldb_context(struct ldb_dn *dn); + +#define LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES 1 + +/** + Determine whether any values in an element are also in another element, + and optionally fix that. + + \param ldb an ldb context + \param mem_ctx a talloc context + \param el an element + \param other_el another element + \param options flags controlling the function behaviour + + Without the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, return + LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS if the elements share values, and + LDB_SUCCESS if they don't. That is, determine whether there is an + intersection without changing anything. + + With the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, any values in common + are removed from the first element and LDB_SUCCESS is returned. + + LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown option. + LDB_ERR_INAPPROPRIATE_MATCHING means the elements differ in name. +*/ + +int ldb_msg_find_common_values(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_message_element *el, + struct ldb_message_element *other_el, + uint32_t options); + +/** + Detect whether an element contains duplicate values + + \param ldb a currently unused ldb_context struct + \param mem_ctx a talloc context + \param el the element to search + \param duplicate will point to a duplicate value if there are duplicates, + or NULL otherwise. + \param options is a flags field. All values are reserved. + + \return an ldb error code. LDB_ERR_OPERATIONS_ERROR indicates an allocation + failure or an unknown option flag. Otherwise LDB_SUCCESS. + + \note This search is case sensitive +*/ +int ldb_msg_find_duplicate_val(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const struct ldb_message_element *el, + struct ldb_val **duplicate, + uint32_t options); +/** + Check if a particular message will match the given filter + + \param ldb an ldb context + \param msg the message to be checked + \param tree the filter tree to check against + \param scope the scope to match against + (to avoid matching special DNs except on a base search) + \param matched a pointer to a boolean set true if it matches, + false otherwise + + returns LDB_SUCCESS or an error + + \note this is a recursive function, and does short-circuit evaluation + */ +int ldb_match_message(struct ldb_context *ldb, + const struct ldb_message *msg, + const struct ldb_parse_tree *tree, + enum ldb_scope scope, bool *matched); + +#endif diff --git a/ldb-2.0.8/ldb.pc.in b/ldb-2.0.8/ldb.pc.in new file mode 100644 index 0000000..aeba17a --- /dev/null +++ b/ldb-2.0.8/ldb.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +modulesdir=@LDB_MODULESDIR@ + +Name: ldb +Description: An LDAP-like embedded database +Version: @PACKAGE_VERSION@ +Requires.private: tdb +Requires: talloc +Libs: @LIB_RPATH@ -L${libdir} -lldb +Libs.private: @LDAP_LIBS@ +Cflags: -I${includedir} +Modulesdir: ${modulesdir} +URL: http://ldb.samba.org/ diff --git a/ldb-2.0.8/ldb_key_value/ldb_kv.c b/ldb-2.0.8/ldb_key_value/ldb_kv.c new file mode 100644 index 0000000..4e7b8a1 --- /dev/null +++ b/ldb-2.0.8/ldb_key_value/ldb_kv.c @@ -0,0 +1,2292 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2006-2008 + Copyright (C) Matthias Dieter Wallnöfer 2009-2010 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb_kv + * + * Component: ldb key value backend + * + * Description: core functions for ldb key value backend + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + * + * Modifications: + * + * - description: make the module use asynchronous calls + * date: Feb 2006 + * Author: Simo Sorce + * + * - description: make it possible to use event contexts + * date: Jan 2008 + * Author: Simo Sorce + * + * - description: fix up memory leaks and small bugs + * date: Oct 2009 + * Author: Matthias Dieter Wallnöfer + */ + +#include "ldb_kv.h" +#include "ldb_private.h" +#include "lib/util/attr.h" + +/* + prevent memory errors on callbacks +*/ +struct ldb_kv_req_spy { + struct ldb_kv_context *ctx; +}; + +/* + * Determine if this key could hold a record. We allow the new GUID + * index, the old DN index and a possible future ID= + */ +bool ldb_kv_key_is_normal_record(struct ldb_val key) +{ + if (key.length < 4) { + return false; + } + + /* + * @ records are not normal records, we don't want to index + * them nor search on them + */ + if (key.length > 4 && + memcmp(key.data, "DN=@", 4) == 0) { + return false; + } + + /* All other DN= records are however */ + if (memcmp(key.data, "DN=", 3) == 0) { + return true; + } + + if (memcmp(key.data, "ID=", 3) == 0) { + return true; + } + + if (key.length < sizeof(LDB_KV_GUID_KEY_PREFIX)) { + return false; + } + + if (memcmp(key.data, LDB_KV_GUID_KEY_PREFIX, + sizeof(LDB_KV_GUID_KEY_PREFIX) - 1) == 0) { + return true; + } + + return false; +} + +/* + form a ldb_val for a record key + caller frees + + note that the key for a record can depend on whether the + dn refers to a case sensitive index record or not +*/ +struct ldb_val ldb_kv_key_dn(TALLOC_CTX *mem_ctx, + struct ldb_dn *dn) +{ + struct ldb_val key; + char *key_str = NULL; + const char *dn_folded = NULL; + + /* + most DNs are case insensitive. The exception is index DNs for + case sensitive attributes + + there are 3 cases dealt with in this code: + + 1) if the dn doesn't start with @ then uppercase the attribute + names and the attributes values of case insensitive attributes + 2) if the dn starts with @ then leave it alone - + the indexing code handles the rest + */ + + dn_folded = ldb_dn_get_casefold(dn); + if (!dn_folded) { + goto failed; + } + + key_str = talloc_strdup(mem_ctx, "DN="); + if (!key_str) { + goto failed; + } + + key_str = talloc_strdup_append_buffer(key_str, dn_folded); + if (!key_str) { + goto failed; + } + + key.data = (uint8_t *)key_str; + key.length = strlen(key_str) + 1; + + return key; + +failed: + errno = ENOMEM; + key.data = NULL; + key.length = 0; + return key; +} + +/* The caller is to provide a correctly sized key */ +int ldb_kv_guid_to_key(const struct ldb_val *GUID_val, + struct ldb_val *key) +{ + const char *GUID_prefix = LDB_KV_GUID_KEY_PREFIX; + const int GUID_prefix_len = sizeof(LDB_KV_GUID_KEY_PREFIX) - 1; + + if (key->length != (GUID_val->length+GUID_prefix_len)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + memcpy(key->data, GUID_prefix, GUID_prefix_len); + memcpy(&key->data[GUID_prefix_len], + GUID_val->data, GUID_val->length); + return LDB_SUCCESS; +} + +/* + * The caller is to provide a correctly sized key, used only in + * the GUID index mode + */ +int ldb_kv_idx_to_key(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + TALLOC_CTX *mem_ctx, + const struct ldb_val *idx_val, + struct ldb_val *key) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_dn *dn; + + if (ldb_kv->cache->GUID_index_attribute != NULL) { + return ldb_kv_guid_to_key(idx_val, key); + } + + dn = ldb_dn_from_ldb_val(mem_ctx, ldb, idx_val); + if (dn == NULL) { + /* + * LDB_ERR_INVALID_DN_SYNTAX would just be confusing + * to the caller, as this in an invalid index value + */ + return LDB_ERR_OPERATIONS_ERROR; + } + /* form the key */ + *key = ldb_kv_key_dn(mem_ctx, dn); + TALLOC_FREE(dn); + if (!key->data) { + return ldb_module_oom(module); + } + return LDB_SUCCESS; +} + +/* + form a TDB_DATA for a record key + caller frees mem_ctx, which may or may not have the key + as a child. + + note that the key for a record can depend on whether a + GUID index is in use, or the DN is used as the key +*/ +struct ldb_val ldb_kv_key_msg(struct ldb_module *module, + TALLOC_CTX *mem_ctx, + const struct ldb_message *msg) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_val key; + const struct ldb_val *guid_val; + int ret; + + if (ldb_kv->cache->GUID_index_attribute == NULL) { + return ldb_kv_key_dn(mem_ctx, msg->dn); + } + + if (ldb_dn_is_special(msg->dn)) { + return ldb_kv_key_dn(mem_ctx, msg->dn); + } + + guid_val = + ldb_msg_find_ldb_val(msg, ldb_kv->cache->GUID_index_attribute); + if (guid_val == NULL) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Did not find GUID attribute %s " + "in %s, required for TDB record " + "key in " LDB_KV_IDXGUID " mode.", + ldb_kv->cache->GUID_index_attribute, + ldb_dn_get_linearized(msg->dn)); + errno = EINVAL; + key.data = NULL; + key.length = 0; + return key; + } + + /* In this case, allocate with talloc */ + key.data = talloc_size(mem_ctx, LDB_KV_GUID_KEY_SIZE); + if (key.data == NULL) { + errno = ENOMEM; + key.data = NULL; + key.length = 0; + return key; + } + key.length = talloc_get_size(key.data); + + ret = ldb_kv_guid_to_key(guid_val, &key); + + if (ret != LDB_SUCCESS) { + errno = EINVAL; + key.data = NULL; + key.length = 0; + return key; + } + return key; +} + +/* + check special dn's have valid attributes + currently only @ATTRIBUTES is checked +*/ +static int ldb_kv_check_special_dn(struct ldb_module *module, + const struct ldb_message *msg) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + unsigned int i, j; + + if (! ldb_dn_is_special(msg->dn) || + ! ldb_dn_check_special(msg->dn, LDB_KV_ATTRIBUTES)) { + return LDB_SUCCESS; + } + + /* we have @ATTRIBUTES, let's check attributes are fine */ + /* should we check that we deny multivalued attributes ? */ + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, "distinguishedName") == 0) continue; + + for (j = 0; j < msg->elements[i].num_values; j++) { + if (ldb_kv_check_at_attributes_values( + &msg->elements[i].values[j]) != 0) { + ldb_set_errstring(ldb, "Invalid attribute value in an @ATTRIBUTES entry"); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + } + } + + return LDB_SUCCESS; +} + +/* + * Called after modifies and when starting a transaction. Checks target pack + * format version and current pack format version, which are set by cache_load, + * and repacks if necessary. + */ +static int ldb_kv_maybe_repack(struct ldb_kv_private *ldb_kv) { + /* Override option taken from ldb options */ + if (ldb_kv->pack_format_override != 0) { + ldb_kv->target_pack_format_version = + ldb_kv->pack_format_override; + } + + if (ldb_kv->pack_format_version != + ldb_kv->target_pack_format_version) { + int r; + struct ldb_context *ldb = ldb_module_get_ctx(ldb_kv->module); + r = ldb_kv_repack(ldb_kv->module); + if (r != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Database repack failed."); + } + return r; + } + + return LDB_SUCCESS; +} + +/* + we've made a modification to a dn - possibly reindex and + update sequence number +*/ +static int ldb_kv_modified(struct ldb_module *module, struct ldb_dn *dn) +{ + int ret = LDB_SUCCESS; + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + + /* only allow modifies inside a transaction, otherwise the + * ldb is unsafe */ + if (ldb_kv->kv_ops->transaction_active(ldb_kv) == false) { + ldb_set_errstring(ldb_module_get_ctx(module), "ltdb modify without transaction"); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ldb_dn_is_special(dn) && + (ldb_dn_check_special(dn, LDB_KV_INDEXLIST) || + ldb_dn_check_special(dn, LDB_KV_ATTRIBUTES)) ) + { + if (ldb_kv->warn_reindex) { + ldb_debug(ldb_module_get_ctx(module), + LDB_DEBUG_ERROR, + "Reindexing %s due to modification on %s", + ldb_kv->kv_ops->name(ldb_kv), + ldb_dn_get_linearized(dn)); + } + ret = ldb_kv_reindex(module); + } + + /* If the modify was to a normal record, or any special except @BASEINFO, update the seq number */ + if (ret == LDB_SUCCESS && + !(ldb_dn_is_special(dn) && + ldb_dn_check_special(dn, LDB_KV_BASEINFO)) ) { + ret = ldb_kv_increase_sequence_number(module); + } + + /* If the modify was to @OPTIONS, reload the cache */ + if (ret == LDB_SUCCESS && + ldb_dn_is_special(dn) && + (ldb_dn_check_special(dn, LDB_KV_OPTIONS)) ) { + ret = ldb_kv_cache_reload(module); + } + + if (ret != LDB_SUCCESS) { + ldb_kv->reindex_failed = true; + } + + return ret; +} +/* + store a record into the db +*/ +int ldb_kv_store(struct ldb_module *module, + const struct ldb_message *msg, + int flgs) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_val key; + struct ldb_val ldb_data; + int ret = LDB_SUCCESS; + TALLOC_CTX *key_ctx = talloc_new(module); + + if (key_ctx == NULL) { + return ldb_module_oom(module); + } + + if (ldb_kv->read_only) { + talloc_free(key_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + key = ldb_kv_key_msg(module, key_ctx, msg); + if (key.data == NULL) { + TALLOC_FREE(key_ctx); + return LDB_ERR_OTHER; + } + + ret = ldb_pack_data(ldb_module_get_ctx(module), + msg, &ldb_data, + ldb_kv->pack_format_version); + if (ret == -1) { + TALLOC_FREE(key_ctx); + return LDB_ERR_OTHER; + } + + ret = ldb_kv->kv_ops->store(ldb_kv, key, ldb_data, flgs); + if (ret != 0) { + bool is_special = ldb_dn_is_special(msg->dn); + ret = ldb_kv->kv_ops->error(ldb_kv); + + /* + * LDB_ERR_ENTRY_ALREADY_EXISTS means the DN, not + * the GUID, so re-map + */ + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS && !is_special && + ldb_kv->cache->GUID_index_attribute != NULL) { + ret = LDB_ERR_CONSTRAINT_VIOLATION; + } + goto done; + } + +done: + TALLOC_FREE(key_ctx); + talloc_free(ldb_data.data); + + return ret; +} + + +/* + check if a attribute is a single valued, for a given element + */ +static bool ldb_kv_single_valued(const struct ldb_schema_attribute *a, + struct ldb_message_element *el) +{ + if (!a) return false; + if (el != NULL) { + if (el->flags & LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK) { + /* override from a ldb module, for example + used for the description field, which is + marked multi-valued in the schema but which + should not actually accept multiple + values */ + return true; + } + if (el->flags & LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK) { + /* override from a ldb module, for example used for + deleted linked attribute entries */ + return false; + } + } + if (a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { + return true; + } + return false; +} + +/* + * Starts a sub transaction if they are supported by the backend + * and the ldb connection has not been opened in batch mode. + */ +static int ldb_kv_sub_transaction_start(struct ldb_kv_private *ldb_kv) +{ + int ret = LDB_SUCCESS; + + if (ldb_kv->batch_mode) { + return ret; + } + + ret = ldb_kv->kv_ops->begin_nested_write(ldb_kv); + if (ret == LDB_SUCCESS) { + ret = ldb_kv_index_sub_transaction_start(ldb_kv); + } + return ret; +} + +/* + * Commits a sub transaction if they are supported by the backend + * and the ldb connection has not been opened in batch mode. + */ +static int ldb_kv_sub_transaction_commit(struct ldb_kv_private *ldb_kv) +{ + int ret = LDB_SUCCESS; + + if (ldb_kv->batch_mode) { + return ret; + } + + ret = ldb_kv_index_sub_transaction_commit(ldb_kv); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = ldb_kv->kv_ops->finish_nested_write(ldb_kv); + return ret; +} + +/* + * Cancels a sub transaction if they are supported by the backend + * and the ldb connection has not been opened in batch mode. + */ +static int ldb_kv_sub_transaction_cancel(struct ldb_kv_private *ldb_kv) +{ + int ret = LDB_SUCCESS; + + if (ldb_kv->batch_mode) { + return ret; + } + + ret = ldb_kv_index_sub_transaction_cancel(ldb_kv); + if (ret != LDB_SUCCESS) { + struct ldb_context *ldb = ldb_module_get_ctx(ldb_kv->module); + /* + * In the event of a failure we log the failure and continue + * as we need to cancel the database transaction. + */ + ldb_debug(ldb, + LDB_DEBUG_ERROR, + __location__": ldb_kv_index_sub_transaction_cancel " + "failed: %s", + ldb_errstring(ldb)); + } + ret = ldb_kv->kv_ops->abort_nested_write(ldb_kv); + return ret; +} + +static int ldb_kv_add_internal(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + bool check_single_value) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + int ret = LDB_SUCCESS; + unsigned int i; + bool valid_dn = false; + + /* Check the new DN is reasonable */ + valid_dn = ldb_dn_validate(msg->dn); + if (valid_dn == false) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Invalid DN in ADD: %s", + ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + + for (i=0;inum_elements;i++) { + struct ldb_message_element *el = &msg->elements[i]; + const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name); + + if (el->num_values == 0) { + ldb_asprintf_errstring(ldb, "attribute '%s' on '%s' specified, but with 0 values (illegal)", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + if (check_single_value && el->num_values > 1 && + ldb_kv_single_valued(a, el)) { + ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + /* Do not check "@ATTRIBUTES" for duplicated values */ + if (ldb_dn_is_special(msg->dn) && + ldb_dn_check_special(msg->dn, LDB_KV_ATTRIBUTES)) { + continue; + } + + if (check_single_value && + !(el->flags & + LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK)) { + struct ldb_val *duplicate = NULL; + + ret = ldb_msg_find_duplicate_val(ldb, discard_const(msg), + el, &duplicate, 0); + if (ret != LDB_SUCCESS) { + return ret; + } + if (duplicate != NULL) { + ldb_asprintf_errstring( + ldb, + "attribute '%s': value '%.*s' on '%s' " + "provided more than once in ADD object", + el->name, + (int)duplicate->length, + duplicate->data, + ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + } + } + + ret = ldb_kv_store(module, msg, TDB_INSERT); + if (ret != LDB_SUCCESS) { + /* + * Try really hard to get the right error code for + * a re-add situation, as this can matter! + */ + if (ret == LDB_ERR_CONSTRAINT_VIOLATION) { + int ret2; + struct ldb_dn *dn2 = NULL; + TALLOC_CTX *mem_ctx = talloc_new(module); + if (mem_ctx == NULL) { + return ldb_module_operr(module); + } + ret2 = + ldb_kv_search_base(module, mem_ctx, msg->dn, &dn2); + TALLOC_FREE(mem_ctx); + if (ret2 == LDB_SUCCESS) { + ret = LDB_ERR_ENTRY_ALREADY_EXISTS; + } + } + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + ldb_asprintf_errstring(ldb, + "Entry %s already exists", + ldb_dn_get_linearized(msg->dn)); + } + return ret; + } + + ret = ldb_kv_index_add_new(module, ldb_kv, msg); + if (ret != LDB_SUCCESS) { + /* + * If we failed to index, delete the message again. + * + * This is particularly important for the GUID index + * case, which will only fail for a duplicate DN + * in the index add. + * + * Note that the caller may not cancel the transation + * and this means the above add might really show up! + */ + ldb_kv_delete_noindex(module, msg); + return ret; + } + + ret = ldb_kv_modified(module, msg->dn); + + /* + * To allow testing of the error recovery code in ldb_kv_add + * cmocka tests can define CMOCKA_UNIT_TEST_ADD_INTERNAL_FAIL + * to inject failures at this point. + */ +#ifdef CMOCKA_UNIT_TEST_ADD_INTERNAL_FAIL + CMOCKA_UNIT_TEST_ADD_INTERNAL_FAIL +#endif + + return ret; +} + +/* + add a record to the database +*/ +static int ldb_kv_add(struct ldb_kv_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int ret = LDB_SUCCESS; + + if (ldb_kv->max_key_length != 0 && + ldb_kv->cache->GUID_index_attribute == NULL && + !ldb_dn_is_special(req->op.add.message->dn)) { + ldb_set_errstring(ldb_module_get_ctx(module), + "Must operate ldb_mdb in GUID " + "index mode, but " LDB_KV_IDXGUID " not set."); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + ret = ldb_kv_check_special_dn(module, req->op.add.message); + if (ret != LDB_SUCCESS) { + return ret; + } + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + if (ldb_kv_cache_load(module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_sub_transaction_start(ldb_kv); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = ldb_kv_add_internal(module, ldb_kv, req->op.add.message, true); + if (ret != LDB_SUCCESS) { + int r = ldb_kv_sub_transaction_cancel(ldb_kv); + if (r != LDB_SUCCESS) { + ldb_debug( + ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + __location__ + ": Unable to roll back sub transaction"); + } + ldb_kv->operation_failed = true; + return ret; + } + ret = ldb_kv_sub_transaction_commit(ldb_kv); + + return ret; +} + +/* + delete a record from the database, not updating indexes (used for deleting + index records) +*/ +int ldb_kv_delete_noindex(struct ldb_module *module, + const struct ldb_message *msg) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_val key; + int ret; + TALLOC_CTX *tdb_key_ctx = talloc_new(module); + + if (tdb_key_ctx == NULL) { + return ldb_module_oom(module); + } + + if (ldb_kv->read_only) { + talloc_free(tdb_key_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + key = ldb_kv_key_msg(module, tdb_key_ctx, msg); + if (!key.data) { + TALLOC_FREE(tdb_key_ctx); + return LDB_ERR_OTHER; + } + + ret = ldb_kv->kv_ops->delete(ldb_kv, key); + TALLOC_FREE(tdb_key_ctx); + + if (ret != 0) { + ret = ldb_kv->kv_ops->error(ldb_kv); + } + + return ret; +} + +static int ldb_kv_delete_internal(struct ldb_module *module, struct ldb_dn *dn) +{ + struct ldb_message *msg; + int ret = LDB_SUCCESS; + + msg = ldb_msg_new(module); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* in case any attribute of the message was indexed, we need + to fetch the old record */ + ret = ldb_kv_search_dn1(module, dn, msg, 0); + if (ret != LDB_SUCCESS) { + /* not finding the old record is an error */ + goto done; + } + + ret = ldb_kv_delete_noindex(module, msg); + if (ret != LDB_SUCCESS) { + goto done; + } + + /* remove any indexed attributes */ + ret = ldb_kv_index_delete(module, msg); + if (ret != LDB_SUCCESS) { + goto done; + } + + ret = ldb_kv_modified(module, dn); + if (ret != LDB_SUCCESS) { + goto done; + } + +done: + talloc_free(msg); + /* + * To allow testing of the error recovery code in ldb_kv_delete + * cmocka tests can define CMOCKA_UNIT_TEST_DELETE_INTERNAL_FAIL + * to inject failures at this point. + */ +#ifdef CMOCKA_UNIT_TEST_DELETE_INTERNAL_FAIL + CMOCKA_UNIT_TEST_DELETE_INTERNAL_FAIL +#endif + return ret; +} + +/* + delete a record from the database +*/ +static int ldb_kv_delete(struct ldb_kv_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int ret = LDB_SUCCESS; + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + if (ldb_kv_cache_load(module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_sub_transaction_start(ldb_kv); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = ldb_kv_delete_internal(module, req->op.del.dn); + if (ret != LDB_SUCCESS) { + int r = ldb_kv_sub_transaction_cancel(ldb_kv); + if (r != LDB_SUCCESS) { + ldb_debug( + ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + __location__ + ": Unable to roll back sub transaction"); + } + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + ldb_kv->operation_failed = true; + } + return ret; + } + ret = ldb_kv_sub_transaction_commit(ldb_kv); + + return ret; +} + +/* + find an element by attribute name. At the moment this does a linear search, + it should be re-coded to use a binary search once all places that modify + records guarantee sorted order + + return the index of the first matching element if found, otherwise -1 +*/ +static int ldb_kv_find_element(const struct ldb_message *msg, const char *name) +{ + unsigned int i; + for (i=0;inum_elements;i++) { + if (ldb_attr_cmp(msg->elements[i].name, name) == 0) { + return i; + } + } + return -1; +} + + +/* + add an element to an existing record. Assumes a elements array that we + can call re-alloc on, and assumed that we can re-use the data pointers from + the passed in additional values. Use with care! + + returns 0 on success, -1 on failure (and sets errno) +*/ +static int ldb_kv_msg_add_element(struct ldb_message *msg, + struct ldb_message_element *el) +{ + struct ldb_message_element *e2; + unsigned int i; + + if (el->num_values == 0) { + /* nothing to do here - we don't add empty elements */ + return 0; + } + + e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, + msg->num_elements+1); + if (!e2) { + errno = ENOMEM; + return -1; + } + + msg->elements = e2; + + e2 = &msg->elements[msg->num_elements]; + + e2->name = el->name; + e2->flags = el->flags; + e2->values = talloc_array(msg->elements, + struct ldb_val, el->num_values); + if (!e2->values) { + errno = ENOMEM; + return -1; + } + for (i=0;inum_values;i++) { + e2->values[i] = el->values[i]; + } + e2->num_values = el->num_values; + + ++msg->num_elements; + + return 0; +} + +/* + delete all elements having a specified attribute name +*/ +static int ldb_kv_msg_delete_attribute(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + struct ldb_message *msg, + const char *name) +{ + int ret; + struct ldb_message_element *el; + bool is_special = ldb_dn_is_special(msg->dn); + + if (!is_special && ldb_kv->cache->GUID_index_attribute != NULL && + ldb_attr_cmp(name, ldb_kv->cache->GUID_index_attribute) == 0) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_asprintf_errstring(ldb, + "Must not modify GUID " + "attribute %s (used as DB index)", + ldb_kv->cache->GUID_index_attribute); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + el = ldb_msg_find_element(msg, name); + if (el == NULL) { + return LDB_ERR_NO_SUCH_ATTRIBUTE; + } + + ret = ldb_kv_index_del_element(module, ldb_kv, msg, el); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_free(el->values); + ldb_msg_remove_element(msg, el); + msg->elements = talloc_realloc(msg, msg->elements, + struct ldb_message_element, + msg->num_elements); + return LDB_SUCCESS; +} + +/* + delete all elements matching an attribute name/value + + return LDB Error on failure +*/ +static int ldb_kv_msg_delete_element(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + struct ldb_message *msg, + const char *name, + const struct ldb_val *val) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + unsigned int i; + int found, ret; + struct ldb_message_element *el; + const struct ldb_schema_attribute *a; + + found = ldb_kv_find_element(msg, name); + if (found == -1) { + return LDB_ERR_NO_SUCH_ATTRIBUTE; + } + + i = (unsigned int) found; + el = &(msg->elements[i]); + + a = ldb_schema_attribute_by_name(ldb, el->name); + + for (i=0;inum_values;i++) { + bool matched; + if (a->syntax->operator_fn) { + ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a, + &el->values[i], val, &matched); + if (ret != LDB_SUCCESS) return ret; + } else { + matched = (a->syntax->comparison_fn(ldb, ldb, + &el->values[i], val) == 0); + } + if (matched) { + if (el->num_values == 1) { + return ldb_kv_msg_delete_attribute( + module, ldb_kv, msg, name); + } + + ret = + ldb_kv_index_del_value(module, ldb_kv, msg, el, i); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (inum_values-1) { + memmove(&el->values[i], &el->values[i+1], + sizeof(el->values[i])* + (el->num_values-(i+1))); + } + el->num_values--; + + /* per definition we find in a canonicalised message an + attribute value only once. So we are finished here */ + return LDB_SUCCESS; + } + } + + /* Not found */ + return LDB_ERR_NO_SUCH_ATTRIBUTE; +} + +/* + modify a record - internal interface + + yuck - this is O(n^2). Luckily n is usually small so we probably + get away with it, but if we ever have really large attribute lists + then we'll need to look at this again + + 'req' is optional, and is used to specify controls if supplied +*/ +int ldb_kv_modify_internal(struct ldb_module *module, + const struct ldb_message *msg, + struct ldb_request *req) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_message *msg2; + unsigned int i, j; + int ret = LDB_SUCCESS, idx; + struct ldb_control *control_permissive = NULL; + TALLOC_CTX *mem_ctx = talloc_new(req); + + if (mem_ctx == NULL) { + return ldb_module_oom(module); + } + + if (req) { + control_permissive = ldb_request_get_control(req, + LDB_CONTROL_PERMISSIVE_MODIFY_OID); + } + + msg2 = ldb_msg_new(mem_ctx); + if (msg2 == NULL) { + ret = LDB_ERR_OTHER; + goto done; + } + + ret = ldb_kv_search_dn1(module, msg->dn, msg2, 0); + if (ret != LDB_SUCCESS) { + goto done; + } + + for (i=0; inum_elements; i++) { + struct ldb_message_element *el = &msg->elements[i], *el2; + struct ldb_val *vals; + const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name); + const char *dn; + uint32_t options = 0; + if (control_permissive != NULL) { + options |= LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES; + } + + switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + + if (el->num_values == 0) { + ldb_asprintf_errstring(ldb, + "attribute '%s': attribute on '%s' specified, but with 0 values (illegal)", + el->name, ldb_dn_get_linearized(msg2->dn)); + ret = LDB_ERR_CONSTRAINT_VIOLATION; + goto done; + } + + /* make a copy of the array so that a permissive + * control can remove duplicates without changing the + * original values, but do not copy data as we do not + * need to keep it around once the operation is + * finished */ + if (control_permissive) { + el = talloc(msg2, struct ldb_message_element); + if (!el) { + ret = LDB_ERR_OTHER; + goto done; + } + *el = msg->elements[i]; + el->values = talloc_array(el, struct ldb_val, el->num_values); + if (el->values == NULL) { + ret = LDB_ERR_OTHER; + goto done; + } + for (j = 0; j < el->num_values; j++) { + el->values[j] = msg->elements[i].values[j]; + } + } + + if (el->num_values > 1 && ldb_kv_single_valued(a, el)) { + ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", + el->name, ldb_dn_get_linearized(msg2->dn)); + ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + goto done; + } + + /* Checks if element already exists */ + idx = ldb_kv_find_element(msg2, el->name); + if (idx == -1) { + if (ldb_kv_msg_add_element(msg2, el) != 0) { + ret = LDB_ERR_OTHER; + goto done; + } + ret = ldb_kv_index_add_element( + module, ldb_kv, msg2, el); + if (ret != LDB_SUCCESS) { + goto done; + } + } else { + j = (unsigned int) idx; + el2 = &(msg2->elements[j]); + + /* We cannot add another value on a existing one + if the attribute is single-valued */ + if (ldb_kv_single_valued(a, el)) { + ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", + el->name, ldb_dn_get_linearized(msg2->dn)); + ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + goto done; + } + + /* Check that values don't exist yet on multi- + valued attributes or aren't provided twice */ + if (!(el->flags & + LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK)) { + struct ldb_val *duplicate = NULL; + ret = ldb_msg_find_common_values(ldb, + msg2, + el, + el2, + options); + + if (ret == + LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) { + ldb_asprintf_errstring(ldb, + "attribute '%s': value " + "#%u on '%s' already " + "exists", el->name, j, + ldb_dn_get_linearized(msg2->dn)); + goto done; + } else if (ret != LDB_SUCCESS) { + goto done; + } + + ret = ldb_msg_find_duplicate_val( + ldb, msg2, el, &duplicate, 0); + if (ret != LDB_SUCCESS) { + goto done; + } + if (duplicate != NULL) { + ldb_asprintf_errstring( + ldb, + "attribute '%s': value " + "'%.*s' on '%s' " + "provided more than " + "once in ADD", + el->name, + (int)duplicate->length, + duplicate->data, + ldb_dn_get_linearized(msg->dn)); + ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + goto done; + } + } + + /* Now combine existing and new values to a new + attribute record */ + vals = talloc_realloc(msg2->elements, + el2->values, struct ldb_val, + el2->num_values + el->num_values); + if (vals == NULL) { + ldb_oom(ldb); + ret = LDB_ERR_OTHER; + goto done; + } + + for (j=0; jnum_values; j++) { + vals[el2->num_values + j] = + ldb_val_dup(vals, &el->values[j]); + } + + el2->values = vals; + el2->num_values += el->num_values; + + ret = ldb_kv_index_add_element( + module, ldb_kv, msg2, el); + if (ret != LDB_SUCCESS) { + goto done; + } + } + + break; + + case LDB_FLAG_MOD_REPLACE: + + if (el->num_values > 1 && ldb_kv_single_valued(a, el)) { + ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", + el->name, 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)) { + struct ldb_val *duplicate = NULL; + + ret = ldb_msg_find_duplicate_val(ldb, msg2, el, + &duplicate, 0); + if (ret != LDB_SUCCESS) { + goto done; + } + if (duplicate != NULL) { + ldb_asprintf_errstring( + ldb, + "attribute '%s': value '%.*s' " + "on '%s' provided more than " + "once in REPLACE", + el->name, + (int)duplicate->length, + duplicate->data, + ldb_dn_get_linearized(msg2->dn)); + ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + goto done; + } + } + + /* Checks if element already exists */ + idx = ldb_kv_find_element(msg2, el->name); + if (idx != -1) { + j = (unsigned int) idx; + el2 = &(msg2->elements[j]); + + /* we consider two elements to be + * equal only if the order + * matches. This allows dbcheck to + * fix the ordering on attributes + * where order matters, such as + * objectClass + */ + if (ldb_msg_element_equal_ordered(el, el2)) { + continue; + } + + /* Delete the attribute if it exists in the DB */ + if (ldb_kv_msg_delete_attribute( + module, ldb_kv, msg2, el->name) != 0) { + ret = LDB_ERR_OTHER; + goto done; + } + } + + /* Recreate it with the new values */ + if (ldb_kv_msg_add_element(msg2, el) != 0) { + ret = LDB_ERR_OTHER; + goto done; + } + + ret = + ldb_kv_index_add_element(module, ldb_kv, msg2, el); + if (ret != LDB_SUCCESS) { + goto done; + } + + break; + + case LDB_FLAG_MOD_DELETE: + dn = ldb_dn_get_linearized(msg2->dn); + if (dn == NULL) { + ret = LDB_ERR_OTHER; + goto done; + } + + if (msg->elements[i].num_values == 0) { + /* Delete the whole attribute */ + ret = ldb_kv_msg_delete_attribute( + module, + ldb_kv, + msg2, + msg->elements[i].name); + if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && + control_permissive) { + ret = LDB_SUCCESS; + } else { + ldb_asprintf_errstring(ldb, + "attribute '%s': no such attribute for delete on '%s'", + msg->elements[i].name, dn); + } + if (ret != LDB_SUCCESS) { + goto done; + } + } else { + /* Delete specified values from an attribute */ + for (j=0; j < msg->elements[i].num_values; j++) { + ret = ldb_kv_msg_delete_element( + module, + ldb_kv, + msg2, + msg->elements[i].name, + &msg->elements[i].values[j]); + if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && + control_permissive) { + ret = LDB_SUCCESS; + } else if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { + ldb_asprintf_errstring(ldb, + "attribute '%s': no matching attribute value while deleting attribute on '%s'", + msg->elements[i].name, dn); + } + if (ret != LDB_SUCCESS) { + goto done; + } + } + } + break; + default: + ldb_asprintf_errstring(ldb, + "attribute '%s': invalid modify flags on '%s': 0x%x", + msg->elements[i].name, ldb_dn_get_linearized(msg->dn), + msg->elements[i].flags & LDB_FLAG_MOD_MASK); + ret = LDB_ERR_PROTOCOL_ERROR; + goto done; + } + } + + ret = ldb_kv_store(module, msg2, TDB_MODIFY); + if (ret != LDB_SUCCESS) { + goto done; + } + + ret = ldb_kv_modified(module, msg2->dn); + if (ret != LDB_SUCCESS) { + goto done; + } + +done: + TALLOC_FREE(mem_ctx); + /* + * To allow testing of the error recovery code in ldb_kv_modify + * cmocka tests can define CMOCKA_UNIT_TEST_MODIFY_INTERNAL_FAIL + * to inject failures at this point. + */ +#ifdef CMOCKA_UNIT_TEST_MODIFY_INTERNAL_FAIL + CMOCKA_UNIT_TEST_MODIFY_INTERNAL_FAIL +#endif + return ret; +} + +/* + modify a record +*/ +static int ldb_kv_modify(struct ldb_kv_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int ret = LDB_SUCCESS; + + ret = ldb_kv_check_special_dn(module, req->op.mod.message); + if (ret != LDB_SUCCESS) { + return ret; + } + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + if (ldb_kv_cache_load(module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_sub_transaction_start(ldb_kv); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = ldb_kv_modify_internal(module, req->op.mod.message, req); + if (ret != LDB_SUCCESS) { + int r = ldb_kv_sub_transaction_cancel(ldb_kv); + if (r != LDB_SUCCESS) { + ldb_debug( + ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + __location__ + ": Unable to roll back sub transaction"); + } + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + ldb_kv->operation_failed = true; + } + return ret; + } + ret = ldb_kv_sub_transaction_commit(ldb_kv); + + + return ret; +} + +static int ldb_kv_rename_internal(struct ldb_module *module, + struct ldb_request *req, + struct ldb_message *msg) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int ret = LDB_SUCCESS; + + /* Always delete first then add, to avoid conflicts with + * unique indexes. We rely on the transaction to make this + * atomic + */ + ret = ldb_kv_delete_internal(module, msg->dn); + if (ret != LDB_SUCCESS) { + return ret; + } + + msg->dn = ldb_dn_copy(msg, req->op.rename.newdn); + if (msg->dn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* We don't check single value as we can have more than 1 with + * deleted attributes. We could go through all elements but that's + * maybe not the most efficient way + */ + ret = ldb_kv_add_internal(module, ldb_kv, msg, false); + + /* + * To allow testing of the error recovery code in ldb_kv_rename + * cmocka tests can define CMOCKA_UNIT_TEST_RENAME_INTERNAL_FAIL + * to inject failures at this point. + */ +#ifdef CMOCKA_UNIT_TEST_RENAME_INTERNAL_FAIL + CMOCKA_UNIT_TEST_RENAME_INTERNAL_FAIL +#endif + return ret; +} + +/* + rename a record +*/ +static int ldb_kv_rename(struct ldb_kv_context *ctx) +{ + struct ldb_module *module = ctx->module; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_request *req = ctx->req; + struct ldb_message *msg; + int ret = LDB_SUCCESS; + struct ldb_val key, key_old; + struct ldb_dn *db_dn; + bool valid_dn = false; + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + if (ldb_kv_cache_load(ctx->module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + msg = ldb_msg_new(ctx); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Check the new DN is reasonable */ + valid_dn = ldb_dn_validate(req->op.rename.newdn); + if (valid_dn == false) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Invalid New DN: %s", + ldb_dn_get_linearized(req->op.rename.newdn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + + /* we need to fetch the old record to re-add under the new name */ + ret = ldb_kv_search_dn1(module, req->op.rename.olddn, msg, 0); + if (ret == LDB_ERR_INVALID_DN_SYNTAX) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Invalid Old DN: %s", + ldb_dn_get_linearized(req->op.rename.newdn)); + return ret; + } else if (ret != LDB_SUCCESS) { + /* not finding the old record is an error */ + return ret; + } + + /* We need to, before changing the DB, check if the new DN + * exists, so we can return this error to the caller with an + * unmodified DB + * + * Even in GUID index mode we use ltdb_key_dn() as we are + * trying to figure out if this is just a case rename + */ + key = ldb_kv_key_dn(msg, req->op.rename.newdn); + if (!key.data) { + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + key_old = ldb_kv_key_dn(msg, req->op.rename.olddn); + if (!key_old.data) { + talloc_free(msg); + talloc_free(key.data); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * Only declare a conflict if the new DN already exists, + * and it isn't a case change on the old DN + */ + if (key_old.length != key.length + || memcmp(key.data, key_old.data, key.length) != 0) { + ret = ldb_kv_search_base( + module, msg, req->op.rename.newdn, &db_dn); + if (ret == LDB_SUCCESS) { + ret = LDB_ERR_ENTRY_ALREADY_EXISTS; + } else if (ret == LDB_ERR_NO_SUCH_OBJECT) { + ret = LDB_SUCCESS; + } + } + + /* finding the new record already in the DB is an error */ + + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Entry %s already exists", + ldb_dn_get_linearized(req->op.rename.newdn)); + } + if (ret != LDB_SUCCESS) { + talloc_free(key_old.data); + talloc_free(key.data); + talloc_free(msg); + return ret; + } + + talloc_free(key_old.data); + talloc_free(key.data); + + + ret = ldb_kv_sub_transaction_start(ldb_kv); + if (ret != LDB_SUCCESS) { + talloc_free(msg); + return ret; + } + ret = ldb_kv_rename_internal(module, req, msg); + if (ret != LDB_SUCCESS) { + int r = ldb_kv_sub_transaction_cancel(ldb_kv); + if (r != LDB_SUCCESS) { + ldb_debug( + ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + __location__ + ": Unable to roll back sub transaction"); + } + talloc_free(msg); + ldb_kv->operation_failed = true; + return ret; + } + ret = ldb_kv_sub_transaction_commit(ldb_kv); + talloc_free(msg); + + return ret; +} + +static int ldb_kv_start_trans(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(ldb_kv->module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + + /* Do not take out the transaction lock on a read-only DB */ + if (ldb_kv->read_only) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + if (ldb_kv->kv_ops->begin_write(ldb_kv) != 0) { + return ldb_kv->kv_ops->error(ldb_kv); + } + + ldb_kv_index_transaction_start( + module, + ldb_kv->index_transaction_cache_size); + + ldb_kv->reindex_failed = false; + ldb_kv->operation_failed = false; + + return LDB_SUCCESS; +} + +/* + * Forward declaration to allow prepare_commit to in fact abort the + * transaction + */ +static int ldb_kv_del_trans(struct ldb_module *module); + +static int ldb_kv_prepare_commit(struct ldb_module *module) +{ + int ret; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + + if (!ldb_kv->kv_ops->transaction_active(ldb_kv)) { + ldb_set_errstring(ldb_module_get_ctx(module), + "ltdb_prepare_commit() called " + "without transaction active"); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * Check if the last re-index failed. + * + * This can happen if for example a duplicate value was marked + * unique. We must not write a partial re-index into the DB. + */ + if (ldb_kv->reindex_failed) { + /* + * We must instead abort the transaction so we get the + * old values and old index back + */ + ldb_kv_del_trans(module); + ldb_set_errstring(ldb_module_get_ctx(module), + "Failure during re-index, so " + "transaction must be aborted."); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_index_transaction_commit(module); + if (ret != LDB_SUCCESS) { + ldb_kv->kv_ops->abort_write(ldb_kv); + return ret; + } + + /* + * If GUID indexing was toggled in this transaction, we repack at + * format version 2 if GUID indexing was enabled, or version 1 if + * it was disabled. + */ + ret = ldb_kv_maybe_repack(ldb_kv); + if (ret != LDB_SUCCESS) { + ldb_kv_del_trans(module); + ldb_set_errstring(ldb_module_get_ctx(module), + "Failure during re-pack, so " + "transaction must be aborted."); + return ret; + } + + if (ldb_kv->kv_ops->prepare_write(ldb_kv) != 0) { + ret = ldb_kv->kv_ops->error(ldb_kv); + ldb_debug_set(ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + "Failure during " + "prepare_write): %s -> %s", + ldb_kv->kv_ops->errorstr(ldb_kv), + ldb_strerror(ret)); + return ret; + } + + ldb_kv->prepared_commit = true; + + return LDB_SUCCESS; +} + +static int ldb_kv_end_trans(struct ldb_module *module) +{ + int ret; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + + /* + * If in batch mode and there has been an operation failure + * rollback the transaction rather than committing it to avoid + * any possible corruption + */ + if (ldb_kv->batch_mode && ldb_kv->operation_failed) { + ret = ldb_kv_del_trans( module); + if (ret != LDB_SUCCESS) { + ldb_debug_set(ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + "An operation failed during a batch mode " + "transaction. The transaction could not" + "be rolled back, ldb_kv_del_trans " + "returned (%s, %s)", + ldb_kv->kv_ops->errorstr(ldb_kv), + ldb_strerror(ret)); + } else { + ldb_debug_set(ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + "An operation failed during a batch mode " + "transaction, the transaction was " + "rolled back"); + } + return LDB_ERR_OPERATIONS_ERROR; + } + + if (!ldb_kv->prepared_commit) { + ret = ldb_kv_prepare_commit(module); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + ldb_kv->prepared_commit = false; + + if (ldb_kv->kv_ops->finish_write(ldb_kv) != 0) { + ret = ldb_kv->kv_ops->error(ldb_kv); + ldb_asprintf_errstring( + ldb_module_get_ctx(module), + "Failure during tdb_transaction_commit(): %s -> %s", + ldb_kv->kv_ops->errorstr(ldb_kv), + ldb_strerror(ret)); + return ret; + } + + return LDB_SUCCESS; +} + +static int ldb_kv_del_trans(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + + if (ldb_kv_index_transaction_cancel(module) != 0) { + ldb_kv->kv_ops->abort_write(ldb_kv); + return ldb_kv->kv_ops->error(ldb_kv); + } + + ldb_kv->kv_ops->abort_write(ldb_kv); + return LDB_SUCCESS; +} + +/* + return sequenceNumber from @BASEINFO +*/ +static int ldb_kv_sequence_number(struct ldb_kv_context *ctx, + struct ldb_extended **ext) +{ + struct ldb_context *ldb; + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_seqnum_request *seq; + struct ldb_seqnum_result *res; + struct ldb_message *msg = NULL; + struct ldb_dn *dn; + const char *date; + int ret = LDB_SUCCESS; + + ldb = ldb_module_get_ctx(module); + + seq = talloc_get_type(req->op.extended.data, + struct ldb_seqnum_request); + if (seq == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + if (ldb_kv->kv_ops->lock_read(module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + res = talloc_zero(req, struct ldb_seqnum_result); + if (res == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + + tmp_ctx = talloc_new(req); + if (tmp_ctx == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + + dn = ldb_dn_new(tmp_ctx, ldb, LDB_KV_BASEINFO); + if (dn == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + + ret = ldb_kv_search_dn1(module, dn, msg, 0); + if (ret != LDB_SUCCESS) { + goto done; + } + + switch (seq->type) { + case LDB_SEQ_HIGHEST_SEQ: + res->seq_num = ldb_msg_find_attr_as_uint64(msg, LDB_KV_SEQUENCE_NUMBER, 0); + break; + case LDB_SEQ_NEXT: + res->seq_num = ldb_msg_find_attr_as_uint64(msg, LDB_KV_SEQUENCE_NUMBER, 0); + res->seq_num++; + break; + case LDB_SEQ_HIGHEST_TIMESTAMP: + date = ldb_msg_find_attr_as_string(msg, LDB_KV_MOD_TIMESTAMP, NULL); + if (date) { + res->seq_num = ldb_string_to_time(date); + } else { + res->seq_num = 0; + /* zero is as good as anything when we don't know */ + } + break; + } + + *ext = talloc_zero(req, struct ldb_extended); + if (*ext == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + (*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER; + (*ext)->data = talloc_steal(*ext, res); + +done: + talloc_free(tmp_ctx); + + ldb_kv->kv_ops->unlock_read(module); + return ret; +} + +static void ldb_kv_request_done(struct ldb_kv_context *ctx, int error) +{ + struct ldb_context *ldb; + struct ldb_request *req; + struct ldb_reply *ares; + + ldb = ldb_module_get_ctx(ctx->module); + req = ctx->req; + + /* if we already returned an error just return */ + if (ldb_request_get_status(req) != LDB_SUCCESS) { + return; + } + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(ldb); + req->callback(req, NULL); + return; + } + ares->type = LDB_REPLY_DONE; + ares->error = error; + + req->callback(req, ares); +} + +static void ldb_kv_timeout(_UNUSED_ struct tevent_context *ev, + _UNUSED_ struct tevent_timer *te, + _UNUSED_ struct timeval t, + void *private_data) +{ + struct ldb_kv_context *ctx; + ctx = talloc_get_type(private_data, struct ldb_kv_context); + + if (!ctx->request_terminated) { + /* request is done now */ + ldb_kv_request_done(ctx, LDB_ERR_TIME_LIMIT_EXCEEDED); + } + + if (ctx->spy) { + /* neutralize the spy */ + ctx->spy->ctx = NULL; + ctx->spy = NULL; + } + talloc_free(ctx); +} + +static void ldb_kv_request_extended_done(struct ldb_kv_context *ctx, + struct ldb_extended *ext, + int error) +{ + struct ldb_context *ldb; + struct ldb_request *req; + struct ldb_reply *ares; + + ldb = ldb_module_get_ctx(ctx->module); + req = ctx->req; + + /* if we already returned an error just return */ + if (ldb_request_get_status(req) != LDB_SUCCESS) { + return; + } + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(ldb); + req->callback(req, NULL); + return; + } + ares->type = LDB_REPLY_DONE; + ares->response = ext; + ares->error = error; + + req->callback(req, ares); +} + +static void ldb_kv_handle_extended(struct ldb_kv_context *ctx) +{ + struct ldb_extended *ext = NULL; + int ret; + + if (strcmp(ctx->req->op.extended.oid, + LDB_EXTENDED_SEQUENCE_NUMBER) == 0) { + /* get sequence number */ + ret = ldb_kv_sequence_number(ctx, &ext); + } else { + /* not recognized */ + ret = LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; + } + + ldb_kv_request_extended_done(ctx, ext, ret); +} + +static void ldb_kv_callback(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, + void *private_data) +{ + struct ldb_kv_context *ctx; + int ret; + + ctx = talloc_get_type(private_data, struct ldb_kv_context); + + if (ctx->request_terminated) { + goto done; + } + + switch (ctx->req->operation) { + case LDB_SEARCH: + ret = ldb_kv_search(ctx); + break; + case LDB_ADD: + ret = ldb_kv_add(ctx); + break; + case LDB_MODIFY: + ret = ldb_kv_modify(ctx); + break; + case LDB_DELETE: + ret = ldb_kv_delete(ctx); + break; + case LDB_RENAME: + ret = ldb_kv_rename(ctx); + break; + case LDB_EXTENDED: + ldb_kv_handle_extended(ctx); + goto done; + default: + /* no other op supported */ + ret = LDB_ERR_PROTOCOL_ERROR; + } + + if (!ctx->request_terminated) { + /* request is done now */ + ldb_kv_request_done(ctx, ret); + } + +done: + if (ctx->spy) { + /* neutralize the spy */ + ctx->spy->ctx = NULL; + ctx->spy = NULL; + } + talloc_free(ctx); +} + +static int ldb_kv_request_destructor(void *ptr) +{ + struct ldb_kv_req_spy *spy = + talloc_get_type(ptr, struct ldb_kv_req_spy); + + if (spy->ctx != NULL) { + spy->ctx->spy = NULL; + spy->ctx->request_terminated = true; + spy->ctx = NULL; + } + + return 0; +} + +static int ldb_kv_handle_request(struct ldb_module *module, + struct ldb_request *req) +{ + struct ldb_control *control_permissive; + struct ldb_context *ldb; + struct tevent_context *ev; + struct ldb_kv_context *ac; + struct tevent_timer *te; + struct timeval tv; + unsigned int i; + + ldb = ldb_module_get_ctx(module); + + control_permissive = ldb_request_get_control(req, + LDB_CONTROL_PERMISSIVE_MODIFY_OID); + + for (i = 0; req->controls && req->controls[i]; i++) { + if (req->controls[i]->critical && + req->controls[i] != control_permissive) { + ldb_asprintf_errstring(ldb, "Unsupported critical extension %s", + req->controls[i]->oid); + return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; + } + } + + if (req->starttime == 0 || req->timeout == 0) { + ldb_set_errstring(ldb, "Invalid timeout settings"); + return LDB_ERR_TIME_LIMIT_EXCEEDED; + } + + ev = ldb_handle_get_event_context(req->handle); + + ac = talloc_zero(ldb, struct ldb_kv_context); + if (ac == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->module = module; + ac->req = req; + + tv.tv_sec = 0; + tv.tv_usec = 0; + te = tevent_add_timer(ev, ac, tv, ldb_kv_callback, ac); + if (NULL == te) { + talloc_free(ac); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->timeout > 0) { + tv.tv_sec = req->starttime + req->timeout; + tv.tv_usec = 0; + ac->timeout_event = + tevent_add_timer(ev, ac, tv, ldb_kv_timeout, ac); + if (NULL == ac->timeout_event) { + talloc_free(ac); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + /* set a spy so that we do not try to use the request context + * if it is freed before ltdb_callback fires */ + ac->spy = talloc(req, struct ldb_kv_req_spy); + if (NULL == ac->spy) { + talloc_free(ac); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->spy->ctx = ac; + + talloc_set_destructor((TALLOC_CTX *)ac->spy, ldb_kv_request_destructor); + + return LDB_SUCCESS; +} + +static int ldb_kv_init_rootdse(struct ldb_module *module) +{ + /* ignore errors on this - we expect it for non-sam databases */ + ldb_mod_register_control(module, LDB_CONTROL_PERMISSIVE_MODIFY_OID); + + /* there can be no module beyond the backend, just return */ + return LDB_SUCCESS; +} + +static int ldb_kv_lock_read(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + return ldb_kv->kv_ops->lock_read(module); +} + +static int ldb_kv_unlock_read(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + return ldb_kv->kv_ops->unlock_read(module); +} + +static const struct ldb_module_ops ldb_kv_ops = { + .name = "tdb", + .init_context = ldb_kv_init_rootdse, + .search = ldb_kv_handle_request, + .add = ldb_kv_handle_request, + .modify = ldb_kv_handle_request, + .del = ldb_kv_handle_request, + .rename = ldb_kv_handle_request, + .extended = ldb_kv_handle_request, + .start_transaction = ldb_kv_start_trans, + .end_transaction = ldb_kv_end_trans, + .prepare_commit = ldb_kv_prepare_commit, + .del_transaction = ldb_kv_del_trans, + .read_lock = ldb_kv_lock_read, + .read_unlock = ldb_kv_unlock_read, +}; + +int ldb_kv_init_store(struct ldb_kv_private *ldb_kv, + const char *name, + struct ldb_context *ldb, + const char *options[], + struct ldb_module **_module) +{ + if (getenv("LDB_WARN_UNINDEXED")) { + ldb_kv->warn_unindexed = true; + } + + if (getenv("LDB_WARN_REINDEX")) { + ldb_kv->warn_reindex = true; + } + + ldb_kv->sequence_number = 0; + + ldb_kv->pid = getpid(); + + ldb_kv->pack_format_override = 0; + + ldb_kv->module = ldb_module_new(ldb, ldb, name, &ldb_kv_ops); + if (!ldb_kv->module) { + ldb_oom(ldb); + talloc_free(ldb_kv); + return LDB_ERR_OPERATIONS_ERROR; + } + ldb_module_set_private(ldb_kv->module, ldb_kv); + talloc_steal(ldb_kv->module, ldb_kv); + + if (ldb_kv_cache_load(ldb_kv->module) != 0) { + ldb_asprintf_errstring(ldb, "Unable to load ltdb cache " + "records for backend '%s'", name); + talloc_free(ldb_kv->module); + return LDB_ERR_OPERATIONS_ERROR; + } + + *_module = ldb_kv->module; + /* + * Set or override the maximum key length + * + * The ldb_mdb code will have set this to 511, but our tests + * set this even smaller (to make the tests more practical). + * + * This must only be used for the selftest as the length + * becomes encoded in the index keys. + */ + { + const char *len_str = + ldb_options_find(ldb, options, + "max_key_len_for_self_test"); + if (len_str != NULL) { + unsigned len = strtoul(len_str, NULL, 0); + ldb_kv->max_key_length = len; + } + } + + /* + * Usually the presence of GUID indexing determines the pack format + * we use but in certain circumstances such as downgrading an + * MDB-backed database, we want to override the target pack format. + * + * We set/get opaques here because in the Samba partitions module, + * 'options' are not passed correctly so sub-databases can't see + * the options they need. + */ + { + const char *pack_format_override = + ldb_options_find(ldb, options, "pack_format_override"); + if (pack_format_override != NULL) { + int ret; + ldb_kv->pack_format_override = + strtoul(pack_format_override, NULL, 0); + ret = ldb_set_opaque(ldb, + "pack_format_override", + (void *)(intptr_t)ldb_kv->pack_format_override); + if (ret != LDB_SUCCESS) { + talloc_free(ldb_kv->module); + return ldb_module_operr(ldb_kv->module); + } + } else { + /* + * NULL -> 0 is fine, otherwise we get back + * the number we needed + */ + ldb_kv->pack_format_override + = (intptr_t)ldb_get_opaque(ldb, + "pack_format_override"); + } + } + + /* + * Override full DB scans + * + * A full DB scan is expensive on a large database. This + * option is for testing to show that the full DB scan is not + * triggered. + */ + { + const char *len_str = + ldb_options_find(ldb, options, + "disable_full_db_scan_for_self_test"); + if (len_str != NULL) { + ldb_kv->disable_full_db_scan = true; + } + } + + /* + * Set the size of the transaction index cache. + * If the ldb option "transaction_index_cache_size" is set use that + * otherwise use DEFAULT_INDEX_CACHE_SIZE + */ + ldb_kv->index_transaction_cache_size = DEFAULT_INDEX_CACHE_SIZE; + { + const char *size = ldb_options_find( + ldb, + options, + "transaction_index_cache_size"); + if (size != NULL) { + size_t cache_size = 0; + errno = 0; + + cache_size = strtoul( size, NULL, 0); + if (cache_size == 0 || errno == ERANGE) { + ldb_debug( + ldb, + LDB_DEBUG_WARNING, + "Invalid transaction_index_cache_size " + "value [%s], using default(%d)\n", + size, + DEFAULT_INDEX_CACHE_SIZE); + } else { + ldb_kv->index_transaction_cache_size = + cache_size; + } + } + } + /* + * Set batch mode operation. + * This disables the nested sub transactions, and increases the + * chance of index corruption. If using this mode the transaction + * commit will be aborted if any operation fails. + */ + { + const char *batch_mode = ldb_options_find( + ldb, options, "batch_mode"); + if (batch_mode != NULL) { + ldb_kv->batch_mode = true; + } + } + + return LDB_SUCCESS; +} diff --git a/ldb-2.0.8/ldb_key_value/ldb_kv.h b/ldb-2.0.8/ldb_key_value/ldb_kv.h new file mode 100644 index 0000000..f9dffae --- /dev/null +++ b/ldb-2.0.8/ldb_key_value/ldb_kv.h @@ -0,0 +1,336 @@ +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "tdb.h" +#include "ldb_module.h" + +#ifndef __LDB_KV_H__ +#define __LDB_KV_H__ +struct ldb_kv_private; +typedef int (*ldb_kv_traverse_fn)(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val data, + void *ctx); + +struct kv_db_ops { + uint32_t options; + + int (*store)(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val data, + int flags); + int (*delete)(struct ldb_kv_private *ldb_kv, struct ldb_val key); + int (*iterate)(struct ldb_kv_private *ldb_kv, + ldb_kv_traverse_fn fn, + void *ctx); + int (*update_in_iterate)(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val key2, + struct ldb_val data, + void *ctx); + int (*fetch_and_parse)(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + int (*parser)(struct ldb_val key, + struct ldb_val data, + void *private_data), + void *ctx); + int (*iterate_range)(struct ldb_kv_private *ldb_kv, + struct ldb_val start_key, + struct ldb_val end_key, + ldb_kv_traverse_fn fn, + void *ctx); + int (*lock_read)(struct ldb_module *); + int (*unlock_read)(struct ldb_module *); + int (*begin_write)(struct ldb_kv_private *); + int (*prepare_write)(struct ldb_kv_private *); + int (*abort_write)(struct ldb_kv_private *); + int (*finish_write)(struct ldb_kv_private *); + int (*error)(struct ldb_kv_private *ldb_kv); + const char *(*errorstr)(struct ldb_kv_private *ldb_kv); + const char *(*name)(struct ldb_kv_private *ldb_kv); + bool (*has_changed)(struct ldb_kv_private *ldb_kv); + bool (*transaction_active)(struct ldb_kv_private *ldb_kv); + size_t (*get_size)(struct ldb_kv_private *ldb_kv); + int (*begin_nested_write)(struct ldb_kv_private *); + int (*finish_nested_write)(struct ldb_kv_private *); + int (*abort_nested_write)(struct ldb_kv_private *); +}; + +/* this private structure is used by the key value backends in the + ldb_context */ +struct ldb_kv_private { + const struct kv_db_ops *kv_ops; + struct ldb_module *module; + TDB_CONTEXT *tdb; + struct lmdb_private *lmdb_private; + unsigned int connect_flags; + + unsigned long long sequence_number; + uint32_t pack_format_version; + uint32_t target_pack_format_version; + uint32_t pack_format_override; + + /* the low level tdb seqnum - used to avoid loading BASEINFO when + possible */ + int tdb_seqnum; + + struct ldb_kv_cache { + struct ldb_message *indexlist; + bool one_level_indexes; + bool attribute_indexes; + const char *GUID_index_attribute; + const char *GUID_index_dn_component; + } *cache; + + + bool check_base; + bool disallow_dn_filter; + /* + * To improve the performance of batch operations we maintain a cache + * of index records, these entries get written to disk in the + * prepare_commit phase. + */ + struct ldb_kv_idxptr *idxptr; + /* + * To ensure that the indexes in idxptr are consistent we cache any + * index updates during an operation, i.e. ldb_kv_add, ldb_kv_delete ... + * Once the changes to the data record have been commited to disk + * the contents of this cache are copied to idxptr + */ + struct ldb_kv_idxptr *nested_idx_ptr; + /* + * If batch mode is set the sub transactions and index caching + * wrapping individual operations is disabled. + * This is to improve the performance of large batch operations + * i.e. domain joins. + */ + bool batch_mode; + /* + * Has an operation failed, if true and we're in batch_mode + * the transaction commit will fail. + */ + bool operation_failed; + + bool prepared_commit; + int read_lock_count; + + bool warn_unindexed; + bool warn_reindex; + + bool read_only; + + bool reindex_failed; + + const struct ldb_schema_syntax *GUID_index_syntax; + + /* + * Maximum index key length. If non zero keys longer than this length + * will be truncated for non unique indexes. Keys for unique indexes + * greater than this length will be rejected. + */ + unsigned max_key_length; + + /* + * To allow testing that ensures the DB does not fall back + * to a full scan + */ + bool disable_full_db_scan; + + /* + * The PID that opened this database so we don't work in a + * fork()ed child. + */ + pid_t pid; + + /* + * The size to be used for the index transaction cache + */ + size_t index_transaction_cache_size; +}; + +struct ldb_kv_context { + struct ldb_module *module; + struct ldb_request *req; + + bool request_terminated; + struct ldb_kv_req_spy *spy; + + /* search stuff */ + const struct ldb_parse_tree *tree; + struct ldb_dn *base; + enum ldb_scope scope; + const char * const *attrs; + struct tevent_timer *timeout_event; + + /* error handling */ + int error; +}; + +struct ldb_kv_reindex_context { + int error; + uint32_t count; +}; + +struct ldb_kv_repack_context { + int error; + uint32_t count; + bool normal_record_seen; + uint32_t old_version; +}; + + +/* special record types */ +#define LDB_KV_INDEX "@INDEX" +#define LDB_KV_INDEXLIST "@INDEXLIST" +#define LDB_KV_IDX "@IDX" +#define LDB_KV_IDXVERSION "@IDXVERSION" +#define LDB_KV_IDXATTR "@IDXATTR" +#define LDB_KV_IDXONE "@IDXONE" +#define LDB_KV_IDXDN "@IDXDN" +#define LDB_KV_IDXGUID "@IDXGUID" +#define LDB_KV_IDX_DN_GUID "@IDX_DN_GUID" + +/* + * This will be used to indicate when a new, yet to be developed + * sub-database version of the indicies are in use, to ensure we do + * not load future databases unintentionally. + */ + +#define LDB_KV_IDX_LMDB_SUBDB "@IDX_LMDB_SUBDB" + +#define LDB_KV_BASEINFO "@BASEINFO" +#define LDB_KV_OPTIONS "@OPTIONS" +#define LDB_KV_ATTRIBUTES "@ATTRIBUTES" + +/* special attribute types */ +#define LDB_KV_SEQUENCE_NUMBER "sequenceNumber" +#define LDB_KV_CHECK_BASE "checkBaseOnSearch" +#define LDB_KV_DISALLOW_DN_FILTER "disallowDNFilter" +#define LDB_KV_MOD_TIMESTAMP "whenChanged" +#define LDB_KV_OBJECTCLASS "objectClass" + +/* DB keys */ +#define LDB_KV_GUID_KEY_PREFIX "GUID=" +#define LDB_KV_GUID_SIZE 16 +#define LDB_KV_GUID_KEY_SIZE (LDB_KV_GUID_SIZE + sizeof(LDB_KV_GUID_KEY_PREFIX) - 1) + +/* LDB KV options */ +/* + * This allows pointers to be referenced after the callback to any variant of + * iterate or fetch_and_parse -- as long as an overall read lock is held. + */ +#define LDB_KV_OPTION_STABLE_READ_LOCK 0x00000001 + +/* + * The following definitions come from lib/ldb/ldb_key_value/ldb_kv_cache.c + */ + +int ldb_kv_cache_reload(struct ldb_module *module); +int ldb_kv_cache_load(struct ldb_module *module); +int ldb_kv_increase_sequence_number(struct ldb_module *module); +int ldb_kv_check_at_attributes_values(const struct ldb_val *value); + +/* + * The following definitions come from lib/ldb/ldb_key_value/ldb_kv_index.c + */ + +/* + * The default size of the in memory TDB used to cache index records + * The value chosen gives a prime modulo for the hash table and keeps the + * tdb memory overhead under 4 kB + */ +#define DEFAULT_INDEX_CACHE_SIZE 491 + +struct ldb_parse_tree; + +int ldb_kv_search_indexed(struct ldb_kv_context *ctx, uint32_t *); +int ldb_kv_index_add_new(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg); +int ldb_kv_index_delete(struct ldb_module *module, + const struct ldb_message *msg); +int ldb_kv_index_del_element(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el); +int ldb_kv_index_add_element(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el); +int ldb_kv_index_del_value(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el, + unsigned int v_idx); +int ldb_kv_reindex(struct ldb_module *module); +int ldb_kv_repack(struct ldb_module *module); +int ldb_kv_index_transaction_start( + struct ldb_module *module, + size_t cache_size); +int ldb_kv_index_transaction_commit(struct ldb_module *module); +int ldb_kv_index_transaction_cancel(struct ldb_module *module); +int ldb_kv_key_dn_from_idx(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_val *key); + +/* + * The following definitions come from lib/ldb/ldb_key_value/ldb_kv_search.c + */ +int ldb_kv_search_dn1(struct ldb_module *module, + struct ldb_dn *dn, + struct ldb_message *msg, + unsigned int unpack_flags); +int ldb_kv_search_base(struct ldb_module *module, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_dn **ret_dn); +int ldb_kv_search_key(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_val ldb_key, + struct ldb_message *msg, + unsigned int unpack_flags); +int ldb_kv_filter_attrs(struct ldb_context *ldb, + const struct ldb_message *msg, + const char *const *attrs, + struct ldb_message *filtered_msg); +int ldb_kv_search(struct ldb_kv_context *ctx); + +/* + * The following definitions come from lib/ldb/ldb_key_value/ldb_kv.c */ +/* + * Determine if this key could hold a normal record. We allow the new + * GUID index, the old DN index and a possible future ID= but not + * DN=@. + */ +bool ldb_kv_key_is_normal_record(struct ldb_val key); +struct ldb_val ldb_kv_key_dn(TALLOC_CTX *mem_ctx, + struct ldb_dn *dn); +struct ldb_val ldb_kv_key_msg(struct ldb_module *module, + TALLOC_CTX *mem_ctx, + const struct ldb_message *msg); +int ldb_kv_guid_to_key(const struct ldb_val *GUID_val, + struct ldb_val *key); +int ldb_kv_idx_to_key(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + TALLOC_CTX *mem_ctx, + const struct ldb_val *idx_val, + struct ldb_val *key); +int ldb_kv_store(struct ldb_module *module, + const struct ldb_message *msg, + int flgs); +int ldb_kv_modify_internal(struct ldb_module *module, + const struct ldb_message *msg, + struct ldb_request *req); +int ldb_kv_delete_noindex(struct ldb_module *module, + const struct ldb_message *msg); +int ldb_kv_init_store(struct ldb_kv_private *ldb_kv, + const char *name, + struct ldb_context *ldb, + const char *options[], + struct ldb_module **_module); +int ldb_kv_index_sub_transaction_start(struct ldb_kv_private *ldb_kv); +int ldb_kv_index_sub_transaction_cancel(struct ldb_kv_private *ldb_kv); +int ldb_kv_index_sub_transaction_commit(struct ldb_kv_private *ldb_kv); +#endif /* __LDB_KV_H__ */ diff --git a/ldb-2.0.8/ldb_key_value/ldb_kv_cache.c b/ldb-2.0.8/ldb_key_value/ldb_kv_cache.c new file mode 100644 index 0000000..4a3c9f2 --- /dev/null +++ b/ldb-2.0.8/ldb_key_value/ldb_kv_cache.c @@ -0,0 +1,697 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb key value cache functions + * + * Description: cache special records in a ldb/tdb + * + * Author: Andrew Tridgell + */ + +#include "ldb_kv.h" +#include "ldb_private.h" + +#define LDB_KV_FLAG_CASE_INSENSITIVE (1<<0) +#define LDB_KV_FLAG_INTEGER (1<<1) +#define LDB_KV_FLAG_UNIQUE_INDEX (1<<2) +#define LDB_KV_FLAG_ORDERED_INTEGER (1<<3) + +/* valid attribute flags */ +static const struct { + const char *name; + int value; +} ldb_kv_valid_attr_flags[] = { + { "CASE_INSENSITIVE", LDB_KV_FLAG_CASE_INSENSITIVE }, + { "INTEGER", LDB_KV_FLAG_INTEGER }, + { "ORDERED_INTEGER", LDB_KV_FLAG_ORDERED_INTEGER }, + { "HIDDEN", 0 }, + { "UNIQUE_INDEX", LDB_KV_FLAG_UNIQUE_INDEX}, + { "NONE", 0 }, + { NULL, 0 } +}; + +/* + de-register any special handlers for @ATTRIBUTES +*/ +static void ldb_kv_attributes_unload(struct ldb_module *module) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + + ldb_schema_attribute_remove_flagged(ldb, LDB_ATTR_FLAG_FROM_DB); + +} + +/* + add up the attrib flags for a @ATTRIBUTES element +*/ +static int ldb_kv_attributes_flags(struct ldb_message_element *el, unsigned *v) +{ + unsigned int i; + unsigned value = 0; + for (i=0;inum_values;i++) { + unsigned int j; + for (j = 0; ldb_kv_valid_attr_flags[j].name; j++) { + if (strcmp(ldb_kv_valid_attr_flags[j].name, + (char *)el->values[i].data) == 0) { + value |= ldb_kv_valid_attr_flags[j].value; + break; + } + } + if (ldb_kv_valid_attr_flags[j].name == NULL) { + return -1; + } + } + *v = value; + 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 ldb_kv_attributes_load(struct ldb_module *module) +{ + struct ldb_schema_attribute *attrs; + struct ldb_context *ldb; + 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); + + if (ldb->schema.attribute_handler_override) { + /* we skip loading the @ATTRIBUTES record when a module is supplying + its own attribute handling */ + return 0; + } + + attrs_msg = ldb_msg_new(module); + if (attrs_msg == NULL) { + goto failed; + } + + dn = ldb_dn_new(module, ldb, LDB_KV_ATTRIBUTES); + if (dn == NULL) goto failed; + + r = ldb_kv_search_dn1(module, + dn, + attrs_msg, + 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 || 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;inum_elements;i++) { + unsigned flags = 0, attr_flags = 0; + 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 (ldb_kv_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; + } + + if (flags & LDB_KV_FLAG_UNIQUE_INDEX) { + attr_flags = LDB_ATTR_FLAG_UNIQUE_INDEX; + } + flags &= ~LDB_KV_FLAG_UNIQUE_INDEX; + + /* These are not currently flags, each is exclusive */ + if (flags == LDB_KV_FLAG_CASE_INSENSITIVE) { + syntax = LDB_SYNTAX_DIRECTORY_STRING; + } else if (flags == LDB_KV_FLAG_INTEGER) { + syntax = LDB_SYNTAX_INTEGER; + } else if (flags == LDB_KV_FLAG_ORDERED_INTEGER) { + syntax = LDB_SYNTAX_ORDERED_INTEGER; + } else if (flags == 0) { + syntax = LDB_SYNTAX_OCTET_STRING; + } else { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "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, attrs_msg->elements[i].name); + goto failed; + } + + attr_flags |= LDB_ATTR_FLAG_ALLOCATED | LDB_ATTR_FLAG_FROM_DB; + + r = ldb_schema_attribute_fill_with_syntax(ldb, + attrs, + attrs_msg->elements[i].name, + attr_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; +} + +/* + register any index records we find for the DB +*/ +static int ldb_kv_index_load(struct ldb_module *module, + struct ldb_kv_private *ldb_kv) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_dn *indexlist_dn; + int r, lmdb_subdb_version; + + if (ldb->schema.index_handler_override) { + /* + * we skip loading the @INDEXLIST record when a module is + * supplying its own attribute handling + */ + ldb_kv->cache->attribute_indexes = true; + ldb_kv->cache->one_level_indexes = + ldb->schema.one_level_indexes; + ldb_kv->cache->GUID_index_attribute = + ldb->schema.GUID_index_attribute; + ldb_kv->cache->GUID_index_dn_component = + ldb->schema.GUID_index_dn_component; + return 0; + } + + talloc_free(ldb_kv->cache->indexlist); + + ldb_kv->cache->indexlist = ldb_msg_new(ldb_kv->cache); + if (ldb_kv->cache->indexlist == NULL) { + return -1; + } + ldb_kv->cache->one_level_indexes = false; + ldb_kv->cache->attribute_indexes = false; + + indexlist_dn = ldb_dn_new(ldb_kv, ldb, LDB_KV_INDEXLIST); + if (indexlist_dn == NULL) { + return -1; + } + + r = ldb_kv_search_dn1(module, + indexlist_dn, + ldb_kv->cache->indexlist, + LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC | + LDB_UNPACK_DATA_FLAG_NO_DN); + TALLOC_FREE(indexlist_dn); + + if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { + return -1; + } + + if (ldb_msg_find_element(ldb_kv->cache->indexlist, LDB_KV_IDXONE) != + NULL) { + ldb_kv->cache->one_level_indexes = true; + } + if (ldb_msg_find_element(ldb_kv->cache->indexlist, LDB_KV_IDXATTR) != + NULL) { + ldb_kv->cache->attribute_indexes = true; + } + ldb_kv->cache->GUID_index_attribute = ldb_msg_find_attr_as_string( + ldb_kv->cache->indexlist, LDB_KV_IDXGUID, NULL); + ldb_kv->cache->GUID_index_dn_component = ldb_msg_find_attr_as_string( + ldb_kv->cache->indexlist, LDB_KV_IDX_DN_GUID, NULL); + + lmdb_subdb_version = ldb_msg_find_attr_as_int( + ldb_kv->cache->indexlist, LDB_KV_IDX_LMDB_SUBDB, 0); + + if (lmdb_subdb_version != 0) { + ldb_set_errstring(ldb, + "FATAL: This ldb_mdb database has " + "been written in a new version of LDB " + "using a sub-database index that " + "is not understood by ldb " + LDB_VERSION); + return -1; + } + + return 0; +} + +/* + initialise the baseinfo record +*/ +static int ldb_kv_baseinfo_init(struct ldb_module *module) +{ + struct ldb_context *ldb; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_message *msg; + struct ldb_message_element el; + struct ldb_val val; + int ret; + /* the initial sequence number must be different from the one + set in ltdb_cache_free(). Thanks to Jon for pointing this + out. */ + const char *initial_sequence_number = "1"; + + ldb = ldb_module_get_ctx(module); + + ldb_kv->sequence_number = atof(initial_sequence_number); + + msg = ldb_msg_new(ldb_kv); + if (msg == NULL) { + goto failed; + } + + msg->num_elements = 1; + msg->elements = ⪙ + msg->dn = ldb_dn_new(msg, ldb, LDB_KV_BASEINFO); + if (!msg->dn) { + goto failed; + } + el.name = talloc_strdup(msg, LDB_KV_SEQUENCE_NUMBER); + if (!el.name) { + goto failed; + } + el.values = &val; + el.num_values = 1; + el.flags = 0; + val.data = (uint8_t *)talloc_strdup(msg, initial_sequence_number); + if (!val.data) { + goto failed; + } + val.length = 1; + + ret = ldb_kv_store(module, msg, TDB_INSERT); + + talloc_free(msg); + + return ret; + +failed: + talloc_free(msg); + errno = ENOMEM; + return LDB_ERR_OPERATIONS_ERROR; +} + +/* + free any cache records + */ +static void ldb_kv_cache_free(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + + ldb_kv->sequence_number = 0; + talloc_free(ldb_kv->cache); + ldb_kv->cache = NULL; +} + +/* + force a cache reload +*/ +int ldb_kv_cache_reload(struct ldb_module *module) +{ + ldb_kv_attributes_unload(module); + ldb_kv_cache_free(module); + return ldb_kv_cache_load(module); +} +static int get_pack_format_version(struct ldb_val key, + struct ldb_val data, + void *private_data) +{ + uint32_t *v = (uint32_t *) private_data; + return ldb_unpack_get_format(&data, v); +} + +/* + load the cache records +*/ +int ldb_kv_cache_load(struct ldb_module *module) +{ + struct ldb_context *ldb; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_dn *baseinfo_dn = NULL, *options_dn = NULL; + uint64_t seq; + struct ldb_message *baseinfo = NULL, *options = NULL; + const struct ldb_schema_attribute *a; + bool have_write_txn = false; + int r; + struct ldb_val key; + + ldb = ldb_module_get_ctx(module); + + /* a very fast check to avoid extra database reads */ + if (ldb_kv->cache != NULL && !ldb_kv->kv_ops->has_changed(ldb_kv)) { + return 0; + } + + if (ldb_kv->cache == NULL) { + ldb_kv->cache = talloc_zero(ldb_kv, struct ldb_kv_cache); + if (ldb_kv->cache == NULL) + goto failed; + } + + baseinfo = ldb_msg_new(ldb_kv->cache); + if (baseinfo == NULL) goto failed; + + baseinfo_dn = ldb_dn_new(baseinfo, ldb, LDB_KV_BASEINFO); + if (baseinfo_dn == NULL) goto failed; + + r = ldb_kv->kv_ops->lock_read(module); + if (r != LDB_SUCCESS) { + goto failed; + } + + key = ldb_kv_key_dn(baseinfo, baseinfo_dn); + if (!key.data) { + goto failed_and_unlock; + } + + /* Read packing format from first 4 bytes of @BASEINFO record */ + r = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, + get_pack_format_version, + &ldb_kv->pack_format_version); + + /* possibly initialise the baseinfo */ + if (r == LDB_ERR_NO_SUCH_OBJECT) { + + /* Give up the read lock, try again with a write lock */ + r = ldb_kv->kv_ops->unlock_read(module); + if (r != LDB_SUCCESS) { + goto failed; + } + + if (ldb_kv->kv_ops->begin_write(ldb_kv) != 0) { + goto failed; + } + + have_write_txn = true; + + /* + * We need to write but haven't figured out packing format yet. + * Just go with version 1 and we'll repack if we got it wrong. + */ + ldb_kv->pack_format_version = LDB_PACKING_FORMAT; + ldb_kv->target_pack_format_version = LDB_PACKING_FORMAT; + + /* error handling for ltdb_baseinfo_init() is by + looking for the record again. */ + ldb_kv_baseinfo_init(module); + + } else if (r != LDB_SUCCESS) { + goto failed_and_unlock; + } + + /* OK now we definitely have a @BASEINFO record so fetch it */ + r = ldb_kv_search_dn1(module, baseinfo_dn, baseinfo, 0); + if (r != LDB_SUCCESS) { + goto failed_and_unlock; + } + + /* Ignore the result, and update the sequence number */ + ldb_kv->kv_ops->has_changed(ldb_kv); + + /* if the current internal sequence number is the same as the one + in the database then assume the rest of the cache is OK */ + seq = ldb_msg_find_attr_as_uint64(baseinfo, LDB_KV_SEQUENCE_NUMBER, 0); + if (seq == ldb_kv->sequence_number) { + goto done; + } + ldb_kv->sequence_number = seq; + + /* Read an interpret database options */ + + options = ldb_msg_new(ldb_kv->cache); + if (options == NULL) goto failed_and_unlock; + + options_dn = ldb_dn_new(options, ldb, LDB_KV_OPTIONS); + if (options_dn == NULL) goto failed_and_unlock; + + r = ldb_kv_search_dn1(module, options_dn, options, 0); + talloc_free(options_dn); + if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { + goto failed_and_unlock; + } + + /* set flags if they do exist */ + if (r == LDB_SUCCESS) { + ldb_kv->check_base = + ldb_msg_find_attr_as_bool(options, LDB_KV_CHECK_BASE, false); + ldb_kv->disallow_dn_filter = ldb_msg_find_attr_as_bool( + options, LDB_KV_DISALLOW_DN_FILTER, false); + } else { + ldb_kv->check_base = false; + ldb_kv->disallow_dn_filter = false; + } + + /* + * 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. + */ + ldb_kv_attributes_unload(module); + + if (ldb_kv_index_load(module, ldb_kv) == -1) { + goto failed_and_unlock; + } + + /* + * NOTE WELL: This is per-ldb, not per module, so overwrites + * the handlers across all databases when used under Samba's + * partition module. + */ + if (ldb_kv_attributes_load(module) == -1) { + goto failed_and_unlock; + } + + /* + * Initialise packing version and GUID index syntax, and force the + * two to travel together, ie a GUID indexed database must use V2 + * packing format and a DN indexed database must use V1. + */ + ldb_kv->GUID_index_syntax = NULL; + if (ldb_kv->cache->GUID_index_attribute != NULL) { + ldb_kv->target_pack_format_version = LDB_PACKING_FORMAT_V2; + + /* + * Now the attributes are loaded, set the guid_index_syntax. + * This can't fail, it will return a default at worst + */ + a = ldb_schema_attribute_by_name( + ldb, ldb_kv->cache->GUID_index_attribute); + ldb_kv->GUID_index_syntax = a->syntax; + } else { + ldb_kv->target_pack_format_version = LDB_PACKING_FORMAT; + } + +done: + if (have_write_txn) { + if (ldb_kv->kv_ops->finish_write(ldb_kv) != 0) { + goto failed; + } + } else { + ldb_kv->kv_ops->unlock_read(module); + } + + talloc_free(options); + talloc_free(baseinfo); + return 0; + +failed_and_unlock: + if (have_write_txn) { + ldb_kv->kv_ops->abort_write(ldb_kv); + } else { + ldb_kv->kv_ops->unlock_read(module); + } + +failed: + talloc_free(options); + talloc_free(baseinfo); + return -1; +} + + +/* + increase the sequence number to indicate a database change +*/ +int ldb_kv_increase_sequence_number(struct ldb_module *module) +{ + struct ldb_context *ldb; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct ldb_message *msg; + struct ldb_message_element el[2]; + struct ldb_val val; + struct ldb_val val_time; + time_t t = time(NULL); + char *s = NULL; + int ret; + + ldb = ldb_module_get_ctx(module); + + msg = ldb_msg_new(ldb_kv); + if (msg == NULL) { + errno = ENOMEM; + return LDB_ERR_OPERATIONS_ERROR; + } + + s = talloc_asprintf(msg, "%llu", ldb_kv->sequence_number + 1); + if (!s) { + talloc_free(msg); + errno = ENOMEM; + return LDB_ERR_OPERATIONS_ERROR; + } + + msg->num_elements = ARRAY_SIZE(el); + msg->elements = el; + msg->dn = ldb_dn_new(msg, ldb, LDB_KV_BASEINFO); + if (msg->dn == NULL) { + talloc_free(msg); + errno = ENOMEM; + return LDB_ERR_OPERATIONS_ERROR; + } + el[0].name = talloc_strdup(msg, LDB_KV_SEQUENCE_NUMBER); + if (el[0].name == NULL) { + talloc_free(msg); + errno = ENOMEM; + return LDB_ERR_OPERATIONS_ERROR; + } + el[0].values = &val; + el[0].num_values = 1; + el[0].flags = LDB_FLAG_MOD_REPLACE; + val.data = (uint8_t *)s; + val.length = strlen(s); + + el[1].name = talloc_strdup(msg, LDB_KV_MOD_TIMESTAMP); + if (el[1].name == NULL) { + talloc_free(msg); + errno = ENOMEM; + return LDB_ERR_OPERATIONS_ERROR; + } + el[1].values = &val_time; + el[1].num_values = 1; + el[1].flags = LDB_FLAG_MOD_REPLACE; + + s = ldb_timestring(msg, t); + if (s == NULL) { + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + val_time.data = (uint8_t *)s; + val_time.length = strlen(s); + + ret = ldb_kv_modify_internal(module, msg, NULL); + + talloc_free(msg); + + if (ret == LDB_SUCCESS) { + ldb_kv->sequence_number += 1; + } + + /* updating the tdb_seqnum here avoids us reloading the cache + records due to our own modification */ + ldb_kv->kv_ops->has_changed(ldb_kv); + + return ret; +} + +int ldb_kv_check_at_attributes_values(const struct ldb_val *value) +{ + unsigned int i; + + for (i = 0; ldb_kv_valid_attr_flags[i].name != NULL; i++) { + if ((strcmp(ldb_kv_valid_attr_flags[i].name, + (char *)value->data) == 0)) { + return 0; + } + } + + return -1; +} diff --git a/ldb-2.0.8/ldb_key_value/ldb_kv_index.c b/ldb-2.0.8/ldb_key_value/ldb_kv_index.c new file mode 100644 index 0000000..0853b28 --- /dev/null +++ b/ldb-2.0.8/ldb_key_value/ldb_kv_index.c @@ -0,0 +1,3917 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004-2009 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb key value backend - indexing + * + * Description: indexing routines for ldb key value backend + * + * Author: Andrew Tridgell + */ + +/* + +LDB Index design and choice of key: +======================================= + +LDB has index records held as LDB objects with a special record like: + +dn: @INDEX:attr:value + +value may be base64 encoded, if it is deemed not printable: + +dn: @INDEX:attr::base64-value + +In each record, there is two possible formats: + +The original format is: +----------------------- + +dn: @INDEX:NAME:DNSUPDATEPROXY +@IDXVERSION: 2 +@IDX: CN=DnsUpdateProxy,CN=Users,DC=addom,DC=samba,DC=example,DC=com + +In this format, @IDX is multi-valued, one entry for each match + +The corrosponding entry is stored in a TDB record with key: + +DN=CN=DNSUPDATEPROXY,CN=USERS,DC=ADDOM,DC=SAMBA,DC=EXAMPLE,DC=COM + +(This allows a scope BASE search to directly find the record via +a simple casefold of the DN). + +The original mixed-case DN is stored in the entry iself. + + +The new 'GUID index' format is: +------------------------------- + +dn: @INDEX:NAME:DNSUPDATEPROXY +@IDXVERSION: 3 +@IDX: [[...]] + +The binary guid is 16 bytes, as bytes and not expanded as hexidecimal +or pretty-printed. The GUID is chosen from the message to be stored +by the @IDXGUID attribute on @INDEXLIST. + +If there are multiple values the @IDX value simply becomes longer, +in multiples of 16. + +The corrosponding entry is stored in a TDB record with key: + +GUID= + +This allows a very quick translation between the fixed-length index +values and the TDB key, while seperating entries from other data +in the TDB, should they be unlucky enough to start with the bytes of +the 'DN=' prefix. + +Additionally, this allows a scope BASE search to directly find the +record via a simple match on a GUID= extended DN, controlled via +@IDX_DN_GUID on @INDEXLIST + +Exception for special @ DNs: + +@BASEINFO, @INDEXLIST and all other special DNs are stored as per the +original format, as they are never referenced in an index and are used +to bootstrap the database. + + +Control points for choice of index mode +--------------------------------------- + +The choice of index and TDB key mode is made based (for example, from +Samba) on entries in the @INDEXLIST DN: + +dn: @INDEXLIST +@IDXGUID: objectGUID +@IDX_DN_GUID: GUID + +By default, the original DN format is used. + + +Control points for choosing indexed attributes +---------------------------------------------- + +@IDXATTR controls if an attribute is indexed + +dn: @INDEXLIST +@IDXATTR: samAccountName +@IDXATTR: nETBIOSName + + +C Override functions +-------------------- + +void ldb_schema_set_override_GUID_index(struct ldb_context *ldb, + const char *GUID_index_attribute, + const char *GUID_index_dn_component) + +This is used, particularly in combination with the below, instead of +the @IDXGUID and @IDX_DN_GUID values in @INDEXLIST. + +void ldb_schema_set_override_indexlist(struct ldb_context *ldb, + bool one_level_indexes); +void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb, + ldb_attribute_handler_override_fn_t override, + void *private_data); + +When the above two functions are called in combination, the @INDEXLIST +values are not read from the DB, so +ldb_schema_set_override_GUID_index() must be called. + +*/ + +#include "ldb_kv.h" +#include "../ldb_tdb/ldb_tdb.h" +#include "ldb_private.h" +#include "lib/util/binsearch.h" +#include "lib/util/attr.h" + +struct dn_list { + unsigned int count; + struct ldb_val *dn; + /* + * Do not optimise the intersection of this list, + * we must never return an entry not in this + * list. This allows the index for + * SCOPE_ONELEVEL to be trusted. + */ + bool strict; +}; + +struct ldb_kv_idxptr { + /* + * In memory tdb to cache the index updates performed during a + * transaction. This improves the performance of operations like + * re-index and join + */ + struct tdb_context *itdb; + int error; +}; + +enum key_truncation { + KEY_NOT_TRUNCATED, + KEY_TRUNCATED, +}; + +static int ldb_kv_write_index_dn_guid(struct ldb_module *module, + const struct ldb_message *msg, + int add); +static int ldb_kv_index_dn_base_dn(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + struct ldb_dn *base_dn, + struct dn_list *dn_list, + enum key_truncation *truncation); + +static void ldb_kv_dn_list_sort(struct ldb_kv_private *ldb_kv, + struct dn_list *list); + +/* we put a @IDXVERSION attribute on index entries. This + allows us to tell if it was written by an older version +*/ +#define LDB_KV_INDEXING_VERSION 2 + +#define LDB_KV_GUID_INDEXING_VERSION 3 + +static unsigned ldb_kv_max_key_length(struct ldb_kv_private *ldb_kv) +{ + if (ldb_kv->max_key_length == 0) { + return UINT_MAX; + } + return ldb_kv->max_key_length; +} + +/* enable the idxptr mode when transactions start */ +int ldb_kv_index_transaction_start( + struct ldb_module *module, + size_t cache_size) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + ldb_kv->idxptr = talloc_zero(ldb_kv, struct ldb_kv_idxptr); + if (ldb_kv->idxptr == NULL) { + return ldb_oom(ldb_module_get_ctx(module)); + } + + ldb_kv->idxptr->itdb = tdb_open( + NULL, + cache_size, + TDB_INTERNAL, + O_RDWR, + 0); + if (ldb_kv->idxptr->itdb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +/* + see if two ldb_val structures contain exactly the same data + return -1 or 1 for a mismatch, 0 for match +*/ +static int ldb_val_equal_exact_for_qsort(const struct ldb_val *v1, + const struct ldb_val *v2) +{ + if (v1->length > v2->length) { + return -1; + } + if (v1->length < v2->length) { + return 1; + } + return memcmp(v1->data, v2->data, v1->length); +} + +/* + see if two ldb_val structures contain exactly the same data + return -1 or 1 for a mismatch, 0 for match +*/ +static int ldb_val_equal_exact_ordered(const struct ldb_val v1, + const struct ldb_val *v2) +{ + if (v1.length > v2->length) { + return -1; + } + if (v1.length < v2->length) { + return 1; + } + return memcmp(v1.data, v2->data, v1.length); +} + + +/* + find a entry in a dn_list, using a ldb_val. Uses a case sensitive + binary-safe comparison for the 'dn' returns -1 if not found + + This is therefore safe when the value is a GUID in the future + */ +static int ldb_kv_dn_list_find_val(struct ldb_kv_private *ldb_kv, + const struct dn_list *list, + const struct ldb_val *v) +{ + unsigned int i; + struct ldb_val *exact = NULL, *next = NULL; + + if (ldb_kv->cache->GUID_index_attribute == NULL) { + for (i=0; icount; i++) { + if (ldb_val_equal_exact(&list->dn[i], v) == 1) { + return i; + } + } + return -1; + } + + BINARY_ARRAY_SEARCH_GTE(list->dn, list->count, + *v, ldb_val_equal_exact_ordered, + exact, next); + if (exact == NULL) { + return -1; + } + /* Not required, but keeps the compiler quiet */ + if (next != NULL) { + return -1; + } + + i = exact - list->dn; + return i; +} + +/* + find a entry in a dn_list. Uses a case sensitive comparison with the dn + returns -1 if not found + */ +static int ldb_kv_dn_list_find_msg(struct ldb_kv_private *ldb_kv, + struct dn_list *list, + const struct ldb_message *msg) +{ + struct ldb_val v; + const struct ldb_val *key_val; + if (ldb_kv->cache->GUID_index_attribute == NULL) { + const char *dn_str = ldb_dn_get_linearized(msg->dn); + v.data = discard_const_p(unsigned char, dn_str); + v.length = strlen(dn_str); + } else { + key_val = ldb_msg_find_ldb_val( + msg, ldb_kv->cache->GUID_index_attribute); + if (key_val == NULL) { + return -1; + } + v = *key_val; + } + return ldb_kv_dn_list_find_val(ldb_kv, list, &v); +} + +/* + this is effectively a cast function, but with lots of paranoia + checks and also copes with CPUs that are fussy about pointer + alignment + */ +static struct dn_list *ldb_kv_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), + "Bad data size for idxptr %u", (unsigned)rec.dsize); + return NULL; + } + /* note that we can't just use a cast here, as rec.dptr may + not be aligned sufficiently for a pointer. A cast would cause + platforms like some ARM CPUs to crash */ + 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", + talloc_get_name(list)); + return NULL; + } + return list; +} + +enum dn_list_will_be_read_only { + DN_LIST_MUTABLE = 0, + DN_LIST_WILL_BE_READ_ONLY = 1, +}; + +/* + return the @IDX list in an index entry for a dn as a + struct dn_list + */ +static int ldb_kv_dn_list_load(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + struct ldb_dn *dn, + struct dn_list *list, + enum dn_list_will_be_read_only read_only) +{ + struct ldb_message *msg; + int ret, version; + struct ldb_message_element *el; + TDB_DATA rec = {0}; + struct dn_list *list2; + bool from_primary_cache = false; + TDB_DATA key = {0}; + + list->dn = NULL; + list->count = 0; + list->strict = false; + + /* + * See if we have an in memory index cache + */ + if (ldb_kv->idxptr == NULL) { + goto normal_index; + } + + key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn)); + key.dsize = strlen((char *)key.dptr); + + /* + * Have we cached this index record? + * If we have a nested transaction cache try that first. + * then try the transaction cache. + * if the record is not cached it will need to be read from disk. + */ + if (ldb_kv->nested_idx_ptr != NULL) { + rec = tdb_fetch(ldb_kv->nested_idx_ptr->itdb, key); + } + if (rec.dptr == NULL) { + from_primary_cache = true; + rec = tdb_fetch(ldb_kv->idxptr->itdb, key); + } + if (rec.dptr == NULL) { + goto normal_index; + } + + /* we've found an in-memory index entry */ + list2 = ldb_kv_index_idxptr(module, rec); + if (list2 == NULL) { + free(rec.dptr); + return LDB_ERR_OPERATIONS_ERROR; + } + free(rec.dptr); + + /* + * If this is a read only transaction the indexes will not be + * changed so we don't need a copy in the event of a rollback + * + * In this case make an early return + */ + if (read_only == DN_LIST_WILL_BE_READ_ONLY) { + *list = *list2; + return LDB_SUCCESS; + } + + /* + * record was read from the sub transaction cache, so we have + * already copied the primary cache record + */ + if (!from_primary_cache) { + *list = *list2; + return LDB_SUCCESS; + } + + /* + * No index sub transaction active, so no need to cache a copy + */ + if (ldb_kv->nested_idx_ptr == NULL) { + *list = *list2; + return LDB_SUCCESS; + } + + /* + * There is an active index sub transaction, and the record was + * found in the primary index transaction cache. A copy of the + * record needs be taken to prevent the original entry being + * altered, until the index sub transaction is committed. + */ + + { + struct ldb_val *dns = NULL; + size_t x = 0; + + dns = talloc_array( + list, + struct ldb_val, + list2->count); + if (dns == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + for (x = 0; x < list2->count; x++) { + dns[x].length = list2->dn[x].length; + dns[x].data = talloc_memdup( + dns, + list2->dn[x].data, + list2->dn[x].length); + if (dns[x].data == NULL) { + TALLOC_FREE(dns); + return LDB_ERR_OPERATIONS_ERROR; + } + } + list->dn = dns; + list->count = list2->count; + } + return LDB_SUCCESS; + + /* + * Index record not found in the caches, read it from the + * database. + */ +normal_index: + msg = ldb_msg_new(list); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_search_dn1(module, + dn, + msg, + LDB_UNPACK_DATA_FLAG_NO_DN | + /* + * The entry point ldb_kv_search_indexed is + * only called from the read-locked + * ldb_kv_search. + */ + LDB_UNPACK_DATA_FLAG_READ_LOCKED); + if (ret != LDB_SUCCESS) { + talloc_free(msg); + return ret; + } + + el = ldb_msg_find_element(msg, LDB_KV_IDX); + if (!el) { + talloc_free(msg); + return LDB_SUCCESS; + } + + version = ldb_msg_find_attr_as_int(msg, LDB_KV_IDXVERSION, 0); + + /* + * we avoid copying the strings by stealing the list. We have + * to steal msg onto el->values (which looks odd) because + * the memory is allocated on msg, not on each value. + */ + if (ldb_kv->cache->GUID_index_attribute == NULL) { + /* check indexing version number */ + if (version != LDB_KV_INDEXING_VERSION) { + ldb_debug_set(ldb_module_get_ctx(module), + LDB_DEBUG_ERROR, + "Wrong DN index version %d " + "expected %d for %s", + version, LDB_KV_INDEXING_VERSION, + ldb_dn_get_linearized(dn)); + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + talloc_steal(el->values, msg); + list->dn = talloc_steal(list, el->values); + list->count = el->num_values; + } else { + unsigned int i; + if (version != LDB_KV_GUID_INDEXING_VERSION) { + /* This is quite likely during the DB startup + on first upgrade to using a GUID index */ + ldb_debug_set(ldb_module_get_ctx(module), + LDB_DEBUG_ERROR, + "Wrong GUID index version %d " + "expected %d for %s", + version, LDB_KV_GUID_INDEXING_VERSION, + ldb_dn_get_linearized(dn)); + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (el->num_values == 0) { + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + if ((el->values[0].length % LDB_KV_GUID_SIZE) != 0) { + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + list->count = el->values[0].length / LDB_KV_GUID_SIZE; + list->dn = talloc_array(list, struct ldb_val, list->count); + if (list->dn == NULL) { + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * The actual data is on msg. + */ + talloc_steal(list->dn, msg); + for (i = 0; i < list->count; i++) { + list->dn[i].data + = &el->values[0].data[i * LDB_KV_GUID_SIZE]; + list->dn[i].length = LDB_KV_GUID_SIZE; + } + } + + /* We don't need msg->elements any more */ + talloc_free(msg->elements); + return LDB_SUCCESS; +} + +int ldb_kv_key_dn_from_idx(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_val *ldb_key) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + int ret; + int index = 0; + enum key_truncation truncation = KEY_NOT_TRUNCATED; + struct dn_list *list = talloc(mem_ctx, struct dn_list); + if (list == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_index_dn_base_dn(module, ldb_kv, dn, list, &truncation); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(list); + return ret; + } + + if (list->count == 0) { + TALLOC_FREE(list); + return LDB_ERR_NO_SUCH_OBJECT; + } + + if (list->count > 1 && truncation == KEY_NOT_TRUNCATED) { + const char *dn_str = ldb_dn_get_linearized(dn); + ldb_asprintf_errstring(ldb_module_get_ctx(module), + __location__ + ": Failed to read DN index " + "against %s for %s: too many " + "values (%u > 1)", + ldb_kv->cache->GUID_index_attribute, + dn_str, + list->count); + TALLOC_FREE(list); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + if (list->count > 0 && truncation == KEY_TRUNCATED) { + /* + * DN key has been truncated, need to inspect the actual + * records to locate the actual DN + */ + unsigned int i; + index = -1; + for (i=0; i < list->count; i++) { + uint8_t guid_key[LDB_KV_GUID_KEY_SIZE]; + struct ldb_val key = { + .data = guid_key, + .length = sizeof(guid_key) + }; + const int flags = LDB_UNPACK_DATA_FLAG_NO_ATTRS; + struct ldb_message *rec = ldb_msg_new(ldb); + if (rec == NULL) { + TALLOC_FREE(list); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_idx_to_key( + module, ldb_kv, ldb, &list->dn[i], &key); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(list); + TALLOC_FREE(rec); + return ret; + } + + ret = + ldb_kv_search_key(module, ldb_kv, key, rec, flags); + if (key.data != guid_key) { + TALLOC_FREE(key.data); + } + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* + * the record has disappeared? + * yes, this can happen + */ + TALLOC_FREE(rec); + continue; + } + + if (ret != LDB_SUCCESS) { + /* an internal error */ + TALLOC_FREE(rec); + TALLOC_FREE(list); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * We found the actual DN that we wanted from in the + * multiple values that matched the index + * (due to truncation), so return that. + * + */ + if (ldb_dn_compare(dn, rec->dn) == 0) { + index = i; + TALLOC_FREE(rec); + break; + } + } + + /* + * We matched the index but the actual DN we wanted + * was not here. + */ + if (index == -1) { + TALLOC_FREE(list); + return LDB_ERR_NO_SUCH_OBJECT; + } + } + + /* The ldb_key memory is allocated by the caller */ + ret = ldb_kv_guid_to_key(&list->dn[index], ldb_key); + TALLOC_FREE(list); + + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + + + +/* + save a dn_list into a full @IDX style record + */ +static int ldb_kv_dn_list_store_full(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + struct ldb_dn *dn, + struct dn_list *list) +{ + struct ldb_message *msg; + int ret; + + msg = ldb_msg_new(module); + if (!msg) { + return ldb_module_oom(module); + } + + msg->dn = dn; + + if (list->count == 0) { + ret = ldb_kv_delete_noindex(module, msg); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + ret = LDB_SUCCESS; + } + TALLOC_FREE(msg); + return ret; + } + + if (ldb_kv->cache->GUID_index_attribute == NULL) { + ret = ldb_msg_add_fmt(msg, LDB_KV_IDXVERSION, "%u", + LDB_KV_INDEXING_VERSION); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(msg); + return ldb_module_oom(module); + } + } else { + ret = ldb_msg_add_fmt(msg, LDB_KV_IDXVERSION, "%u", + LDB_KV_GUID_INDEXING_VERSION); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(msg); + return ldb_module_oom(module); + } + } + + if (list->count > 0) { + struct ldb_message_element *el; + + ret = ldb_msg_add_empty(msg, LDB_KV_IDX, LDB_FLAG_MOD_ADD, &el); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(msg); + return ldb_module_oom(module); + } + + if (ldb_kv->cache->GUID_index_attribute == NULL) { + el->values = list->dn; + el->num_values = list->count; + } else { + struct ldb_val v; + unsigned int i; + el->values = talloc_array(msg, + struct ldb_val, 1); + if (el->values == NULL) { + TALLOC_FREE(msg); + return ldb_module_oom(module); + } + + v.data = talloc_array_size(el->values, + list->count, + LDB_KV_GUID_SIZE); + if (v.data == NULL) { + TALLOC_FREE(msg); + return ldb_module_oom(module); + } + + v.length = talloc_get_size(v.data); + + for (i = 0; i < list->count; i++) { + if (list->dn[i].length != + LDB_KV_GUID_SIZE) { + TALLOC_FREE(msg); + return ldb_module_operr(module); + } + memcpy(&v.data[LDB_KV_GUID_SIZE*i], + list->dn[i].data, + LDB_KV_GUID_SIZE); + } + el->values[0] = v; + el->num_values = 1; + } + } + + ret = ldb_kv_store(module, msg, TDB_REPLACE); + TALLOC_FREE(msg); + return ret; +} + +/* + save a dn_list into the database, in either @IDX or internal format + */ +static int ldb_kv_dn_list_store(struct ldb_module *module, + struct ldb_dn *dn, + struct dn_list *list) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + TDB_DATA rec = {0}; + TDB_DATA key = {0}; + + int ret = LDB_SUCCESS; + struct dn_list *list2 = NULL; + struct ldb_kv_idxptr *idxptr = NULL; + + key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn)); + if (key.dptr == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + key.dsize = strlen((char *)key.dptr); + + /* + * If there is an index sub transaction active, update the + * sub transaction index cache. Otherwise update the + * primary index cache + */ + if (ldb_kv->nested_idx_ptr != NULL) { + idxptr = ldb_kv->nested_idx_ptr; + } else { + idxptr = ldb_kv->idxptr; + } + /* + * Get the cache entry for the index + * + * As the value in the cache is a pointer to a dn_list we update + * the dn_list directly. + * + */ + rec = tdb_fetch(idxptr->itdb, key); + if (rec.dptr != NULL) { + list2 = ldb_kv_index_idxptr(module, rec); + if (list2 == NULL) { + free(rec.dptr); + return LDB_ERR_OPERATIONS_ERROR; + } + free(rec.dptr); + /* Now put the updated pointer back in the cache */ + if (list->dn == NULL) { + list2->dn = NULL; + list2->count = 0; + } else { + list2->dn = talloc_steal(list2, list->dn); + list2->count = list->count; + } + return LDB_SUCCESS; + } + + list2 = talloc(idxptr, struct dn_list); + if (list2 == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + list2->dn = talloc_steal(list2, list->dn); + list2->count = list->count; + + rec.dptr = (uint8_t *)&list2; + rec.dsize = sizeof(void *); + + + /* + * This is not a store into the main DB, but into an in-memory + * TDB, so we don't need a guard on ltdb->read_only + * + * Also as we directly update the in memory dn_list for existing + * cache entries we must be adding a new entry to the cache. + */ + ret = tdb_store(idxptr->itdb, key, rec, TDB_INSERT); + if (ret != 0) { + return ltdb_err_map( tdb_error(idxptr->itdb)); + } + return LDB_SUCCESS; +} + +/* + traverse function for storing the in-memory index entries on disk + */ +static int ldb_kv_index_traverse_store(_UNUSED_ struct tdb_context *tdb, + TDB_DATA key, + TDB_DATA data, + void *state) +{ + struct ldb_module *module = state; + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + struct ldb_dn *dn; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_val v; + struct dn_list *list; + + list = ldb_kv_index_idxptr(module, data); + if (list == NULL) { + ldb_kv->idxptr->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + + v.data = key.dptr; + v.length = strnlen((char *)key.dptr, key.dsize); + + dn = ldb_dn_from_ldb_val(module, ldb, &v); + if (dn == NULL) { + ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data); + ldb_kv->idxptr->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + + ldb_kv->idxptr->error = + ldb_kv_dn_list_store_full(module, ldb_kv, dn, list); + talloc_free(dn); + if (ldb_kv->idxptr->error != 0) { + return -1; + } + return 0; +} + +/* cleanup the idxptr mode when transaction commits */ +int ldb_kv_index_transaction_commit(struct ldb_module *module) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + int ret; + + struct ldb_context *ldb = ldb_module_get_ctx(module); + + ldb_reset_err_string(ldb); + + if (ldb_kv->idxptr->itdb) { + tdb_traverse( + ldb_kv->idxptr->itdb, ldb_kv_index_traverse_store, module); + tdb_close(ldb_kv->idxptr->itdb); + } + + ret = ldb_kv->idxptr->error; + if (ret != LDB_SUCCESS) { + if (!ldb_errstring(ldb)) { + ldb_set_errstring(ldb, ldb_strerror(ret)); + } + ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb)); + } + + talloc_free(ldb_kv->idxptr); + ldb_kv->idxptr = NULL; + return ret; +} + +/* cleanup the idxptr mode when transaction cancels */ +int ldb_kv_index_transaction_cancel(struct ldb_module *module) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + if (ldb_kv->idxptr && ldb_kv->idxptr->itdb) { + tdb_close(ldb_kv->idxptr->itdb); + } + TALLOC_FREE(ldb_kv->idxptr); + if (ldb_kv->nested_idx_ptr && ldb_kv->nested_idx_ptr->itdb) { + tdb_close(ldb_kv->nested_idx_ptr->itdb); + } + TALLOC_FREE(ldb_kv->nested_idx_ptr); + return LDB_SUCCESS; +} + + +/* + return the dn key to be used for an index + the caller is responsible for freeing +*/ +static struct ldb_dn *ldb_kv_index_key(struct ldb_context *ldb, + struct ldb_kv_private *ldb_kv, + const char *attr, + const struct ldb_val *value, + const struct ldb_schema_attribute **ap, + enum key_truncation *truncation) +{ + struct ldb_dn *ret; + struct ldb_val v; + const struct ldb_schema_attribute *a = NULL; + char *attr_folded = NULL; + const char *attr_for_dn = NULL; + int r; + bool should_b64_encode; + + unsigned int max_key_length = ldb_kv_max_key_length(ldb_kv); + size_t key_len = 0; + size_t attr_len = 0; + const size_t indx_len = sizeof(LDB_KV_INDEX) - 1; + unsigned frmt_len = 0; + const size_t additional_key_length = 4; + unsigned int num_separators = 3; /* Estimate for overflow check */ + const size_t min_data = 1; + const size_t min_key_length = additional_key_length + + indx_len + num_separators + min_data; + struct ldb_val empty; + + /* + * Accept a NULL value as a request for a key with no value. This is + * different from passing an empty value, which might be given + * significance by some canonicalise functions. + */ + bool empty_val = value == NULL; + if (empty_val) { + empty.length = 0; + empty.data = discard_const_p(unsigned char, ""); + value = ∅ + } + + if (attr[0] == '@') { + attr_for_dn = attr; + v = *value; + if (ap != NULL) { + *ap = NULL; + } + } else { + attr_folded = ldb_attr_casefold(ldb, attr); + if (!attr_folded) { + return NULL; + } + + attr_for_dn = attr_folded; + + a = ldb_schema_attribute_by_name(ldb, attr); + if (ap) { + *ap = a; + } + + if (empty_val) { + v = *value; + } else { + ldb_attr_handler_t fn; + if (a->syntax->index_format_fn && + ldb_kv->cache->GUID_index_attribute != NULL) { + fn = a->syntax->index_format_fn; + } else { + fn = a->syntax->canonicalise_fn; + } + r = fn(ldb, ldb, value, &v); + if (r != LDB_SUCCESS) { + const char *errstr = ldb_errstring(ldb); + /* 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", + attr, ldb_strerror(r), + (errstr?":":""), + (errstr?errstr:"")); + talloc_free(attr_folded); + return NULL; + } + } + } + attr_len = strlen(attr_for_dn); + + /* + * Check if there is any hope this will fit into the DB. + * Overflow here is not actually critical the code below + * checks again to make the printf and the DB does another + * check for too long keys + */ + if (max_key_length - attr_len < min_key_length) { + ldb_asprintf_errstring( + ldb, + __location__ ": max_key_length " + "is too small (%u) < (%u)", + max_key_length, + (unsigned)(min_key_length + attr_len)); + talloc_free(attr_folded); + return NULL; + } + + /* + * ltdb_key_dn() makes something 4 bytes longer, it adds a leading + * "DN=" and a trailing string terminator + */ + max_key_length -= additional_key_length; + + /* + * We do not base 64 encode a DN in a key, it has already been + * casefold and lineraized, that is good enough. That already + * avoids embedded NUL etc. + */ + if (ldb_kv->cache->GUID_index_attribute != NULL) { + if (strcmp(attr, LDB_KV_IDXDN) == 0) { + should_b64_encode = false; + } else if (strcmp(attr, LDB_KV_IDXONE) == 0) { + /* + * We can only change the behaviour for IDXONE + * when the GUID index is enabled + */ + should_b64_encode = false; + } else { + should_b64_encode + = ldb_should_b64_encode(ldb, &v); + } + } else { + should_b64_encode = ldb_should_b64_encode(ldb, &v); + } + + if (should_b64_encode) { + size_t vstr_len = 0; + char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length); + if (!vstr) { + talloc_free(attr_folded); + return NULL; + } + vstr_len = strlen(vstr); + /* + * Overflow here is not critical as we only use this + * to choose the printf truncation + */ + key_len = num_separators + indx_len + attr_len + vstr_len; + if (key_len > max_key_length) { + size_t excess = key_len - max_key_length; + frmt_len = vstr_len - excess; + *truncation = KEY_TRUNCATED; + /* + * Truncated keys are placed in a separate key space + * from the non truncated keys + * Note: the double hash "##" is not a typo and + * indicates that the following value is base64 encoded + */ + ret = ldb_dn_new_fmt(ldb, ldb, "%s#%s##%.*s", + LDB_KV_INDEX, attr_for_dn, + frmt_len, vstr); + } else { + frmt_len = vstr_len; + *truncation = KEY_NOT_TRUNCATED; + /* + * Note: the double colon "::" is not a typo and + * indicates that the following value is base64 encoded + */ + ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%.*s", + LDB_KV_INDEX, attr_for_dn, + frmt_len, vstr); + } + talloc_free(vstr); + } else { + /* Only need two seperators */ + num_separators = 2; + + /* + * Overflow here is not critical as we only use this + * to choose the printf truncation + */ + key_len = num_separators + indx_len + attr_len + (int)v.length; + if (key_len > max_key_length) { + size_t excess = key_len - max_key_length; + frmt_len = v.length - excess; + *truncation = KEY_TRUNCATED; + /* + * Truncated keys are placed in a separate key space + * from the non truncated keys + */ + ret = ldb_dn_new_fmt(ldb, ldb, "%s#%s#%.*s", + LDB_KV_INDEX, attr_for_dn, + frmt_len, (char *)v.data); + } else { + frmt_len = v.length; + *truncation = KEY_NOT_TRUNCATED; + ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", + LDB_KV_INDEX, attr_for_dn, + frmt_len, (char *)v.data); + } + } + + if (v.data != value->data && !empty_val) { + talloc_free(v.data); + } + talloc_free(attr_folded); + + return ret; +} + +/* + see if a attribute value is in the list of indexed attributes +*/ +static bool ldb_kv_is_indexed(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const char *attr) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + unsigned int i; + struct ldb_message_element *el; + + if ((ldb_kv->cache->GUID_index_attribute != NULL) && + (ldb_attr_cmp(attr, ldb_kv->cache->GUID_index_attribute) == 0)) { + /* Implicity covered, this is the index key */ + return false; + } + if (ldb->schema.index_handler_override) { + const struct ldb_schema_attribute *a + = ldb_schema_attribute_by_name(ldb, attr); + + if (a == NULL) { + return false; + } + + if (a->flags & LDB_ATTR_FLAG_INDEXED) { + return true; + } else { + return false; + } + } + + if (!ldb_kv->cache->attribute_indexes) { + return false; + } + + el = ldb_msg_find_element(ldb_kv->cache->indexlist, LDB_KV_IDXATTR); + if (el == NULL) { + return false; + } + + /* TODO: this is too expensive! At least use a binary search */ + for (i=0; inum_values; i++) { + if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) { + return true; + } + } + return false; +} + +/* + in the following logic functions, the return value is treated as + follows: + + LDB_SUCCESS: we found some matching index values + + LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches + + LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call, + we'll need a full search + */ + +/* + return a list of dn's that might match a simple indexed search (an + equality search only) + */ +static int ldb_kv_index_dn_simple(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list) +{ + struct ldb_context *ldb; + struct ldb_dn *dn; + int ret; + enum key_truncation truncation = KEY_NOT_TRUNCATED; + + ldb = ldb_module_get_ctx(module); + + list->count = 0; + list->dn = NULL; + + /* if the attribute isn't in the list of indexed attributes then + this node needs a full search */ + if (!ldb_kv_is_indexed(module, ldb_kv, tree->u.equality.attr)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* the attribute is indexed. Pull the list of DNs that match the + search criterion */ + dn = ldb_kv_index_key(ldb, + ldb_kv, + tree->u.equality.attr, + &tree->u.equality.value, + NULL, + &truncation); + /* + * We ignore truncation here and allow multi-valued matches + * as ltdb_search_indexed will filter out the wrong one in + * ltdb_index_filter() which calls ldb_match_message(). + */ + if (!dn) return LDB_ERR_OPERATIONS_ERROR; + + ret = ldb_kv_dn_list_load(module, ldb_kv, dn, list, + DN_LIST_WILL_BE_READ_ONLY); + talloc_free(dn); + return ret; +} + +static bool list_union(struct ldb_context *ldb, + struct ldb_kv_private *ldb_kv, + struct dn_list *list, + struct dn_list *list2); + +/* + return a list of dn's that might match a leaf indexed search + */ +static int ldb_kv_index_dn_leaf(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list) +{ + if (ldb_kv->disallow_dn_filter && + (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0)) { + /* in AD mode we do not support "(dn=...)" search filters */ + list->dn = NULL; + list->count = 0; + return LDB_SUCCESS; + } + if (tree->u.equality.attr[0] == '@') { + /* Do not allow a indexed search against an @ */ + list->dn = NULL; + list->count = 0; + return LDB_SUCCESS; + } + if (ldb_attr_dn(tree->u.equality.attr) == 0) { + enum key_truncation truncation = KEY_NOT_TRUNCATED; + bool valid_dn = false; + struct ldb_dn *dn + = ldb_dn_from_ldb_val(list, + ldb_module_get_ctx(module), + &tree->u.equality.value); + if (dn == NULL) { + /* If we can't parse it, no match */ + list->dn = NULL; + list->count = 0; + return LDB_SUCCESS; + } + + valid_dn = ldb_dn_validate(dn); + if (valid_dn == false) { + /* If we can't parse it, no match */ + list->dn = NULL; + list->count = 0; + return LDB_SUCCESS; + } + + /* + * Re-use the same code we use for a SCOPE_BASE + * search + * + * We can't call TALLOC_FREE(dn) as this must belong + * to list for the memory to remain valid. + */ + return ldb_kv_index_dn_base_dn( + module, ldb_kv, dn, list, &truncation); + /* + * We ignore truncation here and allow multi-valued matches + * as ltdb_search_indexed will filter out the wrong one in + * ltdb_index_filter() which calls ldb_match_message(). + */ + + } else if ((ldb_kv->cache->GUID_index_attribute != NULL) && + (ldb_attr_cmp(tree->u.equality.attr, + ldb_kv->cache->GUID_index_attribute) == 0)) { + int ret; + struct ldb_context *ldb = ldb_module_get_ctx(module); + list->dn = talloc_array(list, struct ldb_val, 1); + if (list->dn == NULL) { + ldb_module_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + /* + * We need to go via the canonicalise_fn() to + * ensure we get the index in binary, rather + * than a string + */ + ret = ldb_kv->GUID_index_syntax->canonicalise_fn( + ldb, list->dn, &tree->u.equality.value, &list->dn[0]); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + list->count = 1; + return LDB_SUCCESS; + } + + return ldb_kv_index_dn_simple(module, ldb_kv, tree, list); +} + + +/* + list intersection + list = list & list2 +*/ +static bool list_intersect(struct ldb_kv_private *ldb_kv, + struct dn_list *list, + const struct dn_list *list2) +{ + const struct dn_list *short_list, *long_list; + struct dn_list *list3; + unsigned int i; + + if (list->count == 0) { + /* 0 & X == 0 */ + return true; + } + if (list2->count == 0) { + /* X & 0 == 0 */ + list->count = 0; + list->dn = NULL; + return true; + } + + /* + * In both of the below we check for strict and in that + * case do not optimise the intersection of this list, + * we must never return an entry not in this + * list. This allows the index for + * SCOPE_ONELEVEL to be trusted. + */ + + /* the indexing code is allowed to return a longer list than + what really matches, as all results are filtered by the + full expression at the end - this shortcut avoids a lot of + work in some cases */ + if (list->count < 2 && list2->count > 10 && list2->strict == false) { + return true; + } + if (list2->count < 2 && list->count > 10 && list->strict == false) { + list->count = list2->count; + list->dn = list2->dn; + /* note that list2 may not be the parent of list2->dn, + as list2->dn may be owned by ltdb->idxptr. In that + case we expect this reparent call to fail, which is + OK */ + talloc_reparent(list2, list, list2->dn); + return true; + } + + if (list->count > list2->count) { + short_list = list2; + long_list = list; + } else { + short_list = list; + long_list = list2; + } + + list3 = talloc_zero(list, struct dn_list); + if (list3 == NULL) { + return false; + } + + list3->dn = talloc_array(list3, struct ldb_val, + MIN(list->count, list2->count)); + if (!list3->dn) { + talloc_free(list3); + return false; + } + list3->count = 0; + + for (i=0;icount;i++) { + /* For the GUID index case, this is a binary search */ + if (ldb_kv_dn_list_find_val( + ldb_kv, long_list, &short_list->dn[i]) != -1) { + list3->dn[list3->count] = short_list->dn[i]; + list3->count++; + } + } + + list->strict |= list2->strict; + list->dn = talloc_steal(list, list3->dn); + list->count = list3->count; + talloc_free(list3); + + return true; +} + + +/* + list union + list = list | list2 +*/ +static bool list_union(struct ldb_context *ldb, + struct ldb_kv_private *ldb_kv, + struct dn_list *list, + struct dn_list *list2) +{ + struct ldb_val *dn3; + unsigned int i = 0, j = 0, k = 0; + + if (list2->count == 0) { + /* X | 0 == X */ + return true; + } + + if (list->count == 0) { + /* 0 | X == X */ + list->count = list2->count; + list->dn = list2->dn; + /* note that list2 may not be the parent of list2->dn, + as list2->dn may be owned by ltdb->idxptr. In that + case we expect this reparent call to fail, which is + OK */ + talloc_reparent(list2, list, list2->dn); + return true; + } + + /* + * Sort the lists (if not in GUID DN mode) so we can do + * the de-duplication during the merge + * + * NOTE: This can sort the in-memory index values, as list or + * list2 might not be a copy! + */ + ldb_kv_dn_list_sort(ldb_kv, list); + ldb_kv_dn_list_sort(ldb_kv, list2); + + dn3 = talloc_array(list, struct ldb_val, list->count + list2->count); + if (!dn3) { + ldb_oom(ldb); + return false; + } + + while (i < list->count || j < list2->count) { + int cmp; + if (i >= list->count) { + cmp = 1; + } else if (j >= list2->count) { + cmp = -1; + } else { + cmp = ldb_val_equal_exact_ordered(list->dn[i], + &list2->dn[j]); + } + + if (cmp < 0) { + /* Take list */ + dn3[k] = list->dn[i]; + i++; + k++; + } else if (cmp > 0) { + /* Take list2 */ + dn3[k] = list2->dn[j]; + j++; + k++; + } else { + /* Equal, take list */ + dn3[k] = list->dn[i]; + i++; + j++; + k++; + } + } + + list->dn = dn3; + list->count = k; + + return true; +} + +static int ldb_kv_index_dn(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list); + +/* + process an OR list (a union) + */ +static int ldb_kv_index_dn_or(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list) +{ + struct ldb_context *ldb; + unsigned int i; + + ldb = ldb_module_get_ctx(module); + + list->dn = NULL; + list->count = 0; + + for (i=0; iu.list.num_elements; i++) { + struct dn_list *list2; + int ret; + + list2 = talloc_zero(list, struct dn_list); + if (list2 == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_index_dn( + module, ldb_kv, tree->u.list.elements[i], list2); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* X || 0 == X */ + talloc_free(list2); + continue; + } + + if (ret != LDB_SUCCESS) { + /* X || * == * */ + talloc_free(list2); + return ret; + } + + if (!list_union(ldb, ldb_kv, list, list2)) { + talloc_free(list2); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + if (list->count == 0) { + return LDB_ERR_NO_SUCH_OBJECT; + } + + return LDB_SUCCESS; +} + + +/* + NOT an index results + */ +static int ldb_kv_index_dn_not(_UNUSED_ struct ldb_module *module, + _UNUSED_ struct ldb_kv_private *ldb_kv, + _UNUSED_ const struct ldb_parse_tree *tree, + _UNUSED_ struct dn_list *list) +{ + /* the only way to do an indexed not would be if we could + negate the not via another not or if we knew the total + number of database elements so we could know that the + existing expression covered the whole database. + + instead, we just give up, and rely on a full index scan + (unless an outer & manages to reduce the list) + */ + return LDB_ERR_OPERATIONS_ERROR; +} + +/* + * These things are unique, so avoid a full scan if this is a search + * by GUID, DN or a unique attribute + */ +static bool ldb_kv_index_unique(struct ldb_context *ldb, + struct ldb_kv_private *ldb_kv, + const char *attr) +{ + const struct ldb_schema_attribute *a; + if (ldb_kv->cache->GUID_index_attribute != NULL) { + if (ldb_attr_cmp(attr, ldb_kv->cache->GUID_index_attribute) == + 0) { + return true; + } + } + if (ldb_attr_dn(attr) == 0) { + return true; + } + + a = ldb_schema_attribute_by_name(ldb, attr); + if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) { + return true; + } + return false; +} + +/* + process an AND expression (intersection) + */ +static int ldb_kv_index_dn_and(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list) +{ + struct ldb_context *ldb; + unsigned int i; + bool found; + + ldb = ldb_module_get_ctx(module); + + list->dn = NULL; + list->count = 0; + + /* in the first pass we only look for unique simple + equality tests, in the hope of avoiding having to look + at any others */ + for (i=0; iu.list.num_elements; i++) { + const struct ldb_parse_tree *subtree = tree->u.list.elements[i]; + int ret; + + if (subtree->operation != LDB_OP_EQUALITY || + !ldb_kv_index_unique( + ldb, ldb_kv, subtree->u.equality.attr)) { + continue; + } + + ret = ldb_kv_index_dn(module, ldb_kv, subtree, list); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* 0 && X == 0 */ + return LDB_ERR_NO_SUCH_OBJECT; + } + if (ret == LDB_SUCCESS) { + /* a unique index match means we can + * stop. Note that we don't care if we return + * a few too many objects, due to later + * filtering */ + return LDB_SUCCESS; + } + } + + /* now do a full intersection */ + found = false; + + for (i=0; iu.list.num_elements; i++) { + const struct ldb_parse_tree *subtree = tree->u.list.elements[i]; + struct dn_list *list2; + int ret; + + list2 = talloc_zero(list, struct dn_list); + if (list2 == NULL) { + return ldb_module_oom(module); + } + + ret = ldb_kv_index_dn(module, ldb_kv, subtree, list2); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* X && 0 == 0 */ + list->dn = NULL; + list->count = 0; + talloc_free(list2); + return LDB_ERR_NO_SUCH_OBJECT; + } + + if (ret != LDB_SUCCESS) { + /* this didn't adding anything */ + talloc_free(list2); + continue; + } + + if (!found) { + talloc_reparent(list2, list, list->dn); + list->dn = list2->dn; + list->count = list2->count; + found = true; + } else if (!list_intersect(ldb_kv, list, list2)) { + 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 */ + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +struct ldb_kv_ordered_index_context { + struct ldb_module *module; + int error; + struct dn_list *dn_list; +}; + +static int traverse_range_index(_UNUSED_ struct ldb_kv_private *ldb_kv, + _UNUSED_ struct ldb_val key, + struct ldb_val data, + void *state) +{ + + struct ldb_context *ldb; + struct ldb_kv_ordered_index_context *ctx = + (struct ldb_kv_ordered_index_context *)state; + struct ldb_module *module = ctx->module; + struct ldb_message_element *el = NULL; + struct ldb_message *msg = NULL; + int version; + size_t dn_array_size, additional_length; + unsigned int i; + + ldb = ldb_module_get_ctx(module); + + msg = ldb_msg_new(module); + + ctx->error = ldb_unpack_data_flags(ldb, &data, msg, + LDB_UNPACK_DATA_FLAG_NO_DN); + + if (ctx->error != LDB_SUCCESS) { + talloc_free(msg); + return ctx->error; + } + + el = ldb_msg_find_element(msg, LDB_KV_IDX); + if (!el) { + talloc_free(msg); + return LDB_SUCCESS; + } + + version = ldb_msg_find_attr_as_int(msg, LDB_KV_IDXVERSION, 0); + + /* + * we avoid copying the strings by stealing the list. We have + * to steal msg onto el->values (which looks odd) because + * the memory is allocated on msg, not on each value. + */ + if (version != LDB_KV_GUID_INDEXING_VERSION) { + /* This is quite likely during the DB startup + on first upgrade to using a GUID index */ + ldb_debug_set(ldb_module_get_ctx(module), + LDB_DEBUG_ERROR, __location__ + ": Wrong GUID index version %d expected %d", + version, LDB_KV_GUID_INDEXING_VERSION); + talloc_free(msg); + ctx->error = LDB_ERR_OPERATIONS_ERROR; + return ctx->error; + } + + if (el->num_values == 0) { + talloc_free(msg); + ctx->error = LDB_ERR_OPERATIONS_ERROR; + return ctx->error; + } + + if ((el->values[0].length % LDB_KV_GUID_SIZE) != 0 + || el->values[0].length == 0) { + talloc_free(msg); + ctx->error = LDB_ERR_OPERATIONS_ERROR; + return ctx->error; + } + + dn_array_size = talloc_array_length(ctx->dn_list->dn); + + additional_length = el->values[0].length / LDB_KV_GUID_SIZE; + + if (ctx->dn_list->count + additional_length < ctx->dn_list->count) { + talloc_free(msg); + ctx->error = LDB_ERR_OPERATIONS_ERROR; + return ctx->error; + } + + if ((ctx->dn_list->count + additional_length) >= dn_array_size) { + size_t new_array_length; + + if (dn_array_size * 2 < dn_array_size) { + talloc_free(msg); + ctx->error = LDB_ERR_OPERATIONS_ERROR; + return ctx->error; + } + + new_array_length = MAX(ctx->dn_list->count + additional_length, + dn_array_size * 2); + + ctx->dn_list->dn = talloc_realloc(ctx->dn_list, + ctx->dn_list->dn, + struct ldb_val, + new_array_length); + } + + if (ctx->dn_list->dn == NULL) { + talloc_free(msg); + ctx->error = LDB_ERR_OPERATIONS_ERROR; + return ctx->error; + } + + /* + * The actual data is on msg. + */ + talloc_steal(ctx->dn_list->dn, msg); + for (i = 0; i < additional_length; i++) { + ctx->dn_list->dn[i + ctx->dn_list->count].data + = &el->values[0].data[i * LDB_KV_GUID_SIZE]; + ctx->dn_list->dn[i + ctx->dn_list->count].length = LDB_KV_GUID_SIZE; + + } + + ctx->dn_list->count += additional_length; + + talloc_free(msg->elements); + + return LDB_SUCCESS; +} + +/* + * >= and <= indexing implemented using lexicographically sorted keys + * + * We only run this in GUID indexing mode and when there is no write + * transaction (only implicit read locks are being held). Otherwise, we would + * have to deal with the in-memory index cache. + * + * We rely on the implementation of index_format_fn on a schema syntax which + * will can help us to construct keys which can be ordered correctly, and we + * terminate using schema agnostic start and end keys. + * + * index_format_fn must output values which can be memcmp-able to produce the + * correct ordering as defined by the schema syntax class. + */ +static int ldb_kv_index_dn_ordered(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list, bool ascending) +{ + enum key_truncation truncation = KEY_NOT_TRUNCATED; + struct ldb_context *ldb = ldb_module_get_ctx(module); + + struct ldb_val ldb_key = { 0 }, ldb_key2 = { 0 }; + struct ldb_val start_key, end_key; + struct ldb_dn *key_dn = NULL; + const struct ldb_schema_attribute *a = NULL; + + struct ldb_kv_ordered_index_context ctx; + int ret; + + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + + if (!ldb_kv_is_indexed(module, ldb_kv, tree->u.comparison.attr)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ldb_kv->cache->GUID_index_attribute == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* bail out if we're in a transaction, full search instead. */ + if (ldb_kv->kv_ops->transaction_active(ldb_kv)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ldb_kv->disallow_dn_filter && + (ldb_attr_cmp(tree->u.comparison.attr, "dn") == 0)) { + /* in AD mode we do not support "(dn=...)" search filters */ + list->dn = NULL; + list->count = 0; + return LDB_SUCCESS; + } + if (tree->u.comparison.attr[0] == '@') { + /* Do not allow a indexed search against an @ */ + list->dn = NULL; + list->count = 0; + return LDB_SUCCESS; + } + + a = ldb_schema_attribute_by_name(ldb, tree->u.comparison.attr); + + /* + * If there's no index format function defined for this attr, then + * the lexicographic order in the database doesn't correspond to the + * attr's ordering, so we can't use the iterate_range op. + */ + if (a->syntax->index_format_fn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + key_dn = ldb_kv_index_key(ldb, ldb_kv, tree->u.comparison.attr, + &tree->u.comparison.value, + NULL, &truncation); + if (!key_dn) { + return LDB_ERR_OPERATIONS_ERROR; + } else if (truncation == KEY_TRUNCATED) { + ldb_debug(ldb, LDB_DEBUG_WARNING, + __location__ + ": ordered index violation: key dn truncated: %s\n", + ldb_dn_get_linearized(key_dn)); + return LDB_ERR_OPERATIONS_ERROR; + } + ldb_key = ldb_kv_key_dn(tmp_ctx, key_dn); + talloc_free(key_dn); + if (ldb_key.data == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + key_dn = ldb_kv_index_key(ldb, ldb_kv, tree->u.comparison.attr, + NULL, NULL, &truncation); + if (!key_dn) { + return LDB_ERR_OPERATIONS_ERROR; + } else if (truncation == KEY_TRUNCATED) { + ldb_debug(ldb, LDB_DEBUG_WARNING, + __location__ + ": ordered index violation: key dn truncated: %s\n", + ldb_dn_get_linearized(key_dn)); + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_key2 = ldb_kv_key_dn(tmp_ctx, key_dn); + talloc_free(key_dn); + if (ldb_key2.data == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * In order to avoid defining a start and end key for the search, we + * notice that each index key is of the form: + * + * DN=@INDEX::\0. + * + * We can simply make our start key DN=@INDEX:: and our end + * key DN=@INDEX:; to return all index entries for a + * particular attribute. + * + * Our LMDB backend uses the default memcmp for key comparison. + */ + + /* Eliminate NUL byte at the end of the empty key */ + ldb_key2.length--; + + if (ascending) { + /* : becomes ; for pseudo end-key */ + ldb_key2.data[ldb_key2.length-1]++; + start_key = ldb_key; + end_key = ldb_key2; + } else { + start_key = ldb_key2; + end_key = ldb_key; + } + + ctx.module = module; + ctx.error = 0; + ctx.dn_list = list; + ctx.dn_list->count = 0; + ctx.dn_list->dn = talloc_zero_array(ctx.dn_list, struct ldb_val, 2); + + ret = ldb_kv->kv_ops->iterate_range(ldb_kv, start_key, end_key, + traverse_range_index, &ctx); + + if (ret != LDB_SUCCESS || ctx.error != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + TYPESAFE_QSORT(ctx.dn_list->dn, ctx.dn_list->count, + ldb_val_equal_exact_for_qsort); + + talloc_free(tmp_ctx); + + return LDB_SUCCESS; +} + +static int ldb_kv_index_dn_greater(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list) +{ + return ldb_kv_index_dn_ordered(module, + ldb_kv, + tree, + list, true); +} + +static int ldb_kv_index_dn_less(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list) +{ + return ldb_kv_index_dn_ordered(module, + ldb_kv, + tree, + list, false); +} + +/* + return a list of matching objects using a one-level index + */ +static int ldb_kv_index_dn_attr(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const char *attr, + struct ldb_dn *dn, + struct dn_list *list, + enum key_truncation *truncation) +{ + struct ldb_context *ldb; + struct ldb_dn *key; + struct ldb_val val; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* work out the index key from the parent DN */ + val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(dn)); + if (val.data == NULL) { + const char *dn_str = ldb_dn_get_linearized(dn); + ldb_asprintf_errstring(ldb_module_get_ctx(module), + __location__ + ": Failed to get casefold DN " + "from: %s", + dn_str); + return LDB_ERR_OPERATIONS_ERROR; + } + val.length = strlen((char *)val.data); + key = ldb_kv_index_key(ldb, ldb_kv, attr, &val, NULL, truncation); + if (!key) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_dn_list_load(module, ldb_kv, key, list, + DN_LIST_WILL_BE_READ_ONLY); + talloc_free(key); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (list->count == 0) { + return LDB_ERR_NO_SUCH_OBJECT; + } + + return LDB_SUCCESS; +} + +/* + return a list of matching objects using a one-level index + */ +static int ldb_kv_index_dn_one(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + struct ldb_dn *parent_dn, + struct dn_list *list, + enum key_truncation *truncation) +{ + /* + * Ensure we do not shortcut on intersection for this list. + * We must never be lazy and return an entry not in this + * list. This allows the index for + * SCOPE_ONELEVEL to be trusted. + */ + + list->strict = true; + return ldb_kv_index_dn_attr( + module, ldb_kv, LDB_KV_IDXONE, parent_dn, list, truncation); +} + +/* + return a list of matching objects using the DN index + */ +static int ldb_kv_index_dn_base_dn(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + struct ldb_dn *base_dn, + struct dn_list *dn_list, + enum key_truncation *truncation) +{ + const struct ldb_val *guid_val = NULL; + if (ldb_kv->cache->GUID_index_attribute == NULL) { + dn_list->dn = talloc_array(dn_list, struct ldb_val, 1); + if (dn_list->dn == NULL) { + return ldb_module_oom(module); + } + dn_list->dn[0].data = discard_const_p(unsigned char, + ldb_dn_get_linearized(base_dn)); + if (dn_list->dn[0].data == NULL) { + talloc_free(dn_list->dn); + return ldb_module_oom(module); + } + dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data); + dn_list->count = 1; + + return LDB_SUCCESS; + } + + if (ldb_kv->cache->GUID_index_dn_component != NULL) { + guid_val = ldb_dn_get_extended_component( + base_dn, ldb_kv->cache->GUID_index_dn_component); + } + + if (guid_val != NULL) { + dn_list->dn = talloc_array(dn_list, struct ldb_val, 1); + if (dn_list->dn == NULL) { + return ldb_module_oom(module); + } + dn_list->dn[0].data = guid_val->data; + dn_list->dn[0].length = guid_val->length; + dn_list->count = 1; + + return LDB_SUCCESS; + } + + return ldb_kv_index_dn_attr( + module, ldb_kv, LDB_KV_IDXDN, base_dn, dn_list, truncation); +} + +/* + return a list of dn's that might match a indexed search or + an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches + */ +static int ldb_kv_index_dn(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_parse_tree *tree, + struct dn_list *list) +{ + int ret = LDB_ERR_OPERATIONS_ERROR; + + switch (tree->operation) { + case LDB_OP_AND: + ret = ldb_kv_index_dn_and(module, ldb_kv, tree, list); + break; + + case LDB_OP_OR: + ret = ldb_kv_index_dn_or(module, ldb_kv, tree, list); + break; + + case LDB_OP_NOT: + ret = ldb_kv_index_dn_not(module, ldb_kv, tree, list); + break; + + case LDB_OP_EQUALITY: + ret = ldb_kv_index_dn_leaf(module, ldb_kv, tree, list); + break; + + case LDB_OP_GREATER: + ret = ldb_kv_index_dn_greater(module, ldb_kv, tree, list); + break; + + case LDB_OP_LESS: + ret = ldb_kv_index_dn_less(module, ldb_kv, tree, list); + break; + + case LDB_OP_SUBSTRING: + case LDB_OP_PRESENT: + case LDB_OP_APPROX: + case LDB_OP_EXTENDED: + /* we can't index with fancy bitops yet */ + ret = LDB_ERR_OPERATIONS_ERROR; + break; + } + + return ret; +} + +/* + filter a candidate dn_list from an indexed search into a set of results + extracting just the given attributes +*/ +static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv, + const struct dn_list *dn_list, + struct ldb_kv_context *ac, + uint32_t *match_count, + enum key_truncation scope_one_truncation) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + struct ldb_message *msg; + struct ldb_message *filtered_msg; + unsigned int i; + unsigned int num_keys = 0; + uint8_t previous_guid_key[LDB_KV_GUID_KEY_SIZE] = {}; + struct ldb_val *keys = NULL; + + /* + * We have to allocate the key list (rather than just walk the + * caller supplied list) as the callback could change the list + * (by modifying an indexed attribute hosted in the in-memory + * index cache!) + */ + keys = talloc_array(ac, struct ldb_val, dn_list->count); + if (keys == NULL) { + return ldb_module_oom(ac->module); + } + + if (ldb_kv->cache->GUID_index_attribute != NULL) { + /* + * We speculate that the keys will be GUID based and so + * pre-fill in enough space for a GUID (avoiding a pile of + * small allocations) + */ + struct guid_tdb_key { + uint8_t guid_key[LDB_KV_GUID_KEY_SIZE]; + } *key_values = NULL; + + key_values = talloc_array(keys, + struct guid_tdb_key, + dn_list->count); + + if (key_values == NULL) { + talloc_free(keys); + return ldb_module_oom(ac->module); + } + for (i = 0; i < dn_list->count; i++) { + keys[i].data = key_values[i].guid_key; + keys[i].length = sizeof(key_values[i].guid_key); + } + } else { + for (i = 0; i < dn_list->count; i++) { + keys[i].data = NULL; + keys[i].length = 0; + } + } + + for (i = 0; i < dn_list->count; i++) { + int ret; + + ret = ldb_kv_idx_to_key( + ac->module, ldb_kv, keys, &dn_list->dn[i], &keys[num_keys]); + if (ret != LDB_SUCCESS) { + talloc_free(keys); + return ret; + } + + if (ldb_kv->cache->GUID_index_attribute != NULL) { + /* + * If we are in GUID index mode, then the dn_list is + * sorted. If we got a duplicate, forget about it, as + * otherwise we would send the same entry back more + * than once. + * + * This is needed in the truncated DN case, or if a + * duplicate was forced in via + * LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK + */ + + if (memcmp(previous_guid_key, + keys[num_keys].data, + sizeof(previous_guid_key)) == 0) { + continue; + } + + memcpy(previous_guid_key, + keys[num_keys].data, + sizeof(previous_guid_key)); + } + num_keys++; + } + + + /* + * Now that the list is a safe copy, send the callbacks + */ + for (i = 0; i < num_keys; i++) { + int ret; + bool matched; + msg = ldb_msg_new(ac); + if (!msg) { + talloc_free(keys); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = + ldb_kv_search_key(ac->module, + ldb_kv, + keys[i], + msg, + LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC | + /* + * The entry point ldb_kv_search_indexed is + * only called from the read-locked + * ldb_kv_search. + */ + LDB_UNPACK_DATA_FLAG_READ_LOCKED); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* + * the record has disappeared? yes, this can + * happen if the entry is deleted by something + * operating in the callback (not another + * process, as we have a read lock) + */ + talloc_free(msg); + continue; + } + + if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { + /* an internal error */ + talloc_free(keys); + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * We trust the index for LDB_SCOPE_ONELEVEL + * unless the index key has been truncated. + * + * LDB_SCOPE_BASE is not passed in by our only caller. + */ + if (ac->scope == LDB_SCOPE_ONELEVEL && + ldb_kv->cache->one_level_indexes && + scope_one_truncation == KEY_NOT_TRUNCATED) { + ret = ldb_match_message(ldb, msg, ac->tree, + ac->scope, &matched); + } else { + ret = ldb_match_msg_error(ldb, msg, + ac->tree, ac->base, + ac->scope, &matched); + } + + if (ret != LDB_SUCCESS) { + talloc_free(keys); + talloc_free(msg); + return ret; + } + if (!matched) { + talloc_free(msg); + continue; + } + + filtered_msg = ldb_msg_new(ac); + if (filtered_msg == NULL) { + TALLOC_FREE(keys); + TALLOC_FREE(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + filtered_msg->dn = talloc_steal(filtered_msg, msg->dn); + + /* filter the attributes that the user wants */ + ret = ldb_kv_filter_attrs(ldb, msg, ac->attrs, filtered_msg); + + talloc_free(msg); + + if (ret == -1) { + TALLOC_FREE(filtered_msg); + talloc_free(keys); + return LDB_ERR_OPERATIONS_ERROR; + } + + 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 + * not be talloc_free()'ed */ + ac->request_terminated = true; + talloc_free(keys); + return ret; + } + + (*match_count)++; + } + + TALLOC_FREE(keys); + return LDB_SUCCESS; +} + +/* + sort a DN list + */ +static void ldb_kv_dn_list_sort(struct ldb_kv_private *ltdb, + struct dn_list *list) +{ + if (list->count < 2) { + return; + } + + /* We know the list is sorted when using the GUID index */ + if (ltdb->cache->GUID_index_attribute != NULL) { + return; + } + + TYPESAFE_QSORT(list->dn, list->count, + ldb_val_equal_exact_for_qsort); +} + +/* + search the database with a LDAP-like expression using indexes + returns -1 if an indexed search is not possible, in which + case the caller should call ltdb_search_full() +*/ +int ldb_kv_search_indexed(struct ldb_kv_context *ac, uint32_t *match_count) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(ac->module), struct ldb_kv_private); + struct dn_list *dn_list; + int ret; + enum ldb_scope index_scope; + enum key_truncation scope_one_truncation = KEY_NOT_TRUNCATED; + + /* see if indexing is enabled */ + if (!ldb_kv->cache->attribute_indexes && + !ldb_kv->cache->one_level_indexes && ac->scope != LDB_SCOPE_BASE) { + /* fallback to a full search */ + return LDB_ERR_OPERATIONS_ERROR; + } + + dn_list = talloc_zero(ac, struct dn_list); + if (dn_list == NULL) { + return ldb_module_oom(ac->module); + } + + /* + * For the purposes of selecting the switch arm below, if we + * don't have a one-level index then treat it like a subtree + * search + */ + if (ac->scope == LDB_SCOPE_ONELEVEL && + !ldb_kv->cache->one_level_indexes) { + index_scope = LDB_SCOPE_SUBTREE; + } else { + index_scope = ac->scope; + } + + switch (index_scope) { + case LDB_SCOPE_BASE: + /* + * The only caller will have filtered the operation out + * so we should never get here + */ + return ldb_operr(ldb); + + case LDB_SCOPE_ONELEVEL: + + /* + * First, load all the one-level child objects (regardless of + * whether they match the search filter or not). The database + * maintains a one-level index, so retrieving this is quick. + */ + ret = ldb_kv_index_dn_one(ac->module, + ldb_kv, + ac->base, + dn_list, + &scope_one_truncation); + if (ret != LDB_SUCCESS) { + talloc_free(dn_list); + return ret; + } + + /* + * If we have too many children, running ldb_kv_index_filter() + * over all the child objects can be quite expensive. So next + * we do a separate indexed query using the search filter. + * + * This should be quick, but it may return objects that are not + * the direct one-level child objects we're interested in. + * + * We only do this in the GUID index mode, which is + * O(n*log(m)) otherwise the intersection below will + * be too costly at O(n*m). + * + * We don't set a heuristic for 'too many' but instead + * do it always and rely on the index lookup being + * fast enough in the small case. + */ + if (ldb_kv->cache->GUID_index_attribute != NULL) { + struct dn_list *indexed_search_result + = talloc_zero(ac, struct dn_list); + if (indexed_search_result == NULL) { + talloc_free(dn_list); + return ldb_module_oom(ac->module); + } + + if (!ldb_kv->cache->attribute_indexes) { + talloc_free(indexed_search_result); + talloc_free(dn_list); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * Try to do an indexed database search + */ + ret = ldb_kv_index_dn( + ac->module, ldb_kv, ac->tree, + indexed_search_result); + + /* + * We can stop if we're sure the object doesn't exist + */ + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(indexed_search_result); + talloc_free(dn_list); + return LDB_ERR_NO_SUCH_OBJECT; + } + + /* + * Once we have a successful search result, we + * intersect it with the one-level children (dn_list). + * This should give us exactly the result we're after + * (we still need to run ldb_kv_index_filter() to + * handle potential index truncation cases). + * + * The indexed search may fail because we don't support + * indexing on that type of search operation, e.g. + * matching against '*'. In which case we fall through + * and run ldb_kv_index_filter() over all the one-level + * children (which is still better than bailing out here + * and falling back to a full DB scan). + */ + if (ret == LDB_SUCCESS) { + if (!list_intersect(ldb_kv, + dn_list, + indexed_search_result)) { + talloc_free(indexed_search_result); + talloc_free(dn_list); + return LDB_ERR_OPERATIONS_ERROR; + } + } + } + break; + + case LDB_SCOPE_SUBTREE: + case LDB_SCOPE_DEFAULT: + if (!ldb_kv->cache->attribute_indexes) { + talloc_free(dn_list); + return LDB_ERR_OPERATIONS_ERROR; + } + /* + * Here we load the index for the tree. We have no + * index for the subtree. + */ + ret = ldb_kv_index_dn(ac->module, ldb_kv, ac->tree, dn_list); + if (ret != LDB_SUCCESS) { + talloc_free(dn_list); + return ret; + } + break; + } + + /* + * It is critical that this function do the re-filter even + * on things found by the index as the index can over-match + * in cases of truncation (as well as when it decides it is + * not worth further filtering) + * + * If this changes, then the index code above would need to + * pass up a flag to say if any index was truncated during + * processing as the truncation here refers only to the + * SCOPE_ONELEVEL index. + */ + ret = ldb_kv_index_filter( + ldb_kv, dn_list, ac, match_count, scope_one_truncation); + talloc_free(dn_list); + return ret; +} + +/** + * @brief Add a DN in the index list of a given attribute name/value pair + * + * This function will add the DN in the index list for the index for + * the given attribute name and value. + * + * @param[in] module A ldb_module structure + * + * @param[in] dn The string representation of the DN as it + * will be stored in the index entry + * + * @param[in] el A ldb_message_element array, one of the entry + * referred by the v_idx is the attribute name and + * value pair which will be used to construct the + * index name + * + * @param[in] v_idx The index of element in the el array to use + * + * @return An ldb error code + */ +static int ldb_kv_index_add1(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el, + int v_idx) +{ + struct ldb_context *ldb; + struct ldb_dn *dn_key; + int ret; + const struct ldb_schema_attribute *a; + struct dn_list *list; + unsigned alloc_len; + enum key_truncation truncation = KEY_TRUNCATED; + + + ldb = ldb_module_get_ctx(module); + + list = talloc_zero(module, struct dn_list); + if (list == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + dn_key = ldb_kv_index_key( + ldb, ldb_kv, el->name, &el->values[v_idx], &a, &truncation); + if (!dn_key) { + talloc_free(list); + return LDB_ERR_OPERATIONS_ERROR; + } + /* + * Samba only maintains unique indexes on the objectSID and objectGUID + * so if a unique index key exceeds the maximum length there is a + * problem. + */ + if ((truncation == KEY_TRUNCATED) && (a != NULL && + (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX || + (el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX)))) { + + ldb_asprintf_errstring( + ldb, + __location__ ": unique index key on %s in %s, " + "exceeds maximum key length of %u (encoded).", + el->name, + ldb_dn_get_linearized(msg->dn), + ldb_kv->max_key_length); + talloc_free(list); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + talloc_steal(list, dn_key); + + ret = ldb_kv_dn_list_load(module, ldb_kv, dn_key, list, + DN_LIST_MUTABLE); + if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(list); + return ret; + } + + /* + * Check for duplicates in the @IDXDN DN -> GUID record + * + * This is very normal, it just means a duplicate DN creation + * was attempted, so don't set the error string or print scary + * messages. + */ + if (list->count > 0 && + ldb_attr_cmp(el->name, LDB_KV_IDXDN) == 0 && + truncation == KEY_NOT_TRUNCATED) { + + talloc_free(list); + return LDB_ERR_CONSTRAINT_VIOLATION; + + } else if (list->count > 0 + && ldb_attr_cmp(el->name, LDB_KV_IDXDN) == 0) { + + /* + * At least one existing entry in the DN->GUID index, which + * arises when the DN indexes have been truncated + * + * So need to pull the DN's to check if it's really a duplicate + */ + unsigned int i; + for (i=0; i < list->count; i++) { + uint8_t guid_key[LDB_KV_GUID_KEY_SIZE]; + struct ldb_val key = { + .data = guid_key, + .length = sizeof(guid_key) + }; + const int flags = LDB_UNPACK_DATA_FLAG_NO_ATTRS; + struct ldb_message *rec = ldb_msg_new(ldb); + if (rec == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_idx_to_key( + module, ldb_kv, ldb, &list->dn[i], &key); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(list); + TALLOC_FREE(rec); + return ret; + } + + ret = + ldb_kv_search_key(module, ldb_kv, key, rec, flags); + if (key.data != guid_key) { + TALLOC_FREE(key.data); + } + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* + * the record has disappeared? + * yes, this can happen + */ + talloc_free(rec); + continue; + } + + if (ret != LDB_SUCCESS) { + /* an internal error */ + TALLOC_FREE(rec); + TALLOC_FREE(list); + return LDB_ERR_OPERATIONS_ERROR; + } + /* + * The DN we are trying to add to the DB and index + * is already here, so we must deny the addition + */ + if (ldb_dn_compare(msg->dn, rec->dn) == 0) { + TALLOC_FREE(rec); + TALLOC_FREE(list); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + } + } + + /* + * Check for duplicates in unique indexes + * + * We don't need to do a loop test like the @IDXDN case + * above as we have a ban on long unique index values + * at the start of this function. + */ + if (list->count > 0 && + ((a != NULL + && (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX || + (el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX))))) { + /* + * We do not want to print info about a possibly + * confidential DN that the conflict was with in the + * user-visible error string + */ + + if (ldb_kv->cache->GUID_index_attribute == NULL) { + ldb_debug(ldb, LDB_DEBUG_WARNING, + __location__ + ": unique index violation on %s in %s, " + "conflicts with %*.*s in %s", + el->name, ldb_dn_get_linearized(msg->dn), + (int)list->dn[0].length, + (int)list->dn[0].length, + list->dn[0].data, + ldb_dn_get_linearized(dn_key)); + } else { + /* This can't fail, gives a default at worst */ + const struct ldb_schema_attribute *attr = + ldb_schema_attribute_by_name( + ldb, ldb_kv->cache->GUID_index_attribute); + struct ldb_val v; + ret = attr->syntax->ldif_write_fn(ldb, list, + &list->dn[0], &v); + if (ret == LDB_SUCCESS) { + ldb_debug(ldb, + LDB_DEBUG_WARNING, + __location__ + ": unique index violation on %s in " + "%s, conflicts with %s %*.*s in %s", + el->name, + ldb_dn_get_linearized(msg->dn), + ldb_kv->cache->GUID_index_attribute, + (int)v.length, + (int)v.length, + v.data, + ldb_dn_get_linearized(dn_key)); + } + } + ldb_asprintf_errstring(ldb, + __location__ ": unique index violation " + "on %s in %s", + el->name, + ldb_dn_get_linearized(msg->dn)); + talloc_free(list); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + /* overallocate the list a bit, to reduce the number of + * 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) { + talloc_free(list); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ldb_kv->cache->GUID_index_attribute == NULL) { + const char *dn_str = ldb_dn_get_linearized(msg->dn); + list->dn[list->count].data + = (uint8_t *)talloc_strdup(list->dn, dn_str); + if (list->dn[list->count].data == NULL) { + talloc_free(list); + return LDB_ERR_OPERATIONS_ERROR; + } + list->dn[list->count].length = strlen(dn_str); + } else { + const struct ldb_val *key_val; + struct ldb_val *exact = NULL, *next = NULL; + key_val = ldb_msg_find_ldb_val( + msg, ldb_kv->cache->GUID_index_attribute); + if (key_val == NULL) { + talloc_free(list); + return ldb_module_operr(module); + } + + if (key_val->length != LDB_KV_GUID_SIZE) { + talloc_free(list); + return ldb_module_operr(module); + } + + BINARY_ARRAY_SEARCH_GTE(list->dn, list->count, + *key_val, ldb_val_equal_exact_ordered, + exact, next); + + /* + * Give a warning rather than fail, this could be a + * duplicate value in the record allowed by a caller + * forcing in the value with + * LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK + */ + if (exact != NULL && truncation == KEY_NOT_TRUNCATED) { + /* This can't fail, gives a default at worst */ + const struct ldb_schema_attribute *attr = + ldb_schema_attribute_by_name( + ldb, ldb_kv->cache->GUID_index_attribute); + struct ldb_val v; + ret = attr->syntax->ldif_write_fn(ldb, list, + exact, &v); + if (ret == LDB_SUCCESS) { + ldb_debug(ldb, + LDB_DEBUG_WARNING, + __location__ + ": duplicate attribute value in %s " + "for index on %s, " + "duplicate of %s %*.*s in %s", + ldb_dn_get_linearized(msg->dn), + el->name, + ldb_kv->cache->GUID_index_attribute, + (int)v.length, + (int)v.length, + v.data, + ldb_dn_get_linearized(dn_key)); + } + } + + if (next == NULL) { + next = &list->dn[list->count]; + } else { + memmove(&next[1], next, + sizeof(*next) * (list->count - (next - list->dn))); + } + *next = ldb_val_dup(list->dn, key_val); + if (next->data == NULL) { + talloc_free(list); + return ldb_module_operr(module); + } + } + list->count++; + + ret = ldb_kv_dn_list_store(module, dn_key, list); + + talloc_free(list); + + return ret; +} + +/* + add index entries for one elements in a message + */ +static int ldb_kv_index_add_el(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el) +{ + unsigned int i; + for (i = 0; i < el->num_values; i++) { + int ret = ldb_kv_index_add1(module, ldb_kv, msg, el, i); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + +/* + add index entries for all elements in a message + */ +static int ldb_kv_index_add_all(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg) +{ + struct ldb_message_element *elements = msg->elements; + unsigned int i; + const char *dn_str; + int ret; + + if (ldb_dn_is_special(msg->dn)) { + return LDB_SUCCESS; + } + + dn_str = ldb_dn_get_linearized(msg->dn); + if (dn_str == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_write_index_dn_guid(module, msg, 1); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (!ldb_kv->cache->attribute_indexes) { + /* no indexed fields */ + return LDB_SUCCESS; + } + + for (i = 0; i < msg->num_elements; i++) { + if (!ldb_kv_is_indexed(module, ldb_kv, elements[i].name)) { + continue; + } + ret = ldb_kv_index_add_el(module, ldb_kv, msg, &elements[i]); + if (ret != LDB_SUCCESS) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_asprintf_errstring(ldb, + __location__ ": Failed to re-index %s in %s - %s", + elements[i].name, dn_str, + ldb_errstring(ldb)); + return ret; + } + } + + return LDB_SUCCESS; +} + + +/* + insert a DN index for a message +*/ +static int ldb_kv_modify_index_dn(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_dn *dn, + const char *index, + int add) +{ + struct ldb_message_element el; + struct ldb_val val; + int ret; + + val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(dn)); + if (val.data == NULL) { + const char *dn_str = ldb_dn_get_linearized(dn); + ldb_asprintf_errstring(ldb_module_get_ctx(module), + __location__ ": Failed to modify %s " + "against %s in %s: failed " + "to get casefold DN", + index, + ldb_kv->cache->GUID_index_attribute, + dn_str); + return LDB_ERR_OPERATIONS_ERROR; + } + + val.length = strlen((char *)val.data); + el.name = index; + el.values = &val; + el.num_values = 1; + + if (add) { + ret = ldb_kv_index_add1(module, ldb_kv, msg, &el, 0); + } else { /* delete */ + ret = ldb_kv_index_del_value(module, ldb_kv, msg, &el, 0); + } + + if (ret != LDB_SUCCESS) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + const char *dn_str = ldb_dn_get_linearized(dn); + ldb_asprintf_errstring(ldb, + __location__ ": Failed to modify %s " + "against %s in %s - %s", + index, + ldb_kv->cache->GUID_index_attribute, + dn_str, + ldb_errstring(ldb)); + return ret; + } + return ret; +} + +/* + insert a one level index for a message +*/ +static int ldb_kv_index_onelevel(struct ldb_module *module, + const struct ldb_message *msg, + int add) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + struct ldb_dn *pdn; + int ret; + + /* We index for ONE Level only if requested */ + if (!ldb_kv->cache->one_level_indexes) { + return LDB_SUCCESS; + } + + pdn = ldb_dn_get_parent(module, msg->dn); + if (pdn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + ret = + ldb_kv_modify_index_dn(module, ldb_kv, msg, pdn, LDB_KV_IDXONE, add); + + talloc_free(pdn); + + return ret; +} + +/* + insert a one level index for a message +*/ +static int ldb_kv_write_index_dn_guid(struct ldb_module *module, + const struct ldb_message *msg, + int add) +{ + int ret; + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + + /* We index for DN only if using a GUID index */ + if (ldb_kv->cache->GUID_index_attribute == NULL) { + return LDB_SUCCESS; + } + + ret = ldb_kv_modify_index_dn( + module, ldb_kv, msg, msg->dn, LDB_KV_IDXDN, add); + + if (ret == LDB_ERR_CONSTRAINT_VIOLATION) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Entry %s already exists", + ldb_dn_get_linearized(msg->dn)); + ret = LDB_ERR_ENTRY_ALREADY_EXISTS; + } + return ret; +} + +/* + add the index entries for a new element in a record + The caller guarantees that these element values are not yet indexed +*/ +int ldb_kv_index_add_element(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el) +{ + if (ldb_dn_is_special(msg->dn)) { + return LDB_SUCCESS; + } + if (!ldb_kv_is_indexed(module, ldb_kv, el->name)) { + return LDB_SUCCESS; + } + return ldb_kv_index_add_el(module, ldb_kv, msg, el); +} + +/* + add the index entries for a new record +*/ +int ldb_kv_index_add_new(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg) +{ + int ret; + + if (ldb_dn_is_special(msg->dn)) { + return LDB_SUCCESS; + } + + ret = ldb_kv_index_add_all(module, ldb_kv, msg); + if (ret != LDB_SUCCESS) { + /* + * Because we can't trust the caller to be doing + * transactions properly, clean up any index for this + * entry rather than relying on a transaction + * cleanup + */ + + ldb_kv_index_delete(module, msg); + return ret; + } + + ret = ldb_kv_index_onelevel(module, msg, 1); + if (ret != LDB_SUCCESS) { + /* + * Because we can't trust the caller to be doing + * transactions properly, clean up any index for this + * entry rather than relying on a transaction + * cleanup + */ + ldb_kv_index_delete(module, msg); + return ret; + } + return ret; +} + + +/* + delete an index entry for one message element +*/ +int ldb_kv_index_del_value(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el, + unsigned int v_idx) +{ + struct ldb_context *ldb; + struct ldb_dn *dn_key; + const char *dn_str; + int ret, i; + unsigned int j; + struct dn_list *list; + struct ldb_dn *dn = msg->dn; + enum key_truncation truncation = KEY_NOT_TRUNCATED; + + ldb = ldb_module_get_ctx(module); + + dn_str = ldb_dn_get_linearized(dn); + if (dn_str == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (dn_str[0] == '@') { + return LDB_SUCCESS; + } + + dn_key = ldb_kv_index_key( + ldb, ldb_kv, el->name, &el->values[v_idx], NULL, &truncation); + /* + * We ignore key truncation in ltdb_index_add1() so + * match that by ignoring it here as well + * + * Multiple values are legitimate and accepted + */ + if (!dn_key) { + return LDB_ERR_OPERATIONS_ERROR; + } + + list = talloc_zero(dn_key, struct dn_list); + if (list == NULL) { + talloc_free(dn_key); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_dn_list_load(module, ldb_kv, dn_key, list, + DN_LIST_MUTABLE); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* it wasn't indexed. Did we have an earlier error? If we did then + its gone now */ + talloc_free(dn_key); + return LDB_SUCCESS; + } + + if (ret != LDB_SUCCESS) { + talloc_free(dn_key); + return ret; + } + + /* + * Find one of the values matching this message to remove + */ + i = ldb_kv_dn_list_find_msg(ldb_kv, list, msg); + if (i == -1) { + /* nothing to delete */ + talloc_free(dn_key); + return LDB_SUCCESS; + } + + j = (unsigned int) i; + if (j != list->count - 1) { + memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1))); + } + 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 = ldb_kv_dn_list_store(module, dn_key, list); + + talloc_free(dn_key); + + return ret; +} + +/* + delete the index entries for a element + return -1 on failure +*/ +int ldb_kv_index_del_element(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_message *msg, + struct ldb_message_element *el) +{ + const char *dn_str; + int ret; + unsigned int i; + + if (!ldb_kv->cache->attribute_indexes) { + /* no indexed fields */ + return LDB_SUCCESS; + } + + dn_str = ldb_dn_get_linearized(msg->dn); + if (dn_str == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (dn_str[0] == '@') { + return LDB_SUCCESS; + } + + if (!ldb_kv_is_indexed(module, ldb_kv, el->name)) { + return LDB_SUCCESS; + } + for (i = 0; i < el->num_values; i++) { + ret = ldb_kv_index_del_value(module, ldb_kv, msg, el, i); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + +/* + delete the index entries for a record + return -1 on failure +*/ +int ldb_kv_index_delete(struct ldb_module *module, + const struct ldb_message *msg) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + int ret; + unsigned int i; + + if (ldb_dn_is_special(msg->dn)) { + return LDB_SUCCESS; + } + + ret = ldb_kv_index_onelevel(module, msg, 0); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_kv_write_index_dn_guid(module, msg, 0); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (!ldb_kv->cache->attribute_indexes) { + /* no indexed fields */ + return LDB_SUCCESS; + } + + for (i = 0; i < msg->num_elements; i++) { + ret = ldb_kv_index_del_element( + module, ldb_kv, msg, &msg->elements[i]); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + + +/* + traversal function that deletes all @INDEX records in the in-memory + TDB. + + This does not touch the actual DB, that is done at transaction + commit, which in turn greatly reduces DB churn as we will likely + be able to do a direct update into the old record. +*/ +static int delete_index(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + _UNUSED_ struct ldb_val data, + void *state) +{ + struct ldb_module *module = state; + const char *dnstr = "DN=" LDB_KV_INDEX ":"; + struct dn_list list; + struct ldb_dn *dn; + struct ldb_val v; + int ret; + + if (strncmp((char *)key.data, dnstr, strlen(dnstr)) != 0) { + return 0; + } + /* we need to put a empty list in the internal tdb for this + * index entry */ + list.dn = NULL; + list.count = 0; + + /* the offset of 3 is to remove the DN= prefix. */ + v.data = key.data + 3; + v.length = strnlen((char *)key.data, key.length) - 3; + + dn = ldb_dn_from_ldb_val(ldb_kv, ldb_module_get_ctx(module), &v); + + /* + * This does not actually touch the DB quite yet, just + * the in-memory index cache + */ + ret = ldb_kv_dn_list_store(module, dn, &list); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Unable to store null index for %s\n", + ldb_dn_get_linearized(dn)); + talloc_free(dn); + return -1; + } + talloc_free(dn); + return 0; +} + +/* + traversal function that adds @INDEX records during a re index TODO wrong comment +*/ +static int re_key(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val val, + void *state) +{ + struct ldb_context *ldb; + struct ldb_kv_reindex_context *ctx = + (struct ldb_kv_reindex_context *)state; + struct ldb_module *module = ldb_kv->module; + struct ldb_message *msg; + int ret; + struct ldb_val key2; + bool is_record; + + ldb = ldb_module_get_ctx(module); + + is_record = ldb_kv_key_is_normal_record(key); + if (is_record == false) { + return 0; + } + + msg = ldb_msg_new(module); + if (msg == NULL) { + return -1; + } + + ret = ldb_unpack_data(ldb, &val, msg); + if (ret != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n", + ldb_dn_get_linearized(msg->dn)); + ctx->error = ret; + talloc_free(msg); + return -1; + } + + if (msg->dn == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Refusing to re-index as GUID " + "key %*.*s with no DN\n", + (int)key.length, (int)key.length, + (char *)key.data); + talloc_free(msg); + return -1; + } + + /* check if the DN key has changed, perhaps due to the case + insensitivity of an element changing, or a change from DN + to GUID keys */ + key2 = ldb_kv_key_msg(module, msg, msg); + if (key2.data == NULL) { + /* probably a corrupt record ... darn */ + ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s", + ldb_dn_get_linearized(msg->dn)); + talloc_free(msg); + return 0; + } + if (key.length != key2.length || + (memcmp(key.data, key2.data, key.length) != 0)) { + ldb_kv->kv_ops->update_in_iterate( + ldb_kv, key, key2, val, ctx); + } + talloc_free(key2.data); + + talloc_free(msg); + + ctx->count++; + if (ctx->count % 10000 == 0) { + ldb_debug(ldb, LDB_DEBUG_WARNING, + "Reindexing: re-keyed %u records so far", + ctx->count); + } + + return 0; +} + +/* + traversal function that adds @INDEX records during a re index +*/ +static int re_index(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val val, + void *state) +{ + struct ldb_context *ldb; + struct ldb_kv_reindex_context *ctx = + (struct ldb_kv_reindex_context *)state; + struct ldb_module *module = ldb_kv->module; + struct ldb_message *msg; + int ret; + bool is_record; + + ldb = ldb_module_get_ctx(module); + + is_record = ldb_kv_key_is_normal_record(key); + if (is_record == false) { + return 0; + } + + msg = ldb_msg_new(module); + if (msg == NULL) { + return -1; + } + + ret = ldb_unpack_data(ldb, &val, msg); + if (ret != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n", + ldb_dn_get_linearized(msg->dn)); + ctx->error = ret; + talloc_free(msg); + return -1; + } + + if (msg->dn == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Refusing to re-index as GUID " + "key %*.*s with no DN\n", + (int)key.length, (int)key.length, + (char *)key.data); + talloc_free(msg); + return -1; + } + + ret = ldb_kv_index_onelevel(module, msg, 1); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Adding special ONE LEVEL index failed (%s)!", + ldb_dn_get_linearized(msg->dn)); + talloc_free(msg); + return -1; + } + + ret = ldb_kv_index_add_all(module, ldb_kv, msg); + + if (ret != LDB_SUCCESS) { + ctx->error = ret; + talloc_free(msg); + return -1; + } + + talloc_free(msg); + + ctx->count++; + if (ctx->count % 10000 == 0) { + ldb_debug(ldb, LDB_DEBUG_WARNING, + "Reindexing: re-indexed %u records so far", + ctx->count); + } + + return 0; +} + +/* + * Convert the 4-byte pack format version to a number that's slightly + * more intelligible to a user e.g. version 0, 1, 2, etc. + */ +static uint32_t displayable_pack_version(uint32_t version) { + if (version < LDB_PACKING_FORMAT_NODN) { + return version; /* unknown - can't convert */ + } + + return (version - LDB_PACKING_FORMAT_NODN); +} + +static int re_pack(struct ldb_kv_private *ldb_kv, + _UNUSED_ struct ldb_val key, + struct ldb_val val, + void *state) +{ + struct ldb_context *ldb; + struct ldb_message *msg; + struct ldb_module *module = ldb_kv->module; + struct ldb_kv_repack_context *ctx = + (struct ldb_kv_repack_context *)state; + int ret; + + ldb = ldb_module_get_ctx(module); + + msg = ldb_msg_new(module); + if (msg == NULL) { + return -1; + } + + ret = ldb_unpack_data(ldb, &val, msg); + if (ret != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Repack: unpack failed: %s\n", + ldb_dn_get_linearized(msg->dn)); + ctx->error = ret; + talloc_free(msg); + return -1; + } + + ret = ldb_kv_store(module, msg, TDB_MODIFY); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Repack: store failed: %s\n", + ldb_dn_get_linearized(msg->dn)); + ctx->error = ret; + talloc_free(msg); + return -1; + } + + /* + * Warn the user that we're repacking the first time we see a normal + * record. This means we never warn if we're repacking a database with + * only @ records. This is because during database initialisation, + * we might repack as initial settings are written out, and we don't + * want to spam the log. + */ + if ((!ctx->normal_record_seen) && (!ldb_dn_is_special(msg->dn))) { + ldb_debug(ldb, LDB_DEBUG_ALWAYS_LOG, + "Repacking database from v%u to v%u format " + "(first record %s)", + displayable_pack_version(ctx->old_version), + displayable_pack_version(ldb_kv->pack_format_version), + ldb_dn_get_linearized(msg->dn)); + ctx->normal_record_seen = true; + } + + ctx->count++; + if (ctx->count % 10000 == 0) { + ldb_debug(ldb, LDB_DEBUG_WARNING, + "Repack: re-packed %u records so far", + ctx->count); + } + + talloc_free(msg); + return 0; +} + +int ldb_kv_repack(struct ldb_module *module) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_kv_repack_context ctx; + int ret; + + ctx.old_version = ldb_kv->pack_format_version; + ctx.count = 0; + ctx.error = LDB_SUCCESS; + ctx.normal_record_seen = false; + + ldb_kv->pack_format_version = ldb_kv->target_pack_format_version; + + /* Iterate all database records and repack them in the new format */ + ret = ldb_kv->kv_ops->iterate(ldb_kv, re_pack, &ctx); + if (ret < 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Repack traverse failed: %s", + ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ctx.error != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Repack failed: %s", + ldb_errstring(ldb)); + return ctx.error; + } + + return LDB_SUCCESS; +} + +/* + force a complete reindex of the database +*/ +int ldb_kv_reindex(struct ldb_module *module) +{ + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + int ret; + struct ldb_kv_reindex_context ctx; + size_t index_cache_size = 0; + + /* + * Only triggered after a modification, but make clear we do + * not re-index a read-only DB + */ + if (ldb_kv->read_only) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + if (ldb_kv_cache_reload(module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * Ensure we read (and so remove) the entries from the real + * DB, no values stored so far are any use as we want to do a + * re-index + */ + ldb_kv_index_transaction_cancel(module); + if (ldb_kv->nested_idx_ptr != NULL) { + ldb_kv_index_sub_transaction_cancel(ldb_kv); + } + + /* + * Calculate the size of the index cache needed for + * the re-index. If specified always use the + * ldb_kv->index_transaction_cache_size otherwise use the maximum + * of the size estimate or the DEFAULT_INDEX_CACHE_SIZE + */ + if (ldb_kv->index_transaction_cache_size > 0) { + index_cache_size = ldb_kv->index_transaction_cache_size; + } else { + index_cache_size = ldb_kv->kv_ops->get_size(ldb_kv); + if (index_cache_size < DEFAULT_INDEX_CACHE_SIZE) { + index_cache_size = DEFAULT_INDEX_CACHE_SIZE; + } + } + + /* + * Note that we don't start an index sub transaction for re-indexing + */ + ret = ldb_kv_index_transaction_start(module, index_cache_size); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* first traverse the database deleting any @INDEX records by + * putting NULL entries in the in-memory tdb + */ + ret = ldb_kv->kv_ops->iterate(ldb_kv, delete_index, module); + if (ret < 0) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_asprintf_errstring(ldb, "index deletion traverse failed: %s", + ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + ctx.error = 0; + ctx.count = 0; + + ret = ldb_kv->kv_ops->iterate(ldb_kv, re_key, &ctx); + if (ret < 0) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_asprintf_errstring(ldb, "key correction traverse failed: %s", + ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ctx.error != LDB_SUCCESS) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb)); + return ctx.error; + } + + ctx.error = 0; + ctx.count = 0; + + /* now traverse adding any indexes for normal LDB records */ + ret = ldb_kv->kv_ops->iterate(ldb_kv, re_index, &ctx); + if (ret < 0) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s", + ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ctx.error != LDB_SUCCESS) { + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb)); + return ctx.error; + } + + if (ctx.count > 10000) { + ldb_debug(ldb_module_get_ctx(module), + LDB_DEBUG_WARNING, + "Reindexing: re_index successful on %s, " + "final index write-out will be in transaction commit", + ldb_kv->kv_ops->name(ldb_kv)); + } + return LDB_SUCCESS; +} + +/* + * Copy the contents of the nested transaction index cache record to the + * transaction index cache. + * + * During this 'commit' of the subtransaction to the main transaction + * (cache), care must be taken to free any existing index at the top + * level because otherwise we would leak memory. + */ +static int ldb_kv_sub_transaction_traverse( + struct tdb_context *tdb, + TDB_DATA key, + TDB_DATA data, + void *state) +{ + struct ldb_module *module = state; + struct ldb_kv_private *ldb_kv = talloc_get_type( + ldb_module_get_private(module), struct ldb_kv_private); + TDB_DATA rec = {0}; + struct dn_list *index_in_subtransaction = NULL; + struct dn_list *index_in_top_level = NULL; + int ret = 0; + + /* + * This unwraps the pointer in the DB into a pointer in + * memory, we are abusing TDB as a hash map, not a linearised + * database store + */ + index_in_subtransaction = ldb_kv_index_idxptr(module, data); + if (index_in_subtransaction == NULL) { + ldb_kv->idxptr->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + + /* + * Do we already have an entry in the primary transaction cache + * If so free it's dn_list and replace it with the dn_list from + * the secondary cache + * + * The TDB and so the fetched rec contains NO DATA, just a + * pointer to data held in memory. + */ + rec = tdb_fetch(ldb_kv->idxptr->itdb, key); + if (rec.dptr != NULL) { + index_in_top_level = ldb_kv_index_idxptr(module, rec); + free(rec.dptr); + if (index_in_top_level == NULL) { + abort(); + } + /* + * We had this key at the top level. However we made a copy + * at the sub-transaction level so that we could possibly + * roll back. We have to free the top level index memory + * otherwise we would leak + */ + if (index_in_top_level->count > 0) { + TALLOC_FREE(index_in_top_level->dn); + } + index_in_top_level->dn + = talloc_steal(index_in_top_level, + index_in_subtransaction->dn); + index_in_top_level->count = index_in_subtransaction->count; + return 0; + } + + index_in_top_level = talloc(ldb_kv->idxptr, struct dn_list); + if (index_in_top_level == NULL) { + ldb_kv->idxptr->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + index_in_top_level->dn + = talloc_steal(index_in_top_level, + index_in_subtransaction->dn); + index_in_top_level->count = index_in_subtransaction->count; + + rec.dptr = (uint8_t *)&index_in_top_level; + rec.dsize = sizeof(void *); + + + /* + * This is not a store into the main DB, but into an in-memory + * TDB, so we don't need a guard on ltdb->read_only + */ + ret = tdb_store(ldb_kv->idxptr->itdb, key, rec, TDB_INSERT); + if (ret != 0) { + ldb_kv->idxptr->error = ltdb_err_map( + tdb_error(ldb_kv->idxptr->itdb)); + return -1; + } + return 0; +} + +/* + * Initialise the index cache for a sub transaction. + */ +int ldb_kv_index_sub_transaction_start(struct ldb_kv_private *ldb_kv) +{ + ldb_kv->nested_idx_ptr = talloc_zero(ldb_kv, struct ldb_kv_idxptr); + if (ldb_kv->nested_idx_ptr == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * We use a tiny hash size for the sub-database (11). + * + * The sub-transaction is only for one record at a time, we + * would use a linked list but that would make the code even + * more complex when manipulating the index, as it would have + * to know if we were in a nested transaction (normal + * operations) or the top one (a reindex). + */ + ldb_kv->nested_idx_ptr->itdb = + tdb_open(NULL, 11, TDB_INTERNAL, O_RDWR, 0); + if (ldb_kv->nested_idx_ptr->itdb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + return LDB_SUCCESS; +} + +/* + * Clear the contents of the nested transaction index cache when the nested + * transaction is cancelled. + */ +int ldb_kv_index_sub_transaction_cancel(struct ldb_kv_private *ldb_kv) +{ + if (ldb_kv->nested_idx_ptr != NULL) { + tdb_close(ldb_kv->nested_idx_ptr->itdb); + TALLOC_FREE(ldb_kv->nested_idx_ptr); + } + return LDB_SUCCESS; +} + +/* + * Commit a nested transaction, + * Copy the contents of the nested transaction index cache to the + * transaction index cache. + */ +int ldb_kv_index_sub_transaction_commit(struct ldb_kv_private *ldb_kv) +{ + int ret = 0; + + if (ldb_kv->nested_idx_ptr == NULL) { + return LDB_SUCCESS; + } + if (ldb_kv->nested_idx_ptr->itdb == NULL) { + return LDB_SUCCESS; + } + tdb_traverse( + ldb_kv->nested_idx_ptr->itdb, + ldb_kv_sub_transaction_traverse, + ldb_kv->module); + tdb_close(ldb_kv->nested_idx_ptr->itdb); + ldb_kv->nested_idx_ptr->itdb = NULL; + + ret = ldb_kv->nested_idx_ptr->error; + if (ret != LDB_SUCCESS) { + struct ldb_context *ldb = ldb_module_get_ctx(ldb_kv->module); + if (!ldb_errstring(ldb)) { + ldb_set_errstring(ldb, ldb_strerror(ret)); + } + ldb_asprintf_errstring( + ldb, + __location__": Failed to update index records in " + "sub transaction commit: %s", + ldb_errstring(ldb)); + } + TALLOC_FREE(ldb_kv->nested_idx_ptr); + return ret; +} diff --git a/ldb-2.0.8/ldb_key_value/ldb_kv_search.c b/ldb-2.0.8/ldb_key_value/ldb_kv_search.c new file mode 100644 index 0000000..f2d9619 --- /dev/null +++ b/ldb-2.0.8/ldb_key_value/ldb_kv_search.c @@ -0,0 +1,707 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb search functions + * + * Description: functions to search ldb+tdb databases + * + * Author: Andrew Tridgell + */ + +#include "ldb_kv.h" +#include "ldb_private.h" +#include "lib/util/attr.h" +/* + search the database for a single simple dn. + return LDB_ERR_NO_SUCH_OBJECT on record-not-found + and LDB_SUCCESS on success +*/ +int ldb_kv_search_base(struct ldb_module *module, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_dn **ret_dn) +{ + int exists; + int ret; + struct ldb_message *msg = NULL; + + if (ldb_dn_is_null(dn)) { + return LDB_ERR_NO_SUCH_OBJECT; + } + + /* + * We can't use tdb_exists() directly on a key when the TDB + * key is the GUID one, not the DN based one. So we just do a + * normal search and avoid most of the allocation with the + * LDB_UNPACK_DATA_FLAG_NO_ATTRS flag + */ + msg = ldb_msg_new(module); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_kv_search_dn1(module, dn, msg, LDB_UNPACK_DATA_FLAG_NO_ATTRS); + if (ret == LDB_SUCCESS) { + const char *dn_linearized + = ldb_dn_get_linearized(dn); + const char *msg_dn_linearized + = ldb_dn_get_linearized(msg->dn); + + if (strcmp(dn_linearized, msg_dn_linearized) == 0) { + /* + * Re-use the full incoming DN for + * subtree checks + */ + *ret_dn = dn; + } else { + /* + * Use the string DN from the unpack, so that + * we have a case-exact match of the base + */ + *ret_dn = talloc_steal(mem_ctx, msg->dn); + } + exists = true; + } else if (ret == LDB_ERR_NO_SUCH_OBJECT) { + exists = false; + } else { + talloc_free(msg); + return ret; + } + talloc_free(msg); + if (exists) { + return LDB_SUCCESS; + } + return LDB_ERR_NO_SUCH_OBJECT; +} + +struct ldb_kv_parse_data_unpack_ctx { + struct ldb_message *msg; + struct ldb_module *module; + struct ldb_kv_private *ldb_kv; + unsigned int unpack_flags; +}; + +static int ldb_kv_parse_data_unpack(struct ldb_val key, + struct ldb_val data, + void *private_data) +{ + struct ldb_kv_parse_data_unpack_ctx *ctx = private_data; + int ret; + struct ldb_context *ldb = ldb_module_get_ctx(ctx->module); + struct ldb_val data_parse = data; + + struct ldb_kv_private *ldb_kv = ctx->ldb_kv; + + if ((ldb_kv->kv_ops->options & LDB_KV_OPTION_STABLE_READ_LOCK) && + (ctx->unpack_flags & LDB_UNPACK_DATA_FLAG_READ_LOCKED) && + !ldb_kv->kv_ops->transaction_active(ldb_kv)) { + /* + * In the case where no transactions are active and + * we're in a read-lock, we can point directly into + * database memory. + * + * The database can't be changed underneath us and we + * will duplicate this data in the call to filter. + * + * This is seen in: + * - ldb_kv_index_filter + * - ldb_kv_search_and_return_base + */ + } else { + /* + * In every other case, since unpack doesn't memdup, we need + * to at least do a memdup on the whole data buffer as that + * may change later and the caller needs a stable result. + * + * During transactions, pointers could change and in + * TDB, there just aren't the same guarantees. + */ + data_parse.data = talloc_memdup(ctx->msg, + data.data, + data.length); + if (data_parse.data == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Unable to allocate data(%d) for %*.*s\n", + (int)data.length, + (int)key.length, (int)key.length, key.data); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + ret = ldb_unpack_data_flags(ldb, &data_parse, + ctx->msg, ctx->unpack_flags); + if (ret == -1) { + if (data_parse.data != data.data) { + talloc_free(data_parse.data); + } + + ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %*.*s\n", + (int)key.length, (int)key.length, key.data); + return LDB_ERR_OPERATIONS_ERROR; + } + return ret; +} + +/* + search the database for a single simple dn, returning all attributes + in a single message + + return LDB_ERR_NO_SUCH_OBJECT on record-not-found + and LDB_SUCCESS on success +*/ +int ldb_kv_search_key(struct ldb_module *module, + struct ldb_kv_private *ldb_kv, + const struct ldb_val ldb_key, + struct ldb_message *msg, + unsigned int unpack_flags) +{ + int ret; + struct ldb_kv_parse_data_unpack_ctx ctx = { + .msg = msg, + .module = module, + .unpack_flags = unpack_flags, + .ldb_kv = ldb_kv + }; + + memset(msg, 0, sizeof(*msg)); + + msg->num_elements = 0; + msg->elements = NULL; + + ret = ldb_kv->kv_ops->fetch_and_parse( + ldb_kv, ldb_key, ldb_kv_parse_data_unpack, &ctx); + + if (ret == -1) { + ret = ldb_kv->kv_ops->error(ldb_kv); + if (ret == LDB_SUCCESS) { + /* + * Just to be sure we don't turn errors + * into success + */ + return LDB_ERR_OPERATIONS_ERROR; + } + return ret; + } else if (ret != LDB_SUCCESS) { + return ret; + } + + return LDB_SUCCESS; +} + +/* + search the database for a single simple dn, returning all attributes + in a single message + + return LDB_ERR_NO_SUCH_OBJECT on record-not-found + and LDB_SUCCESS on success +*/ +int ldb_kv_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 ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int ret; + uint8_t guid_key[LDB_KV_GUID_KEY_SIZE]; + struct ldb_val key = { + .data = guid_key, + .length = sizeof(guid_key) + }; + TALLOC_CTX *tdb_key_ctx = NULL; + + bool valid_dn = ldb_dn_validate(dn); + if (valid_dn == false) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Invalid Base DN: %s", + ldb_dn_get_linearized(dn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + + if (ldb_kv->cache->GUID_index_attribute == NULL || + ldb_dn_is_special(dn)) { + + tdb_key_ctx = talloc_new(msg); + if (!tdb_key_ctx) { + return ldb_module_oom(module); + } + + /* form the key */ + key = ldb_kv_key_dn(tdb_key_ctx, dn); + if (!key.data) { + TALLOC_FREE(tdb_key_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + } else { + /* + * Look in the index to find the key for this DN. + * + * the tdb_key memory is allocated above, msg is just + * used for internal memory. + * + */ + ret = ldb_kv_key_dn_from_idx(module, ldb_kv, msg, dn, &key); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + ret = ldb_kv_search_key(module, ldb_kv, key, msg, unpack_flags); + + TALLOC_FREE(tdb_key_ctx); + + if (ret != LDB_SUCCESS) { + return ret; + } + + 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; +} + +/* + * filter the specified list of attributes from msg, + * adding requested attributes, and perhaps all for *, + * but not the DN to filtered_msg. + */ +int ldb_kv_filter_attrs(struct ldb_context *ldb, + const struct ldb_message *msg, + const char *const *attrs, + struct ldb_message *filtered_msg) +{ + return ldb_filter_attrs(ldb, msg, attrs, filtered_msg); +} + +/* + search function for a non-indexed search + */ +static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val val, + void *state) +{ + struct ldb_context *ldb; + struct ldb_kv_context *ac; + struct ldb_message *msg, *filtered_msg; + int ret; + bool matched; + + ac = talloc_get_type(state, struct ldb_kv_context); + ldb = ldb_module_get_ctx(ac->module); + + /* + * We want to skip @ records early in a search full scan + * + * @ records like @IDXLIST are only available via a base + * search on the specific name but the method by which they + * were excluded was expensive, after the unpack the DN is + * exploded and ldb_match_msg_error() would reject it for + * failing to match the scope. + * + * ldb_kv_key_is_normal_record() uses the fact that @ records + * have the DN=@ prefix on their TDB/LMDB key to quickly + * exclude them from consideration. + * + * (any other non-records are also excluded by the same key + * match) + */ + + if (ldb_kv_key_is_normal_record(key) == false) { + return 0; + } + + msg = ldb_msg_new(ac); + if (!msg) { + ac->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + + /* unpack the record */ + ret = ldb_unpack_data_flags(ldb, &val, msg, + LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC); + if (ret == -1) { + talloc_free(msg); + ac->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + + if (!msg->dn) { + msg->dn = ldb_dn_new(msg, ldb, + (char *)key.data + 3); + if (msg->dn == NULL) { + talloc_free(msg); + ac->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + } + + /* see if it matches the given expression */ + ret = ldb_match_msg_error(ldb, msg, + ac->tree, ac->base, ac->scope, &matched); + if (ret != LDB_SUCCESS) { + talloc_free(msg); + ac->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + if (!matched) { + talloc_free(msg); + return 0; + } + + filtered_msg = ldb_msg_new(ac); + if (filtered_msg == NULL) { + TALLOC_FREE(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + filtered_msg->dn = talloc_steal(filtered_msg, msg->dn); + + /* filter the attributes that the user wants */ + ret = ldb_kv_filter_attrs(ldb, msg, ac->attrs, filtered_msg); + talloc_free(msg); + + if (ret == -1) { + TALLOC_FREE(filtered_msg); + ac->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + + ret = ldb_module_send_entry(ac->req, filtered_msg, NULL); + if (ret != LDB_SUCCESS) { + ac->request_terminated = true; + /* the callback failed, abort the operation */ + ac->error = LDB_ERR_OPERATIONS_ERROR; + return -1; + } + + return 0; +} + + +/* + search the database with a LDAP-like expression. + this is the "full search" non-indexed variant +*/ +static int ldb_kv_search_full(struct ldb_kv_context *ctx) +{ + void *data = ldb_module_get_private(ctx->module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int ret; + + ctx->error = LDB_SUCCESS; + ret = ldb_kv->kv_ops->iterate(ldb_kv, search_func, ctx); + + if (ret < 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ctx->error; +} + +static int ldb_kv_search_and_return_base(struct ldb_kv_private *ldb_kv, + struct ldb_kv_context *ctx) +{ + struct ldb_message *msg, *filtered_msg; + struct ldb_context *ldb = ldb_module_get_ctx(ctx->module); + const char *dn_linearized; + const char *msg_dn_linearized; + int ret; + bool matched; + + msg = ldb_msg_new(ctx); + if (!msg) { + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_kv_search_dn1(ctx->module, + ctx->base, + msg, + LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC | + LDB_UNPACK_DATA_FLAG_READ_LOCKED); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + if (ldb_kv->check_base == false) { + /* + * In this case, we are done, as no base + * checking is allowed in this DB + */ + talloc_free(msg); + return LDB_SUCCESS; + } + ldb_asprintf_errstring(ldb, + "No such Base DN: %s", + ldb_dn_get_linearized(ctx->base)); + } + if (ret != LDB_SUCCESS) { + talloc_free(msg); + return ret; + } + + + /* + * We use this, not ldb_match_msg_error() as we know + * we matched on the scope BASE, as we just fetched + * the base DN + */ + + ret = ldb_match_message(ldb, msg, + ctx->tree, + ctx->scope, + &matched); + if (ret != LDB_SUCCESS) { + talloc_free(msg); + return ret; + } + if (!matched) { + talloc_free(msg); + return LDB_SUCCESS; + } + + dn_linearized = ldb_dn_get_linearized(ctx->base); + msg_dn_linearized = ldb_dn_get_linearized(msg->dn); + + filtered_msg = ldb_msg_new(ctx); + if (filtered_msg == NULL) { + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (strcmp(dn_linearized, msg_dn_linearized) == 0) { + /* + * If the DN is exactly the same string, then + * re-use the full incoming DN for the + * returned result, as it has already been + * casefolded + */ + filtered_msg->dn = ldb_dn_copy(filtered_msg, ctx->base); + } + + /* + * If the ldb_dn_copy() failed, or if we did not choose that + * optimisation (filtered_msg is zeroed at allocation), + * steal the one from the unpack + */ + if (filtered_msg->dn == NULL) { + filtered_msg->dn = talloc_steal(filtered_msg, msg->dn); + } + + /* + * filter the attributes that the user wants. + */ + ret = ldb_kv_filter_attrs(ldb, msg, ctx->attrs, filtered_msg); + if (ret == -1) { + talloc_free(msg); + filtered_msg = NULL; + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * Remove any extended components possibly copied in from + * msg->dn, we just want the casefold components + */ + ldb_dn_remove_extended_components(filtered_msg->dn); + talloc_free(msg); + + ret = ldb_module_send_entry(ctx->req, filtered_msg, NULL); + if (ret != LDB_SUCCESS) { + /* Regardless of success or failure, the msg + * is the callbacks responsiblity, and should + * not be talloc_free()'ed */ + ctx->request_terminated = true; + return ret; + } + + return LDB_SUCCESS; +} + +/* + search the database with a LDAP-like expression. + choses a search method +*/ +int ldb_kv_search(struct ldb_kv_context *ctx) +{ + struct ldb_context *ldb; + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int ret; + + ldb = ldb_module_get_ctx(module); + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + if (ldb_kv->kv_ops->lock_read(module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ldb_kv_cache_load(module) != 0) { + ldb_kv->kv_ops->unlock_read(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->op.search.tree == NULL) { + ldb_kv->kv_ops->unlock_read(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + ctx->tree = req->op.search.tree; + ctx->scope = req->op.search.scope; + ctx->base = req->op.search.base; + ctx->attrs = req->op.search.attrs; + + if ((req->op.search.base == NULL) || (ldb_dn_is_null(req->op.search.base) == true)) { + + /* Check what we should do with a NULL dn */ + switch (req->op.search.scope) { + case LDB_SCOPE_BASE: + ldb_asprintf_errstring(ldb, + "NULL Base DN invalid for a base search"); + ret = LDB_ERR_INVALID_DN_SYNTAX; + break; + case LDB_SCOPE_ONELEVEL: + ldb_asprintf_errstring(ldb, + "NULL Base DN invalid for a one-level search"); + ret = LDB_ERR_INVALID_DN_SYNTAX; + break; + case LDB_SCOPE_SUBTREE: + default: + /* We accept subtree searches from a NULL base DN, ie over the whole DB */ + ret = LDB_SUCCESS; + } + } else if (req->op.search.scope == LDB_SCOPE_BASE) { + + /* + * If we are LDB_SCOPE_BASE, do just one search and + * return early. This is critical to ensure we do not + * go into the index code for special DNs, as that + * will try to look up an index record for a special + * record (which doesn't exist). + */ + ret = ldb_kv_search_and_return_base(ldb_kv, ctx); + + ldb_kv->kv_ops->unlock_read(module); + + return ret; + + } else if (ldb_kv->check_base) { + /* + * This database has been marked as + * 'checkBaseOnSearch', so do a spot check of the base + * dn. Also optimise the subsequent filter by filling + * in the ctx->base to be exactly case correct + */ + ret = ldb_kv_search_base( + module, ctx, req->op.search.base, &ctx->base); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + ldb_asprintf_errstring(ldb, + "No such Base DN: %s", + ldb_dn_get_linearized(req->op.search.base)); + } + + } else if (ldb_dn_validate(req->op.search.base) == false) { + + /* We don't want invalid base DNs here */ + ldb_asprintf_errstring(ldb, + "Invalid Base DN: %s", + ldb_dn_get_linearized(req->op.search.base)); + ret = LDB_ERR_INVALID_DN_SYNTAX; + + } else { + /* If we are not checking the base DN life is easy */ + ret = LDB_SUCCESS; + } + + if (ret == LDB_SUCCESS) { + uint32_t match_count = 0; + + ret = ldb_kv_search_indexed(ctx, &match_count); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* Not in the index, therefore OK! */ + ret = LDB_SUCCESS; + + } + /* Check if we got just a normal error. + * In that case proceed to a full search unless we got a + * callback error */ + if (!ctx->request_terminated && ret != LDB_SUCCESS) { + /* Not indexed, so we need to do a full scan */ + if (ldb_kv->warn_unindexed || + ldb_kv->disable_full_db_scan) { + /* useful for debugging when slow performance + * is caused by unindexed searches */ + char *expression = ldb_filter_from_tree(ctx, ctx->tree); + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb FULL SEARCH: %s SCOPE: %s DN: %s", + expression, + req->op.search.scope==LDB_SCOPE_BASE?"base": + req->op.search.scope==LDB_SCOPE_ONELEVEL?"one": + req->op.search.scope==LDB_SCOPE_SUBTREE?"sub":"UNKNOWN", + ldb_dn_get_linearized(req->op.search.base)); + + talloc_free(expression); + } + + if (match_count != 0) { + /* the indexing code gave an error + * after having returned at least one + * entry. This means the indexes are + * corrupt or a database record is + * corrupt. We cannot continue with a + * full search or we may return + * duplicate entries + */ + ldb_kv->kv_ops->unlock_read(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (ldb_kv->disable_full_db_scan) { + ldb_set_errstring(ldb, + "ldb FULL SEARCH disabled"); + ldb_kv->kv_ops->unlock_read(module); + return LDB_ERR_INAPPROPRIATE_MATCHING; + } + + ret = ldb_kv_search_full(ctx); + if (ret != LDB_SUCCESS) { + ldb_set_errstring(ldb, "Indexed and full searches both failed!\n"); + } + } + } + + ldb_kv->kv_ops->unlock_read(module); + + return ret; +} diff --git a/ldb-2.0.8/ldb_ldap/ldb_ldap.c b/ldb-2.0.8/ldb_ldap/ldb_ldap.c new file mode 100644 index 0000000..d722299 --- /dev/null +++ b/ldb-2.0.8/ldb_ldap/ldb_ldap.c @@ -0,0 +1,969 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Simo Sorce 2006 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb_ldap + * + * Component: ldb ldap backend + * + * Description: core files for LDAP backend + * + * Author: Andrew Tridgell + * + * Modifications: + * + * - description: make the module use asynchronous calls + * date: Feb 2006 + * author: Simo Sorce + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_module.h" +#include "ldb_private.h" + +#define LDAP_DEPRECATED 1 +#include + +struct lldb_private { + LDAP *ldap; +}; + +struct lldb_context { + struct ldb_module *module; + struct ldb_request *req; + + struct lldb_private *lldb; + + struct ldb_control **controls; + int msgid; +}; + +static int lldb_ldap_to_ldb(int err) { + /* Ldap errors and ldb errors are defined to the same values */ + return err; +} + +/* + convert a ldb_message structure to a list of LDAPMod structures + ready for ldap_add() or ldap_modify() +*/ +static LDAPMod **lldb_msg_to_mods(void *mem_ctx, const struct ldb_message *msg, int use_flags) +{ + LDAPMod **mods; + unsigned int i, j; + int num_mods = 0; + + /* allocate maximum number of elements needed */ + mods = talloc_array(mem_ctx, LDAPMod *, msg->num_elements+1); + if (!mods) { + errno = ENOMEM; + return NULL; + } + mods[0] = NULL; + + for (i=0;inum_elements;i++) { + const struct ldb_message_element *el = &msg->elements[i]; + + mods[num_mods] = talloc(mods, LDAPMod); + if (!mods[num_mods]) { + goto failed; + } + mods[num_mods+1] = NULL; + mods[num_mods]->mod_op = LDAP_MOD_BVALUES; + if (use_flags) { + switch (el->flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + mods[num_mods]->mod_op |= LDAP_MOD_ADD; + break; + case LDB_FLAG_MOD_DELETE: + mods[num_mods]->mod_op |= LDAP_MOD_DELETE; + break; + case LDB_FLAG_MOD_REPLACE: + mods[num_mods]->mod_op |= LDAP_MOD_REPLACE; + break; + } + } + mods[num_mods]->mod_type = discard_const_p(char, el->name); + mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], + struct berval *, + 1+el->num_values); + if (!mods[num_mods]->mod_vals.modv_bvals) { + goto failed; + } + + for (j=0;jnum_values;j++) { + mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals, + struct berval); + if (!mods[num_mods]->mod_vals.modv_bvals[j]) { + goto failed; + } + mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = (char *)el->values[j].data; + mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length; + } + mods[num_mods]->mod_vals.modv_bvals[j] = NULL; + num_mods++; + } + + return mods; + +failed: + talloc_free(mods); + return NULL; +} + +/* + add a single set of ldap message values to a ldb_message +*/ +static int lldb_add_msg_attr(struct ldb_context *ldb, + struct ldb_message *msg, + const char *attr, struct berval **bval) +{ + int count, i, ret; + struct ldb_message_element *el; + + count = ldap_count_values_len(bval); + + if (count <= 0) { + return -1; + } + + ret = ldb_msg_add_empty(msg, attr, 0, &el); + if (ret != LDB_SUCCESS) { + errno = ENOMEM; + return -1; + } + + el->values = talloc_array(msg->elements, struct ldb_val, count); + if (!el->values) { + errno = ENOMEM; + return -1; + } + + for (i=0;ivalues[i].data = talloc_size(el->values, bval[i]->bv_len+1); + if (!el->values[i].data) { + errno = ENOMEM; + return -1; + } + memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len); + el->values[i].data[bval[i]->bv_len] = 0; + el->values[i].length = bval[i]->bv_len; + el->num_values++; + } + + msg->num_elements++; + + return 0; +} + +/* + search for matching records +*/ +static int lldb_search(struct lldb_context *lldb_ac) +{ + struct ldb_context *ldb; + struct lldb_private *lldb = lldb_ac->lldb; + struct ldb_module *module = lldb_ac->module; + struct ldb_request *req = lldb_ac->req; + struct timeval tv; + int ldap_scope; + char *search_base; + char *expression; + int ret; + + ldb = ldb_module_get_ctx(module); + + if (!req->callback || !req->context) { + ldb_set_errstring(ldb, "Async interface called with NULL callback function or NULL context"); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->op.search.tree == NULL) { + ldb_set_errstring(ldb, "Invalid expression parse tree"); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->controls != NULL) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!"); + } + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + search_base = ldb_dn_alloc_linearized(lldb_ac, req->op.search.base); + if (req->op.search.base == NULL) { + search_base = talloc_strdup(lldb_ac, ""); + } + if (search_base == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + expression = ldb_filter_from_tree(lldb_ac, req->op.search.tree); + if (expression == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + switch (req->op.search.scope) { + case LDB_SCOPE_BASE: + ldap_scope = LDAP_SCOPE_BASE; + break; + case LDB_SCOPE_ONELEVEL: + ldap_scope = LDAP_SCOPE_ONELEVEL; + break; + default: + ldap_scope = LDAP_SCOPE_SUBTREE; + break; + } + + tv.tv_sec = 0; + tv.tv_usec = 0; + if (req->timeout > 0) { + tv.tv_sec = req->timeout; + } + + ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope, + expression, + discard_const_p(char *, req->op.search.attrs), + 0, + NULL, + NULL, + &tv, + LDAP_NO_LIMIT, + &lldb_ac->msgid); + + if (ret != LDAP_SUCCESS) { + ldb_set_errstring(ldb, ldap_err2string(ret)); + } + + return lldb_ldap_to_ldb(ret); +} + +/* + add a record +*/ +static int lldb_add(struct lldb_context *lldb_ac) +{ + struct ldb_context *ldb; + struct lldb_private *lldb = lldb_ac->lldb; + struct ldb_module *module = lldb_ac->module; + struct ldb_request *req = lldb_ac->req; + LDAPMod **mods; + char *dn; + int ret; + + ldb = ldb_module_get_ctx(module); + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + mods = lldb_msg_to_mods(lldb_ac, req->op.add.message, 0); + if (mods == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + dn = ldb_dn_alloc_linearized(lldb_ac, req->op.add.message->dn); + if (dn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldap_add_ext(lldb->ldap, dn, mods, + NULL, + NULL, + &lldb_ac->msgid); + + if (ret != LDAP_SUCCESS) { + ldb_set_errstring(ldb, ldap_err2string(ret)); + } + + return lldb_ldap_to_ldb(ret); +} + +/* + modify a record +*/ +static int lldb_modify(struct lldb_context *lldb_ac) +{ + struct ldb_context *ldb; + struct lldb_private *lldb = lldb_ac->lldb; + struct ldb_module *module = lldb_ac->module; + struct ldb_request *req = lldb_ac->req; + LDAPMod **mods; + char *dn; + int ret; + + ldb = ldb_module_get_ctx(module); + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + mods = lldb_msg_to_mods(lldb_ac, req->op.mod.message, 1); + if (mods == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + dn = ldb_dn_alloc_linearized(lldb_ac, req->op.mod.message->dn); + if (dn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldap_modify_ext(lldb->ldap, dn, mods, + NULL, + NULL, + &lldb_ac->msgid); + + if (ret != LDAP_SUCCESS) { + ldb_set_errstring(ldb, ldap_err2string(ret)); + } + + return lldb_ldap_to_ldb(ret); +} + +/* + delete a record +*/ +static int lldb_delete(struct lldb_context *lldb_ac) +{ + struct ldb_context *ldb; + struct lldb_private *lldb = lldb_ac->lldb; + struct ldb_module *module = lldb_ac->module; + struct ldb_request *req = lldb_ac->req; + char *dnstr; + int ret; + + ldb = ldb_module_get_ctx(module); + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + dnstr = ldb_dn_alloc_linearized(lldb_ac, req->op.del.dn); + + ret = ldap_delete_ext(lldb->ldap, dnstr, + NULL, + NULL, + &lldb_ac->msgid); + + if (ret != LDAP_SUCCESS) { + ldb_set_errstring(ldb, ldap_err2string(ret)); + } + + return lldb_ldap_to_ldb(ret); +} + +/* + rename a record +*/ +static int lldb_rename(struct lldb_context *lldb_ac) +{ + struct ldb_context *ldb; + struct lldb_private *lldb = lldb_ac->lldb; + struct ldb_module *module = lldb_ac->module; + struct ldb_request *req = lldb_ac->req; + const char *rdn_name; + const struct ldb_val *rdn_val; + char *old_dn; + char *newrdn; + char *parentdn; + int ret; + + ldb = ldb_module_get_ctx(module); + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + old_dn = ldb_dn_alloc_linearized(lldb_ac, req->op.rename.olddn); + if (old_dn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + rdn_name = ldb_dn_get_rdn_name(req->op.rename.newdn); + rdn_val = ldb_dn_get_rdn_val(req->op.rename.newdn); + + if ((rdn_name != NULL) && (rdn_val != NULL)) { + newrdn = talloc_asprintf(lldb_ac, "%s=%s", rdn_name, + rdn_val->length > 0 ? ldb_dn_escape_value(lldb, *rdn_val) : ""); + } else { + newrdn = talloc_strdup(lldb_ac, ""); + } + if (!newrdn) { + return LDB_ERR_OPERATIONS_ERROR; + } + + parentdn = ldb_dn_alloc_linearized(lldb_ac, ldb_dn_get_parent(lldb_ac, req->op.rename.newdn)); + if (!parentdn) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn, + 1, NULL, NULL, + &lldb_ac->msgid); + + if (ret != LDAP_SUCCESS) { + ldb_set_errstring(ldb, ldap_err2string(ret)); + } + + return lldb_ldap_to_ldb(ret); +} + +static int lldb_start_trans(struct ldb_module *module) +{ + /* TODO implement a local transaction mechanism here */ + + return LDB_SUCCESS; +} + +static int lldb_end_trans(struct ldb_module *module) +{ + /* TODO implement a local transaction mechanism here */ + + return LDB_SUCCESS; +} + +static int lldb_del_trans(struct ldb_module *module) +{ + /* TODO implement a local transaction mechanism here */ + + return LDB_SUCCESS; +} + +static void lldb_request_done(struct lldb_context *ac, + struct ldb_control **ctrls, int error) +{ + struct ldb_request *req; + struct ldb_reply *ares; + + req = ac->req; + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(ldb_module_get_ctx(ac->module)); + req->callback(req, NULL); + return; + } + ares->type = LDB_REPLY_DONE; + ares->controls = talloc_steal(ares, ctrls); + ares->error = error; + + req->callback(req, ares); +} + +/* return false if the request is still in progress + * return true if the request is completed + */ +static bool lldb_parse_result(struct lldb_context *ac, LDAPMessage *result) +{ + struct ldb_context *ldb; + struct lldb_private *lldb = ac->lldb; + LDAPControl **serverctrlsp = NULL; + char **referralsp = NULL; + char *matcheddnp = NULL; + char *errmsgp = NULL; + LDAPMessage *msg; + int type; + struct ldb_message *ldbmsg = NULL; + char *referral; + bool callback_failed; + bool request_done; + bool lret; + unsigned int i; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + type = ldap_msgtype(result); + callback_failed = false; + request_done = false; + + switch (type) { + case LDAP_RES_SEARCH_ENTRY: + + msg = ldap_first_entry(lldb->ldap, result); + if (msg != NULL) { + BerElement *berptr = NULL; + char *attr, *dn; + + ldbmsg = ldb_msg_new(ac); + if (!ldbmsg) { + ldb_oom(ldb); + ret = LDB_ERR_OPERATIONS_ERROR; + break; + } + + dn = ldap_get_dn(lldb->ldap, msg); + if (!dn) { + ldb_oom(ldb); + talloc_free(ldbmsg); + ret = LDB_ERR_OPERATIONS_ERROR; + break; + } + ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, dn); + if ( ! ldb_dn_validate(ldbmsg->dn)) { + ldb_asprintf_errstring(ldb, "Invalid DN '%s' in reply", dn); + talloc_free(ldbmsg); + ret = LDB_ERR_OPERATIONS_ERROR; + ldap_memfree(dn); + break; + } + ldap_memfree(dn); + /* loop over all attributes */ + for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr); + attr; + attr=ldap_next_attribute(lldb->ldap, msg, berptr)) { + struct berval **bval; + bval = ldap_get_values_len(lldb->ldap, msg, attr); + + if (bval) { + lldb_add_msg_attr(ldb, ldbmsg, attr, bval); + ldap_value_free_len(bval); + } + } + if (berptr) ber_free(berptr, 0); + + ret = ldb_module_send_entry(ac->req, ldbmsg, NULL /* controls not yet supported */); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, "entry send failed: %s", + ldb_errstring(ldb)); + callback_failed = true; + } + } else { + ret = LDB_ERR_OPERATIONS_ERROR; + } + break; + + case LDAP_RES_SEARCH_REFERENCE: + + ret = ldap_parse_reference(lldb->ldap, result, + &referralsp, &serverctrlsp, 0); + if (ret != LDAP_SUCCESS) { + ldb_asprintf_errstring(ldb, "ldap reference parse error: %s : %s", + ldap_err2string(ret), errmsgp); + ret = LDB_ERR_OPERATIONS_ERROR; + break; + } + if (referralsp == NULL) { + ldb_asprintf_errstring(ldb, "empty ldap referrals list"); + ret = LDB_ERR_PROTOCOL_ERROR; + break; + } + + for (i = 0; referralsp[i]; i++) { + referral = talloc_strdup(ac, referralsp[i]); + + ret = ldb_module_send_referral(ac->req, referral); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, "referral send failed: %s", + ldb_errstring(ldb)); + callback_failed = true; + break; + } + } + break; + + case LDAP_RES_SEARCH_RESULT: + case LDAP_RES_MODIFY: + case LDAP_RES_ADD: + case LDAP_RES_DELETE: + case LDAP_RES_MODDN: + + if (ldap_parse_result(lldb->ldap, result, &ret, + &matcheddnp, &errmsgp, + &referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) { + ret = LDB_ERR_OPERATIONS_ERROR; + } + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, "ldap parse error for type %d: %s : %s", + type, ldap_err2string(ret), errmsgp); + break; + } + + if (serverctrlsp != NULL) { + /* FIXME: transform the LDAPControl list into an ldb_control one */ + ac->controls = NULL; + } + + request_done = true; + break; + + default: + ldb_asprintf_errstring(ldb, "unknown ldap return type: %d", type); + ret = LDB_ERR_PROTOCOL_ERROR; + break; + } + + if (ret != LDB_SUCCESS) { + + /* if the callback failed the caller will have freed the + * request. Just return and don't try to use it */ + if (callback_failed) { + + /* tell lldb_wait to remove the request from the + * queue */ + lret = true; + goto free_and_return; + } + + request_done = true; + } + + if (request_done) { + lldb_request_done(ac, ac->controls, ret); + lret = true; + goto free_and_return; + } + + lret = false; + +free_and_return: + + if (matcheddnp) ldap_memfree(matcheddnp); + if (errmsgp && *errmsgp) { + ldb_set_errstring(ldb, errmsgp); + } + if (errmsgp) { + ldap_memfree(errmsgp); + } + if (referralsp) ldap_value_free(referralsp); + if (serverctrlsp) ldap_controls_free(serverctrlsp); + + ldap_msgfree(result); + + return lret; +} + +static void lldb_timeout(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, + void *private_data) +{ + struct lldb_context *ac; + ac = talloc_get_type(private_data, struct lldb_context); + + lldb_request_done(ac, NULL, LDB_ERR_TIME_LIMIT_EXCEEDED); +} + +static void lldb_callback(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, + void *private_data) +{ + struct lldb_context *ac; + struct tevent_timer *lte; + struct timeval tv; + LDAPMessage *result; + int lret; + + ac = talloc_get_type(private_data, struct lldb_context); + + if (!ac->msgid) { + lldb_request_done(ac, NULL, LDB_ERR_OPERATIONS_ERROR); + return; + } + + tv.tv_sec = 0; + tv.tv_usec = 0; + lret = ldap_result(ac->lldb->ldap, ac->msgid, 0, &tv, &result); + if (lret == 0) { + goto respin; + } + if (lret == -1) { + lldb_request_done(ac, NULL, LDB_ERR_OPERATIONS_ERROR); + return; + } + + if ( ! lldb_parse_result(ac, result)) { + goto respin; + } + + return; + +respin: + tv.tv_sec = 0; + tv.tv_usec = 100; + lte = tevent_add_timer(ev, ac, tv, lldb_callback, ac); + if (NULL == lte) { + lldb_request_done(ac, NULL, LDB_ERR_OPERATIONS_ERROR); + } +} + +static bool lldb_dn_is_special(struct ldb_request *req) +{ + struct ldb_dn *dn = NULL; + + switch (req->operation) { + case LDB_ADD: + dn = req->op.add.message->dn; + break; + case LDB_MODIFY: + dn = req->op.mod.message->dn; + break; + case LDB_DELETE: + dn = req->op.del.dn; + break; + case LDB_RENAME: + dn = req->op.rename.olddn; + break; + default: + break; + } + + if (dn && ldb_dn_is_special(dn)) { + return true; + } + return false; +} + +static void lldb_auto_done_callback(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, + void *private_data) +{ + struct lldb_context *ac; + + ac = talloc_get_type(private_data, struct lldb_context); + lldb_request_done(ac, NULL, LDB_SUCCESS); +} + +static int lldb_handle_request(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct lldb_private *lldb; + struct lldb_context *ac; + struct tevent_context *ev; + struct tevent_timer *te; + struct timeval tv; + int ret; + + lldb = talloc_get_type(ldb_module_get_private(module), struct lldb_private); + ldb = ldb_module_get_ctx(module); + + if (req->starttime == 0 || req->timeout == 0) { + ldb_set_errstring(ldb, "Invalid timeout settings"); + return LDB_ERR_TIME_LIMIT_EXCEEDED; + } + + ev = ldb_get_event_context(ldb); + if (NULL == ev) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac = talloc_zero(ldb, struct lldb_context); + if (ac == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->module = module; + ac->req = req; + ac->lldb = lldb; + ac->msgid = 0; + + if (lldb_dn_is_special(req)) { + tv.tv_sec = 0; + tv.tv_usec = 0; + te = tevent_add_timer(ev, ac, tv, + lldb_auto_done_callback, ac); + if (NULL == te) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; + } + + switch (ac->req->operation) { + case LDB_SEARCH: + ret = lldb_search(ac); + break; + case LDB_ADD: + ret = lldb_add(ac); + break; + case LDB_MODIFY: + ret = lldb_modify(ac); + break; + case LDB_DELETE: + ret = lldb_delete(ac); + break; + case LDB_RENAME: + ret = lldb_rename(ac); + break; + default: + /* no other op supported */ + ret = LDB_ERR_PROTOCOL_ERROR; + break; + } + + if (ret != LDB_SUCCESS) { + lldb_request_done(ac, NULL, ret); + return ret; + } + + tv.tv_sec = 0; + tv.tv_usec = 0; + te = tevent_add_timer(ev, ac, tv, lldb_callback, ac); + if (NULL == te) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->timeout > 0) { + tv.tv_sec = req->starttime + req->timeout; + tv.tv_usec = 0; + te = tevent_add_timer(ev, ac, tv, lldb_timeout, ac); + if (NULL == te) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + return LDB_SUCCESS; +} + +static const struct ldb_module_ops lldb_ops = { + .name = "ldap", + .search = lldb_handle_request, + .add = lldb_handle_request, + .modify = lldb_handle_request, + .del = lldb_handle_request, + .rename = lldb_handle_request, + .request = lldb_handle_request, + .start_transaction = lldb_start_trans, + .end_transaction = lldb_end_trans, + .del_transaction = lldb_del_trans, +}; + + +static int lldb_destructor(struct lldb_private *lldb) +{ + ldap_unbind(lldb->ldap); + return 0; +} + + +/* + optionally perform a bind + */ +static int lldb_bind(struct ldb_module *module, + const char *options[]) +{ + const char *bind_mechanism; + struct lldb_private *lldb; + struct ldb_context *ldb = ldb_module_get_ctx(module); + int ret; + + bind_mechanism = ldb_options_find(ldb, options, "bindMech"); + if (bind_mechanism == NULL) { + /* no bind wanted */ + return LDB_SUCCESS; + } + + lldb = talloc_get_type(ldb_module_get_private(module), struct lldb_private); + + if (strcmp(bind_mechanism, "simple") == 0) { + const char *bind_id, *bind_secret; + + bind_id = ldb_options_find(ldb, options, "bindID"); + bind_secret = ldb_options_find(ldb, options, "bindSecret"); + if (bind_id == NULL || bind_secret == NULL) { + ldb_asprintf_errstring(ldb, "simple bind requires bindID and bindSecret"); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldap_simple_bind_s(lldb->ldap, bind_id, bind_secret); + if (ret != LDAP_SUCCESS) { + ldb_asprintf_errstring(ldb, "bind failed: %s", ldap_err2string(ret)); + return ret; + } + return LDB_SUCCESS; + } + + ldb_asprintf_errstring(ldb, "bind failed: unknown mechanism %s", bind_mechanism); + return LDB_ERR_INAPPROPRIATE_AUTHENTICATION; +} + +/* + connect to the database +*/ +static int lldb_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[], + struct ldb_module **_module) +{ + struct ldb_module *module; + struct lldb_private *lldb; + int version = 3; + int ret; + + module = ldb_module_new(ldb, ldb, "ldb_ldap backend", &lldb_ops); + if (!module) return LDB_ERR_OPERATIONS_ERROR; + + lldb = talloc_zero(module, struct lldb_private); + if (!lldb) { + ldb_oom(ldb); + goto failed; + } + ldb_module_set_private(module, lldb); + + ret = ldap_initialize(&lldb->ldap, url); + if (ret != LDAP_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s", + url, ldap_err2string(ret)); + goto failed; + } + + talloc_set_destructor(lldb, lldb_destructor); + + ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); + if (ret != LDAP_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s", + ldap_err2string(ret)); + goto failed; + } + + *_module = module; + + ret = lldb_bind(module, options); + if (ret != LDB_SUCCESS) { + goto failed; + } + + + return LDB_SUCCESS; + +failed: + talloc_free(module); + return LDB_ERR_OPERATIONS_ERROR; +} + +/* + initialise the module + */ +int ldb_ldap_init(const char *version) +{ + int ret, i; + const char *names[] = { "ldap", "ldaps", "ldapi", NULL }; + LDB_MODULE_CHECK_VERSION(version); + for (i=0; names[i]; i++) { + ret = ldb_register_backend(names[i], lldb_connect, false); + if (ret != LDB_SUCCESS) { + return ret; + } + } + return LDB_SUCCESS; +} diff --git a/ldb-2.0.8/ldb_ldb/ldb_ldb.c b/ldb-2.0.8/ldb_ldb/ldb_ldb.c new file mode 100644 index 0000000..a5a3612 --- /dev/null +++ b/ldb-2.0.8/ldb_ldb/ldb_ldb.c @@ -0,0 +1,80 @@ +/* + * ldb connection and module initialisation + * + * Copyright (C) Andrew Bartlett 2018 + * + * 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 . + * + */ +#include "ldb_private.h" +#include "../ldb_tdb/ldb_tdb.h" +#ifdef HAVE_LMDB +#include "../ldb_mdb/ldb_mdb.h" +#endif /* HAVE_LMDB */ + +/* + connect to the database +*/ +static int lldb_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[], + struct ldb_module **module) +{ + const char *path; + int ret; + + /* + * Check and remove the url prefix + */ + if (strchr(url, ':')) { + if (strncmp(url, "ldb://", 6) != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Invalid ldb URL '%s'", url); + return LDB_ERR_OPERATIONS_ERROR; + } + path = url+6; + } else { + path = url; + } + + /* + * Don't create the database if it's not there + */ + flags |= LDB_FLG_DONT_CREATE_DB; +#ifdef HAVE_LMDB + /* + * Try opening the database as an lmdb + */ + ret = lmdb_connect(ldb, path, flags, options, module); + if (ret == LDB_SUCCESS) { + return ret; + } + if (ret != LDB_ERR_UNAVAILABLE) { + return ret; + } + + /* + * Not mdb so try as tdb + */ +#endif /* HAVE_LMDB */ + ret = ltdb_connect(ldb, path, flags, options, module); + return ret; +} + +int ldb_ldb_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_backend("ldb", lldb_connect, false); +} diff --git a/ldb-2.0.8/ldb_map/ldb_map.c b/ldb-2.0.8/ldb_map/ldb_map.c new file mode 100644 index 0000000..b453dff --- /dev/null +++ b/ldb-2.0.8/ldb_map/ldb_map.c @@ -0,0 +1,1156 @@ +/* + ldb database mapping module + + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Martin Kuehl 2006 + Copyright (C) Simo Sorce 2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . + +*/ + +/* + * Name: ldb + * + * Component: ldb ldb_map module + * + * Description: Map portions of data into a different format on a + * remote partition. + * + * Author: Jelmer Vernooij, Martin Kuehl + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_map.h" +#include "ldb_map_private.h" + +#ifndef _PUBLIC_ +#define _PUBLIC_ +#endif + +/* Description of the provided ldb requests: + - special attribute 'isMapped' + + - search: + - if parse tree can be split + - search remote records w/ remote attrs and parse tree + - otherwise + - enumerate all remote records + - for each remote result + - map remote result to local message + - search local result + - is present + - merge local into remote result + - run callback on merged result + - otherwise + - run callback on remote result + + - add: + - split message into local and remote part + - if local message is not empty + - add isMapped to local message + - add local message + - add remote message + + - modify: + - split message into local and remote part + - if local message is not empty + - add isMapped to local message + - search for local record + - if present + - modify local record + - otherwise + - add local message + - modify remote record + + - delete: + - search for local record + - if present + - delete local record + - delete remote record + + - rename: + - search for local record + - if present + - rename local record + - modify local isMapped + - rename remote record +*/ + + + +/* Private data structures + * ======================= */ + +/* Global private data */ +/* Extract mappings from private data. */ +const struct ldb_map_context *map_get_context(struct ldb_module *module) +{ + const struct map_private *data = talloc_get_type(ldb_module_get_private(module), struct map_private); + return data->context; +} + +/* Create a generic request context. */ +struct map_context *map_init_context(struct ldb_module *module, + struct ldb_request *req) +{ + struct ldb_context *ldb; + struct map_context *ac; + + ldb = ldb_module_get_ctx(module); + + ac = talloc_zero(req, struct map_context); + if (ac == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return NULL; + } + + ac->module = module; + ac->req = req; + + return ac; +} + +/* Dealing with DNs for different partitions + * ========================================= */ + +/* Check whether any data should be stored in the local partition. */ +bool map_check_local_db(struct ldb_module *module) +{ + const struct ldb_map_context *data = map_get_context(module); + + if (!data->remote_base_dn || !data->local_base_dn) { + return false; + } + + return true; +} + +/* Copy a DN with the base DN of the local partition. */ +static struct ldb_dn *ldb_dn_rebase_local(void *mem_ctx, const struct ldb_map_context *data, struct ldb_dn *dn) +{ + struct ldb_dn *new_dn; + + new_dn = ldb_dn_copy(mem_ctx, dn); + if ( ! ldb_dn_validate(new_dn)) { + talloc_free(new_dn); + return NULL; + } + + /* may be we don't need to rebase at all */ + if ( ! data->remote_base_dn || ! data->local_base_dn) { + return new_dn; + } + + if ( ! ldb_dn_remove_base_components(new_dn, ldb_dn_get_comp_num(data->remote_base_dn))) { + talloc_free(new_dn); + return NULL; + } + + if ( ! ldb_dn_add_base(new_dn, data->local_base_dn)) { + talloc_free(new_dn); + return NULL; + } + + return new_dn; +} + +/* Copy a DN with the base DN of the remote partition. */ +static struct ldb_dn *ldb_dn_rebase_remote(void *mem_ctx, const struct ldb_map_context *data, struct ldb_dn *dn) +{ + struct ldb_dn *new_dn; + + new_dn = ldb_dn_copy(mem_ctx, dn); + if ( ! ldb_dn_validate(new_dn)) { + talloc_free(new_dn); + return NULL; + } + + /* may be we don't need to rebase at all */ + if ( ! data->remote_base_dn || ! data->local_base_dn) { + return new_dn; + } + + if ( ! ldb_dn_remove_base_components(new_dn, ldb_dn_get_comp_num(data->local_base_dn))) { + talloc_free(new_dn); + return NULL; + } + + if ( ! ldb_dn_add_base(new_dn, data->remote_base_dn)) { + talloc_free(new_dn); + return NULL; + } + + return new_dn; +} + +/* Run a request and make sure it targets the remote partition. */ +/* TODO: free old DNs and messages? */ +int ldb_next_remote_request(struct ldb_module *module, struct ldb_request *request) +{ + const struct ldb_map_context *data = map_get_context(module); + struct ldb_context *ldb; + struct ldb_message *msg; + + ldb = ldb_module_get_ctx(module); + + switch (request->operation) { + case LDB_SEARCH: + if (request->op.search.base) { + request->op.search.base = ldb_dn_rebase_remote(request, data, request->op.search.base); + } else { + request->op.search.base = data->remote_base_dn; + /* TODO: adjust scope? */ + } + break; + + case LDB_ADD: + msg = ldb_msg_copy_shallow(request, request->op.add.message); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn); + request->op.add.message = msg; + break; + + case LDB_MODIFY: + msg = ldb_msg_copy_shallow(request, request->op.mod.message); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn); + request->op.mod.message = msg; + break; + + case LDB_DELETE: + request->op.del.dn = ldb_dn_rebase_remote(request, data, request->op.del.dn); + break; + + case LDB_RENAME: + request->op.rename.olddn = ldb_dn_rebase_remote(request, data, request->op.rename.olddn); + request->op.rename.newdn = ldb_dn_rebase_remote(request, data, request->op.rename.newdn); + break; + + default: + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "Invalid remote request!"); + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(module, request); +} + + +/* Finding mappings for attributes and objectClasses + * ================================================= */ + +/* Find an objectClass mapping by the local name. */ +static const struct ldb_map_objectclass *map_objectclass_find_local(const struct ldb_map_context *data, const char *name) +{ + unsigned int i; + + for (i = 0; data->objectclass_maps && data->objectclass_maps[i].local_name; i++) { + if (ldb_attr_cmp(data->objectclass_maps[i].local_name, name) == 0) { + return &data->objectclass_maps[i]; + } + } + + return NULL; +} + +/* Find an objectClass mapping by the remote name. */ +static const struct ldb_map_objectclass *map_objectclass_find_remote(const struct ldb_map_context *data, const char *name) +{ + unsigned int i; + + for (i = 0; data->objectclass_maps && data->objectclass_maps[i].remote_name; i++) { + if (ldb_attr_cmp(data->objectclass_maps[i].remote_name, name) == 0) { + return &data->objectclass_maps[i]; + } + } + + return NULL; +} + +/* Find an attribute mapping by the local name. */ +const struct ldb_map_attribute *map_attr_find_local(const struct ldb_map_context *data, const char *name) +{ + unsigned int i; + + for (i = 0; data->attribute_maps[i].local_name; i++) { + if (ldb_attr_cmp(data->attribute_maps[i].local_name, name) == 0) { + return &data->attribute_maps[i]; + } + } + for (i = 0; data->attribute_maps[i].local_name; i++) { + if (ldb_attr_cmp(data->attribute_maps[i].local_name, "*") == 0) { + return &data->attribute_maps[i]; + } + } + + return NULL; +} + +/* Find an attribute mapping by the remote name. */ +const struct ldb_map_attribute *map_attr_find_remote(const struct ldb_map_context *data, const char *name) +{ + const struct ldb_map_attribute *map; + const struct ldb_map_attribute *wildcard = NULL; + unsigned int i, j; + + for (i = 0; data->attribute_maps[i].local_name; i++) { + map = &data->attribute_maps[i]; + if (ldb_attr_cmp(map->local_name, "*") == 0) { + wildcard = &data->attribute_maps[i]; + } + + switch (map->type) { + case LDB_MAP_IGNORE: + break; + + case LDB_MAP_KEEP: + if (ldb_attr_cmp(map->local_name, name) == 0) { + return map; + } + break; + + case LDB_MAP_RENAME: + case LDB_MAP_RENDROP: + case LDB_MAP_CONVERT: + if (ldb_attr_cmp(map->u.rename.remote_name, name) == 0) { + return map; + } + break; + + case LDB_MAP_GENERATE: + for (j = 0; map->u.generate.remote_names[j]; j++) { + if (ldb_attr_cmp(map->u.generate.remote_names[j], name) == 0) { + return map; + } + } + break; + } + } + + /* We didn't find it, so return the wildcard record if one was configured */ + return wildcard; +} + + +/* Mapping attributes + * ================== */ + +/* Check whether an attribute will be mapped into the remote partition. */ +bool map_attr_check_remote(const struct ldb_map_context *data, const char *attr) +{ + const struct ldb_map_attribute *map = map_attr_find_local(data, attr); + + if (map == NULL) { + return false; + } + if (map->type == LDB_MAP_IGNORE) { + return false; + } + + return true; +} + +/* Map an attribute name into the remote partition. */ +const char *map_attr_map_local(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr) +{ + if (map == NULL) { + return talloc_strdup(mem_ctx, attr); + } + + switch (map->type) { + case LDB_MAP_KEEP: + return talloc_strdup(mem_ctx, attr); + + case LDB_MAP_RENAME: + case LDB_MAP_RENDROP: + case LDB_MAP_CONVERT: + return talloc_strdup(mem_ctx, map->u.rename.remote_name); + + default: + return NULL; + } +} + +/* Map an attribute name back into the local partition. */ +const char *map_attr_map_remote(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr) +{ + if (map == NULL) { + return talloc_strdup(mem_ctx, attr); + } + + if (map->type == LDB_MAP_KEEP) { + return talloc_strdup(mem_ctx, attr); + } + + return talloc_strdup(mem_ctx, map->local_name); +} + + +/* Merge two lists of attributes into a single one. */ +int map_attrs_merge(struct ldb_module *module, void *mem_ctx, + const char ***attrs, const char * const *more_attrs) +{ + unsigned int i, j, k; + + for (i = 0; *attrs && (*attrs)[i]; i++) /* noop */ ; + for (j = 0; more_attrs && more_attrs[j]; j++) /* noop */ ; + + *attrs = talloc_realloc(mem_ctx, *attrs, const char *, i+j+1); + if (*attrs == NULL) { + map_oom(module); + return -1; + } + + for (k = 0; k < j; k++) { + (*attrs)[i + k] = more_attrs[k]; + } + + (*attrs)[i+k] = NULL; + + return 0; +} + +/* Mapping ldb values + * ================== */ + +/* Map an ldb value into the remote partition. */ +struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, + const struct ldb_map_attribute *map, const struct ldb_val *val) +{ + if (map && (map->type == LDB_MAP_CONVERT) && (map->u.convert.convert_local)) { + return map->u.convert.convert_local(module, mem_ctx, val); + } + + return ldb_val_dup(mem_ctx, val); +} + +/* Map an ldb value back into the local partition. */ +struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, + const struct ldb_map_attribute *map, const struct ldb_val *val) +{ + if (map && (map->type == LDB_MAP_CONVERT) && (map->u.convert.convert_remote)) { + return map->u.convert.convert_remote(module, mem_ctx, val); + } + + return ldb_val_dup(mem_ctx, val); +} + + +/* Mapping DNs + * =========== */ + +/* Check whether a DN is below the local baseDN. */ +bool ldb_dn_check_local(struct ldb_module *module, struct ldb_dn *dn) +{ + const struct ldb_map_context *data = map_get_context(module); + + if (!data->local_base_dn) { + return true; + } + + return ldb_dn_compare_base(data->local_base_dn, dn) == 0; +} + +/* Map a DN into the remote partition. */ +struct ldb_dn *ldb_dn_map_local(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn) +{ + const struct ldb_map_context *data = map_get_context(module); + struct ldb_context *ldb; + struct ldb_dn *newdn; + const struct ldb_map_attribute *map; + enum ldb_map_attr_type map_type; + const char *name; + struct ldb_val value; + int i, ret; + + if (dn == NULL) { + return NULL; + } + + ldb = ldb_module_get_ctx(module); + + newdn = ldb_dn_copy(mem_ctx, dn); + if (newdn == NULL) { + map_oom(module); + return NULL; + } + + /* For each RDN, map the component name and possibly the value */ + for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) { + map = map_attr_find_local(data, ldb_dn_get_component_name(dn, i)); + + /* Unknown attribute - leave this RDN as is and hope the best... */ + if (map == NULL) { + map_type = LDB_MAP_KEEP; + } else { + map_type = map->type; + } + + switch (map_type) { + case LDB_MAP_IGNORE: + case LDB_MAP_GENERATE: + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' " + "used in DN!", ldb_dn_get_component_name(dn, i)); + goto failed; + + case LDB_MAP_CONVERT: + if (map->u.convert.convert_local == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "'convert_local' not set for attribute '%s' " + "used in DN!", ldb_dn_get_component_name(dn, i)); + goto failed; + } + + FALL_THROUGH; + case LDB_MAP_KEEP: + case LDB_MAP_RENAME: + case LDB_MAP_RENDROP: + name = map_attr_map_local(newdn, map, ldb_dn_get_component_name(dn, i)); + if (name == NULL) goto failed; + + value = ldb_val_map_local(module, newdn, map, ldb_dn_get_component_val(dn, i)); + if (value.data == NULL) goto failed; + + ret = ldb_dn_set_component(newdn, i, name, value); + if (ret != LDB_SUCCESS) { + goto failed; + } + + break; + } + } + + return newdn; + +failed: + talloc_free(newdn); + return NULL; +} + +/* Map a DN into the local partition. */ +struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn) +{ + const struct ldb_map_context *data = map_get_context(module); + struct ldb_context *ldb; + struct ldb_dn *newdn; + const struct ldb_map_attribute *map; + enum ldb_map_attr_type map_type; + const char *name; + struct ldb_val value; + int i, ret; + + if (dn == NULL) { + return NULL; + } + + ldb = ldb_module_get_ctx(module); + + newdn = ldb_dn_copy(mem_ctx, dn); + if (newdn == NULL) { + map_oom(module); + return NULL; + } + + /* For each RDN, map the component name and possibly the value */ + for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) { + map = map_attr_find_remote(data, ldb_dn_get_component_name(dn, i)); + + /* Unknown attribute - leave this RDN as is and hope the best... */ + if (map == NULL) { + map_type = LDB_MAP_KEEP; + } else { + map_type = map->type; + } + + switch (map_type) { + case LDB_MAP_IGNORE: + case LDB_MAP_GENERATE: + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' " + "used in DN!", ldb_dn_get_component_name(dn, i)); + goto failed; + + case LDB_MAP_CONVERT: + if (map->u.convert.convert_remote == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "'convert_remote' not set for attribute '%s' " + "used in DN!", ldb_dn_get_component_name(dn, i)); + goto failed; + } + + FALL_THROUGH; + case LDB_MAP_KEEP: + case LDB_MAP_RENAME: + case LDB_MAP_RENDROP: + name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i)); + if (name == NULL) goto failed; + + value = ldb_val_map_remote(module, newdn, map, ldb_dn_get_component_val(dn, i)); + if (value.data == NULL) goto failed; + + ret = ldb_dn_set_component(newdn, i, name, value); + if (ret != LDB_SUCCESS) { + goto failed; + } + + break; + } + } + + return newdn; + +failed: + talloc_free(newdn); + return NULL; +} + +/* Map a DN and its base into the local partition. */ +/* TODO: This should not be required with GUIDs. */ +struct ldb_dn *ldb_dn_map_rebase_remote(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn) +{ + const struct ldb_map_context *data = map_get_context(module); + struct ldb_dn *dn1, *dn2; + + dn1 = ldb_dn_rebase_local(mem_ctx, data, dn); + dn2 = ldb_dn_map_remote(module, mem_ctx, dn1); + + talloc_free(dn1); + return dn2; +} + + +/* Converting DNs and objectClasses (as ldb values) + * ================================================ */ + +/* Map a DN contained in an ldb value into the remote partition. */ +static struct ldb_val ldb_dn_convert_local(struct ldb_module *module, void *mem_ctx, const struct ldb_val *val) +{ + struct ldb_context *ldb; + struct ldb_dn *dn, *newdn; + struct ldb_val newval; + + ldb = ldb_module_get_ctx(module); + + dn = ldb_dn_from_ldb_val(mem_ctx, ldb, val); + if (! ldb_dn_validate(dn)) { + newval.length = 0; + newval.data = NULL; + talloc_free(dn); + return newval; + } + newdn = ldb_dn_map_local(module, mem_ctx, dn); + talloc_free(dn); + + newval.length = 0; + newval.data = (uint8_t *)ldb_dn_alloc_linearized(mem_ctx, newdn); + if (newval.data) { + newval.length = strlen((char *)newval.data); + } + talloc_free(newdn); + + return newval; +} + +/* Map a DN contained in an ldb value into the local partition. */ +static struct ldb_val ldb_dn_convert_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_val *val) +{ + struct ldb_context *ldb; + struct ldb_dn *dn, *newdn; + struct ldb_val newval; + + ldb = ldb_module_get_ctx(module); + + dn = ldb_dn_from_ldb_val(mem_ctx, ldb, val); + if (! ldb_dn_validate(dn)) { + newval.length = 0; + newval.data = NULL; + talloc_free(dn); + return newval; + } + newdn = ldb_dn_map_remote(module, mem_ctx, dn); + talloc_free(dn); + + newval.length = 0; + newval.data = (uint8_t *)ldb_dn_alloc_linearized(mem_ctx, newdn); + if (newval.data) { + newval.length = strlen((char *)newval.data); + } + talloc_free(newdn); + + return newval; +} + +/* Map an objectClass into the remote partition. */ +static struct ldb_val map_objectclass_convert_local(struct ldb_module *module, void *mem_ctx, const struct ldb_val *val) +{ + const struct ldb_map_context *data = map_get_context(module); + const char *name = (char *)val->data; + const struct ldb_map_objectclass *map = map_objectclass_find_local(data, name); + struct ldb_val newval; + + if (map) { + newval.data = (uint8_t*)talloc_strdup(mem_ctx, map->remote_name); + newval.length = strlen((char *)newval.data); + return newval; + } + + return ldb_val_dup(mem_ctx, val); +} + +/* Generate a remote message with a mapped objectClass. */ +static void map_objectclass_generate_remote(struct ldb_module *module, const char *local_attr, const struct ldb_message *old, struct ldb_message *remote, struct ldb_message *local) +{ + const struct ldb_map_context *data = map_get_context(module); + struct ldb_context *ldb; + struct ldb_message_element *el, *oc; + struct ldb_val val; + bool found_extensibleObject = false; + unsigned int i; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* Find old local objectClass */ + oc = ldb_msg_find_element(old, "objectClass"); + if (oc == NULL) { + return; + } + + /* Prepare new element */ + el = talloc_zero(remote, struct ldb_message_element); + if (el == NULL) { + ldb_oom(ldb); + return; /* TODO: fail? */ + } + + /* Copy local objectClass element, reverse space for an extra value */ + el->num_values = oc->num_values + 1; + el->values = talloc_array(el, struct ldb_val, el->num_values); + if (el->values == NULL) { + talloc_free(el); + ldb_oom(ldb); + return; /* TODO: fail? */ + } + + /* Copy local element name "objectClass" */ + el->name = talloc_strdup(el, local_attr); + + /* Convert all local objectClasses */ + for (i = 0; i < el->num_values - 1; i++) { + el->values[i] = map_objectclass_convert_local(module, el->values, &oc->values[i]); + if (ldb_attr_cmp((char *)el->values[i].data, data->add_objectclass) == 0) { + found_extensibleObject = true; + } + } + + if (!found_extensibleObject) { + val.data = (uint8_t *)talloc_strdup(el->values, data->add_objectclass); + val.length = strlen((char *)val.data); + + /* Append additional objectClass data->add_objectclass */ + el->values[i] = val; + } else { + el->num_values--; + } + + /* Add new objectClass to remote message */ + ret = ldb_msg_add(remote, el, 0); + if (ret != LDB_SUCCESS) { + ldb_oom(ldb); + return; + } +} + +/* Map an objectClass into the local partition. */ +static struct ldb_val map_objectclass_convert_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_val *val) +{ + const struct ldb_map_context *data = map_get_context(module); + const char *name = (char *)val->data; + const struct ldb_map_objectclass *map = map_objectclass_find_remote(data, name); + struct ldb_val newval; + + if (map) { + newval.data = (uint8_t*)talloc_strdup(mem_ctx, map->local_name); + newval.length = strlen((char *)newval.data); + return newval; + } + + return ldb_val_dup(mem_ctx, val); +} + +/* Generate a local message with a mapped objectClass. */ +static struct ldb_message_element *map_objectclass_generate_local(struct ldb_module *module, void *mem_ctx, const char *local_attr, const struct ldb_message *remote) +{ + const struct ldb_map_context *data = map_get_context(module); + struct ldb_context *ldb; + struct ldb_message_element *el, *oc; + struct ldb_val val; + unsigned int i; + + ldb = ldb_module_get_ctx(module); + + /* Find old remote objectClass */ + oc = ldb_msg_find_element(remote, "objectClass"); + if (oc == NULL) { + return NULL; + } + + /* Prepare new element */ + el = talloc_zero(mem_ctx, struct ldb_message_element); + if (el == NULL) { + ldb_oom(ldb); + return NULL; + } + + /* Copy remote objectClass element */ + el->num_values = oc->num_values; + el->values = talloc_array(el, struct ldb_val, el->num_values); + if (el->values == NULL) { + talloc_free(el); + ldb_oom(ldb); + return NULL; + } + + /* Copy remote element name "objectClass" */ + el->name = talloc_strdup(el, local_attr); + + /* Convert all remote objectClasses */ + for (i = 0; i < el->num_values; i++) { + el->values[i] = map_objectclass_convert_remote(module, el->values, &oc->values[i]); + } + + val.data = (uint8_t *)talloc_strdup(el->values, data->add_objectclass); + val.length = strlen((char *)val.data); + + /* Remove last value if it was the string in data->add_objectclass (eg samba4top, extensibleObject) */ + if (ldb_val_equal_exact(&val, &el->values[i-1])) { + el->num_values--; + el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values); + if (el->values == NULL) { + talloc_free(el); + ldb_oom(ldb); + return NULL; + } + } + + return el; +} + +static const struct ldb_map_attribute objectclass_convert_map = { + .local_name = "objectClass", + .type = LDB_MAP_CONVERT, + .u = { + .convert = { + .remote_name = "objectClass", + .convert_local = map_objectclass_convert_local, + .convert_remote = map_objectclass_convert_remote, + }, + }, +}; + + +/* Mappings for searches on objectClass= assuming a one-to-one + * mapping. Needed because this is a generate operator for the + * add/modify code */ +static int map_objectclass_convert_operator(struct ldb_module *module, void *mem_ctx, + struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + + return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, &objectclass_convert_map); +} + +/* Auxiliary request construction + * ============================== */ + +/* Build a request to search a record by its DN. */ +struct ldb_request *map_search_base_req(struct map_context *ac, struct ldb_dn *dn, const char * const *attrs, struct ldb_parse_tree *tree, void *context, ldb_map_callback_t callback) +{ + struct ldb_parse_tree *search_tree; + struct ldb_context *ldb; + struct ldb_request *req; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + if (tree) { + search_tree = tree; + } else { + search_tree = ldb_parse_tree(ac, NULL); + if (search_tree == NULL) { + return NULL; + } + } + + ret = ldb_build_search_req_ex(&req, ldb, ac, + dn, LDB_SCOPE_BASE, + search_tree, attrs, + NULL, + context, callback, + ac->req); + LDB_REQ_SET_LOCATION(req); + if (ret != LDB_SUCCESS) { + return NULL; + } + + return req; +} + +/* Build a request to update the 'IS_MAPPED' attribute */ +struct ldb_request *map_build_fixup_req(struct map_context *ac, + struct ldb_dn *olddn, + struct ldb_dn *newdn, + void *context, + ldb_map_callback_t callback) +{ + struct ldb_context *ldb; + struct ldb_request *req; + struct ldb_message *msg; + const char *dn; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + /* Prepare message */ + msg = ldb_msg_new(ac); + if (msg == NULL) { + map_oom(ac->module); + return NULL; + } + + /* Update local 'IS_MAPPED' to the new remote DN */ + msg->dn = ldb_dn_copy(msg, olddn); + dn = ldb_dn_alloc_linearized(msg, newdn); + if ( ! dn || ! ldb_dn_validate(msg->dn)) { + goto failed; + } + if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_REPLACE, NULL) != 0) { + goto failed; + } + if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) { + goto failed; + } + + /* Prepare request */ + ret = ldb_build_mod_req(&req, ldb, + ac, msg, NULL, + context, callback, + ac->req); + LDB_REQ_SET_LOCATION(req); + if (ret != LDB_SUCCESS) { + goto failed; + } + talloc_steal(req, msg); + + return req; +failed: + talloc_free(msg); + return NULL; +} + +/* Module initialization + * ===================== */ + + +/* Builtin mappings for DNs and objectClasses */ +static const struct ldb_map_attribute builtin_attribute_maps[] = { + { + .local_name = "dn", + .type = LDB_MAP_CONVERT, + .u = { + .convert = { + .remote_name = "dn", + .convert_local = ldb_dn_convert_local, + .convert_remote = ldb_dn_convert_remote, + }, + }, + }, + { + .local_name = NULL, + } +}; + +static const struct ldb_map_attribute objectclass_attribute_map = { + .local_name = "objectClass", + .type = LDB_MAP_GENERATE, + .convert_operator = map_objectclass_convert_operator, + .u = { + .generate = { + .remote_names = { "objectClass", NULL }, + .generate_local = map_objectclass_generate_local, + .generate_remote = map_objectclass_generate_remote, + }, + }, +}; + + +/* Find the special 'MAP_DN_NAME' record and store local and remote + * base DNs in private data. */ +static int map_init_dns(struct ldb_module *module, struct ldb_map_context *data, const char *name) +{ + static const char * const attrs[] = { MAP_DN_FROM, MAP_DN_TO, NULL }; + struct ldb_context *ldb; + struct ldb_dn *dn; + struct ldb_message *msg; + struct ldb_result *res; + int ret; + + if (!name) { + data->local_base_dn = NULL; + data->remote_base_dn = NULL; + return LDB_SUCCESS; + } + + ldb = ldb_module_get_ctx(module); + + dn = ldb_dn_new_fmt(data, ldb, "%s=%s", MAP_DN_NAME, name); + if ( ! ldb_dn_validate(dn)) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "Failed to construct '%s' DN!", MAP_DN_NAME); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_search(ldb, data, &res, dn, LDB_SCOPE_BASE, attrs, NULL); + talloc_free(dn); + if (ret != LDB_SUCCESS) { + return ret; + } + if (res->count == 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "No results for '%s=%s'!", MAP_DN_NAME, name); + talloc_free(res); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + if (res->count > 1) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "Too many results for '%s=%s'!", MAP_DN_NAME, name); + talloc_free(res); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + msg = res->msgs[0]; + data->local_base_dn = ldb_msg_find_attr_as_dn(ldb, data, msg, MAP_DN_FROM); + data->remote_base_dn = ldb_msg_find_attr_as_dn(ldb, data, msg, MAP_DN_TO); + talloc_free(res); + + return LDB_SUCCESS; +} + +/* Store attribute maps and objectClass maps in private data. */ +static int map_init_maps(struct ldb_module *module, struct ldb_map_context *data, + const struct ldb_map_attribute *attrs, + const struct ldb_map_objectclass *ocls, + const char * const *wildcard_attributes) +{ + unsigned int i, j, last; + last = 0; + + /* Count specified attribute maps */ + for (i = 0; attrs[i].local_name; i++) /* noop */ ; + /* Count built-in attribute maps */ + for (j = 0; builtin_attribute_maps[j].local_name; j++) /* noop */ ; + + /* Store list of attribute maps */ + data->attribute_maps = talloc_array(data, struct ldb_map_attribute, i+j+2); + if (data->attribute_maps == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Specified ones go first */ + for (i = 0; attrs[i].local_name; i++) { + data->attribute_maps[last] = attrs[i]; + last++; + } + + /* Built-in ones go last */ + for (i = 0; builtin_attribute_maps[i].local_name; i++) { + data->attribute_maps[last] = builtin_attribute_maps[i]; + last++; + } + + if (data->add_objectclass) { + /* ObjectClass one is very last, if required */ + data->attribute_maps[last] = objectclass_attribute_map; + last++; + } else if (ocls) { + data->attribute_maps[last] = objectclass_convert_map; + last++; + } + + /* Ensure 'local_name == NULL' for the last entry */ + memset(&data->attribute_maps[last], 0, sizeof(struct ldb_map_attribute)); + + /* Store list of objectClass maps */ + data->objectclass_maps = ocls; + + data->wildcard_attributes = wildcard_attributes; + + return LDB_SUCCESS; +} + +/* Initialize global private data. */ +_PUBLIC_ int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, + const struct ldb_map_objectclass *ocls, + const char * const *wildcard_attributes, + const char *add_objectclass, + const char *name) +{ + struct map_private *data; + int ret; + + /* Prepare private data */ + data = talloc_zero(module, struct map_private); + if (data == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_module_set_private(module, data); + + data->context = talloc_zero(data, struct ldb_map_context); + if (!data->context) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Store local and remote baseDNs */ + ret = map_init_dns(module, data->context, name); + if (ret != LDB_SUCCESS) { + talloc_free(data); + return ret; + } + + data->context->add_objectclass = add_objectclass; + + /* Store list of attribute and objectClass maps */ + ret = map_init_maps(module, data->context, attrs, ocls, wildcard_attributes); + if (ret != LDB_SUCCESS) { + talloc_free(data); + return ret; + } + + return LDB_SUCCESS; +} diff --git a/ldb-2.0.8/ldb_map/ldb_map.h b/ldb-2.0.8/ldb_map/ldb_map.h new file mode 100644 index 0000000..46ef3cc --- /dev/null +++ b/ldb-2.0.8/ldb_map/ldb_map.h @@ -0,0 +1,174 @@ +/* + ldb database mapping module + + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Martin Kuehl 2006 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . + +*/ + +#ifndef __LDB_MAP_H__ +#define __LDB_MAP_H__ + +#include "ldb_module.h" + +/* ldb_map is a skeleton LDB module that can be used for any other modules + * that need to map attributes. + * + * The term 'remote' in this header refers to the connection where the + * original schema is used on while 'local' means the local connection + * that any upper layers will use. + * + * All local attributes will have to have a definition. Not all remote + * attributes need a definition as LDB is a lot less strict than LDAP + * (in other words, sending unknown attributes to an LDAP server hurts us, + * while returning too many attributes in ldb_search() doesn't) + */ + + +/* Name of the internal attribute pointing from the local to the + * remote part of a record */ +#define IS_MAPPED "isMapped" + + +struct ldb_map_context; + +/* convert a local ldb_val to a remote ldb_val */ +typedef struct ldb_val (*ldb_map_convert_func) (struct ldb_module *module, void *mem_ctx, const struct ldb_val *val); + +#define LDB_MAP_MAX_REMOTE_NAMES 10 + +/* map from local to remote attribute */ +struct ldb_map_attribute { + const char *local_name; /* local name */ + + enum ldb_map_attr_type { + LDB_MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */ + LDB_MAP_KEEP, /* Keep as is. Same name locally and remotely. */ + LDB_MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */ + LDB_MAP_CONVERT, /* Rename + convert data */ + LDB_MAP_GENERATE, /* Use generate function for generating new name/data. + Used for generating attributes based on + multiple remote attributes. */ + LDB_MAP_RENDROP /* Rename the attribute. Strip from Add requests. */ + } type; + + /* if set, will be called for search expressions that contain this attribute */ + int (*convert_operator)(struct ldb_module *, TALLOC_CTX *ctx, struct ldb_parse_tree **ntree, const struct ldb_parse_tree *otree); + + union { + struct { + const char *remote_name; + } rename; + + struct { + const char *remote_name; + + /* Convert local to remote data */ + ldb_map_convert_func convert_local; + + /* Convert remote to local data */ + /* an entry can have convert_remote set to NULL, as long as there as an entry with the same local_name + * that is non-NULL before it. */ + ldb_map_convert_func convert_remote; + } convert; + + struct { + /* Generate the local attribute from remote message */ + struct ldb_message_element *(*generate_local)(struct ldb_module *, TALLOC_CTX *mem_ctx, const char *remote_attr, const struct ldb_message *remote); + + /* Update remote message with information from local message */ + void (*generate_remote)(struct ldb_module *, const char *local_attr, const struct ldb_message *old, struct ldb_message *remote, struct ldb_message *local); + + /* Name(s) for this attribute on the remote server. This is an array since + * one local attribute's data can be split up into several attributes + * remotely */ + const char *remote_names[LDB_MAP_MAX_REMOTE_NAMES]; + + /* Names of additional remote attributes + * required for the generation. NULL + * indicates that `local_attr' suffices. */ + /* +#define LDB_MAP_MAX_SELF_ATTRIBUTES 10 + const char *self_attrs[LDB_MAP_MAX_SELF_ATTRIBUTES]; + */ + } generate; + } u; +}; + + +#define LDB_MAP_MAX_SUBCLASSES 10 +#define LDB_MAP_MAX_MUSTS 10 +#define LDB_MAP_MAX_MAYS 50 + +/* map from local to remote objectClass */ +struct ldb_map_objectclass { + const char *local_name; + const char *remote_name; + const char *base_classes[LDB_MAP_MAX_SUBCLASSES]; + const char *musts[LDB_MAP_MAX_MUSTS]; + const char *mays[LDB_MAP_MAX_MAYS]; +}; + + +/* private context data */ +struct ldb_map_context { + struct ldb_map_attribute *attribute_maps; + /* NOTE: Always declare base classes first here */ + const struct ldb_map_objectclass *objectclass_maps; + + /* Remote (often operational) attributes that should be added + * to any wildcard search */ + const char * const *wildcard_attributes; + + /* ObjectClass (if any) to be added to remote attributes on add */ + const char *add_objectclass; + + /* struct ldb_context *mapped_ldb; */ + struct ldb_dn *local_base_dn; + struct ldb_dn *remote_base_dn; +}; + +/* Global private data */ +struct map_private { + void *caller_private; + struct ldb_map_context *context; +}; + +/* Initialize global private data. */ +int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, + const struct ldb_map_objectclass *ocls, + const char * const *wildcard_attributes, + const char *add_objectclass, + const char *name); + +int ldb_map_add(struct ldb_module *module, struct ldb_request *req); +int ldb_map_search(struct ldb_module *module, struct ldb_request *req); +int ldb_map_rename(struct ldb_module *module, struct ldb_request *req); +int ldb_map_delete(struct ldb_module *module, struct ldb_request *req); +int ldb_map_modify(struct ldb_module *module, struct ldb_request *req); + +#define LDB_MAP_OPS \ + .add = ldb_map_add, \ + .modify = ldb_map_modify, \ + .del = ldb_map_delete, \ + .rename = ldb_map_rename, \ + .search = ldb_map_search, + +#endif /* __LDB_MAP_H__ */ diff --git a/ldb-2.0.8/ldb_map/ldb_map_inbound.c b/ldb-2.0.8/ldb_map/ldb_map_inbound.c new file mode 100644 index 0000000..861c4c1 --- /dev/null +++ b/ldb-2.0.8/ldb_map/ldb_map_inbound.c @@ -0,0 +1,846 @@ +/* + ldb database mapping module + + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Martin Kuehl 2006 + Copyright (C) Simo Sorce 2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . + +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_map.h" +#include "ldb_map_private.h" + + +/* Mapping message elements + * ======================== */ + +/* Map a message element into the remote partition. */ +static struct ldb_message_element *ldb_msg_el_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_message_element *old) +{ + struct ldb_message_element *el; + unsigned int i; + + el = talloc_zero(mem_ctx, struct ldb_message_element); + if (el == NULL) { + map_oom(module); + return NULL; + } + + el->num_values = old->num_values; + el->values = talloc_array(el, struct ldb_val, el->num_values); + if (el->values == NULL) { + talloc_free(el); + map_oom(module); + return NULL; + } + + el->name = map_attr_map_local(el, map, old->name); + + for (i = 0; i < el->num_values; i++) { + el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]); + } + + return el; +} + +/* Add a message element either to a local or to a remote message, + * depending on whether it goes into the local or remote partition. */ +static int ldb_msg_el_partition(struct ldb_module *module, enum ldb_request_type optype, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg, const char *attr_name, /* const char * const names[], */ const struct ldb_message_element *old) +{ + const struct ldb_map_context *data = map_get_context(module); + const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name); + struct ldb_message_element *el=NULL; + struct ldb_context *ldb = ldb_module_get_ctx(module); + + /* Unknown attribute: ignore */ + if (map == NULL) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " + "Not mapping attribute '%s': no mapping found", + old->name); + goto local; + } + + switch (map->type) { + case LDB_MAP_RENDROP: + if (optype != LDB_ADD) { + /* do the same as LDB_MAP_RENAME */ + el = ldb_msg_el_map_local(module, remote, map, old); + break; + } + + FALL_THROUGH; + case LDB_MAP_IGNORE: + goto local; + + case LDB_MAP_CONVERT: + if (map->u.convert.convert_local == NULL) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " + "Not mapping attribute '%s': " + "'convert_local' not set", + map->local_name); + goto local; + } + + FALL_THROUGH; + case LDB_MAP_KEEP: + case LDB_MAP_RENAME: + el = ldb_msg_el_map_local(module, remote, map, old); + break; + + case LDB_MAP_GENERATE: + if (map->u.generate.generate_remote == NULL) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " + "Not mapping attribute '%s': " + "'generate_remote' not set", + map->local_name); + goto local; + } + + /* TODO: if this attr requires context: + * make sure all context attrs are mappable (in 'names') + * make sure all context attrs have already been mapped? + * maybe postpone generation until they have been mapped? + */ + + map->u.generate.generate_remote(module, map->local_name, msg, remote, local); + return 0; + } + + if (el == NULL) { + return -1; + } + + return ldb_msg_add(remote, el, old->flags); + +local: + el = talloc(local, struct ldb_message_element); + if (el == NULL) { + map_oom(module); + return -1; + } + + *el = *old; /* copy the old element */ + + return ldb_msg_add(local, el, old->flags); +} + +/* Mapping messages + * ================ */ + +/* Check whether a message will be (partially) mapped into the remote partition. */ +static bool ldb_msg_check_remote(struct ldb_module *module, const struct ldb_message *msg) +{ + const struct ldb_map_context *data = map_get_context(module); + bool ret; + unsigned int i; + + for (i = 0; i < msg->num_elements; i++) { + ret = map_attr_check_remote(data, msg->elements[i].name); + if (ret) { + return ret; + } + } + + return false; +} + +/* Split message elements that stay in the local partition from those + * that are mapped into the remote partition. */ +static int ldb_msg_partition(struct ldb_module *module, enum ldb_request_type optype, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg) +{ + /* const char * const names[]; */ + struct ldb_context *ldb; + unsigned int i; + int ret; + + ldb = ldb_module_get_ctx(module); + + for (i = 0; i < msg->num_elements; i++) { + /* Skip 'IS_MAPPED' */ + if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " + "Skipping attribute '%s'", + msg->elements[i].name); + continue; + } + + ret = ldb_msg_el_partition(module, optype, local, remote, msg, msg->elements[i].name, &msg->elements[i]); + if (ret) { + return ret; + } + } + + return 0; +} + + +static int map_add_do_local(struct map_context *ac); +static int map_modify_do_local(struct map_context *ac); +static int map_delete_do_local(struct map_context *ac); +static int map_rename_do_local(struct map_context *ac); +static int map_rename_do_fixup(struct map_context *ac); +static int map_rename_local_callback(struct ldb_request *req, + struct ldb_reply *ares); + + +/***************************************************************************** + * COMMON INBOUND functions +*****************************************************************************/ + +/* Store the DN of a single search result in context. */ +static int map_search_self_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct map_context); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + /* We are interested only in the single reply */ + switch(ares->type) { + case LDB_REPLY_ENTRY: + /* We have already found a remote DN */ + if (ac->local_dn) { + ldb_set_errstring(ldb, + "Too many results!"); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + /* Store local DN */ + ac->local_dn = talloc_steal(ac, ares->message->dn); + break; + + case LDB_REPLY_DONE: + + switch (ac->req->operation) { + case LDB_MODIFY: + ret = map_modify_do_local(ac); + break; + case LDB_DELETE: + ret = map_delete_do_local(ac); + break; + case LDB_RENAME: + ret = map_rename_do_local(ac); + break; + default: + /* if we get here we have definitely a problem */ + ret = LDB_ERR_OPERATIONS_ERROR; + } + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + default: + /* ignore referrals */ + break; + } + + talloc_free(ares); + return LDB_SUCCESS; +} + +/* Build a request to search the local record by its DN. */ +static int map_search_self_req(struct ldb_request **req, + struct map_context *ac, + struct ldb_dn *dn) +{ + /* attrs[] is returned from this function in + * ac->search_req->op.search.attrs, so it must be static, as + * otherwise the compiler can put it on the stack */ + static const char * const attrs[] = { IS_MAPPED, NULL }; + struct ldb_parse_tree *tree; + + /* Limit search to records with 'IS_MAPPED' present */ + tree = ldb_parse_tree(ac, "(" IS_MAPPED "=*)"); + if (tree == NULL) { + map_oom(ac->module); + return LDB_ERR_OPERATIONS_ERROR; + } + + *req = map_search_base_req(ac, dn, attrs, tree, + ac, map_search_self_callback); + if (*req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +static int map_op_local_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct map_context); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + if (ares->type != LDB_REPLY_DONE) { + ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + /* Do the remote request. */ + ret = ldb_next_remote_request(ac->module, ac->remote_req); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + return LDB_SUCCESS; +} + +static int map_op_remote_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct map_context *ac; + + ac = talloc_get_type(req->context, struct map_context); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + if (ares->type != LDB_REPLY_DONE) { + ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); +} + + +/***************************************************************************** + * ADD operations +*****************************************************************************/ + + +/* Add a record. */ +int ldb_map_add(struct ldb_module *module, struct ldb_request *req) +{ + const struct ldb_message *msg = req->op.add.message; + struct ldb_context *ldb; + struct map_context *ac; + struct ldb_message *remote_msg; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* Do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_request(module, req); + } + + /* No mapping requested (perhaps no DN mapping specified), skip to next module */ + if (!ldb_dn_check_local(module, msg->dn)) { + return ldb_next_request(module, req); + } + + /* No mapping needed, fail */ + if (!ldb_msg_check_remote(module, msg)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare context and handle */ + ac = map_init_context(module, req); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + + /* Prepare the local message */ + ac->local_msg = ldb_msg_new(ac); + if (ac->local_msg == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->local_msg->dn = msg->dn; + + /* Prepare the remote message */ + remote_msg = ldb_msg_new(ac); + if (remote_msg == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn); + + /* Split local from remote message */ + ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg); + + /* Prepare the remote operation */ + ret = ldb_build_add_req(&ac->remote_req, ldb, + ac, remote_msg, + req->controls, + ac, map_op_remote_callback, + req); + LDB_REQ_SET_LOCATION(ac->remote_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if ((ac->local_msg->num_elements == 0) || + ( ! map_check_local_db(ac->module))) { + /* No local data or db, just run the remote request */ + return ldb_next_remote_request(ac->module, ac->remote_req); + } + + /* Store remote DN in 'IS_MAPPED' */ + /* TODO: use GUIDs here instead */ + ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, + remote_msg->dn); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return map_add_do_local(ac); +} + +/* Add the local record. */ +static int map_add_do_local(struct map_context *ac) +{ + struct ldb_request *local_req; + struct ldb_context *ldb; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + /* Prepare the local operation */ + ret = ldb_build_add_req(&local_req, ldb, ac, + ac->local_msg, + ac->req->controls, + ac, + map_op_local_callback, + ac->req); + LDB_REQ_SET_LOCATION(local_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + return ldb_next_request(ac->module, local_req); +} + +/***************************************************************************** + * MODIFY operations +*****************************************************************************/ + +/* Modify a record. */ +int ldb_map_modify(struct ldb_module *module, struct ldb_request *req) +{ + const struct ldb_message *msg = req->op.mod.message; + struct ldb_request *search_req = NULL; + struct ldb_message *remote_msg; + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* Do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_request(module, req); + } + + /* No mapping requested (perhaps no DN mapping specified), skip to next module */ + if (!ldb_dn_check_local(module, msg->dn)) { + return ldb_next_request(module, req); + } + + /* No mapping needed, skip to next module */ + /* TODO: What if the remote part exists, the local doesn't, + * and this request wants to modify local data and thus + * add the local record? */ + if (!ldb_msg_check_remote(module, msg)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare context and handle */ + ac = map_init_context(module, req); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare the local message */ + ac->local_msg = ldb_msg_new(ac); + if (ac->local_msg == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->local_msg->dn = msg->dn; + + /* Prepare the remote message */ + remote_msg = ldb_msg_new(ac->remote_req); + if (remote_msg == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn); + + /* Split local from remote message */ + ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg); + + /* Prepare the remote operation */ + ret = ldb_build_mod_req(&ac->remote_req, ldb, + ac, remote_msg, + req->controls, + ac, map_op_remote_callback, + req); + LDB_REQ_SET_LOCATION(ac->remote_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if ((ac->local_msg->num_elements == 0) || + ( ! map_check_local_db(ac->module))) { + /* No local data or db, just run the remote request */ + return ldb_next_remote_request(ac->module, ac->remote_req); + } + + /* prepare the search operation */ + ret = map_search_self_req(&search_req, ac, msg->dn); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(module, search_req); +} + +/* Modify the local record. */ +static int map_modify_do_local(struct map_context *ac) +{ + struct ldb_request *local_req; + struct ldb_context *ldb; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + if (ac->local_dn == NULL) { + /* No local record present, add it instead */ + /* Add local 'IS_MAPPED' */ + /* TODO: use GUIDs here instead */ + if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED, + LDB_FLAG_MOD_ADD, NULL) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, + ac->remote_req->op.mod.message->dn); + if (ret != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare the local operation */ + ret = ldb_build_add_req(&local_req, ldb, ac, + ac->local_msg, + ac->req->controls, + ac, + map_op_local_callback, + ac->req); + LDB_REQ_SET_LOCATION(local_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + } else { + /* Prepare the local operation */ + ret = ldb_build_mod_req(&local_req, ldb, ac, + ac->local_msg, + ac->req->controls, + ac, + map_op_local_callback, + ac->req); + LDB_REQ_SET_LOCATION(local_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + return ldb_next_request(ac->module, local_req); +} + +/***************************************************************************** + * DELETE operations +*****************************************************************************/ + +/* Delete a record. */ +int ldb_map_delete(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_request *search_req; + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* Do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.del.dn)) { + return ldb_next_request(module, req); + } + + /* No mapping requested (perhaps no DN mapping specified). + * Skip to next module */ + if (!ldb_dn_check_local(module, req->op.del.dn)) { + return ldb_next_request(module, req); + } + + /* Prepare context and handle */ + ac = map_init_context(module, req); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare the remote operation */ + ret = ldb_build_del_req(&ac->remote_req, ldb, ac, + ldb_dn_map_local(module, ac, req->op.del.dn), + req->controls, + ac, + map_op_remote_callback, + req); + LDB_REQ_SET_LOCATION(ac->remote_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* No local db, just run the remote request */ + if (!map_check_local_db(ac->module)) { + /* Do the remote request. */ + return ldb_next_remote_request(ac->module, ac->remote_req); + } + + /* Prepare the search operation */ + ret = map_search_self_req(&search_req, ac, req->op.del.dn); + if (ret != LDB_SUCCESS) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(module, search_req); +} + +/* Delete the local record. */ +static int map_delete_do_local(struct map_context *ac) +{ + struct ldb_request *local_req; + struct ldb_context *ldb; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + /* No local record, continue remotely */ + if (ac->local_dn == NULL) { + /* Do the remote request. */ + return ldb_next_remote_request(ac->module, ac->remote_req); + } + + /* Prepare the local operation */ + ret = ldb_build_del_req(&local_req, ldb, ac, + ac->req->op.del.dn, + ac->req->controls, + ac, + map_op_local_callback, + ac->req); + LDB_REQ_SET_LOCATION(local_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + return ldb_next_request(ac->module, local_req); +} + +/***************************************************************************** + * RENAME operations +*****************************************************************************/ + +/* Rename a record. */ +int ldb_map_rename(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_request *search_req = NULL; + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* Do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.rename.olddn)) { + return ldb_next_request(module, req); + } + + /* No mapping requested (perhaps no DN mapping specified). + * Skip to next module */ + if ((!ldb_dn_check_local(module, req->op.rename.olddn)) && + (!ldb_dn_check_local(module, req->op.rename.newdn))) { + return ldb_next_request(module, req); + } + + /* Rename into/out of the mapped partition requested, bail out */ + if (!ldb_dn_check_local(module, req->op.rename.olddn) || + !ldb_dn_check_local(module, req->op.rename.newdn)) { + return LDB_ERR_AFFECTS_MULTIPLE_DSAS; + } + + /* Prepare context and handle */ + ac = map_init_context(module, req); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare the remote operation */ + ret = ldb_build_rename_req(&ac->remote_req, ldb, ac, + ldb_dn_map_local(module, ac, req->op.rename.olddn), + ldb_dn_map_local(module, ac, req->op.rename.newdn), + req->controls, + ac, map_op_remote_callback, + req); + LDB_REQ_SET_LOCATION(ac->remote_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* No local db, just run the remote request */ + if (!map_check_local_db(ac->module)) { + /* Do the remote request. */ + return ldb_next_remote_request(ac->module, ac->remote_req); + } + + /* Prepare the search operation */ + ret = map_search_self_req(&search_req, ac, req->op.rename.olddn); + if (ret != LDB_SUCCESS) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(module, search_req); +} + +/* Rename the local record. */ +static int map_rename_do_local(struct map_context *ac) +{ + struct ldb_request *local_req; + struct ldb_context *ldb; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + /* No local record, continue remotely */ + if (ac->local_dn == NULL) { + /* Do the remote request. */ + return ldb_next_remote_request(ac->module, ac->remote_req); + } + + /* Prepare the local operation */ + ret = ldb_build_rename_req(&local_req, ldb, ac, + ac->req->op.rename.olddn, + ac->req->op.rename.newdn, + ac->req->controls, + ac, + map_rename_local_callback, + ac->req); + LDB_REQ_SET_LOCATION(local_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(ac->module, local_req); +} + +static int map_rename_local_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct map_context); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + if (ares->type != LDB_REPLY_DONE) { + ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + /* proceed with next step */ + ret = map_rename_do_fixup(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + return LDB_SUCCESS; +} + +/* Update the local 'IS_MAPPED' attribute. */ +static int map_rename_do_fixup(struct map_context *ac) +{ + struct ldb_request *local_req; + + /* Prepare the fixup operation */ + /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */ + local_req = map_build_fixup_req(ac, + ac->req->op.rename.newdn, + ac->remote_req->op.rename.newdn, + ac, + map_op_local_callback); + if (local_req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(ac->module, local_req); +} diff --git a/ldb-2.0.8/ldb_map/ldb_map_outbound.c b/ldb-2.0.8/ldb_map/ldb_map_outbound.c new file mode 100644 index 0000000..c823ba4 --- /dev/null +++ b/ldb-2.0.8/ldb_map/ldb_map_outbound.c @@ -0,0 +1,1417 @@ +/* + ldb database mapping module + + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Martin Kuehl 2006 + Copyright (C) Andrew Bartlett 2006 + Copyright (C) Simo Sorce 2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . + +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_map.h" +#include "ldb_map_private.h" + + +/* Mapping attributes + * ================== */ + +/* Select attributes that stay in the local partition. */ +static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs) +{ + const struct ldb_map_context *data = map_get_context(module); + const char **result; + unsigned int i, last; + + if (attrs == NULL) + return NULL; + + last = 0; + result = talloc_array(mem_ctx, const char *, 1); + if (result == NULL) { + goto failed; + } + result[0] = NULL; + + for (i = 0; attrs[i]; i++) { + /* Wildcards and ignored attributes are kept locally */ + if ((ldb_attr_cmp(attrs[i], "*") == 0) || + (!map_attr_check_remote(data, attrs[i]))) { + result = talloc_realloc(mem_ctx, result, const char *, last+2); + if (result == NULL) { + goto failed; + } + + result[last] = talloc_strdup(result, attrs[i]); + result[last+1] = NULL; + last++; + } + } + + return result; + +failed: + talloc_free(result); + map_oom(module); + return NULL; +} + +/* Collect attributes that are mapped into the remote partition. */ +static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx, + const char * const *attrs) +{ + const struct ldb_map_context *data = map_get_context(module); + const char **result; + const struct ldb_map_attribute *map; + const char *name=NULL; + unsigned int i, j, last; + int ret; + + last = 0; + result = talloc_array(mem_ctx, const char *, 1); + if (result == NULL) { + goto failed; + } + result[0] = NULL; + + for (i = 0; attrs[i]; i++) { + /* Wildcards are kept remotely, too */ + if (ldb_attr_cmp(attrs[i], "*") == 0) { + const char **new_attrs = NULL; + ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs); + if (ret != LDB_SUCCESS) { + goto failed; + } + ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes); + if (ret != LDB_SUCCESS) { + goto failed; + } + + attrs = new_attrs; + break; + } + } + + for (i = 0; attrs[i]; i++) { + /* Wildcards are kept remotely, too */ + if (ldb_attr_cmp(attrs[i], "*") == 0) { + /* Add all 'include in wildcard' attributes */ + name = attrs[i]; + goto named; + } + + /* Add remote names of mapped attrs */ + map = map_attr_find_local(data, attrs[i]); + if (map == NULL) { + continue; + } + + switch (map->type) { + case LDB_MAP_IGNORE: + continue; + + case LDB_MAP_KEEP: + name = attrs[i]; + goto named; + + case LDB_MAP_RENAME: + case LDB_MAP_RENDROP: + case LDB_MAP_CONVERT: + name = map->u.rename.remote_name; + goto named; + + case LDB_MAP_GENERATE: + /* Add all remote names of "generate" attrs */ + for (j = 0; map->u.generate.remote_names[j]; j++) { + result = talloc_realloc(mem_ctx, result, const char *, last+2); + if (result == NULL) { + goto failed; + } + + result[last] = talloc_strdup(result, map->u.generate.remote_names[j]); + result[last+1] = NULL; + last++; + } + continue; + } + + named: /* We found a single remote name, add that */ + result = talloc_realloc(mem_ctx, result, const char *, last+2); + if (result == NULL) { + goto failed; + } + + result[last] = talloc_strdup(result, name); + result[last+1] = NULL; + last++; + } + + return result; + +failed: + talloc_free(result); + map_oom(module); + return NULL; +} + +/* Split attributes that stay in the local partition from those that + * are mapped into the remote partition. */ +static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs) +{ + *local_attrs = map_attrs_select_local(module, mem_ctx, attrs); + *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs); + + return 0; +} + +/* Mapping message elements + * ======================== */ + +/* Add an element to a message, overwriting any old identically named elements. */ +static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el) +{ + struct ldb_message_element *old; + unsigned j; + old = ldb_msg_find_element(msg, el->name); + + /* no local result, add as new element */ + if (old == NULL) { + if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + else { + talloc_free(old->values); + } + + old->values = talloc_array(msg->elements, struct ldb_val, el->num_values); + old->num_values = el->num_values; + if (old->values == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + /* copy the values into the element */ + for (j=0;jnum_values;j++) { + old->values[j] = ldb_val_dup(old->values, &el->values[j]); + if (old->values[j].data == NULL && el->values[j].length != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + return 0; +} + +/* Map a message element back into the local partition. */ +static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module, + void *mem_ctx, + const struct ldb_map_attribute *map, + const char *attr_name, + const struct ldb_message_element *old) +{ + const struct ldb_map_context *data = map_get_context(module); + const char *local_attr_name = attr_name; + struct ldb_message_element *el; + unsigned int i; + + el = talloc_zero(mem_ctx, struct ldb_message_element); + if (el == NULL) { + map_oom(module); + return NULL; + } + + el->values = talloc_array(el, struct ldb_val, old->num_values); + if (el->values == NULL) { + talloc_free(el); + map_oom(module); + return NULL; + } + + for (i = 0; data->attribute_maps[i].local_name; i++) { + struct ldb_map_attribute *am = &data->attribute_maps[i]; + if (((am->type == LDB_MAP_RENAME || am->type == LDB_MAP_RENDROP) && + !strcmp(am->u.rename.remote_name, attr_name)) + || (am->type == LDB_MAP_CONVERT && + !strcmp(am->u.convert.remote_name, attr_name))) { + + local_attr_name = am->local_name; + break; + } + } + + el->name = talloc_strdup(el, local_attr_name); + if (el->name == NULL) { + talloc_free(el); + map_oom(module); + return NULL; + } + + for (i = 0; i < old->num_values; i++) { + el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]); + /* Conversions might fail, in which case bail */ + if (!el->values[i].data) { + talloc_free(el); + return NULL; + } + el->num_values++; + } + + return el; +} + +/* Merge a remote message element into a local message. */ +static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local, + struct ldb_message *remote, const char *attr_name) +{ + const struct ldb_map_context *data = map_get_context(module); + const struct ldb_map_attribute *map; + struct ldb_message_element *old, *el=NULL; + const char *remote_name = NULL; + struct ldb_context *ldb; + + ldb = ldb_module_get_ctx(module); + + /* We handle wildcards in ldb_msg_el_merge_wildcard */ + if (ldb_attr_cmp(attr_name, "*") == 0) { + return LDB_SUCCESS; + } + + map = map_attr_find_local(data, attr_name); + + /* Unknown attribute in remote message: + * skip, attribute was probably auto-generated */ + if (map == NULL) { + return LDB_SUCCESS; + } + + switch (map->type) { + case LDB_MAP_IGNORE: + break; + case LDB_MAP_CONVERT: + remote_name = map->u.convert.remote_name; + break; + case LDB_MAP_KEEP: + remote_name = attr_name; + break; + case LDB_MAP_RENAME: + case LDB_MAP_RENDROP: + remote_name = map->u.rename.remote_name; + break; + case LDB_MAP_GENERATE: + break; + } + + switch (map->type) { + case LDB_MAP_IGNORE: + return LDB_SUCCESS; + + case LDB_MAP_CONVERT: + if (map->u.convert.convert_remote == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "Skipping attribute '%s': " + "'convert_remote' not set", + attr_name); + return LDB_SUCCESS; + } + + FALL_THROUGH; + case LDB_MAP_KEEP: + case LDB_MAP_RENAME: + case LDB_MAP_RENDROP: + old = ldb_msg_find_element(remote, remote_name); + if (old) { + el = ldb_msg_el_map_remote(module, local, map, attr_name, old); + } else { + return LDB_ERR_NO_SUCH_ATTRIBUTE; + } + break; + + case LDB_MAP_GENERATE: + if (map->u.generate.generate_local == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " + "Skipping attribute '%s': " + "'generate_local' not set", + attr_name); + return LDB_SUCCESS; + } + + el = map->u.generate.generate_local(module, local, attr_name, remote); + if (!el) { + /* Generation failure is probably due to lack of source attributes */ + return LDB_ERR_NO_SUCH_ATTRIBUTE; + } + break; + } + + if (el == NULL) { + return LDB_ERR_NO_SUCH_ATTRIBUTE; + } + + return ldb_msg_replace(local, el); +} + +/* Handle wildcard parts of merging a remote message element into a local message. */ +static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local, + struct ldb_message *remote) +{ + const struct ldb_map_context *data = map_get_context(module); + const struct ldb_map_attribute *map = map_attr_find_local(data, "*"); + struct ldb_message_element *el=NULL; + unsigned int i; + int ret; + + /* Perhaps we have a mapping for "*" */ + if (map && map->type == LDB_MAP_KEEP) { + /* We copy everything over, and hope that anything with a + more specific rule is overwritten */ + for (i = 0; i < remote->num_elements; i++) { + el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name, + &remote->elements[i]); + if (el == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_msg_replace(local, el); + if (ret) { + return ret; + } + } + } + + /* Now walk the list of possible mappings, and apply each */ + for (i = 0; data->attribute_maps[i].local_name; i++) { + ret = ldb_msg_el_merge(module, local, remote, + data->attribute_maps[i].local_name); + if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { + continue; + } else if (ret) { + return ret; + } else { + continue; + } + } + + return LDB_SUCCESS; +} + +/* Mapping messages + * ================ */ + +/* Merge two local messages into a single one. */ +static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2) +{ + unsigned int i; + int ret; + + for (i = 0; i < msg2->num_elements; i++) { + ret = ldb_msg_replace(msg1, &msg2->elements[i]); + if (ret) { + return ret; + } + } + + return LDB_SUCCESS; +} + +/* Merge a local and a remote message into a single local one. */ +static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local, + struct ldb_message *remote) +{ + unsigned int i; + int ret; + const char * const *attrs = ac->all_attrs; + if (!attrs) { + ret = ldb_msg_el_merge_wildcard(ac->module, local, remote); + if (ret) { + return ret; + } + } + + for (i = 0; attrs && attrs[i]; i++) { + if (ldb_attr_cmp(attrs[i], "*") == 0) { + ret = ldb_msg_el_merge_wildcard(ac->module, local, remote); + if (ret) { + return ret; + } + break; + } + } + + /* Try to map each attribute back; + * Add to local message is possible, + * Overwrite old local attribute if necessary */ + for (i = 0; attrs && attrs[i]; i++) { + ret = ldb_msg_el_merge(ac->module, local, remote, + attrs[i]); + if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { + } else if (ret) { + return ret; + } + } + + return LDB_SUCCESS; +} + +/* Mapping search results + * ====================== */ + +/* Map a search result back into the local partition. */ +static int map_reply_remote(struct map_context *ac, struct ldb_reply *ares) +{ + struct ldb_message *msg; + struct ldb_dn *dn; + int ret; + + /* There is no result message, skip */ + if (ares->type != LDB_REPLY_ENTRY) { + return 0; + } + + /* Create a new result message */ + msg = ldb_msg_new(ares); + if (msg == NULL) { + map_oom(ac->module); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Merge remote message into new message */ + ret = ldb_msg_merge_remote(ac, msg, ares->message); + if (ret) { + talloc_free(msg); + return ret; + } + + /* Create corresponding local DN */ + dn = ldb_dn_map_rebase_remote(ac->module, msg, ares->message->dn); + if (dn == NULL) { + talloc_free(msg); + return LDB_ERR_OPERATIONS_ERROR; + } + msg->dn = dn; + + /* Store new message with new DN as the result */ + talloc_free(ares->message); + ares->message = msg; + + return 0; +} + +/* Mapping parse trees + * =================== */ + +/* Check whether a parse tree can safely be split in two. */ +static bool ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree) +{ + const struct ldb_parse_tree *subtree = tree; + bool negate = false; + + while (subtree) { + switch (subtree->operation) { + case LDB_OP_NOT: + negate = !negate; + subtree = subtree->u.isnot.child; + continue; + + case LDB_OP_AND: + return !negate; /* if negate: False */ + + case LDB_OP_OR: + return negate; /* if negate: True */ + + default: + return true; /* simple parse tree */ + } + } + + return true; /* no parse tree */ +} + +/* Collect a list of attributes required to match a given parse tree. */ +static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree) +{ + const char **new_attrs; + unsigned int i; + int ret; + + if (tree == NULL) { + return 0; + } + + switch (tree->operation) { + case LDB_OP_OR: + case LDB_OP_AND: /* attributes stored in list of subtrees */ + for (i = 0; i < tree->u.list.num_elements; i++) { + ret = ldb_parse_tree_collect_attrs(module, mem_ctx, + attrs, tree->u.list.elements[i]); + if (ret) { + return ret; + } + } + return 0; + + case LDB_OP_NOT: /* attributes stored in single subtree */ + return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child); + + default: /* single attribute in tree */ + new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr); + talloc_free(*attrs); + *attrs = new_attrs; + return 0; + } +} + +static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree); + +/* Select a negated subtree that queries attributes in the local partition */ +static int map_subtree_select_local_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + struct ldb_parse_tree *child; + int ret; + + /* Prepare new tree */ + *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree)); + if (*new == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Generate new subtree */ + ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child); + if (ret) { + talloc_free(*new); + return ret; + } + + /* Prune tree without subtree */ + if (child == NULL) { + talloc_free(*new); + *new = NULL; + return 0; + } + + (*new)->u.isnot.child = child; + + return ret; +} + +/* Select a list of subtrees that query attributes in the local partition */ +static int map_subtree_select_local_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + unsigned int i, j; + int ret=0; + + /* Prepare new tree */ + *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree)); + if (*new == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare list of subtrees */ + (*new)->u.list.num_elements = 0; + (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements); + if ((*new)->u.list.elements == NULL) { + map_oom(module); + talloc_free(*new); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Generate new list of subtrees */ + j = 0; + for (i = 0; i < tree->u.list.num_elements; i++) { + struct ldb_parse_tree *child = NULL; + ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]); + if (ret) { + talloc_free(*new); + return ret; + } + + if (child) { + (*new)->u.list.elements[j] = child; + j++; + } + } + + /* Prune tree without subtrees */ + if (j == 0) { + talloc_free(*new); + *new = NULL; + return 0; + } + + /* Fix subtree list size */ + (*new)->u.list.num_elements = j; + (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements); + + return ret; +} + +/* Select a simple subtree that queries attributes in the local partition */ +static int map_subtree_select_local_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + /* Prepare new tree */ + *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree)); + if (*new == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + return 0; +} + +/* Select subtrees that query attributes in the local partition */ +static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + const struct ldb_map_context *data = map_get_context(module); + + if (tree == NULL) { + return 0; + } + + if (tree->operation == LDB_OP_NOT) { + return map_subtree_select_local_not(module, mem_ctx, new, tree); + } + + if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) { + return map_subtree_select_local_list(module, mem_ctx, new, tree); + } + + if (map_attr_check_remote(data, tree->u.equality.attr)) { + *new = NULL; + return 0; + } + + return map_subtree_select_local_simple(module, mem_ctx, new, tree); +} + +static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree); + +/* Collect a negated subtree that queries attributes in the remote partition */ +static int map_subtree_collect_remote_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + struct ldb_parse_tree *child; + int ret; + + /* Prepare new tree */ + *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree)); + if (*new == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Generate new subtree */ + ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child); + if (ret) { + talloc_free(*new); + return ret; + } + + /* Prune tree without subtree */ + if (child == NULL) { + talloc_free(*new); + *new = NULL; + return 0; + } + + (*new)->u.isnot.child = child; + + return ret; +} + +/* Collect a list of subtrees that query attributes in the remote partition */ +static int map_subtree_collect_remote_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + unsigned int i, j; + int ret=0; + + /* Prepare new tree */ + *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree)); + if (*new == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare list of subtrees */ + (*new)->u.list.num_elements = 0; + (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements); + if ((*new)->u.list.elements == NULL) { + map_oom(module); + talloc_free(*new); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Generate new list of subtrees */ + j = 0; + for (i = 0; i < tree->u.list.num_elements; i++) { + struct ldb_parse_tree *child; + ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]); + if (ret) { + talloc_free(*new); + return ret; + } + + if (child) { + (*new)->u.list.elements[j] = child; + j++; + } + } + + /* Prune tree without subtrees */ + if (j == 0) { + talloc_free(*new); + *new = NULL; + return 0; + } + + /* Fix subtree list size */ + (*new)->u.list.num_elements = j; + (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements); + + return ret; +} + +/* Collect a simple subtree that queries attributes in the remote partition */ +int map_subtree_collect_remote_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree, const struct ldb_map_attribute *map) +{ + const char *attr; + + /* Prepare new tree */ + *new = talloc(mem_ctx, struct ldb_parse_tree); + if (*new == NULL) { + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; + } + **new = *tree; + + if (map->type == LDB_MAP_KEEP) { + /* Nothing to do here */ + return 0; + } + + /* Store attribute and value in new tree */ + switch (tree->operation) { + case LDB_OP_PRESENT: + attr = map_attr_map_local(*new, map, tree->u.present.attr); + (*new)->u.present.attr = attr; + break; + case LDB_OP_SUBSTRING: + { + attr = map_attr_map_local(*new, map, tree->u.substring.attr); + (*new)->u.substring.attr = attr; + break; + } + case LDB_OP_EQUALITY: + attr = map_attr_map_local(*new, map, tree->u.equality.attr); + (*new)->u.equality.attr = attr; + break; + case LDB_OP_LESS: + case LDB_OP_GREATER: + case LDB_OP_APPROX: + attr = map_attr_map_local(*new, map, tree->u.comparison.attr); + (*new)->u.comparison.attr = attr; + break; + case LDB_OP_EXTENDED: + attr = map_attr_map_local(*new, map, tree->u.extended.attr); + (*new)->u.extended.attr = attr; + break; + default: /* unknown kind of simple subtree */ + talloc_free(*new); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (attr == NULL) { + talloc_free(*new); + *new = NULL; + return 0; + } + + if (map->type == LDB_MAP_RENAME || map->type == LDB_MAP_RENDROP) { + /* Nothing more to do here, the attribute has been renamed */ + return 0; + } + + /* Store attribute and value in new tree */ + switch (tree->operation) { + case LDB_OP_PRESENT: + break; + case LDB_OP_SUBSTRING: + { + int i; + /* Map value */ + (*new)->u.substring.chunks = NULL; + for (i=0; tree->u.substring.chunks && tree->u.substring.chunks[i]; i++) { + (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2); + if (!(*new)->u.substring.chunks) { + talloc_free(*new); + *new = NULL; + return 0; + } + (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val); + if (!(*new)->u.substring.chunks[i]) { + talloc_free(*new); + *new = NULL; + return 0; + } + *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]); + (*new)->u.substring.chunks[i+1] = NULL; + } + break; + } + case LDB_OP_EQUALITY: + (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value); + break; + case LDB_OP_LESS: + case LDB_OP_GREATER: + case LDB_OP_APPROX: + (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value); + break; + case LDB_OP_EXTENDED: + (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value); + (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id); + break; + default: /* unknown kind of simple subtree */ + talloc_free(*new); + return LDB_ERR_OPERATIONS_ERROR; + } + + return 0; +} + +/* Collect subtrees that query attributes in the remote partition */ +static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) +{ + const struct ldb_map_context *data = map_get_context(module); + const struct ldb_map_attribute *map; + struct ldb_context *ldb; + + ldb = ldb_module_get_ctx(module); + + if (tree == NULL) { + return 0; + } + + if (tree->operation == LDB_OP_NOT) { + return map_subtree_collect_remote_not(module, mem_ctx, new, tree); + } + + if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) { + return map_subtree_collect_remote_list(module, mem_ctx, new, tree); + } + + if (!map_attr_check_remote(data, tree->u.equality.attr)) { + *new = NULL; + return 0; + } + + map = map_attr_find_local(data, tree->u.equality.attr); + if (map == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + if (map->convert_operator) { + return map->convert_operator(module, mem_ctx, new, tree); + } + + if (map->type == LDB_MAP_GENERATE) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " + "Skipping attribute '%s': " + "'convert_operator' not set", + tree->u.equality.attr); + *new = NULL; + return 0; + } + + return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map); +} + +/* Split subtrees that query attributes in the local partition from + * those that query the remote partition. */ +static int ldb_parse_tree_partition(struct ldb_module *module, + void *mem_ctx, + struct ldb_parse_tree **local_tree, + struct ldb_parse_tree **remote_tree, + const struct ldb_parse_tree *tree) +{ + int ret; + + *local_tree = NULL; + *remote_tree = NULL; + + /* No original tree */ + if (tree == NULL) { + return 0; + } + + /* Generate local tree */ + ret = map_subtree_select_local(module, mem_ctx, local_tree, tree); + if (ret) { + return ret; + } + + /* Generate remote tree */ + ret = map_subtree_collect_remote(module, mem_ctx, remote_tree, tree); + if (ret) { + talloc_free(*local_tree); + return ret; + } + + return 0; +} + +/* Collect a list of attributes required either explicitly from a + * given list or implicitly from a given parse tree; split the + * collected list into local and remote parts. */ +static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac, + const char * const *search_attrs, + const struct ldb_parse_tree *tree) +{ + void *tmp_ctx; + const char **tree_attrs; + const char **remote_attrs; + const char **local_attrs; + int ret; + + /* There is no tree, just partition the searched attributes */ + if (tree == NULL) { + ret = map_attrs_partition(module, ac, + &local_attrs, &remote_attrs, search_attrs); + if (ret == 0) { + ac->local_attrs = local_attrs; + ac->remote_attrs = remote_attrs; + ac->all_attrs = search_attrs; + } + return ret; + } + + /* Create context for temporary memory */ + tmp_ctx = talloc_new(ac); + if (tmp_ctx == NULL) { + goto oom; + } + + /* Prepare list of attributes from tree */ + tree_attrs = talloc_array(tmp_ctx, const char *, 1); + if (tree_attrs == NULL) { + talloc_free(tmp_ctx); + goto oom; + } + tree_attrs[0] = NULL; + + /* Collect attributes from tree */ + ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree); + if (ret) { + goto done; + } + + /* Merge attributes from search operation */ + ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs); + if (ret) { + goto done; + } + + /* Split local from remote attributes */ + ret = map_attrs_partition(module, ac, &local_attrs, + &remote_attrs, tree_attrs); + + if (ret == 0) { + ac->local_attrs = local_attrs; + ac->remote_attrs = remote_attrs; + talloc_steal(ac, tree_attrs); + ac->all_attrs = tree_attrs; + } +done: + /* Free temporary memory */ + talloc_free(tmp_ctx); + return ret; + +oom: + map_oom(module); + return LDB_ERR_OPERATIONS_ERROR; +} + + +/* Outbound requests: search + * ========================= */ + +static int map_remote_search_callback(struct ldb_request *req, + struct ldb_reply *ares); +static int map_local_merge_callback(struct ldb_request *req, + struct ldb_reply *ares); +static int map_search_local(struct map_context *ac); + +static int map_save_entry(struct map_context *ac, struct ldb_reply *ares) +{ + struct map_reply *mr; + + mr = talloc_zero(ac, struct map_reply); + if (mr == NULL) { + map_oom(ac->module); + return LDB_ERR_OPERATIONS_ERROR; + } + mr->remote = talloc_steal(mr, ares); + if (ac->r_current) { + ac->r_current->next = mr; + } else { + /* first entry */ + ac->r_list = mr; + } + ac->r_current = mr; + + return LDB_SUCCESS; +} + +/* Pass a merged search result up the callback chain. */ +int map_return_entry(struct map_context *ac, struct ldb_reply *ares) +{ + struct ldb_message_element *el; + const char * const *attrs; + struct ldb_context *ldb; + unsigned int i; + int ret; + bool matched; + + ldb = ldb_module_get_ctx(ac->module); + + /* Merged result doesn't match original query, skip */ + ret = ldb_match_msg_error(ldb, ares->message, + ac->req->op.search.tree, + ac->req->op.search.base, + ac->req->op.search.scope, + &matched); + if (ret != LDB_SUCCESS) return ret; + if (!matched) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: " + "Skipping record '%s': " + "doesn't match original search", + ldb_dn_get_linearized(ares->message->dn)); + return LDB_SUCCESS; + } + + /* Limit result to requested attrs */ + if (ac->req->op.search.attrs && + (! ldb_attr_in_list(ac->req->op.search.attrs, "*"))) { + + attrs = ac->req->op.search.attrs; + i = 0; + + while (i < ares->message->num_elements) { + + el = &ares->message->elements[i]; + if ( ! ldb_attr_in_list(attrs, el->name)) { + ldb_msg_remove_element(ares->message, el); + } else { + i++; + } + } + } + + return ldb_module_send_entry(ac->req, ares->message, ares->controls); +} + +/* Search a record. */ +int ldb_map_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_parse_tree *remote_tree; + struct ldb_parse_tree *local_tree; + struct ldb_request *remote_req; + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + const char *wildcard[] = { "*", NULL }; + const char * const *attrs; + + ldb = ldb_module_get_ctx(module); + + /* if we're not yet initialized, go to the next module */ + if (!ldb_module_get_private(module)) + return ldb_next_request(module, req); + + /* Do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.search.base)) { + return ldb_next_request(module, req); + } + + /* No mapping requested, skip to next module */ + if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) { + return ldb_next_request(module, req); + } + + /* TODO: How can we be sure about which partition we are + * targetting when there is no search base? */ + + /* Prepare context and handle */ + ac = map_init_context(module, req); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* It is easier to deal with the two different ways of + * expressing the wildcard in the same codepath */ + attrs = req->op.search.attrs; + if (attrs == NULL) { + attrs = wildcard; + } + + /* Split local from remote attrs */ + ret = map_attrs_collect_and_partition(module, ac, + attrs, req->op.search.tree); + if (ret) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Split local from remote tree */ + ret = ldb_parse_tree_partition(module, ac, + &local_tree, &remote_tree, + req->op.search.tree); + if (ret) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (((local_tree != NULL) && (remote_tree != NULL)) && + (!ldb_parse_tree_check_splittable(req->op.search.tree))) { + /* The query can't safely be split, enumerate the remote partition */ + local_tree = NULL; + remote_tree = NULL; + } + + if (local_tree == NULL) { + /* Construct default local parse tree */ + local_tree = talloc_zero(ac, struct ldb_parse_tree); + if (local_tree == NULL) { + map_oom(ac->module); + return LDB_ERR_OPERATIONS_ERROR; + } + + local_tree->operation = LDB_OP_PRESENT; + local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED); + } + if (remote_tree == NULL) { + /* Construct default remote parse tree */ + remote_tree = ldb_parse_tree(ac, NULL); + if (remote_tree == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + ac->local_tree = local_tree; + + /* Prepare the remote operation */ + ret = ldb_build_search_req_ex(&remote_req, ldb, ac, + req->op.search.base, + req->op.search.scope, + remote_tree, + ac->remote_attrs, + req->controls, + ac, map_remote_search_callback, + req); + LDB_REQ_SET_LOCATION(remote_req); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_remote_request(module, remote_req); +} + +/* Now, search the local part of a remote search result. */ +static int map_remote_search_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct map_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct map_context); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_REFERRAL: + + /* ignore referrals */ + talloc_free(ares); + return LDB_SUCCESS; + + case LDB_REPLY_ENTRY: + + /* Map result record into a local message */ + ret = map_reply_remote(ac, ares); + if (ret) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + /* if we have no local db, then we can just return the reply to + * the upper layer, otherwise we must save it and process it + * when all replies ahve been gathered */ + if ( ! map_check_local_db(ac->module)) { + ret = map_return_entry(ac, ares); + } else { + ret = map_save_entry(ac,ares); + } + + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, ret); + } + break; + + case LDB_REPLY_DONE: + + if ( ! map_check_local_db(ac->module)) { + return ldb_module_done(ac->req, ares->controls, + ares->response, LDB_SUCCESS); + } + + /* reset the pointer to the start of the list */ + ac->r_current = ac->r_list; + + /* no entry just return */ + if (ac->r_current == NULL) { + ret = ldb_module_done(ac->req, ares->controls, + ares->response, LDB_SUCCESS); + talloc_free(ares); + return ret; + } + + ac->remote_done_ares = talloc_steal(ac, ares); + + ret = map_search_local(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + } + + return LDB_SUCCESS; +} + +static int map_search_local(struct map_context *ac) +{ + struct ldb_request *search_req; + + if (ac->r_current == NULL || ac->r_current->remote == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare local search request */ + /* TODO: use GUIDs here instead? */ + search_req = map_search_base_req(ac, + ac->r_current->remote->message->dn, + NULL, NULL, + ac, map_local_merge_callback); + if (search_req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(ac->module, search_req); +} + +/* Merge the remote and local parts of a search result. */ +int map_local_merge_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct map_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct map_context); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + /* We have already found a local record */ + if (ac->r_current->local) { + talloc_free(ares); + ldb_set_errstring(ldb, "ldb_map: Too many results!"); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + /* Store local result */ + ac->r_current->local = talloc_steal(ac->r_current, ares); + + break; + + case LDB_REPLY_REFERRAL: + /* ignore referrals */ + talloc_free(ares); + break; + + case LDB_REPLY_DONE: + /* We don't need the local 'ares', but we will use the remote one from below */ + talloc_free(ares); + + /* No local record found, map and send remote record */ + if (ac->r_current->local != NULL) { + /* Merge remote into local message */ + ret = ldb_msg_merge_local(ac->module, + ac->r_current->local->message, + ac->r_current->remote->message); + if (ret == LDB_SUCCESS) { + ret = map_return_entry(ac, ac->r_current->local); + } + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + } else { + ret = map_return_entry(ac, ac->r_current->remote); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, + NULL, NULL, ret); + } + } + + if (ac->r_current->next != NULL) { + ac->r_current = ac->r_current->next; + if (ac->r_current->remote->type == LDB_REPLY_ENTRY) { + ret = map_search_local(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, + NULL, NULL, ret); + } + break; + } + } + + /* ok we are done with all search, finally it is time to + * finish operations for this module */ + return ldb_module_done(ac->req, + ac->remote_done_ares->controls, + ac->remote_done_ares->response, + ac->remote_done_ares->error); + } + + return LDB_SUCCESS; +} diff --git a/ldb-2.0.8/ldb_map/ldb_map_private.h b/ldb-2.0.8/ldb_map/ldb_map_private.h new file mode 100644 index 0000000..6e4a9dd --- /dev/null +++ b/ldb-2.0.8/ldb_map/ldb_map_private.h @@ -0,0 +1,96 @@ +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" + +/* A handy macro to report Out of Memory conditions */ +#define map_oom(module) ldb_set_errstring(ldb_module_get_ctx(module), talloc_asprintf(module, "Out of Memory")); + +/* The type of search callback functions */ +typedef int (*ldb_map_callback_t)(struct ldb_request *, struct ldb_reply *); + +/* The special DN from which the local and remote base DNs are fetched */ +#define MAP_DN_NAME "@MAP" +#define MAP_DN_FROM "@FROM" +#define MAP_DN_TO "@TO" + +/* Private data structures + * ======================= */ + +struct map_reply { + struct map_reply *next; + struct ldb_reply *remote; + struct ldb_reply *local; +}; + +/* Context data for mapped requests */ +struct map_context { + + struct ldb_module *module; + struct ldb_request *req; + + struct ldb_dn *local_dn; + const struct ldb_parse_tree *local_tree; + const char * const *local_attrs; + const char * const *remote_attrs; + const char * const *all_attrs; + + struct ldb_message *local_msg; + struct ldb_request *remote_req; + + struct map_reply *r_list; + struct map_reply *r_current; + + /* The response continaing any controls the remote server gave */ + struct ldb_reply *remote_done_ares; +}; + +/* Common operations + * ================= */ + +/* The following definitions come from lib/ldb/modules/ldb_map.c */ +const struct ldb_map_context *map_get_context(struct ldb_module *module); +struct map_context *map_init_context(struct ldb_module *module, + struct ldb_request *req); + +int ldb_next_remote_request(struct ldb_module *module, struct ldb_request *request); + +bool map_check_local_db(struct ldb_module *module); +bool map_attr_check_remote(const struct ldb_map_context *data, const char *attr); +bool ldb_dn_check_local(struct ldb_module *module, struct ldb_dn *dn); + +const struct ldb_map_attribute *map_attr_find_local(const struct ldb_map_context *data, const char *name); +const struct ldb_map_attribute *map_attr_find_remote(const struct ldb_map_context *data, const char *name); + +const char *map_attr_map_local(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr); +const char *map_attr_map_remote(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr); +int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attrs, const char * const *more_attrs); + +struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val); +struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val); + +struct ldb_dn *ldb_dn_map_local(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn); +struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn); +struct ldb_dn *ldb_dn_map_rebase_remote(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn); + +struct ldb_request *map_search_base_req(struct map_context *ac, + struct ldb_dn *dn, + const char * const *attrs, + struct ldb_parse_tree *tree, + void *context, + ldb_map_callback_t callback); +struct ldb_request *map_build_fixup_req(struct map_context *ac, + struct ldb_dn *olddn, + struct ldb_dn *newdn, + void *context, + ldb_map_callback_t callback); +int map_subtree_collect_remote_simple(struct ldb_module *module, void *mem_ctx, + struct ldb_parse_tree **new, + const struct ldb_parse_tree *tree, + const struct ldb_map_attribute *map); +int map_return_fatal_error(struct ldb_request *req, + struct ldb_reply *ares); +int map_return_normal_error(struct ldb_request *req, + struct ldb_reply *ares, + int error); + +int map_return_entry(struct map_context *ac, struct ldb_reply *ares); diff --git a/ldb-2.0.8/ldb_mdb/ldb_mdb.c b/ldb-2.0.8/ldb_mdb/ldb_mdb.c new file mode 100644 index 0000000..6c679c2 --- /dev/null +++ b/ldb-2.0.8/ldb_mdb/ldb_mdb.c @@ -0,0 +1,1126 @@ +/* + ldb database library using mdb back end + + Copyright (C) Jakub Hrozek 2014 + Copyright (C) Catalyst.Net Ltd 2017 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include "ldb_mdb.h" +#include "../ldb_key_value/ldb_kv.h" +#include "include/dlinklist.h" + +#define MDB_URL_PREFIX "mdb://" +#define MDB_URL_PREFIX_SIZE (sizeof(MDB_URL_PREFIX)-1) + +#define LDB_MDB_MAX_KEY_LENGTH 511 + +#define GIGABYTE (1024*1024*1024) + +int ldb_mdb_err_map(int lmdb_err) +{ + switch (lmdb_err) { + case MDB_SUCCESS: + return LDB_SUCCESS; + case EIO: + return LDB_ERR_OPERATIONS_ERROR; +#ifdef EBADE + case EBADE: +#endif + case MDB_INCOMPATIBLE: + case MDB_CORRUPTED: + case MDB_INVALID: + return LDB_ERR_UNAVAILABLE; + case MDB_BAD_TXN: + case MDB_BAD_VALSIZE: +#ifdef MDB_BAD_DBI + case MDB_BAD_DBI: +#endif + case MDB_PANIC: + case EINVAL: + return LDB_ERR_PROTOCOL_ERROR; + case MDB_MAP_FULL: + case MDB_DBS_FULL: + case MDB_READERS_FULL: + case MDB_TLS_FULL: + case MDB_TXN_FULL: + case EAGAIN: + return LDB_ERR_BUSY; + case MDB_KEYEXIST: + return LDB_ERR_ENTRY_ALREADY_EXISTS; + case MDB_NOTFOUND: + case ENOENT: + return LDB_ERR_NO_SUCH_OBJECT; + case EACCES: + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + default: + break; + } + return LDB_ERR_OTHER; +} + +#define ldb_mdb_error(ldb, ecode) lmdb_error_at(ldb, ecode, __FILE__, __LINE__) +static int lmdb_error_at(struct ldb_context *ldb, + int ecode, + const char *file, + int line) +{ + int ldb_err = ldb_mdb_err_map(ecode); + char *reason = mdb_strerror(ecode); + ldb_asprintf_errstring(ldb, + "(%d) - %s at %s:%d", + ecode, + reason, + file, + line); + return ldb_err; +} + +static bool lmdb_transaction_active(struct ldb_kv_private *ldb_kv) +{ + return ldb_kv->lmdb_private->txlist != NULL; +} + +static MDB_txn *lmdb_trans_get_tx(struct lmdb_trans *ltx) +{ + if (ltx == NULL) { + return NULL; + } + + return ltx->tx; +} + +static void trans_push(struct lmdb_private *lmdb, struct lmdb_trans *ltx) +{ + if (lmdb->txlist) { + talloc_steal(lmdb->txlist, ltx); + } + + DLIST_ADD(lmdb->txlist, ltx); +} + +static void trans_finished(struct lmdb_private *lmdb, struct lmdb_trans *ltx) +{ + DLIST_REMOVE(lmdb->txlist, ltx); + talloc_free(ltx); +} + + +static struct lmdb_trans *lmdb_private_trans_head(struct lmdb_private *lmdb) +{ + struct lmdb_trans *ltx; + + ltx = lmdb->txlist; + return ltx; +} + + +static MDB_txn *get_current_txn(struct lmdb_private *lmdb) +{ + MDB_txn *txn = NULL; + + txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb)); + if (txn != NULL) { + return txn; + } + if (lmdb->read_txn != NULL) { + return lmdb->read_txn; + } + lmdb->error = MDB_BAD_TXN; + ldb_set_errstring(lmdb->ldb, __location__":No active transaction\n"); + return NULL; +} + +static int lmdb_store(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val data, + int flags) +{ + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + MDB_val mdb_key; + MDB_val mdb_data; + int mdb_flags; + MDB_txn *txn = NULL; + MDB_dbi dbi = 0; + + if (ldb_kv->read_only) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb)); + if (txn == NULL) { + ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction"); + lmdb->error = MDB_PANIC; + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + mdb_key.mv_size = key.length; + mdb_key.mv_data = key.data; + + mdb_data.mv_size = data.length; + mdb_data.mv_data = data.data; + + if (flags == TDB_INSERT) { + mdb_flags = MDB_NOOVERWRITE; + } else if ((flags == TDB_MODIFY)) { + /* + * Modifying a record, ensure that it exists. + * This mimics the TDB semantics + */ + MDB_val value; + lmdb->error = mdb_get(txn, dbi, &mdb_key, &value); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + mdb_flags = 0; + } else { + mdb_flags = 0; + } + + lmdb->error = mdb_put(txn, dbi, &mdb_key, &mdb_data, mdb_flags); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + return ldb_mdb_err_map(lmdb->error); +} + +static int lmdb_delete(struct ldb_kv_private *ldb_kv, struct ldb_val key) +{ + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + MDB_val mdb_key; + MDB_txn *txn = NULL; + MDB_dbi dbi = 0; + + if (ldb_kv->read_only) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb)); + if (txn == NULL) { + ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction"); + lmdb->error = MDB_PANIC; + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + mdb_key.mv_size = key.length; + mdb_key.mv_data = key.data; + + lmdb->error = mdb_del(txn, dbi, &mdb_key, NULL); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + return ldb_mdb_err_map(lmdb->error); +} + +static int lmdb_traverse_fn(struct ldb_kv_private *ldb_kv, + ldb_kv_traverse_fn fn, + void *ctx) +{ + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + MDB_val mdb_key; + MDB_val mdb_data; + MDB_txn *txn = NULL; + MDB_dbi dbi = 0; + MDB_cursor *cursor = NULL; + int ret; + + txn = get_current_txn(lmdb); + if (txn == NULL) { + ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction"); + lmdb->error = MDB_PANIC; + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + lmdb->error = mdb_cursor_open(txn, dbi, &cursor); + if (lmdb->error != MDB_SUCCESS) { + goto done; + } + + while ((lmdb->error = mdb_cursor_get( + cursor, &mdb_key, + &mdb_data, MDB_NEXT)) == MDB_SUCCESS) { + + struct ldb_val key = { + .length = mdb_key.mv_size, + .data = mdb_key.mv_data, + }; + struct ldb_val data = { + .length = mdb_data.mv_size, + .data = mdb_data.mv_data, + }; + + ret = fn(ldb_kv, key, data, ctx); + if (ret != 0) { + /* + * NOTE: This DOES NOT set lmdb->error! + * + * This means that the caller will get success. + * This matches TDB traverse behaviour, where callbacks + * may terminate the traverse, but do not change the + * return code from success. + * + * Callers SHOULD store their own error codes. + */ + goto done; + } + } + if (lmdb->error == MDB_NOTFOUND) { + lmdb->error = MDB_SUCCESS; + } +done: + if (cursor != NULL) { + mdb_cursor_close(cursor); + } + + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + return ldb_mdb_err_map(lmdb->error); +} + +static int lmdb_update_in_iterate(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val key2, + struct ldb_val data, + void *state) +{ + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + struct ldb_val copy; + int ret = LDB_SUCCESS; + + /* + * Need to take a copy of the data as the delete operation alters the + * data, as it is in private lmdb memory. + */ + copy.length = data.length; + copy.data = talloc_memdup(ldb_kv, data.data, data.length); + if (copy.data == NULL) { + lmdb->error = MDB_PANIC; + return ldb_oom(lmdb->ldb); + } + + lmdb->error = lmdb_delete(ldb_kv, key); + if (lmdb->error != MDB_SUCCESS) { + ldb_debug( + lmdb->ldb, + LDB_DEBUG_ERROR, + "Failed to delete %*.*s " + "for rekey as %*.*s: %s", + (int)key.length, (int)key.length, + (const char *)key.data, + (int)key2.length, (int)key2.length, + (const char *)key.data, + mdb_strerror(lmdb->error)); + ret = ldb_mdb_error(lmdb->ldb, lmdb->error); + goto done; + } + + lmdb->error = lmdb_store(ldb_kv, key2, copy, 0); + if (lmdb->error != MDB_SUCCESS) { + ldb_debug( + lmdb->ldb, + LDB_DEBUG_ERROR, + "Failed to rekey %*.*s as %*.*s: %s", + (int)key.length, (int)key.length, + (const char *)key.data, + (int)key2.length, (int)key2.length, + (const char *)key.data, + mdb_strerror(lmdb->error)); + ret = ldb_mdb_error(lmdb->ldb, lmdb->error); + goto done; + } + +done: + if (copy.data != NULL) { + TALLOC_FREE(copy.data); + copy.length = 0; + } + + /* + * Explicity invalidate the data, as the delete has done this + */ + data.length = 0; + data.data = NULL; + + return ret; +} + +/* Handles only a single record */ +static int lmdb_parse_record(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + int (*parser)(struct ldb_val key, + struct ldb_val data, + void *private_data), + void *ctx) +{ + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + MDB_val mdb_key; + MDB_val mdb_data; + MDB_txn *txn = NULL; + MDB_dbi dbi; + struct ldb_val data; + + txn = get_current_txn(lmdb); + if (txn == NULL) { + ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction active"); + lmdb->error = MDB_PANIC; + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + mdb_key.mv_size = key.length; + mdb_key.mv_data = key.data; + + lmdb->error = mdb_get(txn, dbi, &mdb_key, &mdb_data); + if (lmdb->error != MDB_SUCCESS) { + /* TODO closing a handle should not even be necessary */ + mdb_dbi_close(lmdb->env, dbi); + if (lmdb->error == MDB_NOTFOUND) { + return LDB_ERR_NO_SUCH_OBJECT; + } + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + data.data = mdb_data.mv_data; + data.length = mdb_data.mv_size; + + /* TODO closing a handle should not even be necessary */ + mdb_dbi_close(lmdb->env, dbi); + + return parser(key, data, ctx); +} + +/* + * Exactly the same as iterate, except we have a start key and an end key + * (which are both included in the results if present). + * + * If start > end, return MDB_PANIC. + */ +static int lmdb_iterate_range(struct ldb_kv_private *ldb_kv, + struct ldb_val start_key, + struct ldb_val end_key, + ldb_kv_traverse_fn fn, + void *ctx) +{ + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + MDB_val mdb_key; + MDB_val mdb_data; + MDB_txn *txn = NULL; + MDB_dbi dbi = 0; + MDB_cursor *cursor = NULL; + int ret; + + MDB_val mdb_s_key; + MDB_val mdb_e_key; + + txn = get_current_txn(lmdb); + if (txn == NULL) { + ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction"); + lmdb->error = MDB_PANIC; + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + mdb_s_key.mv_size = start_key.length; + mdb_s_key.mv_data = start_key.data; + + mdb_e_key.mv_size = end_key.length; + mdb_e_key.mv_data = end_key.data; + + if (mdb_cmp(txn, dbi, &mdb_s_key, &mdb_e_key) > 0) { + lmdb->error = MDB_PANIC; + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + lmdb->error = mdb_cursor_open(txn, dbi, &cursor); + if (lmdb->error != MDB_SUCCESS) { + goto done; + } + + lmdb->error = mdb_cursor_get(cursor, &mdb_s_key, &mdb_data, MDB_SET_RANGE); + + if (lmdb->error != MDB_SUCCESS) { + if (lmdb->error == MDB_NOTFOUND) { + lmdb->error = MDB_SUCCESS; + } + goto done; + } else { + struct ldb_val key = { + .length = mdb_s_key.mv_size, + .data = mdb_s_key.mv_data, + }; + struct ldb_val data = { + .length = mdb_data.mv_size, + .data = mdb_data.mv_data, + }; + + if (mdb_cmp(txn, dbi, &mdb_s_key, &mdb_e_key) > 0) { + goto done; + } + + ret = fn(ldb_kv, key, data, ctx); + if (ret != 0) { + /* + * NOTE: This DOES NOT set lmdb->error! + * + * This means that the caller will get success. + * This matches TDB traverse behaviour, where callbacks + * may terminate the traverse, but do not change the + * return code from success. + * + * Callers SHOULD store their own error codes. + */ + goto done; + } + } + + while ((lmdb->error = mdb_cursor_get( + cursor, &mdb_key, + &mdb_data, MDB_NEXT)) == MDB_SUCCESS) { + + struct ldb_val key = { + .length = mdb_key.mv_size, + .data = mdb_key.mv_data, + }; + struct ldb_val data = { + .length = mdb_data.mv_size, + .data = mdb_data.mv_data, + }; + + if (mdb_cmp(txn, dbi, &mdb_key, &mdb_e_key) > 0) { + goto done; + } + + ret = fn(ldb_kv, key, data, ctx); + if (ret != 0) { + /* + * NOTE: This DOES NOT set lmdb->error! + * + * This means that the caller will get success. + * This matches TDB traverse behaviour, where callbacks + * may terminate the traverse, but do not change the + * return code from success. + * + * Callers SHOULD store their own error codes. + */ + goto done; + } + } + if (lmdb->error == MDB_NOTFOUND) { + lmdb->error = MDB_SUCCESS; + } +done: + if (cursor != NULL) { + mdb_cursor_close(cursor); + } + + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + return ldb_mdb_err_map(lmdb->error); +} + +static int lmdb_lock_read(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + pid_t pid = getpid(); + + if (pid != lmdb->pid) { + ldb_asprintf_errstring( + lmdb->ldb, + __location__": Reusing ldb opened by pid %d in " + "process %d\n", + lmdb->pid, + pid); + lmdb->error = MDB_BAD_TXN; + return LDB_ERR_PROTOCOL_ERROR; + } + + lmdb->error = MDB_SUCCESS; + if (lmdb_transaction_active(ldb_kv) == false && + ldb_kv->read_lock_count == 0) { + lmdb->error = mdb_txn_begin(lmdb->env, + NULL, + MDB_RDONLY, + &lmdb->read_txn); + } + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + ldb_kv->read_lock_count++; + return ldb_mdb_err_map(lmdb->error); +} + +static int lmdb_unlock_read(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + + if (lmdb_transaction_active(ldb_kv) == false && + ldb_kv->read_lock_count == 1) { + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + mdb_txn_commit(lmdb->read_txn); + lmdb->read_txn = NULL; + ldb_kv->read_lock_count--; + return LDB_SUCCESS; + } + ldb_kv->read_lock_count--; + return LDB_SUCCESS; +} + +static int lmdb_transaction_start(struct ldb_kv_private *ldb_kv) +{ + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + struct lmdb_trans *ltx; + struct lmdb_trans *ltx_head; + MDB_txn *tx_parent; + pid_t pid = getpid(); + + /* Do not take out the transaction lock on a read-only DB */ + if (ldb_kv->read_only) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + ltx = talloc_zero(lmdb, struct lmdb_trans); + if (ltx == NULL) { + return ldb_oom(lmdb->ldb); + } + + if (pid != lmdb->pid) { + ldb_asprintf_errstring( + lmdb->ldb, + __location__": Reusing ldb opened by pid %d in " + "process %d\n", + lmdb->pid, + pid); + lmdb->error = MDB_BAD_TXN; + return LDB_ERR_PROTOCOL_ERROR; + } + + ltx_head = lmdb_private_trans_head(lmdb); + + tx_parent = lmdb_trans_get_tx(ltx_head); + + lmdb->error = mdb_txn_begin(lmdb->env, tx_parent, 0, <x->tx); + if (lmdb->error != MDB_SUCCESS) { + return ldb_mdb_error(lmdb->ldb, lmdb->error); + } + + trans_push(lmdb, ltx); + + return ldb_mdb_err_map(lmdb->error); +} + +static int lmdb_transaction_cancel(struct ldb_kv_private *ldb_kv) +{ + struct lmdb_trans *ltx; + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + + ltx = lmdb_private_trans_head(lmdb); + if (ltx == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + mdb_txn_abort(ltx->tx); + trans_finished(lmdb, ltx); + return LDB_SUCCESS; +} + +static int lmdb_transaction_prepare_commit(struct ldb_kv_private *ldb_kv) +{ + /* No need to prepare a commit */ + return LDB_SUCCESS; +} + +static int lmdb_transaction_commit(struct ldb_kv_private *ldb_kv) +{ + struct lmdb_trans *ltx; + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + + ltx = lmdb_private_trans_head(lmdb); + if (ltx == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + lmdb->error = mdb_txn_commit(ltx->tx); + trans_finished(lmdb, ltx); + + return lmdb->error; +} + +static int lmdb_error(struct ldb_kv_private *ldb_kv) +{ + return ldb_mdb_err_map(ldb_kv->lmdb_private->error); +} + +static const char *lmdb_errorstr(struct ldb_kv_private *ldb_kv) +{ + return mdb_strerror(ldb_kv->lmdb_private->error); +} + +static const char *lmdb_name(struct ldb_kv_private *ldb_kv) +{ + return "lmdb"; +} + +static bool lmdb_changed(struct ldb_kv_private *ldb_kv) +{ + /* + * lmdb does no provide a quick way to determine if the database + * has changed. This function always returns true. + * + * Note that tdb uses a sequence number that allows this function + * to be implemented efficiently. + */ + return true; +} + +/* + * Get the number of records in the database. + * + * The mdb_env_stat call returns an accurate count, so we return the actual + * number of records in the database rather than an estimate. + */ +static size_t lmdb_get_size(struct ldb_kv_private *ldb_kv) +{ + + struct MDB_stat stats = {0}; + struct lmdb_private *lmdb = ldb_kv->lmdb_private; + int ret = 0; + + ret = mdb_env_stat(lmdb->env, &stats); + if (ret != 0) { + return 0; + } + return stats.ms_entries; +} + +/* + * Start a sub transaction + * As lmdb supports nested transactions we can start a new transaction + */ +static int lmdb_nested_transaction_start(struct ldb_kv_private *ldb_kv) +{ + int ret = lmdb_transaction_start(ldb_kv); + return ret; +} + +/* + * Commit a sub transaction + * As lmdb supports nested transactions we can commit the nested transaction + */ +static int lmdb_nested_transaction_commit(struct ldb_kv_private *ldb_kv) +{ + int ret = lmdb_transaction_commit(ldb_kv); + return ret; +} + +/* + * Cancel a sub transaction + * As lmdb supports nested transactions we can cancel the nested transaction + */ +static int lmdb_nested_transaction_cancel(struct ldb_kv_private *ldb_kv) +{ + int ret = lmdb_transaction_cancel(ldb_kv); + return ret; +} + +static struct kv_db_ops lmdb_key_value_ops = { + .options = LDB_KV_OPTION_STABLE_READ_LOCK, + + .store = lmdb_store, + .delete = lmdb_delete, + .iterate = lmdb_traverse_fn, + .update_in_iterate = lmdb_update_in_iterate, + .fetch_and_parse = lmdb_parse_record, + .iterate_range = lmdb_iterate_range, + .lock_read = lmdb_lock_read, + .unlock_read = lmdb_unlock_read, + .begin_write = lmdb_transaction_start, + .prepare_write = lmdb_transaction_prepare_commit, + .finish_write = lmdb_transaction_commit, + .abort_write = lmdb_transaction_cancel, + .error = lmdb_error, + .errorstr = lmdb_errorstr, + .name = lmdb_name, + .has_changed = lmdb_changed, + .transaction_active = lmdb_transaction_active, + .get_size = lmdb_get_size, + .begin_nested_write = lmdb_nested_transaction_start, + .finish_nested_write = lmdb_nested_transaction_commit, + .abort_nested_write = lmdb_nested_transaction_cancel, +}; + +static const char *lmdb_get_path(const char *url) +{ + const char *path; + + /* parse the url */ + if (strchr(url, ':')) { + if (strncmp(url, MDB_URL_PREFIX, MDB_URL_PREFIX_SIZE) != 0) { + return NULL; + } + path = url + MDB_URL_PREFIX_SIZE; + } else { + path = url; + } + + return path; +} + +static int lmdb_pvt_destructor(struct lmdb_private *lmdb) +{ + struct lmdb_trans *ltx = NULL; + + /* Check if this is a forked child */ + if (getpid() != lmdb->pid) { + int fd = 0; + /* + * We cannot call mdb_env_close or commit any transactions, + * otherwise they might appear finished in the parent. + * + */ + + if (mdb_env_get_fd(lmdb->env, &fd) == 0) { + close(fd); + } + + /* Remove the pointer, so that no access should occur */ + lmdb->env = NULL; + + return 0; + } + + /* + * Close the read transaction if it's open + */ + if (lmdb->read_txn != NULL) { + mdb_txn_abort(lmdb->read_txn); + } + + if (lmdb->env == NULL) { + return 0; + } + + /* + * Abort any currently active transactions + */ + ltx = lmdb_private_trans_head(lmdb); + while (ltx != NULL) { + mdb_txn_abort(ltx->tx); + trans_finished(lmdb, ltx); + ltx = lmdb_private_trans_head(lmdb); + } + lmdb->env = NULL; + + return 0; +} + +struct mdb_env_wrap { + struct mdb_env_wrap *next, *prev; + dev_t device; + ino_t inode; + MDB_env *env; + pid_t pid; +}; + +static struct mdb_env_wrap *mdb_list; + +/* destroy the last connection to an mdb */ +static int mdb_env_wrap_destructor(struct mdb_env_wrap *w) +{ + mdb_env_close(w->env); + DLIST_REMOVE(mdb_list, w); + return 0; +} + +static int lmdb_open_env(TALLOC_CTX *mem_ctx, + MDB_env **env, + struct ldb_context *ldb, + const char *path, + const size_t env_map_size, + unsigned int flags) +{ + int ret; + unsigned int mdb_flags = MDB_NOSUBDIR|MDB_NOTLS; + /* + * MDB_NOSUBDIR implies there is a separate file called path and a + * separate lockfile called path-lock + */ + + struct mdb_env_wrap *w; + struct stat st; + pid_t pid = getpid(); + int fd = 0; + unsigned v; + + if (stat(path, &st) == 0) { + for (w=mdb_list;w;w=w->next) { + if (st.st_dev == w->device && + st.st_ino == w->inode && + pid == w->pid) { + /* + * We must have only one MDB_env per process + */ + if (!talloc_reference(mem_ctx, w)) { + return ldb_oom(ldb); + } + *env = w->env; + return LDB_SUCCESS; + } + } + } + + w = talloc(mem_ctx, struct mdb_env_wrap); + if (w == NULL) { + return ldb_oom(ldb); + } + + ret = mdb_env_create(env); + if (ret != 0) { + ldb_asprintf_errstring( + ldb, + "Could not create MDB environment %s: %s\n", + path, + mdb_strerror(ret)); + return ldb_mdb_err_map(ret); + } + + if (env_map_size > 0) { + ret = mdb_env_set_mapsize(*env, env_map_size); + if (ret != 0) { + ldb_asprintf_errstring( + ldb, + "Could not set MDB mmap() size to %llu " + "on %s: %s\n", + (unsigned long long)(env_map_size), + path, + mdb_strerror(ret)); + TALLOC_FREE(w); + return ldb_mdb_err_map(ret); + } + } + + mdb_env_set_maxreaders(*env, 100000); + /* + * As we ensure that there is only one MDB_env open per database per + * process. We can not use the MDB_RDONLY flag, as another ldb may be + * opened in read write mode + */ + if (flags & LDB_FLG_NOSYNC) { + mdb_flags |= MDB_NOSYNC; + } + ret = mdb_env_open(*env, path, mdb_flags, 0644); + if (ret != 0) { + ldb_asprintf_errstring(ldb, + "Could not open DB %s: %s\n", + path, mdb_strerror(ret)); + TALLOC_FREE(w); + return ldb_mdb_err_map(ret); + } + + { + MDB_envinfo stat = {0}; + ret = mdb_env_info (*env, &stat); + if (ret != 0) { + ldb_asprintf_errstring( + ldb, + "Could not get MDB environment stats %s: %s\n", + path, + mdb_strerror(ret)); + return ldb_mdb_err_map(ret); + } + } + + ret = mdb_env_get_fd(*env, &fd); + if (ret != 0) { + ldb_asprintf_errstring(ldb, + "Could not obtain DB FD %s: %s\n", + path, mdb_strerror(ret)); + TALLOC_FREE(w); + return ldb_mdb_err_map(ret); + } + + /* Just as for TDB: on exec, don't inherit the fd */ + v = fcntl(fd, F_GETFD, 0); + if (v == -1) { + TALLOC_FREE(w); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = fcntl(fd, F_SETFD, v | FD_CLOEXEC); + if (ret == -1) { + TALLOC_FREE(w); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (fstat(fd, &st) != 0) { + ldb_asprintf_errstring( + ldb, + "Could not stat %s:\n", + path); + TALLOC_FREE(w); + return LDB_ERR_OPERATIONS_ERROR; + } + w->env = *env; + w->device = st.st_dev; + w->inode = st.st_ino; + w->pid = pid; + + talloc_set_destructor(w, mdb_env_wrap_destructor); + + DLIST_ADD(mdb_list, w); + + return LDB_SUCCESS; + +} + +static int lmdb_pvt_open(struct lmdb_private *lmdb, + struct ldb_context *ldb, + const char *path, + const size_t env_map_size, + unsigned int flags) +{ + int ret; + int lmdb_max_key_length; + + if (flags & LDB_FLG_DONT_CREATE_DB) { + struct stat st; + if (stat(path, &st) != 0) { + return LDB_ERR_UNAVAILABLE; + } + } + + ret = lmdb_open_env(lmdb, &lmdb->env, ldb, path, env_map_size, flags); + if (ret != 0) { + return ret; + } + + /* Close when lmdb is released */ + talloc_set_destructor(lmdb, lmdb_pvt_destructor); + + /* Store the original pid during the LMDB open */ + lmdb->pid = getpid(); + + lmdb_max_key_length = mdb_env_get_maxkeysize(lmdb->env); + + /* This will never happen, but if it does make sure to freak out */ + if (lmdb_max_key_length < LDB_MDB_MAX_KEY_LENGTH) { + return ldb_operr(ldb); + } + + return LDB_SUCCESS; +} + +int lmdb_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[], + struct ldb_module **_module) +{ + const char *path = NULL; + struct lmdb_private *lmdb = NULL; + struct ldb_kv_private *ldb_kv = NULL; + int ret; + size_t env_map_size = 0; + + /* + * We hold locks, so we must use a private event context + * on each returned handle + */ + ldb_set_require_private_event_context(ldb); + + path = lmdb_get_path(url); + if (path == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid mdb URL '%s'", url); + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_kv = talloc_zero(ldb, struct ldb_kv_private); + if (!ldb_kv) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + lmdb = talloc_zero(ldb_kv, struct lmdb_private); + if (lmdb == NULL) { + TALLOC_FREE(ldb_kv); + return ldb_oom(ldb); + } + lmdb->ldb = ldb; + ldb_kv->kv_ops = &lmdb_key_value_ops; + + { + const char *size = ldb_options_find( + ldb, ldb->options, "lmdb_env_size"); + if (size != NULL) { + env_map_size = strtoull(size, NULL, 0); + } + } + + ret = lmdb_pvt_open(lmdb, ldb, path, env_map_size, flags); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(ldb_kv); + return ret; + } + + ldb_kv->lmdb_private = lmdb; + if (flags & LDB_FLG_RDONLY) { + ldb_kv->read_only = true; + } + + /* + * This maximum length becomes encoded in the index values so + * must never change even if LMDB starts to allow longer keys. + * The override option is max_key_len_for_self_test, and is + * used for testing only. + */ + ldb_kv->max_key_length = LDB_MDB_MAX_KEY_LENGTH; + + return ldb_kv_init_store( + ldb_kv, "ldb_mdb backend", ldb, options, _module); +} diff --git a/ldb-2.0.8/ldb_mdb/ldb_mdb.h b/ldb-2.0.8/ldb_mdb/ldb_mdb.h new file mode 100644 index 0000000..8f21493 --- /dev/null +++ b/ldb-2.0.8/ldb_mdb/ldb_mdb.h @@ -0,0 +1,60 @@ +/* + ldb database library using mdb back end - transaction operations + + Copyright (C) Jakub Hrozek 2015 + Copyright (C) Catalyst.Net Ltd 2017 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#ifndef _LDB_MDB_H_ +#define _LDB_MDB_H_ + +#include "ldb_private.h" +#include + +struct lmdb_private { + struct ldb_context *ldb; + MDB_env *env; + + struct lmdb_trans *txlist; + + struct ldb_mdb_metadata { + struct ldb_message *attributes; + unsigned seqnum; + } *meta; + int error; + MDB_txn *read_txn; + + pid_t pid; + +}; + +struct lmdb_trans { + struct lmdb_trans *next; + struct lmdb_trans *prev; + + MDB_txn *tx; +}; + +int ldb_mdb_err_map(int lmdb_err); +int lmdb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, const char *options[], + struct ldb_module **_module); + +#endif /* _LDB_MDB_H_ */ diff --git a/ldb-2.0.8/ldb_mdb/ldb_mdb_init.c b/ldb-2.0.8/ldb_mdb/ldb_mdb_init.c new file mode 100644 index 0000000..339c3f2 --- /dev/null +++ b/ldb-2.0.8/ldb_mdb/ldb_mdb_init.c @@ -0,0 +1,31 @@ +/* + ldb database library using mdb back end + + Copyright (C) Jakub Hrozek 2014 + Copyright (C) Catalyst.Net Ltd 2017 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include "ldb_mdb.h" + +int ldb_mdb_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_backend("mdb", lmdb_connect, false); +} diff --git a/ldb-2.0.8/ldb_sqlite3/README b/ldb-2.0.8/ldb_sqlite3/README new file mode 100644 index 0000000..6cda0a7 --- /dev/null +++ b/ldb-2.0.8/ldb_sqlite3/README @@ -0,0 +1,7 @@ +trees.ps contains an explanation of the Genealogical Representation of Trees +in Databases which is being used in ldb_sqlite3. Note that we use fgID +representation with 4 bytes per level, so we can represent 6.5E+08 subclasses +of any object class. This should be adequate for our purposes. :-) + +The following document is the primary basis for the schema currently being +used here: http://www.research.ibm.com/journal/sj/392/shi.html diff --git a/ldb-2.0.8/ldb_sqlite3/base160.c b/ldb-2.0.8/ldb_sqlite3/base160.c new file mode 100644 index 0000000..7ad39f7 --- /dev/null +++ b/ldb-2.0.8/ldb_sqlite3/base160.c @@ -0,0 +1,154 @@ +/* + base160 code used by ldb_sqlite3 + + Copyright (C) 2004 Derrell Lipman + + 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 + Lesser 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 . +*/ + + +/* + * ldb_sqlite3_base160() + * + * Convert an integer value to a string containing the base 160 representation + * of the integer. We always convert to a string representation that is 4 + * bytes in length, and we always null terminate. + * + * Parameters: + * val -- + * The value to be converted + * + * result -- + * Buffer in which the result is to be placed + * + * Returns: + * nothing + */ +static unsigned char base160tab[161] = +{ + 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , /* 0-9 */ + 58 , 59 , 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , /* : ; A-H */ + 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , /* I-R */ + 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 97 , 98 , /* S-Z , a-b */ + 99 , 100, 101, 102, 103, 104, 105, 106, 107, 108, /* c-l */ + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, /* m-v */ + 119, 120, 121, 122, 160, 161, 162, 163, 164, 165, /* w-z, latin1 */ + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, /* latin1 */ + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, /* latin1 */ + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, /* latin1 */ + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, /* latin1 */ + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, /* latin1 */ + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, /* latin1 */ + 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, /* latin1 */ + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, /* latin1 */ + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, /* latin1 */ + '\0' +}; + + +/* + * lsqlite3_base160() + * + * Convert an unsigned long integer into a base160 representation of the + * number. + * + * Parameters: + * val -- + * value to be converted + * + * result -- + * character array, 5 bytes long, into which the base160 representation + * will be placed. The result will be a four-digit representation of the + * number (with leading zeros prepended as necessary), and null + * terminated. + * + * Returns: + * Nothing + */ +void +lsqlite3_base160(unsigned long val, + unsigned char result[5]) +{ + int i; + + for (i = 3; i >= 0; i--) { + + result[i] = base160tab[val % 160]; + val /= 160; + } + + result[4] = '\0'; +} + + +/* + * lsqlite3_base160Next() + * + * Retrieve the next-greater number in the base160 sequence for the terminal + * tree node (the last four digits). Only one tree level (four digits) are + * operated on. + * + * Parameters: + * base160 -- a character array containing either an empty string (in which + * case no operation is performed), or a string of base160 digits + * with a length of a multiple of four digits. + * + * Upon return, the trailing four digits (one tree level) will + * have been incremented by 1. + * + * Returns: + * base160 -- the modified array + */ +char * +lsqlite3_base160Next(char base160[]) +{ + int i; + int len; + unsigned char * pTab; + char * pBase160 = base160; + + /* + * We need a minimum of four digits, and we will always get a multiple of + * four digits. + */ + if ((len = strlen(pBase160)) >= 4) + { + pBase160 += strlen(pBase160) - 1; + + /* We only carry through four digits: one level in the tree */ + for (i = 0; i < 4; i++) { + + /* What base160 value does this digit have? */ + pTab = strchr(base160tab, *pBase160); + + /* Is there a carry? */ + if (pTab < base160tab + sizeof(base160tab) - 1) { + + /* Nope. Just increment this value and we're done. */ + *pBase160 = *++pTab; + break; + } else { + + /* + * There's a carry. This value gets base160tab[0], we + * decrement the buffer pointer to get the next higher-order + * digit, and continue in the loop. + */ + *pBase160-- = base160tab[0]; + } + } + } + + return base160; +} diff --git a/ldb-2.0.8/ldb_sqlite3/ldb_sqlite3.c b/ldb-2.0.8/ldb_sqlite3/ldb_sqlite3.c new file mode 100644 index 0000000..0f5abf8 --- /dev/null +++ b/ldb-2.0.8/ldb_sqlite3/ldb_sqlite3.c @@ -0,0 +1,1958 @@ +/* + ldb database library + + Copyright (C) Derrell Lipman 2005 + Copyright (C) Simo Sorce 2005-2009 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb sqlite3 backend + * + * Description: core files for SQLITE3 backend + * + * Author: Derrell Lipman (based on Andrew Tridgell's LDAP backend) + */ + +#include "ldb_module.h" + +#include + +struct lsqlite3_private { + int trans_count; + char **options; + sqlite3 *sqlite; +}; + +struct lsql_context { + struct ldb_module *module; + struct ldb_request *req; + + /* search stuff */ + long long current_eid; + const char * const * attrs; + struct ldb_reply *ares; + + bool callback_failed; + struct tevent_timer *timeout_event; +}; + +/* + * Macros used throughout + */ + +#ifndef FALSE +# define FALSE (0) +# define TRUE (! FALSE) +#endif + +#define RESULT_ATTR_TABLE "temp_result_attrs" + + +/* for testing, define to nothing, (create non-temporary table) */ +#define TEMPTAB "TEMPORARY" + +/* + * Static variables + */ +sqlite3_stmt * stmtGetEID = NULL; + +static char *lsqlite3_tprintf(TALLOC_CTX *mem_ctx, const char *fmt, ...) +{ + char *str, *ret; + va_list ap; + + va_start(ap, fmt); + str = sqlite3_vmprintf(fmt, ap); + va_end(ap); + + if (str == NULL) return NULL; + + ret = talloc_strdup(mem_ctx, str); + if (ret == NULL) { + sqlite3_free(str); + return NULL; + } + + sqlite3_free(str); + return ret; +} + +static char base160tab[161] = { + 48 ,49 ,50 ,51 ,52 ,53 ,54 ,55 ,56 ,57 , /* 0-9 */ + 58 ,59 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 , /* : ; A-H */ + 73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 , /* I-R */ + 83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 ,97 ,98 , /* S-Z , a-b */ + 99 ,100,101,102,103,104,105,106,107,108, /* c-l */ + 109,110,111,112,113,114,115,116,117,118, /* m-v */ + 119,120,121,122,160,161,162,163,164,165, /* w-z, latin1 */ + 166,167,168,169,170,171,172,173,174,175, /* latin1 */ + 176,177,178,179,180,181,182,183,184,185, /* latin1 */ + 186,187,188,189,190,191,192,193,194,195, /* latin1 */ + 196,197,198,199,200,201,202,203,204,205, /* latin1 */ + 206,207,208,209,210,211,212,213,214,215, /* latin1 */ + 216,217,218,219,220,221,222,223,224,225, /* latin1 */ + 226,227,228,229,230,231,232,233,234,235, /* latin1 */ + 236,237,238,239,240,241,242,243,244,245, /* latin1 */ + 246,247,248,249,250,251,252,253,254,255, /* latin1 */ + '\0' +}; + + +/* + * base160() + * + * Convert an unsigned long integer into a base160 representation of the + * number. + * + * Parameters: + * val -- + * value to be converted + * + * result -- + * character array, 5 bytes long, into which the base160 representation + * will be placed. The result will be a four-digit representation of the + * number (with leading zeros prepended as necessary), and null + * terminated. + * + * Returns: + * Nothing + */ +static void +base160_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv) +{ + int i; + long long val; + char result[5]; + + val = sqlite3_value_int64(argv[0]); + + for (i = 3; i >= 0; i--) { + + result[i] = base160tab[val % 160]; + val /= 160; + } + + result[4] = '\0'; + + sqlite3_result_text(hContext, result, -1, SQLITE_TRANSIENT); +} + + +/* + * base160next_sql() + * + * This function enhances sqlite by adding a "base160_next()" function which is + * accessible via queries. + * + * Retrieve the next-greater number in the base160 sequence for the terminal + * tree node (the last four digits). Only one tree level (four digits) is + * operated on. + * + * Input: + * A character string: either an empty string (in which case no operation is + * performed), or a string of base160 digits with a length of a multiple of + * four digits. + * + * Output: + * Upon return, the trailing four digits (one tree level) will have been + * incremented by 1. + */ +static void +base160next_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv) +{ + int i; + int len; + char * pTab; + char * pBase160 = strdup((const char *)sqlite3_value_text(argv[0])); + char * pStart = pBase160; + + /* + * We need a minimum of four digits, and we will always get a multiple + * of four digits. + */ + if (pBase160 != NULL && + (len = strlen(pBase160)) >= 4 && + len % 4 == 0) { + + if (pBase160 == NULL) { + + sqlite3_result_null(hContext); + return; + } + + pBase160 += strlen(pBase160) - 1; + + /* We only carry through four digits: one level in the tree */ + for (i = 0; i < 4; i++) { + + /* What base160 value does this digit have? */ + pTab = strchr(base160tab, *pBase160); + + /* Is there a carry? */ + if (pTab < base160tab + sizeof(base160tab) - 1) { + + /* + * Nope. Just increment this value and we're + * done. + */ + *pBase160 = *++pTab; + break; + } else { + + /* + * There's a carry. This value gets + * base160tab[0], we decrement the buffer + * pointer to get the next higher-order digit, + * and continue in the loop. + */ + *pBase160-- = base160tab[0]; + } + } + + sqlite3_result_text(hContext, + pStart, + strlen(pStart), + free); + } else { + sqlite3_result_value(hContext, argv[0]); + if (pBase160 != NULL) { + free(pBase160); + } + } +} + +static char *parsetree_to_sql(struct ldb_module *module, + void *mem_ctx, + const struct ldb_parse_tree *t) +{ + struct ldb_context *ldb; + const struct ldb_schema_attribute *a; + struct ldb_val value, subval; + char *wild_card_string; + char *child, *tmp; + char *ret = NULL; + char *attr; + unsigned int i; + + ldb = ldb_module_get_ctx(module); + + switch(t->operation) { + case LDB_OP_AND: + + tmp = parsetree_to_sql(module, mem_ctx, t->u.list.elements[0]); + if (tmp == NULL) return NULL; + + for (i = 1; i < t->u.list.num_elements; i++) { + + child = parsetree_to_sql(module, mem_ctx, t->u.list.elements[i]); + if (child == NULL) return NULL; + + tmp = talloc_asprintf_append(tmp, " INTERSECT %s ", child); + if (tmp == NULL) return NULL; + } + + ret = talloc_asprintf(mem_ctx, "SELECT * FROM ( %s )\n", tmp); + + return ret; + + case LDB_OP_OR: + + tmp = parsetree_to_sql(module, mem_ctx, t->u.list.elements[0]); + if (tmp == NULL) return NULL; + + for (i = 1; i < t->u.list.num_elements; i++) { + + child = parsetree_to_sql(module, mem_ctx, t->u.list.elements[i]); + if (child == NULL) return NULL; + + tmp = talloc_asprintf_append(tmp, " UNION %s ", child); + if (tmp == NULL) return NULL; + } + + return talloc_asprintf(mem_ctx, "SELECT * FROM ( %s ) ", tmp); + + case LDB_OP_NOT: + + child = parsetree_to_sql(module, mem_ctx, t->u.isnot.child); + if (child == NULL) return NULL; + + return talloc_asprintf(mem_ctx, + "SELECT eid FROM ldb_entry " + "WHERE eid NOT IN ( %s ) ", child); + + case LDB_OP_EQUALITY: + /* + * For simple searches, we want to retrieve the list of EIDs that + * match the criteria. + */ + attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + a = ldb_schema_attribute_by_name(ldb, attr); + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + if (strcasecmp(t->u.equality.attr, "dn") == 0) { + /* DN query is a special ldb case */ + const char *cdn = ldb_dn_get_casefold( + ldb_dn_new(mem_ctx, ldb, + (const char *)value.data)); + if (cdn == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_entry " + "WHERE norm_dn = '%q'", cdn); + + } else { + /* A normal query. */ + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = '%q' " + "AND norm_attr_value = '%q'", + attr, + value.data); + + } + + case LDB_OP_SUBSTRING: + + wild_card_string = talloc_strdup(mem_ctx, + (t->u.substring.start_with_wildcard)?"*":""); + if (wild_card_string == NULL) return NULL; + + for (i = 0; t->u.substring.chunks[i]; i++) { + wild_card_string = talloc_asprintf_append(wild_card_string, "%s*", + t->u.substring.chunks[i]->data); + if (wild_card_string == NULL) return NULL; + } + + if ( ! t->u.substring.end_with_wildcard ) { + /* remove last wildcard */ + wild_card_string[strlen(wild_card_string) - 1] = '\0'; + } + + attr = ldb_attr_casefold(mem_ctx, t->u.substring.attr); + if (attr == NULL) return NULL; + a = ldb_schema_attribute_by_name(ldb, attr); + + subval.data = (void *)wild_card_string; + subval.length = strlen(wild_card_string) + 1; + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, mem_ctx, &(subval), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = '%q' " + "AND norm_attr_value GLOB '%q'", + attr, + value.data); + + case LDB_OP_GREATER: + attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + a = ldb_schema_attribute_by_name(ldb, attr); + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = '%q' " + "AND ldap_compare(norm_attr_value, '>=', '%q', '%q') ", + attr, + value.data, + attr); + + case LDB_OP_LESS: + attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + a = ldb_schema_attribute_by_name(ldb, attr); + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = '%q' " + "AND ldap_compare(norm_attr_value, '<=', '%q', '%q') ", + attr, + value.data, + attr); + + case LDB_OP_PRESENT: + if (strcasecmp(t->u.present.attr, "dn") == 0) { + return talloc_strdup(mem_ctx, "SELECT eid FROM ldb_entry"); + } + + attr = ldb_attr_casefold(mem_ctx, t->u.present.attr); + if (attr == NULL) return NULL; + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = '%q' ", + attr); + + case LDB_OP_APPROX: + attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + a = ldb_schema_attribute_by_name(ldb, attr); + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = '%q' " + "AND ldap_compare(norm_attr_value, '~%', 'q', '%q') ", + attr, + value.data, + attr); + + case LDB_OP_EXTENDED: +#warning "work out how to handle bitops" + return NULL; + + default: + break; + }; + + /* should never occur */ + abort(); + return NULL; +} + +/* + * query_int() + * + * This function is used for the common case of queries that return a single + * integer value. + * + * NOTE: If more than one value is returned by the query, all but the first + * one will be ignored. + */ +static int +query_int(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pSql, + ...) +{ + int ret; + int bLoop; + char * p; + sqlite3_stmt * pStmt; + va_list args; + + /* Begin access to variable argument list */ + va_start(args, pSql); + + /* Format the query */ + if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { + va_end(args); + return SQLITE_NOMEM; + } + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + p, + -1, + &pStmt, + NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + continue; + } else if (ret != SQLITE_OK) { + break; + } + + /* One row expected */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_finalize(pStmt); + break; + } + + /* Get the value to be returned */ + *pRet = sqlite3_column_int64(pStmt, 0); + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + bLoop = FALSE; + } + + /* All done with variable argument list */ + va_end(args); + + + /* Free the memory we allocated for our query string */ + sqlite3_free(p); + + return ret; +} + +/* + * This is a bad hack to support ldap style comparisons within sqlite. + * val is the attribute in the row currently under test + * func is the desired test "<=" ">=" "~" ":" + * cmp is the value to compare against (eg: "test") + * attr is the attribute name the value of which we want to test + */ + +static void lsqlite3_compare(sqlite3_context *ctx, int argc, + sqlite3_value **argv) +{ + struct ldb_context *ldb = (struct ldb_context *)sqlite3_user_data(ctx); + const char *val = (const char *)sqlite3_value_text(argv[0]); + const char *func = (const char *)sqlite3_value_text(argv[1]); + const char *cmp = (const char *)sqlite3_value_text(argv[2]); + const char *attr = (const char *)sqlite3_value_text(argv[3]); + const struct ldb_schema_attribute *a; + struct ldb_val valX; + struct ldb_val valY; + int ret; + + switch (func[0]) { + /* greater */ + case '>': /* >= */ + a = ldb_schema_attribute_by_name(ldb, attr); + valX.data = (uint8_t *)cmp; + valX.length = strlen(cmp); + valY.data = (uint8_t *)val; + valY.length = strlen(val); + ret = a->syntax->comparison_fn(ldb, ldb, &valY, &valX); + if (ret >= 0) + sqlite3_result_int(ctx, 1); + else + sqlite3_result_int(ctx, 0); + return; + + /* lesser */ + case '<': /* <= */ + a = ldb_schema_attribute_by_name(ldb, attr); + valX.data = (uint8_t *)cmp; + valX.length = strlen(cmp); + valY.data = (uint8_t *)val; + valY.length = strlen(val); + ret = a->syntax->comparison_fn(ldb, ldb, &valY, &valX); + if (ret <= 0) + sqlite3_result_int(ctx, 1); + else + sqlite3_result_int(ctx, 0); + return; + + /* approx */ + case '~': + /* TODO */ + sqlite3_result_int(ctx, 0); + return; + + /* bitops */ + case ':': + /* TODO */ + sqlite3_result_int(ctx, 0); + return; + + default: + break; + } + + sqlite3_result_error(ctx, "Value must start with a special operation char (<>~:)!", -1); + return; +} + + +/* rename a record */ +static int lsqlite3_safe_rollback(sqlite3 *sqlite) +{ + char *errmsg; + int ret; + + /* execute */ + ret = sqlite3_exec(sqlite, "ROLLBACK;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_safe_rollback: Error: %s\n", errmsg); + free(errmsg); + } + return -1; + } + + return 0; +} + +/* return an eid as result */ +static int lsqlite3_eid_callback(void *result, int col_num, char **cols, char **names) +{ + long long *eid = (long long *)result; + + if (col_num != 1) return SQLITE_ABORT; + if (strcasecmp(names[0], "eid") != 0) return SQLITE_ABORT; + + *eid = atoll(cols[0]); + return SQLITE_OK; +} + +/* + * add a single set of ldap message values to a ldb_message + */ +static int lsqlite3_search_callback(void *result, int col_num, char **cols, char **names) +{ + struct ldb_context *ldb; + struct lsql_context *ac; + struct ldb_message *msg; + long long eid; + unsigned int i; + int ret; + + ac = talloc_get_type(result, struct lsql_context); + ldb = ldb_module_get_ctx(ac->module); + + /* eid, dn, attr_name, attr_value */ + if (col_num != 4) return SQLITE_ABORT; + + eid = atoll(cols[0]); + + if (ac->ares) { + msg = ac->ares->message; + } + + if (eid != ac->current_eid) { /* here begin a new entry */ + + /* call the async callback for the last entry + * except the first time */ + if (ac->current_eid != 0) { + ret = ldb_msg_normalize(ldb, ac->req, msg, &msg); + if (ret != LDB_SUCCESS) { + return SQLITE_ABORT; + } + + ret = ldb_module_send_entry(ac->req, msg, NULL); + if (ret != LDB_SUCCESS) { + ac->callback_failed = true; + /* free msg object */ + TALLOC_FREE(msg); + return SQLITE_ABORT; + } + + /* free msg object */ + TALLOC_FREE(msg); + } + + /* start over */ + ac->ares = talloc_zero(ac, struct ldb_reply); + if (!ac->ares) return SQLITE_ABORT; + + msg = ldb_msg_new(ac->ares); + if (!msg) return SQLITE_ABORT; + + ac->ares->type = LDB_REPLY_ENTRY; + ac->current_eid = eid; + } + + if (msg->dn == NULL) { + msg->dn = ldb_dn_new(msg, ldb, cols[1]); + if (msg->dn == NULL) + return SQLITE_ABORT; + } + + if (ac->attrs) { + int found = 0; + for (i = 0; ac->attrs[i]; i++) { + if (strcasecmp(cols[2], ac->attrs[i]) == 0) { + found = 1; + break; + } + } + if (!found) goto done; + } + + if (ldb_msg_add_string(msg, cols[2], cols[3]) != 0) { + return SQLITE_ABORT; + } + +done: + ac->ares->message = msg; + return SQLITE_OK; +} + + +/* + * lsqlite3_get_eid() + * lsqlite3_get_eid_ndn() + * + * These functions are used for the very common case of retrieving an EID value + * given a (normalized) DN. + */ + +static long long lsqlite3_get_eid_ndn(sqlite3 *sqlite, void *mem_ctx, const char *norm_dn) +{ + char *errmsg; + char *query; + long long eid = -1; + long long ret; + + /* get object eid */ + query = lsqlite3_tprintf(mem_ctx, "SELECT eid " + "FROM ldb_entry " + "WHERE norm_dn = '%q';", norm_dn); + if (query == NULL) return -1; + + ret = sqlite3_exec(sqlite, query, lsqlite3_eid_callback, &eid, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_get_eid: Fatal Error: %s\n", errmsg); + free(errmsg); + } + return -1; + } + + return eid; +} + +static long long lsqlite3_get_eid(struct lsqlite3_private *lsqlite3, + struct ldb_dn *dn) +{ + TALLOC_CTX *local_ctx; + long long eid = -1; + char *cdn; + + /* ignore ltdb specials */ + if (ldb_dn_is_special(dn)) { + return -1; + } + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_get_eid local context"); + if (local_ctx == NULL) { + return -1; + } + + cdn = ldb_dn_alloc_casefold(local_ctx, dn); + if (!cdn) goto done; + + eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, cdn); + +done: + talloc_free(local_ctx); + return eid; +} + +/* + * Interface functions referenced by lsqlite3_ops + */ + +/* search for matching records, by tree */ +int lsql_search(struct lsql_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + struct lsqlite3_private *lsqlite3; + struct ldb_context *ldb; + char *norm_basedn; + char *sqlfilter; + char *errmsg; + char *query = NULL; + int ret; + + ldb = ldb_module_get_ctx(module); + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + if ((( ! ldb_dn_is_valid(req->op.search.base)) || + ldb_dn_is_null(req->op.search.base)) && + (req->op.search.scope == LDB_SCOPE_BASE || + req->op.search.scope == LDB_SCOPE_ONELEVEL)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->op.search.base) { + norm_basedn = ldb_dn_alloc_casefold(ctx, req->op.search.base); + if (norm_basedn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + } else norm_basedn = talloc_strdup(ctx, ""); + + /* Convert filter into a series of SQL conditions (constraints) */ + sqlfilter = parsetree_to_sql(module, ctx, req->op.search.tree); + + switch(req->op.search.scope) { + case LDB_SCOPE_DEFAULT: + case LDB_SCOPE_SUBTREE: + if (*norm_basedn != '\0') { + query = lsqlite3_tprintf(ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE (ldb_entry.norm_dn GLOB('*,%q')\n" + " OR ldb_entry.norm_dn = '%q')\n" + " AND ldb_entry.eid IN\n" + " (%s)\n" + " )\n" + + " ORDER BY entry.eid ASC;", + norm_basedn, + norm_basedn, + sqlfilter); + } else { + query = lsqlite3_tprintf(ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE ldb_entry.eid IN\n" + " (%s)\n" + " )\n" + + " ORDER BY entry.eid ASC;", + sqlfilter); + } + + break; + + case LDB_SCOPE_BASE: + query = lsqlite3_tprintf(ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE ldb_entry.norm_dn = '%q'\n" + " AND ldb_entry.eid IN\n" + " (%s)\n" + " )\n" + + " ORDER BY entry.eid ASC;", + norm_basedn, + sqlfilter); + break; + + case LDB_SCOPE_ONELEVEL: + query = lsqlite3_tprintf(ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE norm_dn GLOB('*,%q')\n" + " AND NOT norm_dn GLOB('*,*,%q')\n" + " AND ldb_entry.eid IN\n(%s)\n" + " )\n" + + " ORDER BY entry.eid ASC;", + norm_basedn, + norm_basedn, + sqlfilter); + break; + } + + if (query == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* * / + printf ("%s\n", query); + / * */ + + ctx->current_eid = 0; + ctx->attrs = req->op.search.attrs; + ctx->ares = NULL; + + ldb_request_set_state(req, LDB_ASYNC_PENDING); + + ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, ctx, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + + /* complete the last message if any */ + if (ctx->ares) { + ret = ldb_msg_normalize(ldb, ctx->ares, + ctx->ares->message, + &ctx->ares->message); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_module_send_entry(req, ctx->ares->message, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + + return LDB_SUCCESS; +} + +/* add a record */ +static int lsql_add(struct lsql_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + struct lsqlite3_private *lsqlite3; + struct ldb_context *ldb; + struct ldb_message *msg = req->op.add.message; + long long eid; + char *dn, *ndn; + char *errmsg; + char *query; + unsigned int i; + int ret; + + ldb = ldb_module_get_ctx(module); + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + /* See if this is an ltdb special */ + if (ldb_dn_is_special(msg->dn)) { +/* + struct ldb_dn *c; + c = ldb_dn_new(local_ctx, ldb, "@INDEXLIST"); + if (ldb_dn_compare(ldb, msg->dn, c) == 0) { +#warning "should we handle indexes somehow ?" + ret = LDB_ERR_UNWILLING_TO_PERFORM; + goto done; + } +*/ + /* Others return an error */ + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + /* create linearized and normalized dns */ + dn = ldb_dn_alloc_linearized(ctx, msg->dn); + ndn = ldb_dn_alloc_casefold(ctx, msg->dn); + if (dn == NULL || ndn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + query = lsqlite3_tprintf(ctx, + /* Add new entry */ + "INSERT OR ABORT INTO ldb_entry " + "('dn', 'norm_dn') " + "VALUES ('%q', '%q');", + dn, ndn); + if (query == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + + eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, ctx, ndn); + if (eid == -1) { + return LDB_ERR_OPERATIONS_ERROR; + } + + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_message_element *el = &msg->elements[i]; + const struct ldb_schema_attribute *a; + char *attr; + unsigned int j; + + /* Get a case-folded copy of the attribute name */ + attr = ldb_attr_casefold(ctx, el->name); + if (attr == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + a = ldb_schema_attribute_by_name(ldb, el->name); + + if (el->num_value == 0) { + ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { + struct ldb_val value; + char *insert; + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, ctx, &(el->values[j]), &value); + if (value.data == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + insert = lsqlite3_tprintf(ctx, + "INSERT OR ROLLBACK INTO ldb_attribute_values " + "('eid', 'attr_name', 'norm_attr_name'," + " 'attr_value', 'norm_attr_value') " + "VALUES ('%lld', '%q', '%q', '%q', '%q');", + eid, el->name, attr, + el->values[j].data, value.data); + if (insert == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = sqlite3_exec(lsqlite3->sqlite, insert, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + } + } + + return LDB_SUCCESS; +} + +/* modify a record */ +static int lsql_modify(struct lsql_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + struct lsqlite3_private *lsqlite3; + struct ldb_context *ldb; + struct ldb_message *msg = req->op.mod.message; + long long eid; + char *errmsg; + unsigned int i; + int ret; + + ldb = ldb_module_get_ctx(module); + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + /* See if this is an ltdb special */ + if (ldb_dn_is_special(msg->dn)) { + /* Others return an error */ + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + eid = lsqlite3_get_eid(lsqlite3, msg->dn); + if (eid == -1) { + return LDB_ERR_OPERATIONS_ERROR; + } + + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_message_element *el = &msg->elements[i]; + const struct ldb_schema_attribute *a; + unsigned int flags = el->flags & LDB_FLAG_MOD_MASK; + char *attr; + char *mod; + unsigned int j; + + /* Get a case-folded copy of the attribute name */ + attr = ldb_attr_casefold(ctx, el->name); + if (attr == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + a = ldb_schema_attribute_by_name(ldb, el->name); + + switch (flags) { + + case LDB_FLAG_MOD_REPLACE: + struct ldb_val *duplicate = NULL; + + ret = ldb_msg_find_duplicate_val(ldb, el, el, + &duplicate, 0); + if (ret != LDB_SUCCESS) { + return ret; + } + if (duplicate != NULL) { + ldb_asprintf_errstring( + ldb, + "attribute '%s': value '%.*s' " + "on '%s' provided more than " + "once in REPLACE", + el->name, + (int)duplicate->length, + duplicate->data, + ldb_dn_get_linearized(msg2->dn)); + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + + /* remove all attributes before adding the replacements */ + mod = lsqlite3_tprintf(ctx, + "DELETE FROM ldb_attribute_values " + "WHERE eid = '%lld' " + "AND norm_attr_name = '%q';", + eid, attr); + if (mod == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + + /* MISSING break is INTENTIONAL */ + + case LDB_FLAG_MOD_ADD: + + if (el->num_values == 0) { + ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illigal)", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { + struct ldb_val value; + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, ctx, &(el->values[j]), &value); + if (value.data == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + mod = lsqlite3_tprintf(ctx, + "INSERT OR ROLLBACK INTO ldb_attribute_values " + "('eid', 'attr_name', 'norm_attr_name'," + " 'attr_value', 'norm_attr_value') " + "VALUES ('%lld', '%q', '%q', '%q', '%q');", + eid, el->name, attr, + el->values[j].data, value.data); + + if (mod == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + } + + break; + + case LDB_FLAG_MOD_DELETE: +#warning "We should throw an error if the attribute we are trying to delete does not exist!" + if (el->num_values == 0) { + mod = lsqlite3_tprintf(ctx, + "DELETE FROM ldb_attribute_values " + "WHERE eid = '%lld' " + "AND norm_attr_name = '%q';", + eid, attr); + if (mod == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + } + + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { + struct ldb_val value; + + /* Get a canonicalised copy of the data */ + a->syntax->canonicalise_fn(ldb, ctx, &(el->values[j]), &value); + if (value.data == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + mod = lsqlite3_tprintf(ctx, + "DELETE FROM ldb_attribute_values " + "WHERE eid = '%lld' " + "AND norm_attr_name = '%q' " + "AND norm_attr_value = '%q';", + eid, attr, value.data); + + if (mod == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + } + + break; + } + } + + return LDB_SUCCESS; +} + +/* delete a record */ +static int lsql_delete(struct lsql_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + struct lsqlite3_private *lsqlite3; + struct ldb_context *ldb; + long long eid; + char *errmsg; + char *query; + int ret; + + ldb = ldb_module_get_ctx(module); + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + eid = lsqlite3_get_eid(lsqlite3, req->op.del.dn); + if (eid == -1) { + return LDB_ERR_OPERATIONS_ERROR; + } + + query = lsqlite3_tprintf(ctx, + /* Delete entry */ + "DELETE FROM ldb_entry WHERE eid = %lld; " + /* Delete attributes */ + "DELETE FROM ldb_attribute_values WHERE eid = %lld; ", + eid, eid); + if (query == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +/* rename a record */ +static int lsql_rename(struct lsql_context *ctx) +{ + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; + struct lsqlite3_private *lsqlite3; + struct ldb_context *ldb; + char *new_dn, *new_cdn, *old_cdn; + char *errmsg; + char *query; + int ret; + + ldb = ldb_module_get_ctx(module); + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + /* create linearized and normalized dns */ + old_cdn = ldb_dn_alloc_casefold(ctx, req->op.rename.olddn); + new_cdn = ldb_dn_alloc_casefold(ctx, req->op.rename.newdn); + new_dn = ldb_dn_alloc_linearized(ctx, req->op.rename.newdn); + if (old_cdn == NULL || new_cdn == NULL || new_dn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* build the SQL query */ + query = lsqlite3_tprintf(ctx, + "UPDATE ldb_entry SET dn = '%q', norm_dn = '%q' " + "WHERE norm_dn = '%q';", + new_dn, new_cdn, old_cdn); + if (query == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* execute */ + ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + ldb_set_errstring(ldb, errmsg); + free(errmsg); + } + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +static int lsql_start_trans(struct ldb_module * module) +{ + int ret; + char *errmsg; + struct lsqlite3_private *lsqlite3; + + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + if (lsqlite3->trans_count == 0) { + ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN IMMEDIATE;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_start_trans: error: %s\n", errmsg); + free(errmsg); + } + return -1; + } + }; + + lsqlite3->trans_count++; + + return 0; +} + +static int lsql_end_trans(struct ldb_module *module) +{ + int ret; + char *errmsg; + struct lsqlite3_private *lsqlite3; + + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + if (lsqlite3->trans_count > 0) { + lsqlite3->trans_count--; + } else return -1; + + if (lsqlite3->trans_count == 0) { + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_end_trans: error: %s\n", errmsg); + free(errmsg); + } + return -1; + } + } + + return 0; +} + +static int lsql_del_trans(struct ldb_module *module) +{ + struct lsqlite3_private *lsqlite3; + + lsqlite3 = talloc_get_type(ldb_module_get_private(module), + struct lsqlite3_private); + + if (lsqlite3->trans_count > 0) { + lsqlite3->trans_count--; + } else return -1; + + if (lsqlite3->trans_count == 0) { + return lsqlite3_safe_rollback(lsqlite3->sqlite); + } + + return -1; +} + +static int destructor(struct lsqlite3_private *lsqlite3) +{ + if (lsqlite3->sqlite) { + sqlite3_close(lsqlite3->sqlite); + } + return 0; +} + +static void lsql_request_done(struct lsql_context *ctx, int error) +{ + struct ldb_context *ldb; + struct ldb_request *req; + struct ldb_reply *ares; + + ldb = ldb_module_get_ctx(ctx->module); + req = ctx->req; + + /* if we already returned an error just return */ + if (ldb_request_get_status(req) != LDB_SUCCESS) { + return; + } + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(ldb); + req->callback(req, NULL); + return; + } + ares->type = LDB_REPLY_DONE; + ares->error = error; + + req->callback(req, ares); +} + +static void lsql_timeout(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, + void *private_data) +{ + struct lsql_context *ctx; + ctx = talloc_get_type(private_data, struct lsql_context); + + lsql_request_done(ctx, LDB_ERR_TIME_LIMIT_EXCEEDED); +} + +static void lsql_callback(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, + void *private_data) +{ + struct lsql_context *ctx; + int ret; + + ctx = talloc_get_type(private_data, struct lsql_context); + + switch (ctx->req->operation) { + case LDB_SEARCH: + ret = lsql_search(ctx); + break; + case LDB_ADD: + ret = lsql_add(ctx); + break; + case LDB_MODIFY: + ret = lsql_modify(ctx); + break; + case LDB_DELETE: + ret = lsql_delete(ctx); + break; + case LDB_RENAME: + ret = lsql_rename(ctx); + break; +/* TODO: + case LDB_EXTENDED: + ret = lsql_extended(ctx); + break; + */ + default: + /* no other op supported */ + ret = LDB_ERR_PROTOCOL_ERROR; + } + + if (!ctx->callback_failed) { + /* Once we are done, we do not need timeout events */ + talloc_free(ctx->timeout_event); + lsql_request_done(ctx, ret); + } +} + +static int lsql_handle_request(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct tevent_context *ev; + struct lsql_context *ac; + struct tevent_timer *te; + struct timeval tv; + + if (ldb_check_critical_controls(req->controls)) { + return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; + } + + if (req->starttime == 0 || req->timeout == 0) { + ldb_set_errstring(ldb, "Invalid timeout settings"); + return LDB_ERR_TIME_LIMIT_EXCEEDED; + } + + ldb = ldb_module_get_ctx(module); + ev = ldb_get_event_context(ldb); + + ac = talloc_zero(req, struct lsql_context); + if (ac == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->module = module; + ac->req = req; + + tv.tv_sec = 0; + tv.tv_usec = 0; + te = tevent_add_timer(ev, ac, tv, lsql_callback, ac); + if (NULL == te) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->timeout > 0) { + tv.tv_sec = req->starttime + req->timeout; + tv.tv_usec = 0; + ac->timeout_event = tevent_add_timer(ev, ac, tv, lsql_timeout, ac); + if (NULL == ac->timeout_event) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + return LDB_SUCCESS; +} + +/* + * Table of operations for the sqlite3 backend + */ +static const struct ldb_module_ops lsqlite3_ops = { + .name = "sqlite", + .search = lsql_handle_request, + .add = lsql_handle_request, + .modify = lsql_handle_request, + .del = lsql_handle_request, + .rename = lsql_handle_request, + .extended = lsql_handle_request, + .start_transaction = lsql_start_trans, + .end_transaction = lsql_end_trans, + .del_transaction = lsql_del_trans, +}; + +/* + * Static functions + */ + +static int initialize(struct lsqlite3_private *lsqlite3, + struct ldb_context *ldb, const char *url, + unsigned int flags) +{ + TALLOC_CTX *local_ctx; + long long queryInt; + int rollback = 0; + char *errmsg; + char *schema; + int ret; + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_rename local context"); + if (local_ctx == NULL) { + return -1; + } + + schema = lsqlite3_tprintf(local_ctx, + + + "CREATE TABLE ldb_info AS " + " SELECT 'LDB' AS database_type," + " '1.0' AS version;" + + /* + * The entry table holds the information about an entry. + * This table is used to obtain the EID of the entry and to + * support scope=one and scope=base. The parent and child + * table is included in the entry table since all the other + * attributes are dependent on EID. + */ + "CREATE TABLE ldb_entry " + "(" + " eid INTEGER PRIMARY KEY AUTOINCREMENT," + " dn TEXT UNIQUE NOT NULL," + " norm_dn TEXT UNIQUE NOT NULL" + ");" + + + "CREATE TABLE ldb_object_classes" + "(" + " class_name TEXT PRIMARY KEY," + " parent_class_name TEXT," + " tree_key TEXT UNIQUE," + " max_child_num INTEGER DEFAULT 0" + ");" + + /* + * We keep a full listing of attribute/value pairs here + */ + "CREATE TABLE ldb_attribute_values" + "(" + " eid INTEGER REFERENCES ldb_entry," + " attr_name TEXT," + " norm_attr_name TEXT," + " attr_value TEXT," + " norm_attr_value TEXT " + ");" + + + /* + * Indexes + */ + "CREATE INDEX ldb_attribute_values_eid_idx " + " ON ldb_attribute_values (eid);" + + "CREATE INDEX ldb_attribute_values_name_value_idx " + " ON ldb_attribute_values (attr_name, norm_attr_value);" + + + + /* + * Triggers + */ + + "CREATE TRIGGER ldb_object_classes_insert_tr" + " AFTER INSERT" + " ON ldb_object_classes" + " FOR EACH ROW" + " BEGIN" + " UPDATE ldb_object_classes" + " SET tree_key = COALESCE(tree_key, " + " (" + " SELECT tree_key || " + " (SELECT base160(max_child_num + 1)" + " FROM ldb_object_classes" + " WHERE class_name = " + " new.parent_class_name)" + " FROM ldb_object_classes " + " WHERE class_name = new.parent_class_name " + " ));" + " UPDATE ldb_object_classes " + " SET max_child_num = max_child_num + 1" + " WHERE class_name = new.parent_class_name;" + " END;" + + /* + * Table initialization + */ + + "INSERT INTO ldb_object_classes " + " (class_name, tree_key) " + " VALUES " + " ('TOP', '0001');"); + + /* Skip protocol indicator of url */ + if (strncmp(url, "sqlite3://", 10) != 0) { + return SQLITE_MISUSE; + } + + /* Update pointer to just after the protocol indicator */ + url += 10; + + /* Try to open the (possibly empty/non-existent) database */ + if ((ret = sqlite3_open(url, &lsqlite3->sqlite)) != SQLITE_OK) { + return ret; + } + + /* In case this is a new database, enable auto_vacuum */ + ret = sqlite3_exec(lsqlite3->sqlite, "PRAGMA auto_vacuum = 1;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3 initializaion error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + + if (flags & LDB_FLG_NOSYNC) { + /* DANGEROUS */ + ret = sqlite3_exec(lsqlite3->sqlite, "PRAGMA synchronous = OFF;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3 initializaion error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + } + + /* */ + + /* Establish a busy timeout of 30 seconds */ + if ((ret = sqlite3_busy_timeout(lsqlite3->sqlite, + 30000)) != SQLITE_OK) { + return ret; + } + + /* Create a function, callable from sql, to increment a tree_key */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite,/* handle */ + "base160_next", /* function name */ + 1, /* number of args */ + SQLITE_ANY, /* preferred text type */ + NULL, /* user data */ + base160next_sql, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; + } + + /* Create a function, callable from sql, to convert int to base160 */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite,/* handle */ + "base160", /* function name */ + 1, /* number of args */ + SQLITE_ANY, /* preferred text type */ + NULL, /* user data */ + base160_sql, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; + } + + /* Create a function, callable from sql, to perform various comparisons */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite, /* handle */ + "ldap_compare", /* function name */ + 4, /* number of args */ + SQLITE_ANY, /* preferred text type */ + ldb , /* user data */ + lsqlite3_compare, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; + } + + /* Begin a transaction */ + ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN EXCLUSIVE;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3: initialization error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + rollback = 1; + + /* Determine if this is a new database. No tables means it is. */ + if (query_int(lsqlite3, + &queryInt, + "SELECT COUNT(*)\n" + " FROM sqlite_master\n" + " WHERE type = 'table';") != 0) { + goto failed; + } + + if (queryInt == 0) { + /* + * Create the database schema + */ + ret = sqlite3_exec(lsqlite3->sqlite, schema, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3 initializaion error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + } else { + /* + * Ensure that the database we opened is one of ours + */ + if (query_int(lsqlite3, + &queryInt, + "SELECT " + " (SELECT COUNT(*) = 2" + " FROM sqlite_master " + " WHERE type = 'table' " + " AND name IN " + " (" + " 'ldb_entry', " + " 'ldb_object_classes' " + " ) " + " ) " + " AND " + " (SELECT 1 " + " FROM ldb_info " + " WHERE database_type = 'LDB' " + " AND version = '1.0'" + " );") != 0 || + queryInt != 1) { + + /* It's not one that we created. See ya! */ + goto failed; + } + } + + /* Commit the transaction */ + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3: iniialization error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + + return SQLITE_OK; + +failed: + if (rollback) lsqlite3_safe_rollback(lsqlite3->sqlite); + sqlite3_close(lsqlite3->sqlite); + return -1; +} + +/* + * connect to the database + */ +static int lsqlite3_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[], + struct ldb_module **_module) +{ + struct ldb_module *module; + struct lsqlite3_private *lsqlite3; + unsigned int i; + int ret; + + module = ldb_module_new(ldb, ldb, "ldb_sqlite3 backend", &lsqlite3_ops); + if (!module) return LDB_ERR_OPERATIONS_ERROR; + + lsqlite3 = talloc(module, struct lsqlite3_private); + if (!lsqlite3) { + goto failed; + } + + lsqlite3->sqlite = NULL; + lsqlite3->options = NULL; + lsqlite3->trans_count = 0; + + ret = initialize(lsqlite3, ldb, url, flags); + if (ret != SQLITE_OK) { + goto failed; + } + + talloc_set_destructor(lsqlite3, destructor); + + ldb_module_set_private(module, lsqlite3); + + if (options) { + /* + * take a copy of the options array, so we don't have to rely + * on the caller keeping it around (it might be dynamic) + */ + for (i=0;options[i];i++) ; + + lsqlite3->options = talloc_array(lsqlite3, char *, i+1); + if (!lsqlite3->options) { + goto failed; + } + + for (i=0;options[i];i++) { + + lsqlite3->options[i+1] = NULL; + lsqlite3->options[i] = + talloc_strdup(lsqlite3->options, options[i]); + if (!lsqlite3->options[i]) { + goto failed; + } + } + } + + *_module = module; + return LDB_SUCCESS; + +failed: + if (lsqlite3 && lsqlite3->sqlite != NULL) { + (void) sqlite3_close(lsqlite3->sqlite); + } + talloc_free(lsqlite3); + return LDB_ERR_OPERATIONS_ERROR; +} + +int ldb_sqlite3_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_backend("sqlite3", lsqlite3_connect, false); +} diff --git a/ldb-2.0.8/ldb_sqlite3/schema b/ldb-2.0.8/ldb_sqlite3/schema new file mode 100644 index 0000000..ab7c5cc --- /dev/null +++ b/ldb-2.0.8/ldb_sqlite3/schema @@ -0,0 +1,328 @@ + -- ------------------------------------------------------ + + PRAGMA auto_vacuum=1; + + -- ------------------------------------------------------ + + BEGIN EXCLUSIVE; + + -- ------------------------------------------------------ + + CREATE TABLE ldb_info AS + SELECT 'LDB' AS database_type, + '1.0' AS version; + + /* + * Get the next USN value with: + * BEGIN EXCLUSIVE; + * UPDATE usn SET value = value + 1; + * SELECT value FROM usn; + * COMMIT; + */ + CREATE TABLE usn + ( + value INTEGER + ); + + CREATE TABLE ldb_object + ( + /* tree_key is auto-generated by the insert trigger */ + tree_key TEXT PRIMARY KEY, + + parent_tree_key TEXT, + dn TEXT, + + attr_name TEXT REFERENCES ldb_attributes, + attr_value TEXT, + + /* + * object_type can take on these values (to date): + * 1: object is a node of a DN + * 2: object is an attribute/value pair of its parent DN + */ + object_type INTEGER, + + /* + * if object_type is 1, the node can have children. + * this tracks the maximum previously assigned child + * number so we can generate a new unique tree key for + * a new child object. note that this is always incremented, + * so if children are deleted, this will not represent + * the _number_ of children. + */ + max_child_num INTEGER, + + /* + * Automatically maintained meta-data (a gift for metze) + */ + object_guid TEXT UNIQUE, + timestamp INTEGER, -- originating_time + invoke_id TEXT, -- GUID: originating_invocation_id + usn INTEGER, -- hyper: originating_usn + + /* do not allow duplicate name/value pairs */ + UNIQUE (parent_tree_key, attr_name, attr_value, object_type) + ); + + CREATE TABLE ldb_attributes + ( + attr_name TEXT PRIMARY KEY, + parent_tree_key TEXT, + + objectclass_p BOOLEAN DEFAULT 0, + + case_insensitive_p BOOLEAN DEFAULT 0, + wildcard_p BOOLEAN DEFAULT 0, + hidden_p BOOLEAN DEFAULT 0, + integer_p BOOLEAN DEFAULT 0, + + /* tree_key is auto-generated by the insert trigger */ + tree_key TEXT, -- null if not a object/sub class + -- level 1 if an objectclass + -- level 1-n if a subclass + max_child_num INTEGER + ); + + -- ------------------------------------------------------ + + CREATE INDEX ldb_object_dn_idx + ON ldb_object (dn); + + CREATE INDEX ldb_attributes_tree_key_ids + ON ldb_attributes (tree_key); + + -- ------------------------------------------------------ + + /* Gifts for metze. Automatically updated meta-data */ + CREATE TRIGGER ldb_object_insert_tr + AFTER INSERT + ON ldb_object + FOR EACH ROW + BEGIN + UPDATE ldb_object + SET max_child_num = max_child_num + 1 + WHERE tree_key = new.parent_tree_key; + UPDATE usn SET value = value + 1; + UPDATE ldb_object + SET tree_key = + (SELECT + new.tree_key || + base160(SELECT max_child_num + FROM ldb_object + WHERE tree_key = + new.parent_tree_key)); + max_child_num = 0, + object_guid = random_guid(), + timestamp = strftime('%s', 'now'), + usn = (SELECT value FROM usn); + WHERE tree_key = new.tree_key; + END; + + CREATE TRIGGER ldb_object_update_tr + AFTER UPDATE + ON ldb_object + FOR EACH ROW + BEGIN + UPDATE usn SET value = value + 1; + UPDATE ldb_object + SET timestamp = strftime('%s', 'now'), + usn = (SELECT value FROM usn); + WHERE tree_key = new.tree_key; + END; + + CREATE TRIGGER ldb_attributes_insert_tr + AFTER INSERT + ON ldb_attributes + FOR EACH ROW + BEGIN + UPDATE ldb_attributes + SET max_child_num = max_child_num + 1 + WHERE tree_key = new.parent_tree_key; + UPDATE ldb_attributes + SET tree_key = + (SELECT + new.tree_key || + base160(SELECT max_child_num + FROM ldb_attributes + WHERE tree_key = + new.parent_tree_key)); + max_child_num = 0 + WHERE tree_key = new.tree_key; + END; + + + -- ------------------------------------------------------ + + /* Initialize usn */ + INSERT INTO usn (value) VALUES (0); + + /* Create root object */ + INSERT INTO ldb_object + (tree_key, parent_tree_key, + dn, + object_type, max_child_num) + VALUES ('', NULL, + '', + 1, 0); + + /* We need an implicit "top" level object class */ + INSERT INTO ldb_attributes (attr_name, + parent_tree_key) + SELECT 'top', ''; + + -- ------------------------------------------------------ + + COMMIT; + + -- ------------------------------------------------------ + +/* + * dn: o=University of Michigan,c=US + * objectclass: organization + * objectclass: domainRelatedObject + */ +-- newDN +BEGIN; + +INSERT OR IGNORE INTO ldb_object + (parent_tree_key + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('', + 'c=US', + 'c', 'US', 1, 0); + +INSERT INTO ldb_object + (parent_tree_key, + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('0001', + 'o=University of Michigan,c=US', + 'o', 'University of Michigan', 1, 0); + +-- newObjectClass +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('objectclass', '', 1); + +INSERT INTO ldb_object + (parent_tree_key, + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', + NULL, + 'objectclass', 'organization', 2, 0); + +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('objectclass', '', 1); + +INSERT INTO ldb_object + (parent_tree_key, + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', + NULL, + 'objectclass', 'domainRelatedObject', 2, 0); + +COMMIT; + + +/* + * dn: o=University of Michigan,c=US + * l: Ann Arbor, Michigan + * st: Michigan + * o: University of Michigan + * o: UMICH + * seeAlso: + * telephonenumber: +1 313 764-1817 + */ +-- addAttrValuePair +BEGIN; + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'l', 'Ann Arbor, Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'st', 'Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'o', 'University of Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'o', 'UMICH', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'seeAlso', '', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'telephonenumber', '+1 313 764-1817', 2, 0); + +COMMIT; + +-- ---------------------------------------------------------------------- + +/* + * dn: @ATTRIBUTES + * uid: CASE_INSENSITIVE WILDCARD + * cn: CASE_INSENSITIVE + * ou: CASE_INSENSITIVE + * dn: CASE_INSENSITIVE + */ +-- newAttribute + +BEGIN; + +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('uid', '', 0); + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 1, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'uid' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'cn' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'ou' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'dn' + diff --git a/ldb-2.0.8/ldb_sqlite3/trees.ps b/ldb-2.0.8/ldb_sqlite3/trees.ps new file mode 100644 index 0000000..433a064 --- /dev/null +++ b/ldb-2.0.8/ldb_sqlite3/trees.ps @@ -0,0 +1,1760 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: trees.dvi +%%Pages: 7 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -f trees.dvi +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2000.05.06:2055 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (trees.dvi) +@start +%DVIPSBitmapFont: Fa cmr10 10 6 +/Fa 6 55 df<146014E0EB01C0EB0380EB0700130E131E5B5BA25B485AA2485AA212075B +120F90C7FCA25A121EA2123EA35AA65AB2127CA67EA3121EA2121F7EA27F12077F1203A2 +6C7EA26C7E1378A27F7F130E7FEB0380EB01C0EB00E01460135278BD20>40 +D<12C07E12707E7E7E120F6C7E6C7EA26C7E6C7EA21378A2137C133C133E131EA2131F7F +A21480A3EB07C0A6EB03E0B2EB07C0A6EB0F80A31400A25B131EA2133E133C137C1378A2 +5BA2485A485AA2485A48C7FC120E5A5A5A5A5A13527CBD20>I<15301578B3A6007FB812 +F8B912FCA26C17F8C80078C8FCB3A6153036367BAF41>43 D48 DI54 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fb cmr7 7 3 +/Fb 3 55 df48 D<13381378EA01F8121F12FE12E01200B3AB487EB512F8A2 +15267BA521>I54 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fc cmmi10 10 1 +/Fc 1 69 df<0103B7FC4916E018F8903B0007F80007FE4BEB00FFF03F80020FED1FC018 +0F4B15E0F007F0021F1503A24B15F81801143F19FC5DA2147FA292C8FCA25C18035CA213 +0119F84A1507A2130319F04A150FA2010717E0181F4A16C0A2010FEE3F80A24AED7F0018 +7E011F16FE4D5A4A5D4D5A013F4B5A4D5A4A4A5A057FC7FC017F15FEEE03FC91C7EA0FF0 +49EC7FC0B8C8FC16FC16C03E397DB845>68 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fd ectt1000 10 73 +/Fd 73 126 df37 +D39 +D<143814FC13011303EB07F8EB0FF0EB1FC0EB3F80EB7F0013FE485A485A5B12075B120F +5B485AA2123F90C7FCA25A127EA312FE5AAC7E127EA3127F7EA27F121FA26C7E7F12077F +12037F6C7E6C7E137FEB3F80EB1FC0EB0FF0EB07F8EB03FC130113001438164272B92C> +I<127012FC7E7E6C7E6C7EEA0FE06C7E6C7E6C7E6C7E137F7F1480131F14C0130FEB07E0 +A214F01303A214F81301A314FC1300AC130114F8A3130314F0A2130714E0A2EB0FC0131F +1480133F14005B13FE485A485A485A485AEA3FC0485A48C7FC5A5A1270164279B92C>I< +EB0380497EA60020140800F8143E00FE14FE00FF13C1EBC7C7EBE7CF003FB512F8000F14 +E0000314806C140038007FFCA248B5FC481480000F14E0003F14F839FFE7CFFEEBC7C7EB +07C100FE13C000F8143E0020140800001400A66D5A1F247AAA2C>I<147014F8AF003FB6 +12E0B712F8A4C700F8C7FCB0147025267DAB2C>II<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B708A2C>46 +D<1507ED0F80A2151F16005D153E157E157CA215FC5D14015D14035D14075D140F5D141F +92C7FC5C143EA2147E147C14FC5C13015C13035C13075C130F5C131F91C8FC5B133EA213 +7E137C13FC5B12015B12035B12075B120F5B121F90C9FCA25A123E127E127C12FC5AA212 +7021417BB92C>II<1307497EA2131F +A2133F137F13FF5A1207127FB5FC13DF139FEA7C1F1200B3AE007FB512E0B612F0A36C14 +E01C3477B32C>II<000FB512FE4880A35D0180C8FCADEB83FE90389FFF8090B512E015F881 +9038FE03FE9038F000FF01C07F49EB3F8090C7121F6C15C0C8120FA2ED07E0A4123C127E +B4FC150F16C0A248141F007EEC3F80007FEC7F006C6C5B6D485A391FF80FFC6CB55A6C5C +000114C06C6C90C7FCEB0FF823347CB22C>53 DI<1278B712C016E0A316C000FCC7EA3F80ED7F0015FE00785CC712014A +5A4A5A5D140F5D4A5A143F92C7FC5C147E14FE5C13015CA2495AA213075CA3495AA4495A +A5133F91C8FCAA131E23357CB32C>I59 D<1502ED0F80151F157F15 +FF913803FE00EC0FFCEC1FF0EC7FE0ECFF80D903FEC7FC495AEB1FF0495AEBFF80000390 +C8FCEA07FCEA1FF8EA3FE0EAFF8090C9FCA27FEA3FE0EA1FF8EA07FC6CB4FCC67FEB3FE0 +6D7EEB07FC6D7E903800FF80EC7FE0EC1FF0EC0FFCEC03FE913800FF80157F151F150FED +0200212A7BAD2C>I<007FB612F0B712F8A36C15F0CAFCA8007FB612F0B712F8A36C15F0 +25127DA12C>I<122012F87EB4FC7FEA3FE0EA1FF8EA07FC6CB4FCC67FEB3FE06D7EEB07 +FC6D7E903800FF80EC7FE0EC1FF0EC0FFCEC03FE913800FF80157FA215FF913803FE00EC +0FFCEC1FF0EC7FE0ECFF80D903FEC7FC495AEB1FF0495AEBFF80000390C8FCEA07FCEA1F +F8EA3FE0EAFF8090C9FC12FC5A1220212A7BAD2C>I<14FE497EA4497FA214EFA2130781 +A214C7A2010F7FA314C390381F83F0A590383F01F8A490387E00FCA549137E90B512FEA3 +4880A29038F8003FA34848EB1F80A4000715C049130FD87FFEEBFFFC6D5AB514FE6C15FC +497E27347EB32C>65 D<007FB512E015F8B612FE6C8016C03903F0003FED0FE0ED07F015 +03A2ED01F8A6ED03F0A21507ED0FE0ED1FC0EDFF8090B612005D5D15FF16C09039F0001F +E0ED07F0ED03F81501ED00FCA216FE167EA616FE16FC1501ED03F8150FED3FF0007FB612 +E016C0B712806CECFE0015F027337FB22C>I<02FF13700107EBE0F84913F9013F13FD49 +13FFEBFF813901FE007F4848131FD807F0130F1507485A491303485A150148C7FCA25A00 +7EEC00F01600A212FE5AAB7E127EA3007F15F06CEC01F8A26C7EA26C6C13036D14F06C6C +130716E0D803FC131F6C6CEB3FC03A00FF81FF806DB512006D5B010F5B6D13F001001380 +25357DB32C>I<007FB5FCB612C015F0816C803907E003FEEC00FFED7F80153FED1FC0ED +0FE0A2150716F0150316F81501A4ED00FCACED01F8A3150316F0A2150716E0150FED1FC0 +153FED7F80EDFF00EC03FE007FB55AB65A5D15C06C91C7FC26337EB22C>I<007FB612F0 +B712F8A37E3903F00001A7ED00F01600A4EC01E04A7EA490B5FCA5EBF003A46E5A91C8FC +A5163C167EA8007FB612FEB7FCA36C15FC27337EB22C>I<007FB612F8B712FCA37ED803 +F0C7FCA716781600A515F04A7EA490B5FCA5EBF001A46E5A92C7FCAD387FFFE0B5FC805C +7E26337EB22C>I<903901FC038090390FFF87C04913EF017F13FF90B6FC4813073803FC +01497E4848137F4848133F49131F121F5B003F140F90C7FCA2127EED078092C7FCA212FE +5AA8913803FFF84A13FCA27E007E6D13F89138000FC0A36C141FA27F121F6D133F120F6D +137F6C7E6C6C13FF6D5A3801FF076C90B5FC6D13EF011F13CF6DEB0780D901FCC7FC2635 +7DB32C>II<007FB512F8B612FCA36C14 +F839000FC000B3B3A5007FB512F8B612FCA36C14F81E3379B22C>I75 D<387FFFE0B57EA36C5BD803F0C8FCB3AE16F0 +ED01F8A8007FB6FCB7FCA36C15F025337DB22C>IIII<007FB512C0B612 +F88115FF6C15802603F00013C0153FED0FE0ED07F0A2150316F81501A6150316F01507A2 +ED0FE0ED3FC015FF90B61280160015FC5D15C001F0C8FCB0387FFF80B57EA36C5B25337E +B22C>II<387FFFFCB67E15E015F86C803907E007FE1401EC007F6F7E151FA2 +6F7EA64B5AA2153F4BC7FCEC01FE140790B55A5D15E081819038E007FCEC01FE1400157F +81A8160FEE1F80A5D87FFEEB1FBFB5ECFF00815E6C486D5AC8EA01F029347EB22C>I<90 +381FF80790B5EA0F804814CF000714FF5A381FF01F383FC003497E48C7FC007E147F00FE +143F5A151FA46CEC0F00007E91C7FC127F7FEA3FE0EA1FFCEBFFC06C13FC0003EBFFC06C +14F06C6C7F01077F9038007FFEEC07FF02001380153FED1FC0A2ED0FE0A20078140712FC +A56CEC0FC0A26CEC1F806D133F01E0EB7F009038FE01FF90B55A5D00F914F0D8F83F13C0 +D8700790C7FC23357CB32C>I<007FB612FCB712FEA43AFC007E007EA70078153CC71400 +B3AF90383FFFFCA2497F6D5BA227337EB22C>I<3B7FFF803FFFC0B56C4813E0A36C496C +13C03B03F00001F800B3AF6D130300015DA26D130700005D6D130F017F495A6D6C485AEC +E0FF6DB5C7FC6D5B010313F86D5B9038003F802B3480B22C>III<3A3FFF03FFE0484913F0148714076C6D13E03A01 +F800FE007F0000495A13FE017E5BEB7F03013F5B1487011F5B14CF010F5B14FF6D5BA26D +90C7FCA26D5AA26D5AA2497EA2497EA2497F81EB0FCF81EB1FC7EC87F0EB3F83EC03F8EB +7F01017E7FEBFE00497F0001147E49137F000380491480151FD87FFEEBFFFC6D5AB514FE +6C15FC497E27337EB22C>II<387FFFFCB512FEA314FC00FCC7FCB3B3B3B512FC14FEA36C13FC +17416FB92C>91 D<127012F8A27E127C127E123E123F7EA27F120F7F12077F12037F1201 +7F12007F137C137E133EA2133F7F80130F80130780130380130180130080147C147E143E +A2143F8081140F81140781140381140181140081157CA2157E153E153F811680150FA2ED +070021417BB92C>I<387FFFFCB512FEA37EC7127EB3B3B3387FFFFEB5FCA36C13FC1741 +7DB92C>II<007FB6FCB71280A46C150021067B7D +2C>I<1338137CEA01FC1203EA07F813F0EA0FC0EA1F80A2EA3F00123E127E127CA212FC +5AA3EAFFC013E013F013F8A2127FA2123F13F0EA1FE0EA07C00E1D72B82C>I<3801FFF0 +000713FE001F6D7E15E048809038C01FF81407EC01FC381F80000006C77EC8127EA3ECFF +FE131F90B5FC1203120F48EB807E383FF800EA7FC090C7FC12FE5AA47E007F14FEEB8003 +383FE01F6CB612FC6C15FE6C14BF0001EBFE1F3A003FF007FC27247CA32C>II<90 +3803FFE0011F13F8017F13FE48B5FC48804848C6FCEA0FF0485A49137E4848131890C9FC +5A127EA25AA8127EA2127F6C140F6DEB1F806C7E6D133F6C6CEB7F003907FE03FF6CB55A +6C5C6C6C5B011F13E0010390C7FC21247AA32C>III103 +DI< +1307EB1FC0A2497EA36D5AA20107C7FC90C8FCA7387FFFC080B5FC7EA2EA0007B3A8007F +B512FCB612FEA36C14FC1F3479B32C>I107 D<387FFFE0B57EA37EEA0003B3B3A5007F +B61280B712C0A36C158022337BB22C>I<3A7F83F007E09039CFFC1FF83AFFDFFE3FFCD8 +7FFF13FF91B57E3A07FE1FFC3E01FCEBF83F496C487E01F013E001E013C0A301C01380B3 +3B7FFC3FF87FF0027F13FFD8FFFE6D13F8D87FFC4913F0023F137F2D2481A32C>I<397F +F01FE039FFF87FFC9038F9FFFE01FB7F6CB6FC00019038F03F80ECC01F02807FEC000F5B +5BA25BB3267FFFE0B5FCB500F11480A36C01E0140029247FA32C>II<397FF01FE0 +39FFF8FFF801FB13FE90B6FC6C158000019038F07FC09138801FE091380007F049EB03F8 +5BED01FC491300A216FE167EA816FE6D14FCA2ED01F86D13036DEB07F0150F9138801FE0 +9138E07FC091B51280160001FB5B01F813F8EC3FC091C8FCAD387FFFE0B57EA36C5B2736 +7FA32C>I<903903FC078090391FFF0FC0017F13CF48B512EF4814FF3807FE07380FF001 +48487E49137F4848133F90C7FC48141F127E150F5AA87E007E141FA26C143F7F6C6C137F +6D13FF380FF0033807FC0F6CB6FC6C14EF6C6C138F6D130FEB07F890C7FCAD0203B5FC4A +1480A36E140029367DA32C>II<90387FF8700003B512F8120F5A5A387FC00F387E00034813015AA36CEB +00F0007F140013F0383FFFC06C13FE6CEBFF80000314E0C66C13F8010113FCEB0007EC00 +FE0078147F00FC143F151F7EA26C143F6D133E6D13FE9038F007FC90B5FC15F815E000F8 +148039701FFC0020247AA32C>I<131E133FA9007FB6FCB71280A36C1500D8003FC8FCB1 +ED03C0ED07E0A5EC800F011FEB1FC0ECE07F6DB51280160001035B6D13F89038003FE023 +2E7EAD2C>I<3A7FF003FF80486C487FA3007F7F0001EB000FB3A3151FA2153F6D137F39 +00FE03FF90B7FC6D15807F6D13CF902603FE07130029247FA32C>I<3A3FFF03FFF04801 +8713F8A36C010313F03A00FC007E005D90387E01F8013F5BEB1F83EC87E090380FCFC090 +3807EF80EB03FF6D90C7FC5C6D5A147C14FE130180903803EF80903807CFC0EB0FC7EC83 +E090381F01F0013F7FEB7E00017C137C49137E0001803A7FFF01FFFC1483B514FE6C15FC +140127247EA32C>120 D<3A7FFF01FFFCB5008113FE148314816C010113FC3A03E0000F +806C7E151F6D140012005D6D133E137C017E137E013E137CA2013F13FC6D5BA2EB0F815D +A2EB07C1ECC3E0A2EB03E3ECE7C0130114F75DEB00FFA292C7FC80A2143EA2147E147CA2 +14FC5CA2EA0C01003F5BEA7F83EB87E0EA7E0F495A387FFF806C90C8FC6C5A6C5AEA07E0 +27367EA32C>I<15FF02071380141F147F91B512004913C04AC7FCEB03F85CB31307EB1F +E013FF007F5BB55A49C8FC6D7E6C7FC67F131FEB07F01303B380EB01FEECFFC06D13FF6E +1380141F14070200130021417BB92C>123 D<127812FCB3B3B3A9127806416DB92C>II E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fe ecti1000 10 33 +/Fe 33 122 df28 D<150C151C153815F0EC01E0EC03C0EC0780EC0F00141E5C147C5C5C495A1303 +495A5C130F49C7FCA2133EA25BA25BA2485AA212035B12075BA2120F5BA2121FA290C8FC +A25AA2123EA2127EA2127CA412FC5AAD1278A57EA3121C121EA2120E7EA26C7E6C7EA212 +001E5274BD22>40 D<140C140E80EC0380A2EC01C015E0A2140015F0A21578A4157C153C +AB157CA715FCA215F8A21401A215F0A21403A215E0A21407A215C0140F1580A2141F1500 +A2143EA25CA25CA2495AA2495A5C1307495A91C7FC5B133E133C5B5B485A12035B48C8FC +120E5A12785A12C01E527FBD22>I<4B7EA3150393C8FCA35D1506A3150E150CA3151C15 +18A315381530A31570B912E0A2C80060C8FC15E05DA314015DA3140392C9FCA35C1406A3 +140E140CA3141C1418A2333275AD40>43 DI<120E +EA3F80127F12FFA31300127E123C0909778819>46 D<0103B612FEEFFFC018F0903B0007 +F8000FF84BEB03FCEF00FE020F157FF03F804B141F19C0021F150F19E05D1807143F19F0 +5DA2147FA292C8FCA25C180F5CA2130119E04A151FA2130319C04A153FA201071780187F +4A1600A2010F16FEA24A4A5A60011F15034D5A4A5D4D5A013F4B5A173F4A4AC7FC17FC01 +7FEC03F84C5A91C7EA1FC04949B45A007F90B548C8FCB712F016803C397CB83F>68 +D<0103B512F8A390390007F8005DA2140FA25DA2141FA25DA2143FA25DA2147FA292C7FC +A25CA25CA21301A25CA21303A25CA21307A25CA2130FA25CA2131FA25CA2133FA25CA213 +7FA291C8FC497EB6FCA25C25397CB820>73 D<0107B512FCA25E9026000FF8C7FC5D5D14 +1FA25DA2143FA25DA2147FA292C8FCA25CA25CA21301A25CA21303A25CA21307A25CA213 +0F170C4A141CA2011F153C17384A1478A2013F157017F04A14E01601017F140317C091C7 +1207160F49EC1F80163F4914FF000102071300B8FCA25E2E397BB834>76 +D79 +D81 D<92383FC00E913901FFF01C020713FC91 +391FC07E3C91393F001F7C027CEB0FF84A130749481303495A4948EB01F0A2495AA2011F +15E091C7FCA34915C0A36E90C7FCA2806D7E14FCECFF806D13F015FE6D6D7E6D14E00100 +80023F7F14079138007FFC150F15031501A21500A2167C120EA3001E15FC5EA3003E4A5A +A24B5AA2007F4A5A4B5A6D49C7FC6D133ED8F9F013FC39F8FC03F839F07FFFE0D8E01F13 +8026C003FCC8FC2F3D7ABA2F>83 D<0007B812E0A25AD9F800EB001F01C049EB07C0485A +D900011403121E001C5C003C17801403123800785C00701607140700F01700485CA2140F +C792C7FC5DA2141FA25DA2143FA25DA2147FA292C9FCA25CA25CA21301A25CA21303A25C +A21307A25CA2130FA25CEB3FF0007FB512F8B6FCA2333971B83B>I<14F8EB07FE90381F +871C90383E03FE137CEBF801120148486C5A485A120FEBC001001F5CA2EA3F801403007F +5C1300A21407485C5AA2140F5D48ECC1C0A2141F15831680143F1587007C017F1300ECFF +076C485B9038038F8E391F0F079E3907FE03FC3901F000F0222677A42A>97 +D<133FEA1FFFA3C67E137EA313FE5BA312015BA312035BA31207EBE0F8EBE7FE9038EF0F +80390FFC07C013F89038F003E013E0D81FC013F0A21380A2123F1300A214075A127EA214 +0F12FE4814E0A2141F15C05AEC3F80A215005C147E5C387801F8007C5B383C03E0383E07 +C0381E1F80D80FFEC7FCEA01F01C3B77B926>I<147F903803FFC090380FC1E090381F00 +70017E13784913383901F801F83803F003120713E0120FD81FC013F091C7FC485AA2127F +90C8FCA35A5AA45AA3153015381578007C14F0007EEB01E0003EEB03C0EC0F806CEB3E00 +380F81F83803FFE0C690C7FC1D2677A426>II<147F903803FFC090380FC1E09038 +3F00F0017E13785B485A485A485A120F4913F8001F14F0383F8001EC07E0EC1F80397F81 +FF00EBFFF8148090C8FC5A5AA55AA21530007C14381578007E14F0003EEB01E0EC03C06C +EB0F806CEB3E00380781F83803FFE0C690C7FC1D2677A426>IIIII108 +DII<147F903803FFC090380FC1F090381F00F8 +017E137C5B4848137E4848133E0007143F5B120F485AA2485A157F127F90C7FCA215FF5A +4814FEA2140115FC5AEC03F8A2EC07F015E0140F007C14C0007EEB1F80003EEB3F00147E +6C13F8380F83F03803FFC0C648C7FC202677A42A>I<9039078007C090391FE03FF09039 +3CF0787C903938F8E03E9038787FC00170497EECFF00D9F0FE148013E05CEA01E113C15C +A2D80003143FA25CA20107147FA24A1400A2010F5C5E5C4B5A131F5EEC80035E013F495A +6E485A5E6E48C7FC017F133EEC70FC90387E3FF0EC0F8001FEC9FCA25BA21201A25BA212 +03A25B1207B512C0A3293580A42A>I<3903C003F0390FF01FFC391E783C0F381C7C703A +3C3EE03F8038383FC0EB7F800078150000701300151CD8F07E90C7FCEAE0FE5BA2120012 +015BA312035BA312075BA3120F5BA3121F5BA3123F90C9FC120E212679A423>114 +D<14FE903807FF8090380F83C090383E00E04913F00178137001F813F00001130313F0A2 +15E00003EB01C06DC7FC7FEBFFC06C13F814FE6C7F6D13807F010F13C01300143F141F14 +0F123E127E00FE1480A348EB1F0012E06C133E00705B6C5B381E03E06CB45AD801FEC7FC +1C267AA422>II<01F013 +0ED803FC133FD8071EEB7F80EA0E1F121C123C0038143F49131F0070140FA25BD8F07E14 +0000E08013FEC6485B150E12015B151E0003141C5BA2153C000714385B5DA35DA24A5A14 +0300035C6D48C7FC0001130E3800F83CEB7FF8EB0FC0212679A426>118 +D<903907E007C090391FF81FF89039787C383C9038F03E703A01E01EE0FE3803C01F0180 +13C0D8070014FC481480000E1570023F1300001E91C7FC121CA2C75AA2147EA214FEA25C +A21301A24A1370A2010314F016E0001C5B007E1401010714C000FEEC0380010F1307010E +EB0F0039781CF81E9038387C3C393FF03FF03907C00FC027267CA427>120 +D<13F0D803FCEB01C0D8071EEB03E0D80E1F1307121C123C0038140F4914C01270A24913 +1FD8F07E148012E013FEC648133F160012015B5D0003147E5BA215FE00075C5BA214015D +A314035D14070003130FEBF01F3901F87FE038007FF7EB1FC7EB000F5DA2141F003F5C48 +133F92C7FC147E147C007E13FC387001F8EB03E06C485A383C1F80D80FFEC8FCEA03F023 +3679A428>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Ff cmsy10 10 1 +/Ff 1 16 df15 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fg ecbx1000 10 36 +/Fg 36 119 df<913803FFC0027F13F00103B512FC010FEB00FED93FF8133FD97FE0EBFF +8049485A5A1480484A13C04A6C1380A36F1300167E93C7FCA592383FFFC0B8FCA4000390 +C7FCB3ABB5D8FC3F13FFA4303A7EB935>28 D45 +DI<141E143E +14FE1307137FB5FCA3138FEA000FB3B3A5007FB61280A4213679B530>49 +DI54 D58 D66 DII73 +D76 DII< +EDFFF8020FEBFF80027F14F0903A01FFC01FFC010790380007FFD91FFC010113C0D93FF0 +6D6C7E49486E7E49486E7E48496E7E48834890C86C7EA248486F1380A248486F13C0A200 +3F18E0A348486F13F0A400FF18F8AC007F18F06D5DA3003F18E0A26D5D001F18C0A26C6C +4B13806C18006E5C6C6D4A5A6C5F6C6D4A5A6D6C4A5AD93FFC49485A6DB401075B0107D9 +C01F90C7FC010190B512FC6D6C14F0020F1480020001F8C8FC3D3B7BB948>III83 D85 DII<13 +FFB5FCA412077EAF4AB47E020F13F0023F13FC9138FE03FFDAF00013804AEB7FC00280EB +3FE091C713F0EE1FF8A217FC160FA217FEAA17FCA3EE1FF8A217F06E133F6EEB7FE06E14 +C0903AFDF001FF80903AF8FC07FE009039F03FFFF8D9E00F13E0D9C00390C7FC2F3A7EB9 +35>98 D100 +D<903803FF80011F13F0017F13FC3901FF83FE3A03FE007F804848133F484814C0001FEC +1FE05B003FEC0FF0A2485A16F8150712FFA290B6FCA301E0C8FCA4127FA36C7E1678121F +6C6C14F86D14F000071403D801FFEB0FE06C9038C07FC06DB51200010F13FC010113E025 +257DA42C>II<161FD907FEEBFFC090387FFFE348B6EAEFE02607FE07138F260FF801131F48486C13 +8F003F15CF4990387FC7C0EEC000007F81A6003F5DA26D13FF001F5D6C6C4890C7FC3907 +FE07FE48B512F86D13E0261E07FEC8FC90CAFCA2123E123F7F6C7E90B512F8EDFF8016E0 +6C15F86C816C815A001F81393FC0000F48C8138048157F5A163FA36C157F6C16006D5C6C +6C495AD81FF0EB07FCD807FEEB3FF00001B612C06C6C91C7FC010713F02B377DA530>I< +EA01F0EA07FC487EA2487EA56C5AA26C5AEA01F0C8FCA913FF127FA412077EB3A9B512F8 +A4153B7DBA1B>105 D<13FFB5FCA412077EAF92380FFFE0A4923803FC0016F0ED0FE0ED +1F804BC7FC157E5DEC03F8EC07E04A5A141FEC7FE04A7E8181A2ECCFFEEC0FFF496C7F80 +6E7F6E7F82157F6F7E6F7E82150F82B5D8F83F13F8A42D3A7EB932>107 +D<13FFB5FCA412077EB3B3ACB512FCA4163A7DB91B>I<01FED97FE0EB0FFC00FF902601 +FFFC90383FFF80020701FF90B512E0DA1F81903983F03FF0DA3C00903887801F000749DA +CF007F00034914DE6D48D97FFC6D7E4A5CA24A5CA291C75BB3A3B5D8FC1FB50083B512F0 +A44C257DA451>I<01FEEB7FC000FF903803FFF8020F13FE91381F03FFDA3C0113800007 +13780003497E6D4814C05CA25CA291C7FCB3A3B5D8FC3F13FFA430257DA435>I<903801 +FFC0010F13F8017F13FFD9FF807F3A03FE003FE048486D7E48486D7E48486D7EA2003F81 +491303007F81A300FF1680A9007F1600A3003F5D6D1307001F5DA26C6C495A6C6C495A6C +6C495A6C6C6CB45A6C6CB5C7FC011F13FC010113C029257DA430>I<9038FE03F000FFEB +0FFEEC3FFF91387C7F809138F8FFC000075B6C6C5A5CA29138807F80ED3F00150C92C7FC +91C8FCB3A2B512FEA422257EA427>114 D<90383FF0383903FFFEF8000F13FF381FC00F +383F0003007E1301007C130012FC15787E7E6D130013FCEBFFE06C13FCECFF806C14C06C +14F06C14F81203C614FC131F9038007FFE140700F0130114007E157E7E157C6C14FC6C14 +F8EB80019038F007F090B512C000F8140038E01FF81F257DA426>I<130FA55BA45BA25B +5BA25A1207001FEBFFE0B6FCA3000390C7FCB21578A815F86CEB80F014816CEBC3E09038 +3FFFC06D1380903803FE001D357EB425>I118 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fh ecrm1000 10 89 +/Fh 89 126 df<486C1360000314E039070001C0000EEB038048EB070000181306003813 +0E0030130C0070131C00601318A200E01338481330A400CEEB338039FF803FE001C013F0 +A3007F131FA2393F800FE0390E0003801C1981B91C>16 D<001C1307007FEB1FC039FF80 +3FE0A201C013F0A3007F131F001CEB073000001300A400011470491360A2000314E090C7 +12C048130100061480000E130348EB070048130E485B006013181C1980B91C>I21 D27 +DI30 D36 D<141FEC7FC0903801F0 +E0903803C0600107137090380F803090381F00381518A25BA2133E133F15381530A21570 +5D5D140190381F838092CAFC1487148E02DC49B51280EB0FF85C4A9039003FF8000107ED +0FC06E5D71C7FC6E140E010F150CD91DFC141C01391518D970FE143801E015302601C07F +1470D803805D00076D6C5BD80F00EBC00148011F5C4890380FE003003E6E48C8FC007E90 +3807F8060203130E00FE6E5A6E6C5A1400ED7F706C4B13036F5A6F7E6C6C6D6C5B701306 +6C6C496C130E6DD979FE5B281FF001F07F133C3C07F80FE03FC0F86CB539800FFFF0C690 +26FE000313C0D91FF0D9007FC7FC393E7DBB41>38 D<121C127FEAFF80A213C0A3127F12 +1C1200A412011380A2120313005A1206120E5A5A5A12600A1979B917>I<146014E0EB01 +C0EB0380EB0700130E131E5B5BA25B485AA2485AA212075B120F90C7FCA25A121EA2123E +A35AA65AB2127CA67EA3121EA2121F7EA27F12077F1203A26C7EA26C7E1378A27F7F130E +7FEB0380EB01C0EB00E01460135278BD20>I<12C07E12707E7E7E120F6C7E6C7EA26C7E +6C7EA21378A2137C133C133E131EA2131F7FA21480A3EB07C0A6EB03E0B2EB07C0A6EB0F +80A31400A25B131EA2133E133C137C1378A25BA2485A485AA2485A48C7FC120E5A5A5A5A +5A13527CBD20>I<1530B3A8B912FCA2C80030C8FCB3A836367BAF41>43 +D<121C127FEAFF80A213C0A3127F121C1200A412011380A2120313005A1206120E5A5A5A +12600A19798817>II<121C127FEAFF80A5EA7F00121C09097988 +17>I<1506A2150E150CA2151C151815381530A215701560A215E015C0A214011580A214 +0315005C1406A2140E140CA2141C1418A214381430A21470146014E05CA213015CA21303 +91C7FCA25B1306A2130E130C131C1318A213381330A213701360A213E05BA212015B1203 +90C8FCA25A1206A2120E120CA2121C1218A21238123012701260A212E05AA21F537BBD2A +>II +III<1538A2157815F8A214011403 +1407A2140F141F141B14331473146314C313011483EB030313071306130C131C13181330 +1370136013C01201EA038013005A120E120C5A123812305A12E0B712F8A3C73803F800AA +4A7E0103B512F8A325387EB72A>I<0006140CD80780133C9038F003F890B5FC5D5D1580 +92C7FC14FC38067FE090C9FCAAEB07F8EB1FFE9038780F809038E007E03907C003F0496C +7E130000066D7E81C8FC8181A21680A4121C127F5A7FA390C713005D12FC00605C12704A +5A6C5C6C1303001E495A6C6C485A3907E03F800001B5C7FC38007FFCEB1FE021397CB62A +>II<12301238123E003FB612E0A316C05A168016 +000070C712060060140E5D5D00E014304814705D5DC712014A5A4AC7FC1406140E5CA25C +1478147014F05C1301A213035C1307A2130FA3131F5CA2133FA5137FA96DC8FC131E233A +7BB72A>III<121C127FEAFF80A5 +EA7F00121CC7FCB2121C127FEAFF80A5EA7F00121C092479A317>I<121C127FEAFF80A5 +EA7F00121CC7FCB2121C127FEAFF80A213C0A3127F121C1200A412011380A2120313005A +1206120E5A5A5A12600A3479A317>II<007FB812F8B912FCCCFCB0B912FC6C17F836147B9E41>I<12E01278121EEA07C0 +EA01F0EA003C130FEB03C0EB00F0143C140FEC03E0EC00F8151EED0780ED01E0ED007816 +1EEE07C0EE01F0EE003C170FEF03C0A2EF0F00173CEE01F0EE07C0041EC7FC1678ED01E0 +ED0780031EC8FC15F8EC03E0020FC9FC143C14F0EB03C0010FCAFC133CEA01F0EA07C000 +1ECBFC127812E0322E79AB41>II<1538A3157CA315FEA34A7EA34A6C7EA202077FEC063FA202 +0E7FEC0C1FA2021C7FEC180FA202387FEC3007A202707FEC6003A202C07F1501A2D90180 +7F81A249C77F167FA20106810107B6FCA24981010CC7121FA2496E7EA3496E7EA3496E7E +A213E0707E1201486C81D80FFC02071380B56C90B512FEA3373C7DBB3E>65 +DI<913A01FF800180020FEBE003027F13F8903A01FF807E07903A03 +FC000F0FD90FF0EB039F4948EB01DFD93F80EB00FF49C8127F01FE153F12014848151F48 +48150FA248481507A2485A1703123F5B007F1601A35B00FF93C7FCAD127F6DED0180A312 +3F7F001F160318006C7E5F6C7E17066C6C150E6C6C5D00001618017F15386D6C5CD91FE0 +5C6D6CEB03C0D903FCEB0F80902701FF803FC7FC9039007FFFFC020F13F002011380313D +7BBA3C>IIIIIII<013FB512 +E0A39039001FFC00EC07F8B3B3A3123FEA7F80EAFFC0A44A5A1380D87F005B0070131F6C +5C6C495A6C49C7FC380781FC3801FFF038007F80233B7DB82B>IIIIIIIII< +D90FF813C090383FFE0190B512813903F807E33907E000F74848137F4848133F48C7121F +003E140F007E1407A2007C140312FC1501A36C1400A37E6D14006C7E7F13F86CB47E6C13 +F8ECFF806C14E06C14F86C14FEC680013F1480010714C0EB007F020713E0EC007FED3FF0 +151F150FED07F8A200C01403A21501A37EA216F07E15036C15E06C14076C15C06C140F6D +EB1F80D8FBF0EB3F00D8F0FE13FE39E03FFFF8010F13E0D8C00190C7FC253D7CBA2E>I< +003FB812E0A3D9C003EB001F273E0001FE130348EE01F00078160000701770A300601730 +A400E01738481718A4C71600B3B0913807FF80011FB612E0A335397DB83C>IIII89 D<003FB7FCA39039FC0001FE +01C0130349495A003EC7FC003C4A5A5E0038141F00784A5A12704B5A5E006014FF4A90C7 +FCA24A5A5DC712074A5AA24A5A5D143F4A5AA24A5A92C8FC5B495AA2495A5C130F4948EB +0180A2495A5C137F495A16034890C7FC5B1203485AEE0700485A495C001F5D48485C5E48 +48495A49130FB8FCA329397BB833>II93 D<007FB81280B912C0A26C17 +803204797041>95 D97 DIIII<147E903803FF8090 +380FC1E0EB1F8790383F0FF0137EA213FCA23901F803C091C7FCADB512FCA3D801F8C7FC +B3AB487E387FFFF8A31C3B7FBA19>IIIIIII<2703F00FF0EB1FE000FFD93FFCEB +7FF8913AF03F01E07E903BF1C01F83803F3D0FF3800FC7001F802603F70013CE01FE14DC +49D907F8EB0FC0A2495CA3495CB3A3486C496CEB1FE0B500C1B50083B5FCA340257EA445 +>I<3903F00FF000FFEB3FFCECF03F9039F1C01F803A0FF3800FC03803F70013FE496D7E +A25BA35BB3A3486C497EB500C1B51280A329257EA42E>II<3903F01F +E000FFEB7FF89038F1E07E9039F3801F803A07F7000FC0D803FEEB07E049EB03F04914F8 +49130116FC150016FEA3167FAA16FEA3ED01FCA26DEB03F816F06D13076DEB0FE001F614 +C09039F7803F009038F1E07E9038F0FFF8EC1FC091C8FCAB487EB512C0A328357EA42E> +II<3807E01F00FFEB7FC09038E1E3E09038E387F0380FE707EA03E613EE9038EC03E0 +9038FC0080491300A45BB3A2487EB512F0A31C257EA421>II<1318A51338A31378A313F812011203 +1207001FB5FCB6FCA2D801F8C7FCB215C0A93800FC011580EB7C03017E13006D5AEB0FFE +EB01F81A347FB220>IIIIII<003FB512FCA2EB8003D83E0013F8003CEB07F00038 +EB0FE012300070EB1FC0EC3F800060137F150014FE495AA2C6485A495AA2495A495A495A +A290387F000613FEA2485A485A0007140E5B4848130C4848131CA24848133C48C7127C48 +EB03FC90B5FCA21F247EA325>II<126012F0B3B3B3 +B3A91260045377BD17>I<12FCEAFFC0EA07F0EA01FCEA007E7F80131F80130FB3A78013 +07806D7E6D7EEB007EEC1FF0EC07F8EC1FF0EC7E00495A495A495A5C130F5CB3A7131F5C +133F91C7FC137E485AEA07F0EAFFC000FCC8FC1D537ABD2A>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fi ecbx1440 14.4 34 +/Fi 34 118 df28 D45 D<151E153E15FE1403140F147FEB07FF00 +03B5FCB6FCA3EBF87FEAFC00C7FCB3B3B3A6007FB712FCA52E4E76CD42>49 +DI<913807FFC0027F13FC0103B67E010F15E090 +261FF80313F890267FC0007F01FEC7EA3FFE48488148486E138013FE486C6C6D13C08048 +17E080A66C5B18C06C5B6C90C75AD80038168090C8FC4C1300A24C5A5F4C5A4B5B4B13C0 +030F5BDB7FFEC7FC91387FFFF816C016FCEEFF80DA000313E09238007FF8EE3FFE707E70 +138018C07013E018F07013F8A218FC82A218FEA3EA03C0EA0FF0EA3FFC487EA2B5FCA218 +FCA25E18F8A26C4816F0495C4916E0D83FE04A13C06C485CD80FF04A1380D807FE91387F +FE003B03FFE003FFFC6C90B65A6C6C15E0010F92C7FC010114FCD9001F1380374F7BCD42 +>I<17FC1601A216031607160FA2161F163F167FA216FF5D5DA25D5D5D167F153E157E15 +FC15F8EC01F01403EC07E015C0EC0F80141FEC3F00143E5C14FC495A5C495A1307495A5C +49C7FC5B137E137C5B1201485A5B485A120F485A90C8FC123E127E5ABA1280A5C901FCC7 +FCAF021FB71280A5394F7CCE42>I<486C150601F0153E01FEEC01FED9FFF0133F91B65A +5F5F5F5F5F94C7FC16FC5E16E093C8FC15FC01F0138091CAFCAC913807FF80023F13F891 +B512FE01F36E7E9026FFFC0113E09139E0007FF891C76C7E496E7E01F86E7E5B70138049 +16C0C9FC18E08218F0A418F8A31203EA0FE0EA3FF8487EA212FF7FA218F0A25B5E6C4816 +E05B01C016C06CC85A18806C6C4A13007FD80FF04A5A6C6CECFFFCD803FE4913F02701FF +E00F5B6C6CB612806D92C7FC010F14F8010114C09026003FFCC8FC354F7ACD42>I58 +D<932603FFF01407047F01FF5C0307B600E05B033F03F85B92B700FE5B02039126C003FF +5B020F01F8C7EA3FC1023F01C0EC0FE391B5C80003B5FC4901FC814949814901E082011F +498249498292CA7E4948834948835A4A83485B4885A2484984A2485B87A2485B87A25AA2 +98C8FC91CFFCA2B5FCAE7E067FB7128080A37E95C76C90C7FC807EA36C7FA26C7FA26C7F +7E806C7F137F6D7E816D6D93B5FC01077F6D01F85D6D7F6D01FF5D023F01E0EC0FEF020F +01FCEC3FE30203903AFFE001FF81020091B6C6FC033F03FC133F030703F0130FDB007F02 +801303040301F8CAFC595479D267>71 D73 D76 +D78 D80 D<93381FFF800303B512FC033FECFFC0 +92B712F00207D9F80113FE021F903AC0003FFF804A48C700077FDAFFF8020113F049496E +7F49496F7E49496F7E49496F7E4990C96C7F4948707F4948707F01FF854849707F4A8248 +86A24849717E48864A83A2481B80A248497113C0A4481BE0A291CB7EA3B51AF0AF6C1BE0 +A36E5FA26C1BC0A36C1B806E5FA26C1B006E5F6C62A26C6DD903FC4A5A6CDB0FFF5D6E49 +EBC0016C4B01E05C6D6C90277E07F0035B6E9039F801F807902A3FFF01F000780F5B6D04 +7C5C6DD981E06D4890C7FC6D01E191381F7FFE010101F1EDFFF86DD9F9F06D5BDA3FFF16 +C06E6D013F5B02079027FE01FFFEC8FC020190B612F8DA003F4B141003071838DB001FEB +83F893C7EA03FC1C7885726C14F8F2C003F2F01F97B512F084A31CE085A27314C01C8085 +1C00735B735B735B735B9638003FC0556A79D263>III<003FBB12FCA59126C0007FEB000301FCC7ED003FD87FF0F00FFE491807 +49180349180190C81600A2007E1A7EA3007C1A3EA500FC1A3F481A1FA6C91700B3B3AC49 +B912C0A550517BD05B>I97 D<913803FFE0023F13FE91B67E010315E0010F9038003FF8D93FFCEB +07FC4948497E4948131F4849497E485B485BA24890C7FC5A5B003F6F5A705A705A007F92 +C8FC5BA312FFAD127F7FA3123F7F6CEE0F80A26C6D141F18006C6D5C6C6D143E6C6D147E +6C6D5C6D6C495A6DB4EB07F0010F9038C01FE06D90B5128001014AC7FCD9003F13F80203 +138031387CB63A>99 D<943803FF80040FB5FCA5EE003F170FB3A4913803FF80023F13F8 +49B512FE0107ECFF8F011F9038C03FEF90273FFE0007B5FCD97FF8130149487F48498048 +4980484980488291C8FC5A5B123FA2127F5BA312FFAD127FA37F123FA3121F7F6C5E6C6D +5C5F6C6D91B5FC6C6D5B6C6D4914E0D97FFCD90FEFEBFF80D91FFFEB7F8F010790B5120F +010114FC6D6C13E00207010049C7FC41547CD249>I<913807FF80027F13F849B512FE01 +076E7E011F010313E0903A3FFC007FF0D97FF06D7E49486D7E4849130F48496D7E488248 +90C77E1880485A82003F17C0A3485A18E082A212FFA290B8FCA401FCCAFCA6127FA37F12 +3FA2EF03E06C7E17076C17C06C6D140F18806C6D141F6C6DEC3F006C6D147ED97FFC495A +D91FFFEB07F86D9038E03FF0010390B512C001005D023F01FCC7FC020113E033387CB63C +>IIII<133FEBFFC0 +487F487FA2487FA66C5BA26C5B6C5B013FC7FC90C8FCAEEB1FF8B5FCA512017EB3B3A6B6 +12F0A51C547CD324>I108 +DII<913801FFC0023F13FE91B67E010315E001 +0F018013F8903A3FFC001FFED97FF0EB07FF49486D7F48496D7F48496D7F91C8127F4883 +488349153F001F83A2003F8349151FA2007F83A400FF1880AC007F1800A3003F5F6D153F +A2001F5FA26C6C4B5AA26C6D4A5A6C5F6C6D495B6C6D495B6D6C4990C7FCD93FFCEB1FFE +6DB46CB45A010790B512F0010115C0D9003F49C8FC020313E039387CB642>II<90393FF001FCB590 +380FFF804B13E0037F13F09238FE1FF89138F1F83F00019138F07FFC6CEBF3E015C0ECF7 +80A2ECFF00EE3FF84AEB1FF0EE0FE093C7FC5CA45CB3ABB612FEA52E367DB535>114 +D<903903FFC00E011FEBFC1E90B6127E000315FE3907FE003FD80FF0130F484813034848 +1301491300127F90C8127EA248153EA27FA27F01F091C7FC13FCEBFF806C13FEECFFF06C +14FE6F7E6C15E06C816C15FC6C81C681133F010F15801301D9000F14C0EC003F030713E0 +150100F880167F6C153FA2161F7EA217C07E6D143F17807F6DEC7F0001F85C6DEB03FE90 +39FF801FFC486CB512F0D8F81F14C0D8F00791C7FC39E0007FF02B387CB634>I<147CA6 +14FCA41301A31303A21307A2130F131F133F137F13FF1203000F90B512FEB7FCA426007F +FCC8FCB3A9EE0F80ABEE1F006D7EA2011F143E806D6D5A6DEBC1F86DEBFFF001005C023F +1380DA03FEC7FC294D7ECB33>II E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fj ecrm0900 9 5 +/Fj 5 109 df<123C127E12FFA4127E123C08087A8715>46 D97 DI104 +D108 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fk ecbx0900 9 7 +/Fk 7 117 df65 D97 DI<903807FF80013F13F090B512FC3903FE01FE4848487EEA0FF8EA1FF0EA3FE0 +A2007F6D5A496C5A153000FF91C7FCA9127F7FA2003FEC07807F6C6C130F000FEC1F00D8 +07FE133E3903FF80FCC6EBFFF8013F13E0010790C7FC21217DA027>I<3901F81F8000FF +EB7FF0ECFFF89038F9E3FC9038FBC7FE380FFF876C1307A213FEEC03FCEC01F8EC006049 +1300B1B512F0A41F217EA024>114 D<9038FFE1C0000713FF5A383F803F387E000F1407 +5A14037EA26C6CC7FC13FCEBFFE06C13FC806CEBFF80000F14C06C14E0C6FC010F13F0EB +007F140F00F0130714037EA26C14E06C13076CEB0FC09038C01F8090B5120000F913FC38 +E03FE01C217DA023>I<133CA5137CA313FCA21201A212031207001FB51280B6FCA3D807 +FCC7FCB0EC03C0A79038FE078012033901FF0F006C13FEEB3FFCEB0FF01A2F7EAE22>I +E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fl ecrm1200 12 25 +/Fl 25 122 df<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A3120113 +80120313005A1206120E5A5A5A12600B1D78891B>44 D<14FF010713E090381F81F89038 +3E007C01FC133F4848EB1F8049130F4848EB07C04848EB03E0A2000F15F0491301001F15 +F8A2003F15FCA390C8FC4815FEA54815FFB3A46C15FEA56D1301003F15FCA3001F15F8A2 +6C6CEB03F0A36C6CEB07E0000315C06D130F6C6CEB1F806C6CEB3F00013E137C90381F81 +F8903807FFE0010090C7FC28447CC131>48 D50 D54 D<16C04B7EA34B7EA34B7EA34B7EA3ED +19FEA3ED30FFA203707FED607FA203E07FEDC03FA2020180ED801FA2DA03007F160FA202 +06801607A24A6D7EA34A6D7EA34A6D7EA20270810260147FA202E08191B7FCA249820280 +C7121FA249C87F170FA20106821707A2496F7EA3496F7EA3496F7EA201788313F8486C83 +D80FFF03037FB500E0027FEBFFC0A342477DC649>65 DI68 D77 +D<003FB912F8A3903BF0001FF8001F01806D481303003EC7150048187C0078183CA20070 +181CA30060180CA5481806A5C81600B3B3A54B7EED7FFE49B77EA33F447DC346>84 +D +I97 +D99 D<167FED3FFFA315018182B3EC7F80903803 +FFF090380FC07C90383F000E017E1307496D5AD803F87F48487F5B000F81485AA2485AA2 +127FA290C8FC5AAB7E7FA2123FA26C7EA2000F5D7F6C6C5B00035C6C6C9038077F806C6C +010E13C0013F011C13FE90380FC0F8903803FFE09026007F0013002F467DC436>II103 D105 D108 D<3901FC01FE00FF903807FFC091381E +07F091383801F8000701707F0003EBE0002601FDC07F5C01FF147F91C7FCA25BA35BB3A8 +486CECFF80B5D8F83F13FEA32F2C7DAB36>110 DI<3903F803F000FFEB1FFCEC3C3EEC707F0007EBE0FF3803F9C000015B13FBEC00 +7E153C01FF13005BA45BB3A748B4FCB512FEA3202C7DAB26>114 +D<90383FE0183901FFFC383907E01F78390F0003F8001E1301481300007C1478127800F8 +1438A21518A27EA27E6C6C13006C7E13FC383FFFE06C13FC6C13FF6C14C06C14E0C614F0 +011F13F81300EC0FFC140300C0EB01FE1400157E7E153EA27EA36C143C6C147C15786C14 +F86CEB01F039F38003E039F1F00F8039E07FFE0038C00FF01F2E7DAC26>I<1306A5130E +A4131EA3133E137EA213FE12011207001FB512F0B6FCA2C648C7FCB3A4150CAA017E131C +017F1318A26D133890381F8030ECC070903807E0E0903801FFC09038007F001E3E7EBC26 +>III< +B539F001FFFCA3000790C7EA7FE06C48EC1F8000011600160E0000150C6D141C6D1418A2 +6E1338013F1430A26D6C5BA26E13E0010F5CA26D6C485AA2ECF803010391C7FCA2903801 +FC06A2ECFE0E0100130CA2EC7F18A215B8EC3FB0A2EC1FE0A36E5AA26E5AA36EC8FCA214 +06A35CA25CA2123C007E5BB4FC5CA25CEAFE01387C0380D87007C9FCEA3C1EEA0FFCEA03 +F02E3F7EAA33>121 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fm ecbx1200 12 47 +/Fm 47 123 df<0118140C017C143E01FC147E48485C4848495A495C4848495A4848495A +001F140F90C75B003E4AC7FCA2003C141E007C143E0078143CA200F8147CA2481478D8F1 +F014F8D8F7FCEB7BFEB46CEB7FFF6D1580028014C0A36C80A36C806C496C13806C486D13 +006C486D5AD801F0EB00F82A2283C427>16 DI28 D46 D48 DIII<163FA25E5E5D5DA25D5D5D5DA25D92B5FCEC01F7EC03E7140715 +C7EC0F87EC1F07143E147E147C14F8EB01F0EB03E0130714C0EB0F80EB1F00133E5BA25B +485A485A485A120F5B48C7FC123E5A12FCB91280A5C8000F90C7FCAC027FB61280A53141 +7DC038>I<0007150301E0143F01FFEB07FF91B6FC5E5E5E5E5E16804BC7FC5D15E092C8 +FC01C0C9FCAAEC3FF001C1B5FC01C714C001DF14F09039FFE03FFC9138000FFE01FC6D7E +01F06D13804915C0497F6C4815E0C8FC6F13F0A317F8A4EA0F80EA3FE0487E12FF7FA317 +F05B5D6C4815E05B007EC74813C0123E003F4A1380D81FC0491300D80FF0495AD807FEEB +FFFC6CB612F0C65D013F1480010F01FCC7FC010113C02D427BC038>I<4AB47E021F13F0 +027F13FC49B6FC01079038807F8090390FFC001FD93FF014C04948137F4948EBFFE04849 +5A5A1400485A120FA248486D13C0EE7F80EE1E00003F92C7FCA25B127FA2EC07FC91381F +FF8000FF017F13E091B512F89039F9F01FFC9039FBC007FE9039FF8003FF17804A6C13C0 +5B6F13E0A24915F0A317F85BA4127FA5123FA217F07F121FA2000F4A13E0A26C6C15C06D +4913806C018014006C6D485A6C9038E01FFC6DB55A011F5C010714C0010191C7FC903800 +3FF02D427BC038>I<121E121F13FC90B712FEA45A17FC17F817F017E017C0A248168000 +7EC8EA3F00007C157E5E00785D15014B5A00F84A5A484A5A5E151FC848C7FC157E5DA24A +5A14035D14074A5AA2141F5D143FA2147F5D14FFA25BA35B92C8FCA35BA55BAA6D5A6D5A +6D5A2F447AC238>I58 D<1A60F101F01907191FF17FC0953801FF00F007FCF01FF0F07FC04D48C7FCEF07 +FCEF3FF0EFFFC0040390C8FCEE0FFCEE3FE0EEFF80DB03FEC9FCED0FF8ED3FE0EDFF80DA +07FECAFCEC1FF8EC7FE0903801FF80D907FCCBFCEB1FF0EB7FC04848CCFCEA07FCEA1FF0 +EA7FC048CDFCA2EA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FC903801FF809038 +007FE0EC1FF8EC07FE913800FF80ED3FE0ED0FF8ED03FE923800FF80EE3FE0EE0FFCEE03 +FF040013C0EF3FF0EF07FCEF01FF9438007FC0F01FF0F007FCF001FF9538007FC0F11FF0 +19071901F10060444277B957>60 D<126012F812FE6C7EEA3FE0EA0FF8EA03FEC66C7EEB +3FE0EB0FF8EB03FE903800FFC0EC3FF0EC0FFCEC03FF9138007FC0ED1FF0ED07FCED01FF +9238007FC0EE1FF0EE07FE933801FF809338007FE0EF1FF8EF03FE943800FF80F03FE0F0 +0FF8F003FE953800FF80F13FE0F10FF0A2F13FE0F1FF80953803FE00F00FF8F03FE0F0FF +80DD03FEC7FCEF1FF8EF7FE0933801FF80DC07FEC8FCEE1FF0EE7FC04B48C9FCED07FCED +1FF0ED7FC0DA03FFCAFCEC0FFCEC3FF0ECFFC0D903FECBFCEB0FF8EB3FE0EBFF80D803FE +CCFCEA0FF8EA3FE0EAFF8048CDFC12F81260444277B957>62 D<923803FFF0037FEBFF80 +0203B612F0020F15FC913A3FFC000FFFDAFFC0010013C0D903FEC8EA1FF0D907F0ED03F8 +D91FC0ED00FE4948167F017ECAEA1F8049717E4848717E49DAFF8013034848010F01F06D +7E4848013F01FC6D7E92B6FC4848489026C07F80137C49489026001FC0133C484948D907 +E0133E001E49486D6C131E003E49480101141F023F913800FFE0003C4A82007C017F1880 +007819074A5AA300F81AC04848491603AB6C6C7F12781B801A076E7E127C003C133F003E +6E1700021F4A5C001E6D6C5B001F6D6C49EBF01E6C6D6C011F143E6D6CD9C07F6D5A6C6C +6C90B5383FFFF8033FD9FC0F5B6C6C010FD9F0035B6C6C0100903980007F806D91CBFC6C +7E137E6D7E6D6CEF7FC0D907F0EE03FFD903FE043F1300902600FFC0913803FFF8DA3FFC +49B512C0020FB748C7FC020316E0DA007F02FCC8FC030349C9FC4A477AC557>64 +DIIII73 D77 D<923807FFC092B512FE0207ECFFC0021F15F0 +91267FFE0013FC902601FFF0EB1FFF01070180010313C04990C76C7FD91FFC6E6C7E4948 +6F7E49486F7E01FF8348496F7E48496F1380A248496F13C0A24890C96C13E0A24819F049 +82003F19F8A3007F19FC49177FA400FF19FEAD007F19FC6D17FFA3003F19F8A26D5E6C19 +F0A26E5D6C19E0A26C6D4B13C06C19806E5D6C6D4B13006C6D4B5A6D6C4B5A6D6C4B5A6D +6C4A5B6D01C001075B6D01F0011F5B010101FE90B5C7FC6D90B65A023F15F8020715C002 +004AC8FC030713C047467AC454>79 D83 D<007FBA12E0BB12F0A46C19E04406776757>95 D<903801FFE0011F13FE017F6D +7E48B612E03A03FE007FF84848EB1FFC6D6D7E486C6D7EA26F7FA36F7F6C5A6C5AEA00F0 +90C7FCA40203B5FC91B6FC1307013F13F19038FFFC01000313E0481380381FFE00485A5B +127F5B12FF5BA35DA26D5B6C6C5B4B13F0D83FFE013EEBFFC03A1FFF80FC7F0007EBFFF8 +6CECE01FC66CEB8007D90FFCC9FC322F7DAD36>97 DIIIIIII<137C48B4FC4813804813C0A24813E0A56C13 +C0A26C13806C1300EA007C90C7FCAAEB7FC0EA7FFFA512037EB3AFB6FCA518467CC520> +I108 D<90277F8007FEEC0FFC +B590263FFFC090387FFF8092B5D8F001B512E002816E4880913D87F01FFC0FE03FF8913D +8FC00FFE1F801FFC0003D99F009026FF3E007F6C019E6D013C130F02BC5D02F86D496D7E +A24A5D4A5DA34A5DB3A7B60081B60003B512FEA5572D7CAC5E>I<90397F8007FEB59038 +3FFF8092B512E0028114F8913987F03FFC91388F801F000390399F000FFE6C139E14BC02 +F86D7E5CA25CA35CB3A7B60083B512FEA5372D7CAC3E>II<90397FC00FF8B590B57E02C314E002CF14F89139DFC03F +FC9139FF001FFE000301FCEB07FF6C496D13804A15C04A6D13E05C7013F0A2EF7FF8A4EF +3FFCACEF7FF8A318F017FFA24C13E06E15C06E5B6E4913806E4913006E495A9139DFC07F +FC02CFB512F002C314C002C091C7FCED1FF092C9FCADB67EA536407DAC3E>II<90387F807FB53881FFE002 +8313F0028F13F8ED8FFC91389F1FFE000313BE6C13BC14F8A214F0ED0FFC9138E007F8ED +01E092C7FCA35CB3A5B612E0A5272D7DAC2E>I<90391FFC038090B51287000314FF120F +381FF003383FC00049133F48C7121F127E00FE140FA215077EA27F01E090C7FC13FE387F +FFF014FF6C14C015F06C14FC6C800003806C15806C7E010F14C0EB003F020313E0140000 +F0143FA26C141F150FA27EA26C15C06C141FA26DEB3F8001E0EB7F009038F803FE90B55A +00FC5CD8F03F13E026E007FEC7FC232F7CAD2C>II< +D97FC049B4FCB50103B5FCA50003EC000F6C81B3A85EA25EA25E7E6E491380017FD901F7 +13FE9138F807E76DB512C7010F1407010313FE9026007FF0EBFC00372E7CAC3E>I +I120 +D<001FB71280A49026FC001F130001E0495A5B49495A90C7485A48495B123E4A5B4A5B00 +3C495BA24A90C7FC4A5A4A5AC7FC4A5A495B495BA2495B499038800780491300A2495A49 +48130F49481400A2485B48495B485BA248495B4890C75A48485C15034848EB1FFEB7FCA4 +292C7DAB32>122 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fn ecrm1728 17.28 8 +/Fn 8 117 df68 D70 D97 D102 D<1378EA01FE487E487FA66C +90C7FC6C5AEA007890C8FCB3A2EB0780EA0FFFB5FCA41203C6FCA2137FB3B3AC497E487F +B61280A4195F7BDE25>105 D<010FEB07F8D80FFFEB1FFEB590387FFF809238F81FC091 +3801E03F913903C07FE00003EB0780C6EB0F00140E6D5A0218EB3FC00238EB1F800230EB +0600027090C7FCA2146014E0A25CA55CB3B0497E4813F0B612F8A42B3F7BBE34>114 +D<9138FFC003010FEBF807017FEBFE0F3A01FF003F9FD803F0EB07DF48486DB4FCD80F80 +1300001F8148C8FC003E81007E81127C00FC81A4827EA27E7F6C7E6D91C7FC13F8EA3FFE +381FFFE06C13FF15F0000314FE6C6E7E6C6C14E0011F14F801078001008002077FDA003F +13801507030113C0ED007F00E0ED3FE0161F17F06C150F1607A36C1503A37EA26C16E016 +077E17C06D140F6D15806D141FD8FDF0EC3F00D8F8F8147E017C495A3AF01F801FF06DB5 +12C0D8E00391C7FC39C0007FF02C417CBF35>I<1470A714F0A51301A31303A21307A213 +0FA2131F133F137F13FF1203000F90B6FCB8FCA326000FF0C8FCB3AEEE01C0AE6D6CEB03 +80A316076D6C14005E6D6C130E6D6C131E6E6C5A91383FE0F86EB45A020713C0020090C7 +FC2A597ED734>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fo ecbx1728 17.28 18 +/Fo 18 117 df68 D<942603FFF8151C94B66C +143C040F03F0147C047F03FC14FC0303B81301030FDAC00113C0033F01F8C7381FF00392 +B500C0913807F807020349C83801FE0F020F01F89238007F1F4A01E0EE3FBF4A49EE0FFF +91B5CA7E494983494983494983495B4949187F4B183F491A1F495B90B5CC120FA2484919 +075A4A19035A4A19015AA24A19005AA348491A7CA35A9AC8FCA35CA2B5FCB07EA26E043F +B81280A47E96C7000701FCC7FCA26C7FA37E80A27E807E807E6C7FA26D7F6D7F7F816D7F +6D6D5F6D7F6D6D5F6D6D7E023F6D5E6E01F05E6E6DEEFE7F020301FF923801FC3F020002 +C0913807F80F033F01FC91381FF007030F903BFFE001FFC001030391B6EA8000DB007F4B +C7123C040F03F8140C040003C091C8FC050301F8CBFC696677E37A>71 +D82 D<001FBD12F0A59126F8000191C7123F4801C0 +060713F849C71700491A7F01F01A1F491A0F491A07A2491A03A290C81801A2007EF300FC +A4007C1C7CA7481C3EA5C91900B3B3B3A5023FB912F8A55F617AE06C>84 +D<913803FFF0027F13FF0103B612E0010F15F890263FFC0013FED97FC090381FFF8049C7 +6C7F4801C06D7F486D6D7F6E6D7F48836E7F84177F84A36C496E7FA26C5B6C5B013FC8FC +90C9FCA75F0307B6FC4AB7FC141F91B5EAF03F0103EBFE00010F13F0013F1380D9FFFEC7 +FC485B485B485B485B485B485BA24890C8FC1A7CA2485AA35FA394B5FC7F6C5D6EEB03DF +6CDB07CFEBC0F86C6DEB0F8F6C6DD91F07EBF3F06C01F8017E14FF6C9027FE01FC0314E0 +C690B5D8F00114C0013F9126C0007F1380010791C7383FFE009026003FF8EC07F846437B +C14D>97 D<903807FF80B6FCA5C6FC7F7FB3A9933801FFE0041F13FE047FEBFFC00381B6 +12F0922687FC0113FC923A9FE0003FFEDBBF8090380FFF8003FEC76C7F4B6E7F4B6E7F4B +6E7F4B824B157F4B82737EA21B80851BC0A31BE085A41BF0AE1BE0A44F13C0A31B80A24F +1300A262197F6F5E6F4B5A4E5B6F4A5BDAFCF84A5BDAF87E4A5B4A6C4A90C7FC9126E01F +C0EB7FFC913BC00FF803FFF8DA8003B612E091C71580013E023F01FCC8FC90C800031380 +4C657CE356>II101 DII105 D<903807FF80B6FCA5C6FC7F7FB3B3B3B3AFB7 +12E0A523647CE32A>108 D110 D<92381FFF804AB512F8020F +14FF023F15C09126FFFC0313F001039039E0007FFC490180EB1FFED91FFEC73807FF8049 +486E7F49486E7F49486E7F48496F7EA248496F7E4884A248496F7EA2481980A24819C091 +C97EA24819E0A5B518F0AD6C19E0A46C6D4B13C0A36C1980A26C6D4B1300A26C606E157F +6C606C6D4B5A6C606D6C4A5B6D6C4A5B6D6C4A5B6D6C6C011F90C7FC010301E0EB7FFC6D +9039FC03FFF86D6CB612E0020F92C8FC020114F8DA001F138044437CC14D>I<903B07FF +8001FFE0B6011F13FE047FEBFFC00381B612F0922687FC0313FC923A9FE0007FFEC6DABF +806D6C7E6D01FEC7000F7F6D496E7F4B824B6E7F4B6E7F4B804B82737EA21B80851BC0A2 +851BE0A4851BF0AE4F13E0A41BC061A21B80A24F1300A24F5AA26F4A5B6F4A5B626F4A5B +6F4A5B03FE4A5B03BF027F90C7FCDB9FC0EBFFFC92268FF8075B0383B612E00380158004 +3F01FCC8FC0403138093CBFCB3A4B712E0A54C5D7CC056>I114 DII E +%EndDVIPSBitmapFont +end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: A4 + +%%EndSetup +%%Page: 1 1 +1 0 bop 290 639 a Fo(Genealogical)56 b(Represen)l(tation)e(of)f(T)-13 +b(rees)52 b(in)g(Databases)1686 822 y Fn(First)46 b(Draft)1247 +1063 y Fm(Miguel)36 b(Sofer)i()1359 1179 +y Fl(Univ)m(ersidad)33 b(T)-8 b(orcuato)33 b(Di)f(T)-8 +b(ella)1728 1295 y(Buenos)33 b(Aires)1797 1411 y(Argen)m(tina)1746 +1606 y(Ma)m(y)h(6,)e(2000)1839 1905 y Fk(Abstract)441 +2035 y Fj(blah)25 b(blah)h(.)13 b(.)g(.)118 2310 y Fi(1)131 +b(In)l(tro)t(duction)118 2491 y Fh(T)-7 b(rees)28 b(are)h(a)g(v)n(ery)f +(frequen)n(t)h(data)f(structure.)41 b(They)30 b(are)e(the)h(natural)g +(represen)n(tation)e(for)i(instance)g(for)f(organiza-)118 +2591 y(tional)f(c)n(harts,)g(threaded)g(discussion)g(groups,)f(some)h +(bills)g(of)h(materials,)e(.)14 b(.)g(.)243 2691 y(A)n(t)28 +b(least)f(t)n(w)n(o)f(alternativ)n(e)h(represen)n(tations)e(for)i +(trees)g(in)h(RDBMs)g(are)e(kno)n(wn)h(and)h(used:)220 +2857 y(1.)41 b Fg(P)m(oin)m(ters:)k Fh(a)31 b(\034eld)h(in)h(the)f(c)n +(hild)g(record)e(references)h(the)h(paren)n(t)f(no)r(de.)50 +b(This)32 b(seems)g(to)f(b)r(e)i(the)f(canonical)326 +2956 y(represen)n(tation.)38 b(Some)29 b(DB)g(engines)f(pro)n(vide)g +(sp)r(ecial)g(SQL)g(extensions)g(to)h(simplify)g(tree)g(searc)n(hes;)e +(Oracle)326 3056 y(tree)d(extensions)g(are)g(an)h(example)f(\(see)h +(for)f(instance)g([1]\);)i(DB2's)f(WITH)g(can)f(b)r(e)i(used)e(for)h +(this)g(purp)r(ose)f(to)r(o)326 3156 y(\(see)j([3],)g(pp)h(139-162\).) +220 3322 y(2.)41 b Fg(Nested)35 b(Sets:)43 b Fh(t)n(w)n(o)30 +b(n)n(umeric)h(\034elds)g(in)g(ev)n(ery)f(no)r(de)h(record)f(co)r(de)h +(the)g(tree)g(structure.)47 b(I)31 b(can't)g(pro)n(vide)f(a)326 +3421 y(b)r(etter)e(or)e(briefer)h(description)g(of)h(this)g(metho)r(d)g +(than)f(the)h(four)f(articles)g([2].)118 3587 y(These)g(t)n(w)n(o)g +(metho)r(ds)h(o\033er)f(di\033eren)n(t)h(adv)-5 b(an)n(tages)25 +b(and)j(disadv)-5 b(an)n(tages:)243 3753 y Ff(\017)41 +b Fh(P)n(oin)n(ters)30 b(are)g(extremely)g(e\036cien)n(t)h(for)f(no)r +(de)h(insertion)f(and/or)g(deletion,)h(but)h(require)e(recursiv)n(e)f +(table)i(ac-)326 3853 y(cesses)e(to)h(searc)n(h)f(the)h(tree)g(\(I)h +(do)f(not)g(kno)n(w)f(the)i(implemen)n(tation)f(details)g(of)g(the)h +(Oracle)e(tree)g(extensions,)326 3953 y(whic)n(h)e(as)g(far)g(as)g(I)g +(kno)n(w)g(ma)n(y)g(solv)n(e)f(this)i(problem)f(in)n(ternally;)g(they)g +(de\034nitely)h(solv)n(e)f(it)g(for)g(the)h(end)g(user\).)243 +4119 y Ff(\017)41 b Fh(Nested)30 b(sets)g(are)f(v)n(ery)f(e\036cien)n +(t)i(for)g(tree)f(searc)n(hes,)g(but)i(are)e(rather)f(exp)r(ensiv)n(e)i +(for)f(no)r(de)h(insertion)f(and/or)326 4218 y(deletion:)37 +b(they)27 b(require)g(up)r(dating)g(p)r(oten)n(tially)h(man)n(y)f(no)r +(des.)243 4384 y(W)-7 b(e)30 b(prop)r(ose)f(here)h(a)g(di\033eren)n(t)h +(represen)n(tation,)e(based)g(on)i(no)r(de)f(iden)n(ti\034ers)g(whic)n +(h)g(are)f(\020genealogical)f(iden)n(ti-)118 4484 y(\034ers\021:)44 +b(they)32 b(con)n(tain)f(the)h(complete)f(genealogy)f(of)h(the)h(no)r +(de,)h(i.e.,)g(the)f(list)g(of)g(ancestors)d(up)j(to)g(the)g(ro)r(ot)f +(of)g(the)118 4584 y(tree.)243 4683 y(This)j(allo)n(ws)f(to)i(replace)e +(man)n(y)h(searc)n(hes)f(in)h(database)g(tables)g(with)h(string)f(op)r +(erations)f(on)h(the)h(index.)58 b(The)118 4783 y(result,)24 +b(as)f(explained)h(in)g(Section)g(3)f(is)h(that)g(tree)f(searc)n(hes)f +(pro)r(ceed)h(at)h(\020nested)f(sets\021)30 b(sp)r(eed,)25 +b(while)f(no)r(de)g(insertions)118 4882 y(and)k(deletions)f(are)f(as)h +(fast)h(as)f(with)h(p)r(oin)n(ters.)243 4982 y(The)i(ob)n(vious)f(do)n +(wnside)h(of)h(the)g(metho)r(d)g(is)f(that)h(the)g(primary)f(k)n(ey)f +(in)i(the)g(tree)f(needs)h(to)f(b)r(e)h(a)g(v)-5 b(ariable)29 +b(size)118 5082 y(text)j(\034eld,)h(and)f(that)g(the)g(iden)n +(ti\034ers)f(ma)n(y)g(b)r(e)i(extremelly)e(long)g(for)g(deep)h(trees.) +49 b(W)-7 b(e)32 b(will)g(pro)n(vide)e(estimates)i(of)118 +5181 y(the)c(size)f(required)g(as)g(a)g(function)h(of)g(the)f +(magnitude)h(of)f(the)h(tree.)1987 5653 y(1)p eop +%%Page: 2 2 +2 1 bop 118 291 a Fi(2)131 b(Genealogical)45 b(iden)l(ti\034ers)g(for)f +(trees)118 489 y Fm(2.1)112 b(De\034nition)118 642 y +Fh(W)-7 b(e)28 b(de\034ne)g Fe(gene)l(alo)l(gic)l(al)k(identi\034ers)j +Fh(recursiv)n(ely)25 b(as)i(follo)n(ws:)326 808 y Fg(De\034nition:)59 +b Fe(The)42 b(gene)l(alo)l(gic)l(al)h(identi\034er)f(\(gID\))e(of)i(a)f +(no)l(de)h(is)f(obtaine)l(d)h(by)g(app)l(ending)g(a)f(child)326 +908 y(identi\034er)30 b(to)g(the)g(gene)l(alo)l(gic)l(al)h +(identi\034er)g(of)f(the)g(p)l(ar)l(ent)f(no)l(de.)243 +1074 y Fh(Remark)40 b(that)h(genealogical)e(iden)n(ti\034ers)i(are)f +(rather)g(w)n(ell)h(kno)n(wn)f(and)h(used;)48 b(common)41 +b(examples)f(are)g(the)118 1174 y(\020path+\034le-name\021)33 +b(in)28 b(a)f(computer)g(\034le)h(system)f(and)h(the)f(URLs)h(within)g +(a)f(WWW.)243 1273 y(The)d(name)g(\020genealogical)e(iden)n +(ti\034er\021)30 b(is)24 b(suggested)g(b)n(y)g(the)g(fact)h(that)f(the) +h(v)-5 b(alue)24 b(of)g(the)h(iden)n(ti\034er)f(con)n(tains)f(the)118 +1373 y(complete)30 b(genealogy)d(of)j(the)g(no)r(de:)41 +b(it)30 b(con)n(tains)e(as)h(a)h(substring)f(the)h(gID)f(of)h(its)g +(father,)g(whic)n(h)f(in)h(turn)g(con)n(tains)118 1472 +y(as)d(a)g(substring)g(the)h(gID)g(of)f(the)h(grandfather,)e(.)14 +b(.)g(.)243 1572 y(The)27 b(ro)r(ot)g(no)r(de)h(of)f(the)h(tree)f(has)g +(a)h(gID)f(with)h(v)-5 b(alue)28 b(\021)34 b(\(the)28 +b(empt)n(y)g(string\),)f(as)g(it)h(has)f(no)g(paren)n(t.)118 +1804 y Fm(2.2)112 b(Child)36 b(iden)m(ti\034ers)118 1958 +y Fh(The)26 b(ob)n(vious)e(c)n(hild)i(iden)n(ti\034er)g(is)f(a)h +(zero-based)d(coun)n(ter:)35 b(iden)n(tify)26 b(the)h(c)n(hild)e(b)n(y) +h(the)g(n)n(um)n(b)r(er)f(of)h(older)f(brethren)g(it)118 +2057 y(has.)243 2157 y(W)-7 b(e)25 b(could)f(represen)n(t)g(the)h(coun) +n(ter)f(in)h(base)f(10;)h(this)g(ho)n(w)n(ev)n(er)e(is)i(extremely)f(w) +n(asteful)g(of)h(resources.)34 b(It)25 b(is)g(m)n(uc)n(h)118 +2257 y(b)r(etter)33 b(to)f(represen)n(t)f(the)h(coun)n(ter)g(in)g(as)g +(large)e(a)i(base)g(as)f(p)r(ossible:)46 b(in)n(terpret)32 +b(as)f(n)n(um)n(b)r(ers)h(a)g(set)g(of)g(c)n(haracters)118 +2356 y(larger)26 b(than)h({0,1,.)14 b(.)g(.)g(9}.)243 +2456 y(As)26 b(tree)f(op)r(erations)f(will)i(in)n(v)n(olv)n(e)f(string) +g(op)r(erations)f(on)i(the)g(indices,)g(in)g(order)f(to)g(a)n(v)n(oid)g +(a)g(\020quoting)g(hell\021)33 b(it)26 b(is)118 2555 +y(desirable)d(to)h(a)n(v)n(oid)e(using)h(an)n(y)g(c)n(haracter)f(with)i +(a)g(sp)r(ecial)f(meaning)h(in)g(LIKE)g(expressions)e(or)g(regular)g +(expressions;)118 2655 y(i.e.,)28 b(w)n(e)f(will)h(not)f(use)h(an)n(y)f +(of)g(the)h(sym)n(b)r(ols)70 b Fd(.)44 b(*)f(^)g(\\)g([)g(])g({)h(})f +(\()g(\))g(<)g(>)71 b Fh(?)37 b(|)28 b(&)f($)243 2755 +y(W)-7 b(e)28 b(prop)r(ose)e(to)h(reserv)n(e)f(also)g(/)i(as)f(a)g +(separator)e(\(see)i(\020V)-7 b(ariable)27 b(Sized)g(gID\021)34 +b(b)r(elo)n(w\).)243 2854 y(If)g(w)n(e)f(limit)i(ourselv)n(es)d(to)i +(ascii)f(c)n(haracters,)g(and)h(a)n(v)n(oid)e(to)i(b)r(e)g(safe)f(a)h +(lot)g(of)g(other)f(c)n(haracters,)g(w)n(e)g(can)h(use)118 +2954 y(n)n(um)n(b)r(ers)27 b(in)h(base)f(64)g(b)n(y)g(represen)n(ting) +243 3120 y Ff(\017)41 b Fh(0-9)26 b(with)i('0'-'9')f(\(dec)g(ascii)g +(co)r(de)h(48-57\))243 3286 y Ff(\017)41 b Fh(10)26 b(with)i(':')37 +b(\(dec)28 b(ascii)f(co)r(de)h(58\))243 3452 y Ff(\017)41 +b Fh(11)26 b(with)i(';')g(\(dec)g(ascii)f(co)r(de)g(59\))243 +3618 y Ff(\017)41 b Fh(12-37)25 b(with)j('A'-'Z')g(\(dec)f(ascii)g(co)r +(de)h(65-90\))243 3784 y Ff(\017)41 b Fh(38-63)25 b(with)j('a'-'z')f +(\(dec)h(ascii)f(co)r(de)g(97-122\))118 3950 y(By)g(using)g(base)f(64,) +h(up)g(to)h(4096)d(c)n(hildren)i(can)f(b)r(e)i(represen)n(ted)e(using)h +(t)n(w)n(o)f(suc)n(h)h(digits,)g(up)h(to)f(262144)d(with)k(three)118 +4050 y(digits,)g(and)f(up)h(to)f(16777216)d(with)k(four)f(digits.)243 +4149 y(If)37 b(the)g(RDBMs)g(supp)r(orts)f(in)n(ternational)g(c)n +(haracters,)h(it)g(is)g(p)r(ossible)f(to)h(further)f(increase)g(the)h +(base;)k(as)36 b(an)118 4249 y(example,)30 b(b)n(y)f(using)g(the)h(95)f +(additional)g(c)n(haracters)e(of)i(the)h(latin-1)f(c)n(haracter)e(set,) +k(w)n(e)e(could)g(co)r(de)g(n)n(um)n(b)r(ers)g(in)h(a)118 +4349 y(base)f(up)g(to)g(160)f(\025)g(remark)g(that)h(ev)n(ery)f(single) +h(digit)g(is)g(still)h(one)e(b)n(yte)h(in)h(this)f(represen)n(tation.) +40 b(This)29 b(means)f(that)118 4448 y(w)n(e)f(expand)h(the)f(sym)n(b)r +(ols)g(ab)r(o)n(v)n(e)f(b)n(y)i(represen)n(ting)243 4614 +y Ff(\017)41 b Fh(64-159)25 b(with)j(dec)f(latin1)g(co)r(de)h(160-255) +243 4780 y(In)23 b(base)g(160,)g(up)g(to)h(25600)d(c)n(hildren)i(can)f +(b)r(e)i(represen)n(ted)e(using)h(t)n(w)n(o)g(digits,)h(up)g(to)f +(4096000)d(with)k(three)f(digits,)118 4880 y(and)28 b(up)f(to)h +(6.5E+08)e(with)i(four)f(digits.)243 4980 y(Remark)g(that)h(base)f(con) +n(v)n(ersions)f(only)h(need)i(to)e(b)r(e)i(p)r(erformed)e(at)h +(insertion)g(time,)g(when)h(the)f(index)g(of)g(a)g(new)118 +5079 y(no)r(de)g(is)f(computed.)37 b(They)28 b(will)f(therefore)g(only) +g(ha)n(v)n(e)f(an)i(impact)f(on)h(insertion)f(timings.)1987 +5653 y(2)p eop +%%Page: 3 3 +3 2 bop 118 291 a Fm(2.3)112 b(Coun)m(ters:)50 b(\020delimited\021)44 +b(vs.)51 b(\020\034xed)38 b(size\021)118 444 y Fh(The)33 +b(standard)g(represen)n(tation)e(of)i(gID)h(uses)e(a)h(v)-5 +b(ariable)32 b(size)h(c)n(hild)h(iden)n(ti\034er,)g(and)f(delimiters)g +(to)h(separate)d(the)118 543 y(gID)f(of)g(the)h(c)n(hild)f(no)r(de)g +(from)f(the)i(gID)f(of)g(its)g(paren)n(t.)43 b(F)-7 b(or)30 +b(example,)g(w)n(e)g(can)f(represen)n(t)g(the)i(\034fth)g(c)n(hild)f +(of)g(no)r(de)118 643 y('/23/27/1')24 b(as)j('/23/27/1/4'.)32 +b(Let)c(us)f(call)g(this)h(a)f Fg(vgID)h Fh(represen)n(tation)e(\(V)-7 +b(ariable)27 b(Size)h(Genealogical)d(ID\).)243 743 y(This)30 +b(represen)n(tation)f(allo)n(ws)f(for)i(an)n(y)g(n)n(um)n(b)r(er)g(of)g +(c)n(hildren)g(of)h(a)f(no)r(de,)h(sub)5 b(ject)30 b(only)g(to)g(the)h +(limitations)f(the)118 842 y(RDBMS)e(ma)n(y)f(ha)n(v)n(e)f(as)h(to)h +(the)g(length)f(of)h(a)f(v)-5 b(ariable)27 b(sized)g(string.)243 +942 y(Alternativ)n(ely)-7 b(,)24 b(w)n(e)f(could)h(c)n(ho)r(ose)f(to)h +(limit)g(from)g(the)g(outset)g(the)g(quan)n(tit)n(y)g(of)f(c)n(hildren) +h(that)g(a)g(no)r(de)g(ma)n(y)f(ha)n(v)n(e;)118 1042 +y(this)28 b(limit)g(w)n(ould)f(dep)r(end)i(of)e(course)f(on)i(the)g +(application.)36 b(Let)27 b(us)h(call)f(this)h(a)f Fg(fgID)h +Fh(represen)n(tation.)243 1141 y(F)-7 b(or)25 b(example,)h(if)g(no)g +(no)r(de)f(is)h(allo)n(w)n(ed)f(to)g(ha)n(v)n(e)g(more)g(than)h(25600)d +(c)n(hildren,)j(w)n(e)g(could)f(represen)n(t)g(the)h(coun)n(ters)118 +1241 y(alw)n(a)n(ys)36 b(with)i(2)f(digits.)67 b(The)38 +b(no)r(de)f(whic)n(h)h(w)n(as)f(previously)f('/23/27/1/4')d(is)k(no)n +(w)g('23270104'.)64 b(If)38 b(w)n(e)f(require)118 1340 +y(a)g(three)g(digit)h(represen)n(tation)d(of)i(no)r(des)g(\(up)h(to)f +(ab)r(out)h(4)f(million)g(c)n(hildren\),)j(then)d(it)h(will)g(b)r(e)f +(represen)n(ted)f(as)118 1440 y('023027001004'.)118 1672 +y Fm(2.4)112 b(Ordering)37 b(of)h(no)s(des)118 1825 y +Fh(F)-7 b(or)35 b(some)g(applications)g(it)h(is)f(necessary)f(to)i +(obtain)f(subtrees)g(ordered)f(according)g(to)i(some)f(sp)r(ecial)g +(rules.)60 b(F)-7 b(or)118 1925 y(instance:)220 2090 +y(1.)41 b(the)34 b(complete)g(subtree)f(starting)g(at)h(a)f(no)r(de)h +(is)g(listed)g(immediately)g(after)f(the)i(no)r(de)f(in)g(question)f +(\(\020depth)326 2189 y(\034rst\021\))220 2354 y(2.)41 +b(no)r(des)27 b(with)h(a)f(common)g(paren)n(t)g(are)g(listed)g(c)n +(hronologically)243 2519 y(F)-7 b(or)39 b(instance,)k(the)d(displa)n(y) +f(of)h(an)f(organization)f(c)n(hart)h(is)g(usually)h(required)e(to)i +(satisfy)g(at)f(least)h(the)g(\034rst)118 2619 y(condition.)h(In)29 +b(a)g(threaded)f(discussion)h(group)e(one)i(wishes)g(to)f(satisfy)h(b)r +(oth)h(conditions)e(to)h(displa)n(y)f(the)h(messages)118 +2718 y(in)20 b(a)g(thread)g(\025)f(the)i(threads)e(themselv)n(es)h +(\(i.e.,)i(c)n(hildren)e(of)g(the)g(ro)r(ot)f(no)r(de\))i(are)e +(usually)g(listed)i(in)f(in)n(v)n(erse)f(c)n(hronolical)118 +2818 y(order.)243 2917 y(T)-7 b(o)35 b(mak)n(e)f(a)h(particular)f +(ordering)g(e\036cien)n(t,)j(it)f(w)n(ould)f(b)r(e)h(a)f(nice)g +(feature)g(if)h(it)g(could)f(b)r(e)h(made)f(to)g(coincide)118 +3017 y(with)28 b(a)f(lexicographic)f(ordering)f(of)j(the)g(indices)f +(\025i.e.,)g(as)g(pro)r(duced)g(b)n(y)h(an)f(\020ORDER)h(BY)f(id)h +(ASC\021)35 b(in)27 b(SQL.)h(The)118 3117 y(lexicographic)d(ordering)h +(of)h(fgID)h(satis\034es)e(b)r(oth)i(conditions.)36 b(The)27 +b(lexicographic)f(ordering)f(of)i(vgID)g(as)g(describ)r(ed)118 +3216 y(ab)r(o)n(v)n(e)34 b(satis\034es)g(the)h(\034rst)g(requisite)f +(if)i(the)f(separator)d(has)j(the)g(minimal)g(binary)g(represen)n +(tation)e(of)i(all)f(allo)n(w)n(ed)118 3316 y(sym)n(b)r(ols)c(in)h(an)f +(index)h(\025)f(this)h(is)g(wh)n(y)f(w)n(e)g(reserv)n(ed)f(/)h(for)g +(the)i(separator.)43 b(But)31 b(the)g(second)f(prop)r(ert)n(y)g(is)g +(missing:)118 3416 y(for)d(instance,)g(the)h(index)g('/1/10')d(is)j +(lexicographically)d(b)r(efore)i('/1/2'.)243 3515 y(If)c(the)h(second)e +(prop)r(ert)n(y)g(is)i(also)e(required)g(for)h(vgID,)g(w)n(e)f(can)h +(sp)r(ecify)h(the)f(c)n(hild)h(iden)n(ti\034ers)e(with)i(coun)n(ters)e +(built)118 3615 y(in)28 b(the)g(follo)n(wing)e(w)n(a)n(y:)36 +b(represen)n(t)26 b(a)h(n)n(um)n(b)r(er)h(b)n(y)f(a)g(string)g(of)g +(digits,)h(where)243 3779 y Ff(\017)41 b Fh(the)25 b(\034rst)g(digit)h +Fc(D)896 3791 y Fb(0)958 3779 y Fh(represen)n(ts)e(the)i(length)f(in)h +(digits)f(of)g(the)h(decimal)f(expansion)f(of)i(the)f(n)n(um)n(b)r(er,) +h(min)n(us)f(one)243 3945 y Ff(\017)41 b Fh(the)28 b(follo)n(wing)e +Fa(\()p Fc(D)920 3957 y Fb(0)976 3945 y Fa(+)18 b(1\))27 +b Fh(digits)h(are)e(the)i(decimal)g(expansion)e(of)i(the)g(n)n(um)n(b)r +(er)118 4109 y(Let)g(us)f(call)h(these)f(iden)n(ti\034ers)g +Fg(m-vgID)p Fh(,)g(\020m\021)34 b(for)27 b(mo)r(di\034ed.)243 +4209 y(As)e(an)f(example,)h(the)g(no)r(de)g(whic)n(h)g(w)n(as)f +(previously)f(represen)n(ted)h(b)n(y)g(/15/3/182)d(will,)k(after)g +(this)g(mo)r(di\034cation,)118 4309 y(ha)n(v)n(e)h(the)i(index)g +(/115/03/2182.)243 4408 y(The)37 b(lexicographic)f(ordering)g(of)i +(m-vgID)f(is)h(the)g(desired)f(ordering)f(of)h(the)h(tree)g(no)r(des.) +67 b(The)38 b(cost)f(of)g(this)118 4508 y(prop)r(ert)n(y)31 +b(is)i(that)f(\(a\))h(the)g(ID)f(are)g(no)n(w)g(longer,)g(\(b\))h(no)f +(no)r(de)g(can)g(ha)n(v)n(e)g(more)f(than)i Fa(160)3106 +4478 y Fb(160)3240 4508 y Fh(c)n(hildren)f(\(actually)-7 +b(,)118 4607 y(this)32 b(is)g(a)f(non-issue\),)h(and)f(\(c\))h(the)g +(index)g(structure)f(is)h(redundan)n(t,)g(some)f(formally)f(correct)h +(indices)g(are)g(in)n(v)-5 b(alid)118 4707 y(\025e.g.,)24 +b(/316/013/11.)30 b(The)24 b(third)g(issue)g(can)g(b)r(e)g(addressed)f +(b)n(y)g(k)n(eeping)g(a)h(strict)g(con)n(trol)e(on)i(the)g(generation)f +(of)h(new)118 4807 y(indices)k(to)f(insure)g(that)h(all)f(indices)h +(are)e(formally)h(correct.)243 4906 y(The)32 b(issue)f(of)h(the)g(rev)n +(erse)e(c)n(hronological)f(indexing)j(of)f(threads)h(in)g(threaded)f +(discussion)g(groups)g(can)g(b)r(e)h(ad-)118 5006 y(dressed)d(easily)f +(enough)h(in)h(fgID:)f(coun)n(t)g(\020do)n(wn\021)36 +b(instead)29 b(of)g(\020up\021)36 b(the)30 b(c)n(hildren)f(of)g(the)h +(ro)r(ot)e(no)r(de)i(\025)f(this)h(implies)118 5106 y(only)e(an)g +(inconsequen)n(tial)f(mo)r(di\034cation)h(of)g(the)g(no)r(de)h +(insertion)e(routine,)h(as)g(sho)n(wn)f(b)r(elo)n(w.)38 +b(The)29 b(problem)e(is)h(less)118 5205 y(trivial)i(with)g(vgID;)h(in)f +(this)h(case,)f(ma)n(yb)r(e)f(a)h(thread)g(iden)n(ti\034er)g(should)g +(b)r(e)h(k)n(ept)f(in)g(a)g(di\033eren)n(t)g(\034eld)h(-)f(i.e.,)h +(repre-)118 5305 y(sen)n(ting)h(the)h(structure)f(as)g(a)h(forest)f +(rather)f(than)i(a)f(tree,)i(where)e(the)h(thread_id)f(\034eld)h +(selects)f(the)h(\020tree\021)38 b(in)33 b(the)118 5404 +y(forest.)1987 5653 y(3)p eop +%%Page: 4 4 +4 3 bop 118 291 a Fi(3)131 b(T)-11 b(ree)45 b(op)t(erations)e(using)h +(genealogical)g(indices)118 472 y Fh(In)32 b(this)f(section)g(w)n(e)g +(sho)n(w)g(ho)n(w)g(to)g(implemen)n(t)h(v)-5 b(arious)30 +b(tree)h(op)r(erations)f(using)h(gID)g(as)g(the)h(primary)e(k)n(ey)h +(in)g(the)118 572 y(no)r(de)d(table.)243 672 y(Some)h(implemen)n +(tation)h(issues)g(are)f(relev)-5 b(an)n(t)29 b(here,)h(esp)r(ecially)f +(concerning)g(the)h(utilisation)g(of)g(indices)g(b)n(y)f(the)118 +771 y(DB)f(engine.)243 871 y(W)-7 b(e)28 b(discuss)f(a)g(tree)g +(represen)n(ted)f(in)i(a)f(table)h(of)f(the)h(form)326 +1034 y Fd(CREATE)41 b(TABLE)g(tree)h(\()456 1134 y(gid)304 +b(text)42 b(PRIMARY)f(KEY,)456 1234 y(nchildren)f(integer)h(DEFAULT)f +(0,)456 1333 y(\\ldots)h(the)i(actual)e(node)h(data)326 +1433 y(\);)118 1597 y Fh(The)26 b(\034eld)g(\020nc)n(hildren\021)32 +b(is)26 b(a)f(coun)n(ter)g(for)g(the)i(n)n(um)n(b)r(er)e(of)h(c)n +(hildren)f(that)h(the)h(no)r(de)f(has)f Fe(ever)35 b +Fh(had;)27 b(w)n(e)e(assume)g(here)118 1696 y(it)j(is)g(not)f(up)r +(dated)h(when)g(no)r(des)f(or)g(subtrees)g(are)f(deleted.)243 +1796 y(Section)h(4)g(pro)n(vides)f(a)i(complete)f(implemen)n(tation)h +(of)f(these)h(op)r(erations)e(for)h(fgID)h(in)g(P)n(ostgreSQL.)118 +2028 y Fm(3.1)112 b(Computing)37 b(the)g(lev)m(el)f(of)h(a)h(no)s(de) +118 2181 y Fg(Cost:)f Fe(string)30 b(op)l(er)l(ations)g(\(no)g(table)g +(ac)l(c)l(ess\))243 2280 y Fh(This)d(is)h(a)f(pure)g(string)g(op)r +(eration,)f(no)i(table)f(access)g(is)g(required.)243 +2460 y Ff(\017)41 b Fg(vgID:)27 b Fh(coun)n(t)h(the)g(n)n(um)n(b)r(er)f +(of)g(separators)e(\('/'\))j(in)g(the)g(PK)243 2625 y +Ff(\017)41 b Fg(fgID:)27 b Fh(coun)n(t)g(the)h(n)n(um)n(b)r(er)g(of)f +(c)n(haracters)e(in)j(the)g(PK,)g(divide)g(b)n(y)f(the)h(\034xed)f +(size)h(of)f(the)h(coun)n(ters.)118 2857 y Fm(3.2)112 +b(Selecting)36 b(or)h(deleting)f(a)i(subtree)118 3010 +y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l(e)l(e)243 +3173 y Ff(\017)41 b Fg(vgID:)27 b Fh(The)h(subtree)f(ro)r(oted)g(at)g +(/26/5/7)e(is)i(selected)g(b)n(y)508 3338 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('/26/5/7\045')d(AND)j(id)h(<)g('/26/5/70')243 +3503 y Ff(\017)e Fg(m-vgID:)26 b Fh(The)h(subtree)h(ro)r(oted)e(at)i +(/126/05/07)22 b(is)28 b(selected)f(b)n(y)508 3668 y +Fd(...)43 b(WHERE)e(id)i(LIKE)f('/126/06/07\045')243 +3833 y Ff(\017)f Fg(fgID:)27 b Fh(The)h(subtree)f(ro)r(oted)g(at)g +(260507)e(is)i(selected)h(b)n(y)508 3997 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('260507\045')118 4229 y Fm(3.3)112 +b(Selecting)36 b(the)h(direct)f(c)m(hildren)g(of)i(a)g(no)s(de)118 +4382 y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l(e)l(e)243 +4562 y Ff(\017)41 b Fg(vgID:)27 b Fh(The)h(direct)f(c)n(hildren)g(of)h +(/26/5/7)c(are)j(selected)g(b)n(y)508 4727 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('/26/5/7/\045')d(AND)j(id)h(NOT)f(LIKE)g +('26/5/7/\045/\045')243 4892 y Ff(\017)f Fg(m-vgID:)26 +b Fh(The)h(direct)h(c)n(hildren)f(of)g(/26/5/7)e(are)h(selected)i(b)n +(y)508 5056 y Fd(...)43 b(WHERE)e(id)i(LIKE)f('/126/06/07/\045')37 +b(AND)43 b(id)f(NOT)h(LIKE)f('/126/05/07/\045/\045)o(')243 +5221 y Ff(\017)f Fg(fgID:)27 b Fh(The)h(direct)f(c)n(hildren)g(of)h +(260507)c(are)j(selected)g(b)n(y)508 5386 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('260507\045')d(AND)k(char_length\(id\))37 +b(=)43 b(\(char_length\('26)o(05)o(07')o(\)+)o(2\))1987 +5653 y Fh(4)p eop +%%Page: 5 5 +5 4 bop 118 291 a Fm(3.4)112 b(Inserting)37 b(a)h(no)s(de)g(or)f(a)h +(subtree)118 444 y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l +(e)l(e)f(+)h(string)f(and)h(math)g(op)l(er)l(ations)243 +543 y Fh(Insertion)f(is)g(a)h(pro)r(cedural)e(op)r(eration.)42 +b(As)30 b(eac)n(h)f(RDBMS)h(has)f(a)h(di\033eren)n(t)f(w)n(a)n(y)g(of)g +(de\034ning)h(pro)r(cedures,)f(w)n(e)118 643 y(will)f(just)g(describ)r +(e)f(here)g(the)h(necessary)e(steps.)37 b(Examples)27 +b(for)g(P)n(ostgreSQL)f(are)h(pro)n(vided)f(in)i(4.)243 +743 y(In)22 b(order)f(to)h(insert)g(a)g(new)g(c)n(hild)h(of)f +(\020daddy\021)28 b(\(either)23 b(one)f(of)g(/26/5/7,)e(/126/05/07)d +(or)22 b(260507)d(in)k(the)f(examples)118 842 y(ab)r(o)n(v)n(e\))27 +b(y)n(ou)f(ha)n(v)n(e)h(to)220 1008 y(1.)41 b(add)27 +b(one)g(to)h(the)g(n)n(um)n(b)r(er)f(of)g(c)n(hildren)h(of)f +(\020daddy\021)508 1174 y Fd(UPDATE)41 b(tree)h(SET)h(nchildren)c(=)k +(\(nchildren)d(+)j(1\))g(WHERE)e(ID)i(=)g(``daddy'';)220 +1340 y Fh(2.)e(enco)r(de)27 b(the)h(n)n(um)n(b)r(er)f(of)g(c)n(hildren) +g(of)h(\020daddy\021)33 b(in)28 b(base)f(160,)f(bring)h(it)h(to)f(the)h +(correct)e(format)h(dep)r(ending)h(on)326 1440 y(the)c(v)-5 +b(arian)n(t)23 b(of)h(gID)g(\(pad)g(with)h(0)e(or)g(not,)i(prep)r(end)f +(a)g(digit)g(coun)n(ter)f(or)g(not,)i(prep)r(end)f(/)g(or)f(not,)i +(coun)n(t)e(do)n(wn)326 1540 y(or)j(up,)i(.)14 b(.)g(.)g(\))37 +b(and)28 b(app)r(end)f(it)h(to)g(daddy's)f(gID)g(to)h(obtain)f(the)h +(new)g(no)r(de's)f(gID.)220 1706 y(3.)41 b(insert)27 +b(the)h(new)f(no)r(de)243 1872 y(When)35 b(inserting)g(a)f(subtree,)j +(the)e(index)g(of)g(the)h(ro)r(ot)e(of)h(the)g(subtree)g(has)f(to)h(b)r +(e)h(computed)f(as)f(ab)r(o)n(v)n(e,)i(and)118 1971 y(prep)r(ended)28 +b(to)f(the)h(index)g(of)f(eac)n(h)g(no)r(de)h(of)f(the)h(subtree)f(b)r +(efore)h(insertion.)243 2071 y(Remark)e(that)i(only)f(the)h(paren)n(t)f +(no)r(de)h(has)f(to)g(b)r(e)h(up)r(dated)g(on)f(insertion.)118 +2303 y Fm(3.5)112 b(Selecting)36 b(the)h(ancestors)h(of)g(a)g(no)s(de) +118 2457 y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l(e)l(e)243 +2556 y Fh(Y)-7 b(ou)27 b(can)g(sp)r(ecify)h(all)g(ancestors)d(of)j(a)f +(no)r(de)h(in)f(a)h(single)f(SQL)g(statemen)n(t;)g(for)g(instance)h +(for)f(vgID)326 2722 y Fd(...)42 b(WHERE)f('/25/6/7')f(LIKE)i(\(id)g +(||)h('/\045'\))f(AND)g(id)h(<)g('/25/6/7')118 2888 y +Fh(The)31 b(second)e(part)h(of)h(the)g(clause,)f(while)h(logically)e +(redundan)n(t,)h(is)h(a)f(\020hin)n(t\021)37 b(to)30 +b(the)h(optimizer.)45 b(A)n(t)31 b(least)f(in)g(P)n(ost-)118 +2988 y(greSQL,)c(without)i(it)g(the)g(optimizer)f(will)h(c)n(ho)r(ose)e +(a)i(sequen)n(tial)e(scan)h(of)h(the)g(table)f(and)h(disregard)d(the)j +(index.)118 3220 y Fm(3.6)112 b(Selecting)36 b(all)g(lea)m(v)m(es)118 +3374 y Fg(Cost:)h Fe(sc)l(an)30 b(of)g(the)g(tr)l(e)l(e)243 +3473 y Fh(A)e(leaf)f(is)g(a)h(no)r(de)f(without)h(descendan)n(ts:)36 +b(it)28 b(has)f(0)g(c)n(hildren.)37 b(Hence)326 3639 +y Fd(...)42 b(WHERE)f(nchildren)f(=)j(0)118 3805 y Fh(If)28 +b(this)g(t)n(yp)r(e)g(of)f(query)g(is)h(often)f(necessary)-7 +b(,)26 b(y)n(ou)h(ma)n(y)g(b)r(e)h(w)n(ell)f(advised)g(to)g(k)n(eep)g +(an)h(index)f(on)h(tree\(nc)n(hildren\).)118 4038 y Fm(3.7)112 +b(Determining)35 b(if)i(A)g(is)g(a)h(descendan)m(t)g(of)g(B)118 +4191 y Fg(Cost:)f Fe(string)30 b(op)l(er)l(ations,)h(no)f(table)g(ac)l +(c)l(ess)243 4291 y Fh(This)d(is)h(a)f(pure)g(string)g(op)r(eration)f +(on)i(the)g(indices,)f(no)g(table)h(access)e(is)i(necessary)-7 +b(.)118 4565 y Fi(4)131 b(Putting)45 b(it)f(all)h(together:)57 +b(a)44 b(P)l(ostgreSQL)f(implemen)l(tation)118 4747 y +Fh(h)n(ttp://www.p)r(ostgresql.org/mhonarc/pgsq)o(l-sql/)o(20)o(00)o +(-0)o(4/)o(msg0)o(02)o(67)o(.h)n(tml)243 4847 y(W)-7 +b(e)30 b(describ)r(e)g(here)g(a)g(small)f(pac)n(k)-5 +b(age)29 b(that)i(can)e(b)r(e)i(used)f(for)g(implemen)n(ting)g(gID)g +(on)g(P)n(ostgreSQL.)f(It)i(can)e(b)r(e)118 4946 y(found)f(at)f()243 5046 y(The)21 b(pac)n(k)-5 b(age)21 b(uses)g(the)h(pro) +r(cedural)e(language)h(PL/PGsql.)35 b(A)22 b(b)r(etter)g(implemen)n +(tation)g(w)n(ould)f(probably)g(de\034ne)118 5145 y(the)28 +b(gID)g(as)f(new)g(P)n(ostgres)f(t)n(yp)r(es,)i(and)f(co)r(de)g(all)h +(this)g(in)f(C.)243 5245 y(The)g(\034les)h(should)f(b)r(e)h(loaded)f +(in)h(alphab)r(etical)f(order.)1987 5653 y(5)p eop +%%Page: 6 6 +6 5 bop 118 291 a Fm(4.1)112 b(tree0_enco)s(ding.sql)118 +444 y Fh(This)28 b(\034le)f(de\034nes)h(and)f(p)r(opulates)h(the)f +(table)h(_b160_digits)d(of)j(\020digits\021)33 b(in)28 +b(base)f(160,)326 604 y Fd(CREATE)41 b(TABLE)g(\\_b160\\_digits)d +(\(deci)j(integer,)f(code)i(char\);)118 764 y Fh(and)28 +b(the)f(t)n(w)n(o)g(functions)326 924 y Fd(CREATE)41 +b(FUNCTION)f(\\_b160\\_encode\(i)o(nt)o(eg)o(er\))d(RETURNS)j(string) +413 1024 y(AS)j('....')e(LANGUAGE)f('plpgsql';)326 1124 +y(CREATE)h(FUNCTION)f(\\_b160\\_encode\(i)o(nt)o(eg)o(er,)o(in)o(te)o +(ger)o(\))d(RETURNS)k(string)413 1223 y(AS)i('....')e(LANGUAGE)f +('plpgsql';)118 1384 y Fh(The)22 b(\034rst)h(function)f(returns)g(a)g +(v)-5 b(ariable)21 b(size)h(enco)r(ding;)i(the)f(second)e(a)h(\034xed)h +(size)f(enco)r(ding)g(\(the)h(second)e(parameter)118 +1483 y(is)g(the)h(size\),)g(and)f(raises)e(an)i(exception)g(if)h(the)f +(n)n(um)n(b)r(er)g(is)g(to)r(o)g(large)e(to)i(b)r(e)h(represen)n(ted)e +(with)h(the)h(requested)e(n)n(um)n(b)r(er)118 1583 y(of)28 +b(digits.)118 1814 y Fm(4.2)112 b(tree1_de\034ne.sql)118 +1967 y Fh(This)28 b(\034le)f(pro)n(vides)f(a)i(function)326 +2127 y Fd(CREATE)41 b(FUNCTION)f(_tree_create\(tex)o(t,)o(in)o(teg)o +(er)o(,t)o(ext)o(,t)o(ex)o(t\))d(RETURNS)k(bpchar)413 +2227 y(AS)i('....')e(LANGUAGE)f('plpgsql';)118 2387 y +Fh(that)e(creates)f(a)h(tree)f(infrastructure)g(of)h(either)g(fgID)g +(or)f(vgID.)h(Assuming)f(y)n(ou)g(ha)n(v)n(e)g(a)h(table)f(\020m)n +(ytable\021)44 b(with)118 2487 y(primary)26 b(k)n(ey)h(\020m)n +(yid\021,)g(then)h(calling)326 2647 y Fd(SELECT)41 b(_tree_create\('m)o +(yt)o(ree)o(',)o(2,')o(my)o(ta)o(ble)o(',)o('m)o(yid)o('\))o(;)118 +2807 y Fh(will)28 b(cause:)220 2967 y(1.)41 b(the)28 +b(creation)e(of)i(a)f(table)508 3131 y Fd(CREATE)41 b(TABLE)h +(mytree_bkg\()683 3230 y(gid)g(text)g(PRIMARY)e(KEY,)683 +3330 y(nchildren)f(int,)683 3429 y(sid)j(integer)f(REFERENCES)e +(mytable\(myid\))508 3529 y(\);)508 3629 y(CREATE)i(UNIQUE)g(INDEX)h +(mytree_bkg_sid)37 b(ON)43 b(mytree_bkg\(sid\);)326 3792 +y Fh(for)27 b(the)h(tree)f(structure.)220 3955 y(2.)41 +b(the)28 b(creation)e(of)i(a)f(view)508 4118 y Fd(CREATE)41 +b(VIEW)h(mytree)f(AS)639 4218 y(SELECT)g(t.gid,n.*)900 +4317 y(FROM)h(mytable)f(n,)i(mytree_bkg)c(t)900 4417 +y(WHERE)j(t.sid=n.myid;)326 4580 y Fh(with:)35 b(a)23 +b(trigger)e(on)i(UPD)n(A)-7 b(TE)25 b(that)e(blo)r(c)n(ks)g(up)r +(dating)g(the)h(gid)f(and)g(allo)n(ws)f(up)r(dating)h(the)g(no)r(de)h +(data,)f(a)g(rule)326 4680 y(on)k(DELETE)i(that)f(deletes)f(the)h +(corresp)r(onding)e(en)n(try)h(b)r(oth)h(in)g(m)n(ytree_bkg)d(and)j(m)n +(ytable,)f(and)g(a)g(trigger)326 4779 y(ON)h(INSER)-7 +b(T)30 b(that)f(raises)e(an)h(exception)g(and)g(informs)h(the)f(user)g +(to)h(use)f(the)h(insertion)f(function)h(describ)r(ed)326 +4879 y(b)r(elo)n(w.)220 5042 y(3.)41 b(t)n(w)n(o)26 b(insertion)h +(functions)h(that)g(compute)g(automatically)e(the)i(gID)g(of)f(the)h +(new)g(no)r(de:)425 5205 y Ff(\017)41 b Fh(a)27 b(function)i(m)n +(ytree_insert\(text,text,in)n(teger,text\))d(for)h(insertion)g(sim)n +(ultaneosly)f(in)i(b)r(oth)g(tables:)508 5305 y(m)n +(ytree_insert\('2201','hello',0,'not)15 b(m)n(uc)n(h'\))j(inserts)g(a)g +(new)g(c)n(hild)h(of)f(2201)f(with)h(data1='hello',)h(data2=0)508 +5404 y(and)28 b(data3='not)e(m)n(uc)n(h')1987 5653 y(6)p +eop +%%Page: 7 7 +7 6 bop 425 291 a Ff(\017)41 b Fh(a)27 b(function)i(m)n +(ytree_insert_no)r(de\(text,in)n(teger\))c(for)i(insertion)g(in)h(m)n +(ytree_bkg)508 390 y(m)n(ytree_insert\('2201',25\))c(inserts)j(in)h(m)n +(ytree_bkg)e(a)h(new)h(c)n(hild)f(of)h(2201)d(with)j(sid=25)220 +556 y(4.)41 b(a)27 b(function)h(m)n(ytree_mo)n(v)n(e\(text,text\))e +(that)i(mo)n(v)n(es)e(subtrees:)326 656 y(m)n(ytree_mo)n(v)n +(e\('2201','23'\))d(mo)n(v)n(es)j(the)i(subtree)f(ro)r(oted)g(at)g +(2201)f(to)h(a)h(place)f(b)r(elo)n(w)g(23)f(\(ma)n(yb)r(e)i(2307\))220 +822 y(5.)41 b(a)c(function)g(m)n(ytree_len\(\))g(that)h(returns)e(the)i +(length)f(of)g(the)h(enco)r(dings)f(used)g(in)h(the)f(gID)g(\(2)h +(here;)j(0)c(if)326 922 y(v)-5 b(ariable)26 b(size\).)118 +1196 y Fi(5)131 b(Non-tree)44 b(hierarc)l(hies)118 1378 +y Fh(sequence)22 b(as)f(id,)j(table)e(with)h(\(id,g-index\))f(with)g(p) +r(ossibly)g(man)n(y)g(g-indices)f(for)h(eac)n(h)f(id)h(\(if)h(TOO)f +(man)n(y)-7 b(,)23 b(bad)f(mo)r(del:)118 1478 y(list)28 +b(all)f(genealogies,)f(i.e.,)h(paths)h(from)f(the)h(ro)r(ot\))118 +1752 y Fi(References)160 1934 y Fh([1])41 b(Philip)28 +b(Greenspun,)g Fe(T)-6 b(r)l(e)l(es)29 b(in)h(Or)l(acle)g(SQL)p +Fh(,)d(in)h Fg(SQL)k(for)g(W)-8 b(eb)31 b(Nerds)289 2033 +y Fh()160 2200 +y([2])41 b(Jo)r(e)27 b(Celk)n(o,)f Fe(SQL)j(for)i(Smarties)p +Fh(,)d(in)g Fg(DBMS)j(Online)p Fh(,)26 b(Marc)n(h)h(to)g(June)h(1996) +289 2299 y()289 +2399 y()289 +2498 y()289 +2598 y()160 +2764 y([3])41 b(Graeme)26 b(Birc)n(hall,)h Fg(DB2)32 +b(UDB)g(V6.1)f(SQL)h(Co)s(okb)s(o)s(ok)p Fh(,)289 2864 +y()1987 5653 +y(7)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/ldb-2.0.8/ldb_tdb/ldb_tdb.c b/ldb-2.0.8/ldb_tdb/ldb_tdb.c new file mode 100644 index 0000000..77cd5e9 --- /dev/null +++ b/ldb-2.0.8/ldb_tdb/ldb_tdb.c @@ -0,0 +1,593 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2006-2008 + Copyright (C) Matthias Dieter Wallnöfer 2009-2010 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb_tdb + * + * Component: ldb tdb backend + * + * Description: core functions for tdb backend + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + * + * Modifications: + * + * - description: make the module use asynchronous calls + * date: Feb 2006 + * Author: Simo Sorce + * + * - description: make it possible to use event contexts + * date: Jan 2008 + * Author: Simo Sorce + * + * - description: fix up memory leaks and small bugs + * date: Oct 2009 + * Author: Matthias Dieter Wallnöfer + */ + +#include "ldb_tdb.h" +#include "ldb_private.h" +#include "../ldb_key_value/ldb_kv.h" +#include + +/* + lock the database for read - use by ltdb_search and ltdb_sequence_number +*/ +static int ltdb_lock_read(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + int tdb_ret = 0; + int ret; + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + + if (tdb_transaction_active(ldb_kv->tdb) == false && + ldb_kv->read_lock_count == 0) { + tdb_ret = tdb_lockall_read(ldb_kv->tdb); + } + if (tdb_ret == 0) { + ldb_kv->read_lock_count++; + return LDB_SUCCESS; + } + ret = ltdb_err_map(tdb_error(ldb_kv->tdb)); + if (ret == LDB_SUCCESS) { + ret = LDB_ERR_OPERATIONS_ERROR; + } + ldb_debug_set(ldb_module_get_ctx(module), + LDB_DEBUG_FATAL, + "Failure during ltdb_lock_read(): %s -> %s", + tdb_errorstr(ldb_kv->tdb), + ldb_strerror(ret)); + return ret; +} + +/* + unlock the database after a ltdb_lock_read() +*/ +static int ltdb_unlock_read(struct ldb_module *module) +{ + void *data = ldb_module_get_private(module); + struct ldb_kv_private *ldb_kv = + talloc_get_type(data, struct ldb_kv_private); + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + if (!tdb_transaction_active(ldb_kv->tdb) && + ldb_kv->read_lock_count == 1) { + tdb_unlockall_read(ldb_kv->tdb); + ldb_kv->read_lock_count--; + return 0; + } + ldb_kv->read_lock_count--; + return 0; +} + +static int ltdb_store(struct ldb_kv_private *ldb_kv, + struct ldb_val ldb_key, + struct ldb_val ldb_data, + int flags) +{ + TDB_DATA key = { + .dptr = ldb_key.data, + .dsize = ldb_key.length + }; + TDB_DATA data = { + .dptr = ldb_data.data, + .dsize = ldb_data.length + }; + bool transaction_active = tdb_transaction_active(ldb_kv->tdb); + if (transaction_active == false){ + return LDB_ERR_PROTOCOL_ERROR; + } + return tdb_store(ldb_kv->tdb, key, data, flags); +} + +static int ltdb_error(struct ldb_kv_private *ldb_kv) +{ + return ltdb_err_map(tdb_error(ldb_kv->tdb)); +} + +static const char *ltdb_errorstr(struct ldb_kv_private *ldb_kv) +{ + return tdb_errorstr(ldb_kv->tdb); +} + +static int ltdb_delete(struct ldb_kv_private *ldb_kv, struct ldb_val ldb_key) +{ + TDB_DATA tdb_key = { + .dptr = ldb_key.data, + .dsize = ldb_key.length + }; + bool transaction_active = tdb_transaction_active(ldb_kv->tdb); + if (transaction_active == false){ + return LDB_ERR_PROTOCOL_ERROR; + } + return tdb_delete(ldb_kv->tdb, tdb_key); +} + +static int ltdb_transaction_start(struct ldb_kv_private *ldb_kv) +{ + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(ldb_kv->module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + + return tdb_transaction_start(ldb_kv->tdb); +} + +static int ltdb_transaction_cancel(struct ldb_kv_private *ldb_kv) +{ + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(ldb_kv->module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + + return tdb_transaction_cancel(ldb_kv->tdb); +} + +static int ltdb_transaction_prepare_commit(struct ldb_kv_private *ldb_kv) +{ + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(ldb_kv->module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + + return tdb_transaction_prepare_commit(ldb_kv->tdb); +} + +static int ltdb_transaction_commit(struct ldb_kv_private *ldb_kv) +{ + pid_t pid = getpid(); + + if (ldb_kv->pid != pid) { + ldb_asprintf_errstring(ldb_module_get_ctx(ldb_kv->module), + __location__ + ": Reusing ldb opend by pid %d in " + "process %d\n", + ldb_kv->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + + return tdb_transaction_commit(ldb_kv->tdb); +} +struct kv_ctx { + ldb_kv_traverse_fn kv_traverse_fn; + void *ctx; + struct ldb_kv_private *ldb_kv; + int (*parser)(struct ldb_val key, + struct ldb_val data, + void *private_data); + int parser_ret; +}; + +static int ltdb_traverse_fn_wrapper(struct tdb_context *tdb, + TDB_DATA tdb_key, + TDB_DATA tdb_data, + void *ctx) +{ + struct kv_ctx *kv_ctx = ctx; + struct ldb_val key = { + .length = tdb_key.dsize, + .data = tdb_key.dptr, + }; + struct ldb_val data = { + .length = tdb_data.dsize, + .data = tdb_data.dptr, + }; + return kv_ctx->kv_traverse_fn(kv_ctx->ldb_kv, key, data, kv_ctx->ctx); +} + +static int ltdb_traverse_fn(struct ldb_kv_private *ldb_kv, + ldb_kv_traverse_fn fn, + void *ctx) +{ + struct kv_ctx kv_ctx = { + .kv_traverse_fn = fn, .ctx = ctx, .ldb_kv = ldb_kv}; + if (tdb_transaction_active(ldb_kv->tdb)) { + return tdb_traverse( + ldb_kv->tdb, ltdb_traverse_fn_wrapper, &kv_ctx); + } else { + return tdb_traverse_read( + ldb_kv->tdb, ltdb_traverse_fn_wrapper, &kv_ctx); + } +} + +static int ltdb_update_in_iterate(struct ldb_kv_private *ldb_kv, + struct ldb_val ldb_key, + struct ldb_val ldb_key2, + struct ldb_val ldb_data, + void *state) +{ + int tdb_ret; + struct ldb_context *ldb; + struct ldb_kv_reindex_context *ctx = + (struct ldb_kv_reindex_context *)state; + struct ldb_module *module = ldb_kv->module; + TDB_DATA key = { + .dptr = ldb_key.data, + .dsize = ldb_key.length + }; + TDB_DATA key2 = { + .dptr = ldb_key2.data, + .dsize = ldb_key2.length + }; + TDB_DATA data = { + .dptr = ldb_data.data, + .dsize = ldb_data.length + }; + + ldb = ldb_module_get_ctx(module); + + tdb_ret = tdb_delete(ldb_kv->tdb, key); + if (tdb_ret != 0) { + ldb_debug(ldb, + LDB_DEBUG_ERROR, + "Failed to delete %*.*s " + "for rekey as %*.*s: %s", + (int)key.dsize, + (int)key.dsize, + (const char *)key.dptr, + (int)key2.dsize, + (int)key2.dsize, + (const char *)key.dptr, + tdb_errorstr(ldb_kv->tdb)); + ctx->error = ltdb_err_map(tdb_error(ldb_kv->tdb)); + return -1; + } + tdb_ret = tdb_store(ldb_kv->tdb, key2, data, 0); + if (tdb_ret != 0) { + ldb_debug(ldb, + LDB_DEBUG_ERROR, + "Failed to rekey %*.*s as %*.*s: %s", + (int)key.dsize, + (int)key.dsize, + (const char *)key.dptr, + (int)key2.dsize, + (int)key2.dsize, + (const char *)key.dptr, + tdb_errorstr(ldb_kv->tdb)); + ctx->error = ltdb_err_map(tdb_error(ldb_kv->tdb)); + return -1; + } + return tdb_ret; +} + +static int ltdb_parse_record_wrapper(TDB_DATA tdb_key, + TDB_DATA tdb_data, + void *ctx) +{ + struct kv_ctx *kv_ctx = ctx; + struct ldb_val key = { + .length = tdb_key.dsize, + .data = tdb_key.dptr, + }; + struct ldb_val data = { + .length = tdb_data.dsize, + .data = tdb_data.dptr, + }; + + kv_ctx->parser_ret = kv_ctx->parser(key, data, kv_ctx->ctx); + return kv_ctx->parser_ret; +} + +static int ltdb_parse_record(struct ldb_kv_private *ldb_kv, + struct ldb_val ldb_key, + int (*parser)(struct ldb_val key, + struct ldb_val data, + void *private_data), + void *ctx) +{ + struct kv_ctx kv_ctx = {.parser = parser, .ctx = ctx, .ldb_kv = ldb_kv}; + TDB_DATA key = { + .dptr = ldb_key.data, + .dsize = ldb_key.length + }; + int ret; + + if (tdb_transaction_active(ldb_kv->tdb) == false && + ldb_kv->read_lock_count == 0) { + return LDB_ERR_PROTOCOL_ERROR; + } + + ret = tdb_parse_record( + ldb_kv->tdb, key, ltdb_parse_record_wrapper, &kv_ctx); + if (kv_ctx.parser_ret != LDB_SUCCESS) { + return kv_ctx.parser_ret; + } else if (ret == 0) { + return LDB_SUCCESS; + } + return ltdb_err_map(tdb_error(ldb_kv->tdb)); +} + +static int ltdb_iterate_range(struct ldb_kv_private *ldb_kv, + struct ldb_val start_key, + struct ldb_val end_key, + ldb_kv_traverse_fn fn, + void *ctx) +{ + /* + * We do not implement this operation because we do not know how to + * iterate from one key to the next (in a sorted fashion). + * + * We could mimic it potentially, but it would violate boundaries of + * knowledge (data type representation). + */ + return LDB_ERR_OPERATIONS_ERROR; +} + +static const char *ltdb_name(struct ldb_kv_private *ldb_kv) +{ + return tdb_name(ldb_kv->tdb); +} + +static bool ltdb_changed(struct ldb_kv_private *ldb_kv) +{ + int seq = tdb_get_seqnum(ldb_kv->tdb); + bool has_changed = (seq != ldb_kv->tdb_seqnum); + + ldb_kv->tdb_seqnum = seq; + + return has_changed; +} + +static bool ltdb_transaction_active(struct ldb_kv_private *ldb_kv) +{ + return tdb_transaction_active(ldb_kv->tdb); +} + +/* + * Get an estimate of the number of records in a tdb database. + * + * This implementation will overestimate the number of records in a sparsely + * populated database. The size estimate is only used for allocating + * an in memory tdb to cache index records during a reindex, overestimating + * the contents is acceptable, and preferable to underestimating + */ +#define RECORD_SIZE 500 +static size_t ltdb_get_size(struct ldb_kv_private *ldb_kv) +{ + size_t map_size = tdb_map_size(ldb_kv->tdb); + size_t size = map_size / RECORD_SIZE; + + return size; +} + +/* + * Start a sub transaction + * As TDB does not currently support nested transactions, we do nothing and + * return LDB_SUCCESS + */ +static int ltdb_nested_transaction_start(struct ldb_kv_private *ldb_kv) +{ + return LDB_SUCCESS; +} + +/* + * Commit a sub transaction + * As TDB does not currently support nested transactions, we do nothing and + * return LDB_SUCCESS + */ +static int ltdb_nested_transaction_commit(struct ldb_kv_private *ldb_kv) +{ + return LDB_SUCCESS; +} + +/* + * Cancel a sub transaction + * As TDB does not currently support nested transactions, we do nothing and + * return LDB_SUCCESS + */ +static int ltdb_nested_transaction_cancel(struct ldb_kv_private *ldb_kv) +{ + return LDB_SUCCESS; +} + +static const struct kv_db_ops key_value_ops = { + /* No support for any additional features */ + .options = 0, + + .store = ltdb_store, + .delete = ltdb_delete, + .iterate = ltdb_traverse_fn, + .update_in_iterate = ltdb_update_in_iterate, + .fetch_and_parse = ltdb_parse_record, + .iterate_range = ltdb_iterate_range, + .lock_read = ltdb_lock_read, + .unlock_read = ltdb_unlock_read, + .begin_write = ltdb_transaction_start, + .prepare_write = ltdb_transaction_prepare_commit, + .finish_write = ltdb_transaction_commit, + .abort_write = ltdb_transaction_cancel, + .error = ltdb_error, + .errorstr = ltdb_errorstr, + .name = ltdb_name, + .has_changed = ltdb_changed, + .transaction_active = ltdb_transaction_active, + .get_size = ltdb_get_size, + .begin_nested_write = ltdb_nested_transaction_start, + .finish_nested_write = ltdb_nested_transaction_commit, + .abort_nested_write = ltdb_nested_transaction_cancel, +}; + +/* + connect to the database +*/ +int ltdb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, const char *options[], + struct ldb_module **_module) +{ + const char *path; + int tdb_flags, open_flags; + struct ldb_kv_private *ldb_kv; + + /* + * We hold locks, so we must use a private event context + * on each returned handle + */ + ldb_set_require_private_event_context(ldb); + + /* parse the url */ + if (strchr(url, ':')) { + if (strncmp(url, "tdb://", 6) != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Invalid tdb URL '%s'", url); + return LDB_ERR_OPERATIONS_ERROR; + } + path = url+6; + } else { + path = url; + } + + tdb_flags = TDB_DEFAULT | TDB_SEQNUM | TDB_DISALLOW_NESTING; + + /* check for the 'nosync' option */ + if (flags & LDB_FLG_NOSYNC) { + tdb_flags |= TDB_NOSYNC; + } + + /* and nommap option */ + if (flags & LDB_FLG_NOMMAP) { + tdb_flags |= TDB_NOMMAP; + } + + ldb_kv = talloc_zero(ldb, struct ldb_kv_private); + if (!ldb_kv) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (flags & LDB_FLG_RDONLY) { + /* + * This is weird, but because we can only have one tdb + * in this process, and the other one could be + * read-write, we can't use the tdb readonly. Plus a + * read only tdb prohibits the all-record lock. + */ + open_flags = O_RDWR; + + ldb_kv->read_only = true; + + } else if (flags & LDB_FLG_DONT_CREATE_DB) { + /* + * This is used by ldbsearch to prevent creation of the database + * if the name is wrong + */ + open_flags = O_RDWR; + } else { + /* + * This is the normal case + */ + open_flags = O_CREAT | O_RDWR; + } + + ldb_kv->kv_ops = &key_value_ops; + + errno = 0; + /* note that we use quite a large default hash size */ + ldb_kv->tdb = ltdb_wrap_open(ldb_kv, + path, + 10000, + tdb_flags, + open_flags, + ldb_get_create_perms(ldb), + ldb); + if (!ldb_kv->tdb) { + ldb_asprintf_errstring(ldb, + "Unable to open tdb '%s': %s", path, strerror(errno)); + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Unable to open tdb '%s': %s", path, strerror(errno)); + talloc_free(ldb_kv); + if (errno == EACCES || errno == EPERM) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_kv_init_store( + ldb_kv, "ldb_tdb backend", ldb, options, _module); +} diff --git a/ldb-2.0.8/ldb_tdb/ldb_tdb.h b/ldb-2.0.8/ldb_tdb/ldb_tdb.h new file mode 100644 index 0000000..5395d42 --- /dev/null +++ b/ldb-2.0.8/ldb_tdb/ldb_tdb.h @@ -0,0 +1,16 @@ +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "tdb.h" +#include "ldb_module.h" + +TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn); +int ltdb_err_map(enum TDB_ERROR tdb_code); + +struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, + const char *path, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + struct ldb_context *ldb); +int ltdb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, const char *options[], + struct ldb_module **_module); diff --git a/ldb-2.0.8/ldb_tdb/ldb_tdb_err_map.c b/ldb-2.0.8/ldb_tdb/ldb_tdb_err_map.c new file mode 100644 index 0000000..41e5318 --- /dev/null +++ b/ldb-2.0.8/ldb_tdb/ldb_tdb_err_map.c @@ -0,0 +1,84 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2006-2008 + Copyright (C) Matthias Dieter Wallnöfer 2009-2010 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb_tdb + * + * Component: ldb tdb backend + * + * Description: core functions for tdb backend + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + * + * Modifications: + * + * - description: make the module use asynchronous calls + * date: Feb 2006 + * Author: Simo Sorce + * + * - description: make it possible to use event contexts + * date: Jan 2008 + * Author: Simo Sorce + * + * - description: fix up memory leaks and small bugs + * date: Oct 2009 + * Author: Matthias Dieter Wallnöfer + */ + +#include "ldb_tdb.h" +#include + +/* + map a tdb error code to a ldb error code +*/ +int ltdb_err_map(enum TDB_ERROR tdb_code) +{ + switch (tdb_code) { + case TDB_SUCCESS: + return LDB_SUCCESS; + case TDB_ERR_CORRUPT: + case TDB_ERR_OOM: + case TDB_ERR_EINVAL: + return LDB_ERR_OPERATIONS_ERROR; + case TDB_ERR_IO: + return LDB_ERR_PROTOCOL_ERROR; + case TDB_ERR_LOCK: + case TDB_ERR_NOLOCK: + return LDB_ERR_BUSY; + case TDB_ERR_LOCK_TIMEOUT: + return LDB_ERR_TIME_LIMIT_EXCEEDED; + case TDB_ERR_EXISTS: + return LDB_ERR_ENTRY_ALREADY_EXISTS; + case TDB_ERR_NOEXIST: + return LDB_ERR_NO_SUCH_OBJECT; + case TDB_ERR_RDONLY: + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + default: + break; + } + return LDB_ERR_OTHER; +} diff --git a/ldb-2.0.8/ldb_tdb/ldb_tdb_init.c b/ldb-2.0.8/ldb_tdb/ldb_tdb_init.c new file mode 100644 index 0000000..b18c98a --- /dev/null +++ b/ldb-2.0.8/ldb_tdb/ldb_tdb_init.c @@ -0,0 +1,59 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2006-2008 + Copyright (C) Matthias Dieter Wallnöfer 2009-2010 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb_tdb + * + * Component: ldb tdb backend + * + * Description: core functions for tdb backend + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + * + * Modifications: + * + * - description: make the module use asynchronous calls + * date: Feb 2006 + * Author: Simo Sorce + * + * - description: make it possible to use event contexts + * date: Jan 2008 + * Author: Simo Sorce + * + * - description: fix up memory leaks and small bugs + * date: Oct 2009 + * Author: Matthias Dieter Wallnöfer + */ + +#include "ldb_tdb.h" +#include "ldb_private.h" + +int ldb_tdb_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_backend("tdb", ltdb_connect, false); +} diff --git a/ldb-2.0.8/ldb_tdb/ldb_tdb_wrap.c b/ldb-2.0.8/ldb_tdb/ldb_tdb_wrap.c new file mode 100644 index 0000000..bc702a2 --- /dev/null +++ b/ldb-2.0.8/ldb_tdb/ldb_tdb_wrap.c @@ -0,0 +1,162 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include "ldb_tdb.h" +#include "dlinklist.h" + +static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ + va_list ap; + const char *name = tdb_name(tdb); + struct ldb_context *ldb = talloc_get_type(tdb_get_logging_private(tdb), struct ldb_context); + enum ldb_debug_level ldb_level; + char *message; + + if (ldb == NULL) + return; + + va_start(ap, fmt); + message = talloc_vasprintf(ldb, fmt, ap); + va_end(ap); + + switch (level) { + case TDB_DEBUG_FATAL: + ldb_level = LDB_DEBUG_FATAL; + break; + case TDB_DEBUG_ERROR: + ldb_level = LDB_DEBUG_ERROR; + break; + case TDB_DEBUG_WARNING: + ldb_level = LDB_DEBUG_WARNING; + break; + case TDB_DEBUG_TRACE: + ldb_level = LDB_DEBUG_TRACE; + break; + default: + ldb_level = LDB_DEBUG_FATAL; + } + + ldb_debug(ldb, ldb_level, "ltdb: tdb(%s): %s", name, message); + talloc_free(message); +} + +/* + the purpose of this code is to work around the braindead posix locking + rules, to allow us to have a ldb open more than once while allowing + locking to work + + TDB2 handles multiple opens, so we don't have this problem there. +*/ + +struct ltdb_wrap { + struct ltdb_wrap *next, *prev; + struct tdb_context *tdb; + dev_t device; + ino_t inode; + pid_t pid; +}; + +static struct ltdb_wrap *tdb_list; + +/* destroy the last connection to a tdb */ +static int ltdb_wrap_destructor(struct ltdb_wrap *w) +{ + tdb_close(w->tdb); + DLIST_REMOVE(tdb_list, w); + return 0; +} + +/* + wrapped connection to a tdb database. The caller should _not_ free + this as it is not a talloc structure (as tdb does not use talloc + yet). It will auto-close when the caller frees the mem_ctx that is + passed to this call + */ +struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, + const char *path, int hash_size, + int tdb_flags, + int open_flags, mode_t mode, + struct ldb_context *ldb) +{ + struct ltdb_wrap *w; + struct tdb_logging_context lctx; + struct stat st; + + if (stat(path, &st) == 0) { + for (w=tdb_list;w;w=w->next) { + if (st.st_dev == w->device && st.st_ino == w->inode) { + pid_t pid = getpid(); + int ret; + if (!talloc_reference(mem_ctx, w)) { + return NULL; + } + if (w->pid != pid) { + ret = tdb_reopen(w->tdb); + if (ret != 0) { + /* + * Avoid use-after-free: + * on fail the TDB + * is closed! + */ + DLIST_REMOVE(tdb_list, + w); + return NULL; + } + w->pid = pid; + } + return w->tdb; + } + } + } + + w = talloc(mem_ctx, struct ltdb_wrap); + if (w == NULL) { + return NULL; + } + + lctx.log_fn = ltdb_log_fn; + lctx.log_private = ldb; + w->tdb = tdb_open_ex(path, hash_size, tdb_flags, open_flags, mode, + &lctx, NULL); + if (w->tdb == NULL) { + talloc_free(w); + return NULL; + } + + if (fstat(tdb_fd(w->tdb), &st) != 0) { + tdb_close(w->tdb); + talloc_free(w); + return NULL; + } + + w->device = st.st_dev; + w->inode = st.st_ino; + w->pid = getpid(); + + talloc_set_destructor(w, ltdb_wrap_destructor); + + DLIST_ADD(tdb_list, w); + + return w->tdb; +} diff --git a/ldb-2.0.8/lib/replace/.checker_innocent b/ldb-2.0.8/lib/replace/.checker_innocent new file mode 100644 index 0000000..e619176 --- /dev/null +++ b/ldb-2.0.8/lib/replace/.checker_innocent @@ -0,0 +1,4 @@ +>>>MISTAKE21_create_files_6a9e68ada99a97cb +>>>MISTAKE21_os2_delete_9b2bfa7f38711d09 +>>>MISTAKE21_os2_delete_2fcc29aaa99a97cb +>>>SECURITY2_os2_delete_9b2bfa7f1c9396ca diff --git a/ldb-2.0.8/lib/replace/Makefile b/ldb-2.0.8/lib/replace/Makefile new file mode 100644 index 0000000..a123a37 --- /dev/null +++ b/ldb-2.0.8/lib/replace/Makefile @@ -0,0 +1,64 @@ +# simple makefile wrapper to run waf + +WAF_BINARY=$(PYTHON) ../../buildtools/bin/waf +WAF=PYTHONHASHSEED=1 WAF_MAKE=1 $(WAF_BINARY) + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: + $(WAF) test $(TEST_OPTIONS) + +testenv: + $(WAF) test --testenv $(TEST_OPTIONS) + +quicktest: + $(WAF) test --quick $(TEST_OPTIONS) + +dist: + touch .tmplock + WAFLOCK=.tmplock $(WAF) dist + +distcheck: + touch .tmplock + WAFLOCK=.tmplock $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +torture: all + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags + +bin/%:: FORCE + $(WAF) --targets=`basename $@` +FORCE: diff --git a/ldb-2.0.8/lib/replace/README b/ldb-2.0.8/lib/replace/README new file mode 100644 index 0000000..6612eab --- /dev/null +++ b/ldb-2.0.8/lib/replace/README @@ -0,0 +1,128 @@ +This subsystem ensures that we can always use a certain core set of +functions and types, that are either provided by the OS or by replacement +functions / definitions in this subsystem. The aim is to try to stick +to POSIX functions in here as much as possible. Convenience functions +that are available on no platform at all belong in other subsystems +(such as LIBUTIL). + +The following functions are guaranteed: + +ftruncate +strlcpy +strlcat +mktime +rename +initgroups +memmove +strdup +setlinebuf +vsyslog +timegm +setenv +unsetenv +strndup +strnlen +waitpid +seteuid +setegid +asprintf +snprintf +vasprintf +vsnprintf +opendir +readdir +telldir +seekdir +clock_gettime +closedir +dlopen +dlclose +dlsym +dlerror +chroot +bzero +strerror +errno +mkdtemp +mkstemp (a secure one!) +pread +pwrite +chown +lchown +readline (the library) +inet_ntoa +inet_ntop +inet_pton +inet_aton +strtoll +strtoull +socketpair +strptime +getaddrinfo +freeaddrinfo +getnameinfo +gai_strerror +getifaddrs +freeifaddrs +utime +utimes +dup2 +link +readlink +symlink +realpath +poll +setproctitle +memset_s + +Types: +bool +socklen_t +uint{8,16,32,64}_t +int{8,16,32,64}_t +intptr_t +sig_atomic_t +blksize_t +blkcnt_t + +Constants: +PATH_NAME_MAX +UINT{16,32,64}_MAX +INT32_MAX +RTLD_LAZY +HOST_NAME_MAX +UINT16_MAX +UINT32_MAX +UINT64_MAX +CHAR_BIT + +Macros: +va_copy +__FUNCTION__ +__FILE__ +__LINE__ +__LINESTR__ +__location__ +__STRING +__STRINGSTRING +MIN +MAX +QSORT_CAST +ZERO_STRUCT +ZERO_STRUCTP +ZERO_STRUCTPN +ZERO_ARRAY +ARRAY_SIZE +PTR_DIFF + +Headers: +stdint.h +stdbool.h + +Optional C keywords: +volatile + +Prerequisites: +memset (for bzero) +syslog (for vsyslog) +mktemp (for mkstemp and mkdtemp) diff --git a/ldb-2.0.8/lib/replace/closefrom.c b/ldb-2.0.8/lib/replace/closefrom.c new file mode 100644 index 0000000..a61a80f --- /dev/null +++ b/ldb-2.0.8/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 . + */ + +#include "replace.h" +#include +#include +#include + +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; fdd_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 + that this crypt routine may sometimes get the wrong answer. Only + use UFC_CRYT if you really need it. + +*/ + +#include "replace.h" + +#ifndef HAVE_CRYPT + +/* + * UFC-crypt: ultra fast crypt(3) implementation + * + * Copyright (C) 1991-1998, Free Software Foundation, Inc. + * + * 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 . + * + * @(#)crypt_util.c 2.31 02/08/92 + * + * Support routines + * + */ + + +#ifndef long32 +#define long32 int32_t +#endif + +#ifndef long64 +#define long64 int64_t +#endif + +#ifndef ufc_long +#define ufc_long unsigned +#endif + +#ifndef _UFC_64_ +#define _UFC_32_ +#endif + +/* + * Permutation done once on the 56 bit + * key derived from the original 8 byte ASCII key. + */ +static int pc1[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +/* + * How much to rotate each 28 bit half of the pc1 permutated + * 56 bit key before using pc2 to give the i' key + */ +static int rots[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +/* + * Permutation giving the key + * of the i' DES round + */ +static int pc2[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * The E expansion table which selects + * bits from the 32 bit intermediate result. + */ +static int esel[48] = { + 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 +}; +static int e_inverse[64]; + +/* + * Permutation done on the + * result of sbox lookups + */ +static int perm32[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +/* + * The sboxes + */ +static int sbox[8][4][16]= { + { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }, + { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 }, + { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 }, + { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } + }, + + { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, + { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 }, + { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 }, + { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } + }, + + { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, + { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 }, + { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 }, + { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } + }, + + { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, + { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 }, + { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 }, + { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } + }, + + { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, + { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, + { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 }, + { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } + }, + + { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, + { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 }, + { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 }, + { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } + }, + + { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, + { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 }, + { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 }, + { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } + }, + + { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, + { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 }, + { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 }, + { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } + } +}; + +/* + * This is the final + * permutation matrix + */ +static int final_perm[64] = { + 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 +}; + +/* + * The 16 DES keys in BITMASK format + */ +#ifdef _UFC_32_ +long32 _ufc_keytab[16][2]; +#endif + +#ifdef _UFC_64_ +long64 _ufc_keytab[16]; +#endif + + +#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') +#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') + +/* Macro to set a bit (0..23) */ +#define BITMASK(i) ( (1<<(11-(i)%12+3)) << ((i)<12?16:0) ) + +/* + * sb arrays: + * + * Workhorses of the inner loop of the DES implementation. + * They do sbox lookup, shifting of this value, 32 bit + * permutation and E permutation for the next round. + * + * Kept in 'BITMASK' format. + */ + +#ifdef _UFC_32_ +long32 _ufc_sb0[8192], _ufc_sb1[8192], _ufc_sb2[8192], _ufc_sb3[8192]; +static long32 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3}; +#endif + +#ifdef _UFC_64_ +long64 _ufc_sb0[4096], _ufc_sb1[4096], _ufc_sb2[4096], _ufc_sb3[4096]; +static long64 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3}; +#endif + +/* + * eperm32tab: do 32 bit permutation and E selection + * + * The first index is the byte number in the 32 bit value to be permuted + * - second - is the value of this byte + * - third - selects the two 32 bit values + * + * The table is used and generated internally in init_des to speed it up + */ +static ufc_long eperm32tab[4][256][2]; + +/* + * do_pc1: permform pc1 permutation in the key schedule generation. + * + * The first index is the byte number in the 8 byte ASCII key + * - second - - the two 28 bits halfs of the result + * - third - selects the 7 bits actually used of each byte + * + * The result is kept with 28 bit per 32 bit with the 4 most significant + * bits zero. + */ +static ufc_long do_pc1[8][2][128]; + +/* + * do_pc2: permform pc2 permutation in the key schedule generation. + * + * The first index is the septet number in the two 28 bit intermediate values + * - second - - - septet values + * + * Knowledge of the structure of the pc2 permutation is used. + * + * The result is kept with 28 bit per 32 bit with the 4 most significant + * bits zero. + */ +static ufc_long do_pc2[8][128]; + +/* + * efp: undo an extra e selection and do final + * permutation giving the DES result. + * + * Invoked 6 bit a time on two 48 bit values + * giving two 32 bit longs. + */ +static ufc_long efp[16][64][2]; + +static unsigned char bytemask[8] = { + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 +}; + +static ufc_long longmask[32] = { + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + + +/* + * Silly rewrite of 'bzero'. I do so + * because some machines don't have + * bzero and some don't have memset. + */ + +static void clearmem(char *start, int cnt) + { while(cnt--) + *start++ = '\0'; + } + +static int initialized = 0; + +/* lookup a 6 bit value in sbox */ + +#define s_lookup(i,s) sbox[(i)][(((s)>>4) & 0x2)|((s) & 0x1)][((s)>>1) & 0xf]; + +/* + * Initialize unit - may be invoked directly + * by fcrypt users. + */ + +static void ufc_init_des(void) + { int comes_from_bit; + int bit, sg; + ufc_long j; + ufc_long mask1, mask2; + + /* + * Create the do_pc1 table used + * to affect pc1 permutation + * when generating keys + */ + for(bit = 0; bit < 56; bit++) { + comes_from_bit = pc1[bit] - 1; + mask1 = bytemask[comes_from_bit % 8 + 1]; + mask2 = longmask[bit % 28 + 4]; + for(j = 0; j < 128; j++) { + if(j & mask1) + do_pc1[comes_from_bit / 8][bit / 28][j] |= mask2; + } + } + + /* + * Create the do_pc2 table used + * to affect pc2 permutation when + * generating keys + */ + for(bit = 0; bit < 48; bit++) { + comes_from_bit = pc2[bit] - 1; + mask1 = bytemask[comes_from_bit % 7 + 1]; + mask2 = BITMASK(bit % 24); + for(j = 0; j < 128; j++) { + if(j & mask1) + do_pc2[comes_from_bit / 7][j] |= mask2; + } + } + + /* + * Now generate the table used to do combined + * 32 bit permutation and e expansion + * + * We use it because we have to permute 16384 32 bit + * longs into 48 bit in order to initialize sb. + * + * Looping 48 rounds per permutation becomes + * just too slow... + * + */ + + clearmem((char*)eperm32tab, sizeof(eperm32tab)); + + for(bit = 0; bit < 48; bit++) { + ufc_long inner_mask1,comes_from; + + comes_from = perm32[esel[bit]-1]-1; + inner_mask1 = bytemask[comes_from % 8]; + + for(j = 256; j--;) { + if(j & inner_mask1) + eperm32tab[comes_from / 8][j][bit / 24] |= BITMASK(bit % 24); + } + } + + /* + * Create the sb tables: + * + * For each 12 bit segment of an 48 bit intermediate + * result, the sb table precomputes the two 4 bit + * values of the sbox lookups done with the two 6 + * bit halves, shifts them to their proper place, + * sends them through perm32 and finally E expands + * them so that they are ready for the next + * DES round. + * + */ + for(sg = 0; sg < 4; sg++) { + int j1, j2; + int s1, s2; + + for(j1 = 0; j1 < 64; j1++) { + s1 = s_lookup(2 * sg, j1); + for(j2 = 0; j2 < 64; j2++) { + ufc_long to_permute, inx; + + s2 = s_lookup(2 * sg + 1, j2); + to_permute = ((s1 << 4) | s2) << (24 - 8 * sg); + +#ifdef _UFC_32_ + inx = ((j1 << 6) | j2) << 1; + sb[sg][inx ] = eperm32tab[0][(to_permute >> 24) & 0xff][0]; + sb[sg][inx+1] = eperm32tab[0][(to_permute >> 24) & 0xff][1]; + sb[sg][inx ] |= eperm32tab[1][(to_permute >> 16) & 0xff][0]; + sb[sg][inx+1] |= eperm32tab[1][(to_permute >> 16) & 0xff][1]; + sb[sg][inx ] |= eperm32tab[2][(to_permute >> 8) & 0xff][0]; + sb[sg][inx+1] |= eperm32tab[2][(to_permute >> 8) & 0xff][1]; + sb[sg][inx ] |= eperm32tab[3][(to_permute) & 0xff][0]; + sb[sg][inx+1] |= eperm32tab[3][(to_permute) & 0xff][1]; +#endif +#ifdef _UFC_64_ + inx = ((j1 << 6) | j2); + sb[sg][inx] = + ((long64)eperm32tab[0][(to_permute >> 24) & 0xff][0] << 32) | + (long64)eperm32tab[0][(to_permute >> 24) & 0xff][1]; + sb[sg][inx] |= + ((long64)eperm32tab[1][(to_permute >> 16) & 0xff][0] << 32) | + (long64)eperm32tab[1][(to_permute >> 16) & 0xff][1]; + sb[sg][inx] |= + ((long64)eperm32tab[2][(to_permute >> 8) & 0xff][0] << 32) | + (long64)eperm32tab[2][(to_permute >> 8) & 0xff][1]; + sb[sg][inx] |= + ((long64)eperm32tab[3][(to_permute) & 0xff][0] << 32) | + (long64)eperm32tab[3][(to_permute) & 0xff][1]; +#endif + } + } + } + + /* + * Create an inverse matrix for esel telling + * where to plug out bits if undoing it + */ + for(bit=48; bit--;) { + e_inverse[esel[bit] - 1 ] = bit; + e_inverse[esel[bit] - 1 + 32] = bit + 48; + } + + /* + * create efp: the matrix used to + * undo the E expansion and effect final permutation + */ + clearmem((char*)efp, sizeof efp); + for(bit = 0; bit < 64; bit++) { + int o_bit, o_long; + ufc_long word_value, inner_mask1, inner_mask2; + int comes_from_f_bit, comes_from_e_bit; + int comes_from_word, bit_within_word; + + /* See where bit i belongs in the two 32 bit long's */ + o_long = bit / 32; /* 0..1 */ + o_bit = bit % 32; /* 0..31 */ + + /* + * And find a bit in the e permutated value setting this bit. + * + * Note: the e selection may have selected the same bit several + * times. By the initialization of e_inverse, we only look + * for one specific instance. + */ + comes_from_f_bit = final_perm[bit] - 1; /* 0..63 */ + comes_from_e_bit = e_inverse[comes_from_f_bit]; /* 0..95 */ + comes_from_word = comes_from_e_bit / 6; /* 0..15 */ + bit_within_word = comes_from_e_bit % 6; /* 0..5 */ + + inner_mask1 = longmask[bit_within_word + 26]; + inner_mask2 = longmask[o_bit]; + + for(word_value = 64; word_value--;) { + if(word_value & inner_mask1) + efp[comes_from_word][word_value][o_long] |= inner_mask2; + } + } + initialized++; + } + +/* + * Process the elements of the sb table permuting the + * bits swapped in the expansion by the current salt. + */ + +#ifdef _UFC_32_ +static void shuffle_sb(long32 *k, ufc_long saltbits) + { ufc_long j; + long32 x; + for(j=4096; j--;) { + x = (k[0] ^ k[1]) & (long32)saltbits; + *k++ ^= x; + *k++ ^= x; + } + } +#endif + +#ifdef _UFC_64_ +static void shuffle_sb(long64 *k, ufc_long saltbits) + { ufc_long j; + long64 x; + for(j=4096; j--;) { + x = ((*k >> 32) ^ *k) & (long64)saltbits; + *k++ ^= (x << 32) | x; + } + } +#endif + +/* + * Setup the unit for a new salt + * Hopefully we'll not see a new salt in each crypt call. + */ + +static unsigned char current_salt[3] = "&&"; /* invalid value */ +static ufc_long current_saltbits = 0; +static int direction = 0; + +static void setup_salt(const char *s1) + { ufc_long i, j, saltbits; + const unsigned char *s2 = (const unsigned char *)s1; + + if(!initialized) + ufc_init_des(); + + if(s2[0] == current_salt[0] && s2[1] == current_salt[1]) + return; + current_salt[0] = s2[0]; current_salt[1] = s2[1]; + + /* + * This is the only crypt change to DES: + * entries are swapped in the expansion table + * according to the bits set in the salt. + */ + saltbits = 0; + for(i = 0; i < 2; i++) { + long c=ascii_to_bin(s2[i]); + if(c < 0 || c > 63) + c = 0; + for(j = 0; j < 6; j++) { + if((c >> j) & 0x1) + saltbits |= BITMASK(6 * i + j); + } + } + + /* + * Permute the sb table values + * to reflect the changed e + * selection table + */ + shuffle_sb(_ufc_sb0, current_saltbits ^ saltbits); + shuffle_sb(_ufc_sb1, current_saltbits ^ saltbits); + shuffle_sb(_ufc_sb2, current_saltbits ^ saltbits); + shuffle_sb(_ufc_sb3, current_saltbits ^ saltbits); + + current_saltbits = saltbits; + } + +static void ufc_mk_keytab(char *key) + { ufc_long v1, v2, *k1; + int i; +#ifdef _UFC_32_ + long32 v, *k2 = &_ufc_keytab[0][0]; +#endif +#ifdef _UFC_64_ + long64 v, *k2 = &_ufc_keytab[0]; +#endif + + v1 = v2 = 0; k1 = &do_pc1[0][0][0]; + for(i = 8; i--;) { + v1 |= k1[*key & 0x7f]; k1 += 128; + v2 |= k1[*key++ & 0x7f]; k1 += 128; + } + + for(i = 0; i < 16; i++) { + k1 = &do_pc2[0][0]; + + v1 = (v1 << rots[i]) | (v1 >> (28 - rots[i])); + v = k1[(v1 >> 21) & 0x7f]; k1 += 128; + v |= k1[(v1 >> 14) & 0x7f]; k1 += 128; + v |= k1[(v1 >> 7) & 0x7f]; k1 += 128; + v |= k1[(v1 ) & 0x7f]; k1 += 128; + +#ifdef _UFC_32_ + *k2++ = v; + v = 0; +#endif +#ifdef _UFC_64_ + v <<= 32; +#endif + + v2 = (v2 << rots[i]) | (v2 >> (28 - rots[i])); + v |= k1[(v2 >> 21) & 0x7f]; k1 += 128; + v |= k1[(v2 >> 14) & 0x7f]; k1 += 128; + v |= k1[(v2 >> 7) & 0x7f]; k1 += 128; + v |= k1[(v2 ) & 0x7f]; + + *k2++ = v; + } + + direction = 0; + } + +/* + * Undo an extra E selection and do final permutations + */ + +ufc_long *_ufc_dofinalperm(ufc_long l1, ufc_long l2, ufc_long r1, ufc_long r2) + { ufc_long v1, v2, x; + static ufc_long ary[2]; + + x = (l1 ^ l2) & current_saltbits; l1 ^= x; l2 ^= x; + x = (r1 ^ r2) & current_saltbits; r1 ^= x; r2 ^= x; + + v1=v2=0; l1 >>= 3; l2 >>= 3; r1 >>= 3; r2 >>= 3; + + v1 |= efp[15][ r2 & 0x3f][0]; v2 |= efp[15][ r2 & 0x3f][1]; + v1 |= efp[14][(r2 >>= 6) & 0x3f][0]; v2 |= efp[14][ r2 & 0x3f][1]; + v1 |= efp[13][(r2 >>= 10) & 0x3f][0]; v2 |= efp[13][ r2 & 0x3f][1]; + v1 |= efp[12][(r2 >>= 6) & 0x3f][0]; v2 |= efp[12][ r2 & 0x3f][1]; + + v1 |= efp[11][ r1 & 0x3f][0]; v2 |= efp[11][ r1 & 0x3f][1]; + v1 |= efp[10][(r1 >>= 6) & 0x3f][0]; v2 |= efp[10][ r1 & 0x3f][1]; + v1 |= efp[ 9][(r1 >>= 10) & 0x3f][0]; v2 |= efp[ 9][ r1 & 0x3f][1]; + v1 |= efp[ 8][(r1 >>= 6) & 0x3f][0]; v2 |= efp[ 8][ r1 & 0x3f][1]; + + v1 |= efp[ 7][ l2 & 0x3f][0]; v2 |= efp[ 7][ l2 & 0x3f][1]; + v1 |= efp[ 6][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 6][ l2 & 0x3f][1]; + v1 |= efp[ 5][(l2 >>= 10) & 0x3f][0]; v2 |= efp[ 5][ l2 & 0x3f][1]; + v1 |= efp[ 4][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 4][ l2 & 0x3f][1]; + + v1 |= efp[ 3][ l1 & 0x3f][0]; v2 |= efp[ 3][ l1 & 0x3f][1]; + v1 |= efp[ 2][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 2][ l1 & 0x3f][1]; + v1 |= efp[ 1][(l1 >>= 10) & 0x3f][0]; v2 |= efp[ 1][ l1 & 0x3f][1]; + v1 |= efp[ 0][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 0][ l1 & 0x3f][1]; + + ary[0] = v1; ary[1] = v2; + return ary; + } + +/* + * crypt only: convert from 64 bit to 11 bit ASCII + * prefixing with the salt + */ + +static char *output_conversion(ufc_long v1, ufc_long v2, const char *salt) + { static char outbuf[14]; + int i, s; + + outbuf[0] = salt[0]; + outbuf[1] = salt[1] ? salt[1] : salt[0]; + + for(i = 0; i < 5; i++) + outbuf[i + 2] = bin_to_ascii((v1 >> (26 - 6 * i)) & 0x3f); + + s = (v2 & 0xf) << 2; + v2 = (v2 >> 2) | ((v1 & 0x3) << 30); + + for(i = 5; i < 10; i++) + outbuf[i + 2] = bin_to_ascii((v2 >> (56 - 6 * i)) & 0x3f); + + outbuf[12] = bin_to_ascii(s); + outbuf[13] = 0; + + return outbuf; + } + +/* + * UNIX crypt function + */ + +static ufc_long *_ufc_doit(ufc_long , ufc_long, ufc_long, ufc_long, ufc_long); + +char *ufc_crypt(const char *key,const char *salt) + { ufc_long *s; + char ktab[9]; + + /* + * Hack DES tables according to salt + */ + setup_salt(salt); + + /* + * Setup key schedule + */ + clearmem(ktab, sizeof ktab); + strncpy(ktab, key, 8); + ufc_mk_keytab(ktab); + + /* + * Go for the 25 DES encryptions + */ + s = _ufc_doit((ufc_long)0, (ufc_long)0, + (ufc_long)0, (ufc_long)0, (ufc_long)25); + + /* + * And convert back to 6 bit ASCII + */ + return output_conversion(s[0], s[1], salt); + } + + +#ifdef _UFC_32_ + +/* + * 32 bit version + */ + +extern long32 _ufc_keytab[16][2]; +extern long32 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[]; + +#define SBA(sb, v) (*(long32*)((char*)(sb)+(v))) + +static ufc_long *_ufc_doit(ufc_long l1, ufc_long l2, ufc_long r1, ufc_long r2, ufc_long itr) + { int i; + long32 s, *k; + + while(itr--) { + k = &_ufc_keytab[0][0]; + for(i=8; i--; ) { + s = *k++ ^ r1; + l1 ^= SBA(_ufc_sb1, s & 0xffff); l2 ^= SBA(_ufc_sb1, (s & 0xffff)+4); + l1 ^= SBA(_ufc_sb0, s >>= 16); l2 ^= SBA(_ufc_sb0, (s) +4); + s = *k++ ^ r2; + l1 ^= SBA(_ufc_sb3, s & 0xffff); l2 ^= SBA(_ufc_sb3, (s & 0xffff)+4); + l1 ^= SBA(_ufc_sb2, s >>= 16); l2 ^= SBA(_ufc_sb2, (s) +4); + + s = *k++ ^ l1; + r1 ^= SBA(_ufc_sb1, s & 0xffff); r2 ^= SBA(_ufc_sb1, (s & 0xffff)+4); + r1 ^= SBA(_ufc_sb0, s >>= 16); r2 ^= SBA(_ufc_sb0, (s) +4); + s = *k++ ^ l2; + r1 ^= SBA(_ufc_sb3, s & 0xffff); r2 ^= SBA(_ufc_sb3, (s & 0xffff)+4); + r1 ^= SBA(_ufc_sb2, s >>= 16); r2 ^= SBA(_ufc_sb2, (s) +4); + } + s=l1; l1=r1; r1=s; s=l2; l2=r2; r2=s; + } + return _ufc_dofinalperm(l1, l2, r1, r2); + } + +#endif + +#ifdef _UFC_64_ + +/* + * 64 bit version + */ + +extern long64 _ufc_keytab[16]; +extern long64 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[]; + +#define SBA(sb, v) (*(long64*)((char*)(sb)+(v))) + +static ufc_long *_ufc_doit(ufc_long l1, ufc_long l2, ufc_long r1, ufc_long r2, ufc_long itr) + { int i; + long64 l, r, s, *k; + + l = (((long64)l1) << 32) | ((long64)l2); + r = (((long64)r1) << 32) | ((long64)r2); + + while(itr--) { + k = &_ufc_keytab[0]; + for(i=8; i--; ) { + s = *k++ ^ r; + l ^= SBA(_ufc_sb3, (s >> 0) & 0xffff); + l ^= SBA(_ufc_sb2, (s >> 16) & 0xffff); + l ^= SBA(_ufc_sb1, (s >> 32) & 0xffff); + l ^= SBA(_ufc_sb0, (s >> 48) & 0xffff); + + s = *k++ ^ l; + r ^= SBA(_ufc_sb3, (s >> 0) & 0xffff); + r ^= SBA(_ufc_sb2, (s >> 16) & 0xffff); + r ^= SBA(_ufc_sb1, (s >> 32) & 0xffff); + r ^= SBA(_ufc_sb0, (s >> 48) & 0xffff); + } + s=l; l=r; r=s; + } + + l1 = l >> 32; l2 = l & 0xffffffff; + r1 = r >> 32; r2 = r & 0xffffffff; + return _ufc_dofinalperm(l1, l2, r1, r2); + } + +#endif + + +#else + int ufc_dummy_procedure(void); + int ufc_dummy_procedure(void) {return 0;} +#endif diff --git a/ldb-2.0.8/lib/replace/cwrap.c b/ldb-2.0.8/lib/replace/cwrap.c new file mode 100644 index 0000000..adc5c1e --- /dev/null +++ b/ldb-2.0.8/lib/replace/cwrap.c @@ -0,0 +1,46 @@ +/* + * Unix SMB/CIFS implementation. + * + * Replaceable functions by cwrap + * + * Copyright (c) 2014 Andreas Schneider + * + * ** 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 + * Lesser 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 . + */ + +#include "replace.h" + +bool nss_wrapper_enabled(void) +{ + return false; +} + +bool nss_wrapper_hosts_enabled(void) +{ + return false; +} + +bool socket_wrapper_enabled(void) +{ + return false; +} + +bool uid_wrapper_enabled(void) +{ + return false; +} diff --git a/ldb-2.0.8/lib/replace/dlfcn.c b/ldb-2.0.8/lib/replace/dlfcn.c new file mode 100644 index 0000000..88431ed --- /dev/null +++ b/ldb-2.0.8/lib/replace/dlfcn.c @@ -0,0 +1,76 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + Copyright (C) Jelmer Vernooij 2006 + + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#ifdef HAVE_DL_H +#include +#endif + +#ifndef HAVE_DLOPEN +#ifdef DLOPEN_TAKES_UNSIGNED_FLAGS +void *rep_dlopen(const char *name, unsigned int flags) +#else +void *rep_dlopen(const char *name, int flags) +#endif +{ +#ifdef HAVE_SHL_LOAD + if (name == NULL) + return PROG_HANDLE; + return (void *)shl_load(name, flags, 0); +#else + return NULL; +#endif +} +#endif + +#ifndef HAVE_DLSYM +void *rep_dlsym(void *handle, const char *symbol) +{ +#ifdef HAVE_SHL_FINDSYM + void *sym_addr; + if (!shl_findsym((shl_t *)&handle, symbol, TYPE_UNDEFINED, &sym_addr)) + return sym_addr; +#endif + return NULL; +} +#endif + +#ifndef HAVE_DLERROR +char *rep_dlerror(void) +{ + return "dynamic loading of objects not supported on this platform"; +} +#endif + +#ifndef HAVE_DLCLOSE +int rep_dlclose(void *handle) +{ +#ifdef HAVE_SHL_CLOSE + return shl_unload((shl_t)handle); +#else + return 0; +#endif +} +#endif diff --git a/ldb-2.0.8/lib/replace/getaddrinfo.c b/ldb-2.0.8/lib/replace/getaddrinfo.c new file mode 100644 index 0000000..8440d8e --- /dev/null +++ b/ldb-2.0.8/lib/replace/getaddrinfo.c @@ -0,0 +1,493 @@ +/* +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this paragraph +and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, +EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS +TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +*/ + +/*------------------------------------------------------------------------- + * + * getaddrinfo.c + * Support getaddrinfo() on platforms that don't have it. + * + * We also supply getnameinfo() here, assuming that the platform will have + * it if and only if it has getaddrinfo(). If this proves false on some + * platform, we'll need to split this file and provide a separate configure + * test for getnameinfo(). + * + * Copyright (c) 2003-2007, PostgreSQL Global Development Group + * + * Copyright (C) 2007 Jeremy Allison. + * Modified to return multiple IPv4 addresses for Samba. + * + *------------------------------------------------------------------------- + */ + +#include "replace.h" +#include "system/network.h" + +#ifndef SMB_MALLOC +#define SMB_MALLOC(s) malloc(s) +#endif + +#ifndef SMB_STRDUP +#define SMB_STRDUP(s) strdup(s) +#endif + +static int check_hostent_err(struct hostent *hp) +{ + if (!hp) { + switch (h_errno) { + case HOST_NOT_FOUND: + case NO_DATA: + return EAI_NONAME; + case TRY_AGAIN: + return EAI_AGAIN; + case NO_RECOVERY: + default: + return EAI_FAIL; + } + } + if (!hp->h_name || hp->h_addrtype != AF_INET) { + return EAI_FAIL; + } + return 0; +} + +static char *canon_name_from_hostent(struct hostent *hp, + int *perr) +{ + char *ret = NULL; + + *perr = check_hostent_err(hp); + if (*perr) { + return NULL; + } + ret = SMB_STRDUP(hp->h_name); + if (!ret) { + *perr = EAI_MEMORY; + } + return ret; +} + +static char *get_my_canon_name(int *perr) +{ + char name[HOST_NAME_MAX+1]; + + if (gethostname(name, HOST_NAME_MAX) == -1) { + *perr = EAI_FAIL; + return NULL; + } + /* Ensure null termination. */ + name[HOST_NAME_MAX] = '\0'; + return canon_name_from_hostent(gethostbyname(name), perr); +} + +static char *get_canon_name_from_addr(struct in_addr ip, + int *perr) +{ + return canon_name_from_hostent( + gethostbyaddr(&ip, sizeof(ip), AF_INET), + perr); +} + +static struct addrinfo *alloc_entry(const struct addrinfo *hints, + struct in_addr ip, + unsigned short port) +{ + struct sockaddr_in *psin = NULL; + struct addrinfo *ai = SMB_MALLOC(sizeof(*ai)); + + if (!ai) { + return NULL; + } + memset(ai, '\0', sizeof(*ai)); + + psin = SMB_MALLOC(sizeof(*psin)); + if (!psin) { + free(ai); + return NULL; + } + + memset(psin, '\0', sizeof(*psin)); + + psin->sin_family = AF_INET; + psin->sin_port = htons(port); + psin->sin_addr = ip; + + ai->ai_flags = 0; + ai->ai_family = AF_INET; + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + ai->ai_addrlen = sizeof(*psin); + ai->ai_addr = (struct sockaddr *) psin; + ai->ai_canonname = NULL; + ai->ai_next = NULL; + + return ai; +} + +/* + * get address info for a single ipv4 address. + * + * Bugs: - servname can only be a number, not text. + */ + +static int getaddr_info_single_addr(const char *service, + uint32_t addr, + const struct addrinfo *hints, + struct addrinfo **res) +{ + + struct addrinfo *ai = NULL; + struct in_addr ip; + unsigned short port = 0; + + if (service) { + port = (unsigned short)atoi(service); + } + ip.s_addr = htonl(addr); + + ai = alloc_entry(hints, ip, port); + if (!ai) { + return EAI_MEMORY; + } + + /* If we're asked for the canonical name, + * make sure it returns correctly. */ + if (!(hints->ai_flags & AI_NUMERICSERV) && + hints->ai_flags & AI_CANONNAME) { + int err; + if (addr == INADDR_LOOPBACK || addr == INADDR_ANY) { + ai->ai_canonname = get_my_canon_name(&err); + } else { + ai->ai_canonname = + get_canon_name_from_addr(ip,&err); + } + if (ai->ai_canonname == NULL) { + freeaddrinfo(ai); + return err; + } + } + + *res = ai; + return 0; +} + +/* + * get address info for multiple ipv4 addresses. + * + * Bugs: - servname can only be a number, not text. + */ + +static int getaddr_info_name(const char *node, + const char *service, + const struct addrinfo *hints, + struct addrinfo **res) +{ + struct addrinfo *listp = NULL, *prevp = NULL; + char **pptr = NULL; + int err; + struct hostent *hp = NULL; + unsigned short port = 0; + + if (service) { + port = (unsigned short)atoi(service); + } + + hp = gethostbyname(node); + err = check_hostent_err(hp); + if (err) { + return err; + } + + for(pptr = hp->h_addr_list; *pptr; pptr++) { + struct in_addr ip = *(struct in_addr *)*pptr; + struct addrinfo *ai = alloc_entry(hints, ip, port); + + if (!ai) { + freeaddrinfo(listp); + return EAI_MEMORY; + } + + if (!listp) { + listp = ai; + prevp = ai; + ai->ai_canonname = SMB_STRDUP(hp->h_name); + if (!ai->ai_canonname) { + freeaddrinfo(listp); + return EAI_MEMORY; + } + } else { + prevp->ai_next = ai; + prevp = ai; + } + } + *res = listp; + return 0; +} + +/* + * get address info for ipv4 sockets. + * + * Bugs: - servname can only be a number, not text. + */ + +int rep_getaddrinfo(const char *node, + const char *service, + const struct addrinfo * hintp, + struct addrinfo ** res) +{ + struct addrinfo hints; + + /* Setup the hints struct. */ + if (hintp == NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + } else { + memcpy(&hints, hintp, sizeof(hints)); + } + + if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC) { + return EAI_FAMILY; + } + + if (hints.ai_socktype == 0) { + hints.ai_socktype = SOCK_STREAM; + } + + if (!node && !service) { + return EAI_NONAME; + } + + if (node) { + if (node[0] == '\0') { + return getaddr_info_single_addr(service, + INADDR_ANY, + &hints, + res); + } else if (hints.ai_flags & AI_NUMERICHOST) { + struct in_addr ip; + if (!inet_aton(node, &ip)) { + return EAI_FAIL; + } + return getaddr_info_single_addr(service, + ntohl(ip.s_addr), + &hints, + res); + } else { + return getaddr_info_name(node, + service, + &hints, + res); + } + } else if (hints.ai_flags & AI_PASSIVE) { + return getaddr_info_single_addr(service, + INADDR_ANY, + &hints, + res); + } + return getaddr_info_single_addr(service, + INADDR_LOOPBACK, + &hints, + res); +} + + +void rep_freeaddrinfo(struct addrinfo *res) +{ + struct addrinfo *next = NULL; + + for (;res; res = next) { + next = res->ai_next; + free(res->ai_canonname); + free(res->ai_addr); + free(res); + } +} + + +const char *rep_gai_strerror(int errcode) +{ +#ifdef HAVE_HSTRERROR + int hcode; + + switch (errcode) + { + case EAI_NONAME: + hcode = HOST_NOT_FOUND; + break; + case EAI_AGAIN: + hcode = TRY_AGAIN; + break; + case EAI_FAIL: + default: + hcode = NO_RECOVERY; + break; + } + + return hstrerror(hcode); +#else /* !HAVE_HSTRERROR */ + + switch (errcode) + { + case EAI_NONAME: + return "Unknown host"; + case EAI_AGAIN: + return "Host name lookup failure"; +#ifdef EAI_BADFLAGS + case EAI_BADFLAGS: + return "Invalid argument"; +#endif +#ifdef EAI_FAMILY + case EAI_FAMILY: + return "Address family not supported"; +#endif +#ifdef EAI_MEMORY + case EAI_MEMORY: + return "Not enough memory"; +#endif +#ifdef EAI_NODATA + case EAI_NODATA: + return "No host data of that type was found"; +#endif +#ifdef EAI_SERVICE + case EAI_SERVICE: + return "Class type not found"; +#endif +#ifdef EAI_SOCKTYPE + case EAI_SOCKTYPE: + return "Socket type not supported"; +#endif + default: + return "Unknown server error"; + } +#endif /* HAVE_HSTRERROR */ +} + +static int gethostnameinfo(const struct sockaddr *sa, + char *node, + size_t nodelen, + int flags) +{ + int ret = -1; + char *p = NULL; + + if (!(flags & NI_NUMERICHOST)) { + struct hostent *hp = gethostbyaddr( + &((struct sockaddr_in *)sa)->sin_addr, + sizeof(struct in_addr), + sa->sa_family); + ret = check_hostent_err(hp); + if (ret == 0) { + /* Name looked up successfully. */ + ret = snprintf(node, nodelen, "%s", hp->h_name); + if (ret < 0 || (size_t)ret >= nodelen) { + return EAI_MEMORY; + } + if (flags & NI_NOFQDN) { + p = strchr(node,'.'); + if (p) { + *p = '\0'; + } + } + return 0; + } + + if (flags & NI_NAMEREQD) { + /* If we require a name and didn't get one, + * automatically fail. */ + return ret; + } + /* Otherwise just fall into the numeric host code... */ + } + p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr); + ret = snprintf(node, nodelen, "%s", p); + if (ret < 0 || (size_t)ret >= nodelen) { + return EAI_MEMORY; + } + return 0; +} + +static int getservicenameinfo(const struct sockaddr *sa, + char *service, + size_t servicelen, + int flags) +{ + int ret = -1; + int port = ntohs(((struct sockaddr_in *)sa)->sin_port); + + if (!(flags & NI_NUMERICSERV)) { + struct servent *se = getservbyport( + port, + (flags & NI_DGRAM) ? "udp" : "tcp"); + if (se && se->s_name) { + /* Service name looked up successfully. */ + ret = snprintf(service, servicelen, "%s", se->s_name); + if (ret < 0 || (size_t)ret >= servicelen) { + return EAI_MEMORY; + } + return 0; + } + /* Otherwise just fall into the numeric service code... */ + } + ret = snprintf(service, servicelen, "%d", port); + if (ret < 0 || (size_t)ret >= servicelen) { + return EAI_MEMORY; + } + return 0; +} + +/* + * Convert an ipv4 address to a hostname. + * + * Bugs: - No IPv6 support. + */ +int rep_getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *node, size_t nodelen, + char *service, size_t servicelen, int flags) +{ + + /* Invalid arguments. */ + if (sa == NULL || (node == NULL && service == NULL)) { + return EAI_FAIL; + } + + if (sa->sa_family != AF_INET) { + return EAI_FAIL; + } + + if (salen < sizeof(struct sockaddr_in)) { + return EAI_FAIL; + } + + if (node) { + return gethostnameinfo(sa, node, nodelen, flags); + } + + if (service) { + return getservicenameinfo(sa, service, servicelen, flags); + } + return 0; +} diff --git a/ldb-2.0.8/lib/replace/getaddrinfo.h b/ldb-2.0.8/lib/replace/getaddrinfo.h new file mode 100644 index 0000000..cf040da --- /dev/null +++ b/ldb-2.0.8/lib/replace/getaddrinfo.h @@ -0,0 +1,91 @@ +/* +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this paragraph +and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, +EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS +TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +*/ + +/*------------------------------------------------------------------------- + * + * getaddrinfo.h + * Support getaddrinfo() on platforms that don't have it. + * + * Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO, + * whether or not the library routine getaddrinfo() can be found. This + * policy is needed because on some platforms a manually installed libbind.a + * may provide getaddrinfo(), yet the system headers may not provide the + * struct definitions needed to call it. To avoid conflict with the libbind + * definition in such cases, we rename our routines to pg_xxx() via macros. + * + +in lib/replace we use rep_xxx() + + * This code will also work on platforms where struct addrinfo is defined + * in the system headers but no getaddrinfo() can be located. + * + * Copyright (c) 2003-2007, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ +#ifndef GETADDRINFO_H +#define GETADDRINFO_H + +#ifndef HAVE_GETADDRINFO + +/* Rename private copies per comments above */ +#ifdef getaddrinfo +#undef getaddrinfo +#endif +#define getaddrinfo rep_getaddrinfo +#define HAVE_GETADDRINFO + +#ifdef freeaddrinfo +#undef freeaddrinfo +#endif +#define freeaddrinfo rep_freeaddrinfo +#define HAVE_FREEADDRINFO + +#ifdef gai_strerror +#undef gai_strerror +#endif +#define gai_strerror rep_gai_strerror +#define HAVE_GAI_STRERROR + +#ifdef getnameinfo +#undef getnameinfo +#endif +#define getnameinfo rep_getnameinfo +#ifndef HAVE_GETNAMEINFO +#define HAVE_GETNAMEINFO +#endif + +extern int rep_getaddrinfo(const char *node, const char *service, + const struct addrinfo * hints, struct addrinfo ** res); +extern void rep_freeaddrinfo(struct addrinfo * res); +extern const char *rep_gai_strerror(int errcode); +extern int rep_getnameinfo(const struct sockaddr * sa, socklen_t salen, + char *node, size_t nodelen, + char *service, size_t servicelen, int flags); +#endif /* HAVE_GETADDRINFO */ + +#endif /* GETADDRINFO_H */ diff --git a/ldb-2.0.8/lib/replace/getifaddrs.c b/ldb-2.0.8/lib/replace/getifaddrs.c new file mode 100644 index 0000000..a55ef7e --- /dev/null +++ b/ldb-2.0.8/lib/replace/getifaddrs.c @@ -0,0 +1,383 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Jeremy Allison 2007 + Copyright (C) Jelmer Vernooij 2007 + + ** 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 . +*/ + +#include "replace.h" +#include "system/network.h" + +#include +#include +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifndef SIOCGIFCONF +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#endif + +#ifdef HAVE_IFACE_GETIFADDRS +#define _FOUND_IFACE_ANY +#else + +void rep_freeifaddrs(struct ifaddrs *ifp) +{ + if (ifp != NULL) { + free(ifp->ifa_name); + free(ifp->ifa_addr); + free(ifp->ifa_netmask); + free(ifp->ifa_dstaddr); + freeifaddrs(ifp->ifa_next); + free(ifp); + } +} + +static struct sockaddr *sockaddr_dup(struct sockaddr *sa) +{ + struct sockaddr *ret; + socklen_t socklen; +#ifdef HAVE_SOCKADDR_SA_LEN + socklen = sa->sa_len; +#else + socklen = sizeof(struct sockaddr_storage); +#endif + ret = calloc(1, socklen); + if (ret == NULL) + return NULL; + memcpy(ret, sa, socklen); + return ret; +} +#endif + +#ifdef HAVE_IFACE_IFCONF + +/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 + V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2. + + It probably also works on any BSD style system. */ + +int rep_getifaddrs(struct ifaddrs **ifap) +{ + struct ifconf ifc; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + n = ifc.ifc_len / sizeof(struct ifreq); + + /* Loop through interfaces, looking for given IP address */ + for (i=n-1; i>=0; i--) { + if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) == -1) { + freeifaddrs(*ifap); + close(fd); + return -1; + } + + curif = calloc(1, sizeof(struct ifaddrs)); + if (curif == NULL) { + freeifaddrs(*ifap); + close(fd); + return -1; + } + curif->ifa_name = strdup(ifr[i].ifr_name); + if (curif->ifa_name == NULL) { + free(curif); + freeifaddrs(*ifap); + close(fd); + return -1; + } + curif->ifa_flags = ifr[i].ifr_flags; + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_next = NULL; + + curif->ifa_addr = NULL; + if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) { + curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr); + if (curif->ifa_addr == NULL) { + free(curif->ifa_name); + free(curif); + freeifaddrs(*ifap); + close(fd); + return -1; + } + } + + curif->ifa_netmask = NULL; + if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) { + curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr); + if (curif->ifa_netmask == NULL) { + if (curif->ifa_addr != NULL) { + free(curif->ifa_addr); + } + free(curif->ifa_name); + free(curif); + freeifaddrs(*ifap); + close(fd); + return -1; + } + } + + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + lastif = curif; + } + + close(fd); + + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFCONF */ +#ifdef HAVE_IFACE_IFREQ + +#ifndef I_STR +#include +#endif + +/**************************************************************************** +this should cover most of the streams based systems +Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code +****************************************************************************/ +int rep_getifaddrs(struct ifaddrs **ifap) +{ + struct ifreq ifreq; + struct strioctl strioctl; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + strioctl.ic_cmd = SIOCGIFCONF; + strioctl.ic_dp = buff; + strioctl.ic_len = sizeof(buff); + if (ioctl(fd, I_STR, &strioctl) < 0) { + close(fd); + return -1; + } + + /* we can ignore the possible sizeof(int) here as the resulting + number of interface structures won't change */ + n = strioctl.ic_len / sizeof(struct ifreq); + + /* we will assume that the kernel returns the length as an int + at the start of the buffer if the offered size is a + multiple of the structure size plus an int */ + if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { + ifr = (struct ifreq *)(buff + sizeof(int)); + } else { + ifr = (struct ifreq *)buff; + } + + /* Loop through interfaces */ + + for (i = 0; iifa_next = curif; + } + + strioctl.ic_cmd = SIOCGIFFLAGS; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_flags = ifreq.ifr_flags; + + strioctl.ic_cmd = SIOCGIFADDR; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_name = strdup(ifreq.ifr_name); + curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr); + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_next = NULL; + curif->ifa_netmask = NULL; + + strioctl.ic_cmd = SIOCGIFNETMASK; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr); + + lastif = curif; + } + + close(fd); + + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFREQ */ +#ifdef HAVE_IFACE_AIX + +/**************************************************************************** +this one is for AIX (tested on 4.2) +****************************************************************************/ +int rep_getifaddrs(struct ifaddrs **ifap) +{ + char buff[8192]; + int fd, i; + struct ifconf ifc; + struct ifreq *ifr=NULL; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + /* Loop through interfaces */ + i = ifc.ifc_len; + + while (i > 0) { + unsigned int inc; + + inc = ifr->ifr_addr.sa_len; + + if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif = calloc(1, sizeof(struct ifaddrs)); + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + + curif->ifa_name = strdup(ifr->ifr_name); + curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr); + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_netmask = NULL; + curif->ifa_next = NULL; + + if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif->ifa_flags = ifr->ifr_flags; + + if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr); + + lastif = curif; + + next: + /* + * Patch from Archie Cobbs (archie@whistle.com). The + * addresses in the SIOCGIFCONF interface list have a + * minimum size. Usually this doesn't matter, but if + * your machine has tunnel interfaces, etc. that have + * a zero length "link address", this does matter. */ + + if (inc < sizeof(ifr->ifr_addr)) + inc = sizeof(ifr->ifr_addr); + inc += IFNAMSIZ; + + ifr = (struct ifreq*) (((char*) ifr) + inc); + i -= inc; + } + + close(fd); + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_AIX */ +#ifndef _FOUND_IFACE_ANY +int rep_getifaddrs(struct ifaddrs **ifap) +{ + errno = ENOSYS; + return -1; +} +#endif diff --git a/ldb-2.0.8/lib/replace/hdr_replace.h b/ldb-2.0.8/lib/replace/hdr_replace.h new file mode 100644 index 0000000..6cfa50f --- /dev/null +++ b/ldb-2.0.8/lib/replace/hdr_replace.h @@ -0,0 +1,2 @@ +/* this is a replacement header for a missing system header */ +#include "replace.h" diff --git a/ldb-2.0.8/lib/replace/inet_aton.c b/ldb-2.0.8/lib/replace/inet_aton.c new file mode 100644 index 0000000..c6b3bb1 --- /dev/null +++ b/ldb-2.0.8/lib/replace/inet_aton.c @@ -0,0 +1,33 @@ +/* + * Unix SMB/CIFS implementation. + * replacement functions + * Copyright (C) Michael Adam 2008 + * + * ** 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 + * Lesser 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 . + */ + +#include "replace.h" +#include "system/network.h" + +/** + * We know that we have inet_pton from earlier libreplace checks. + */ +int rep_inet_aton(const char *src, struct in_addr *dst) +{ + return (inet_pton(AF_INET, src, dst) > 0) ? 1 : 0; +} diff --git a/ldb-2.0.8/lib/replace/inet_ntoa.c b/ldb-2.0.8/lib/replace/inet_ntoa.c new file mode 100644 index 0000000..e3b80eb --- /dev/null +++ b/ldb-2.0.8/lib/replace/inet_ntoa.c @@ -0,0 +1,39 @@ +/* + * Unix SMB/CIFS implementation. + * replacement routines for broken systems + * Copyright (C) Andrew Tridgell 2003 + * Copyright (C) Michael Adam 2008 + * + * ** 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 + * Lesser 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 . + */ + +#include "replace.h" +#include "system/network.h" + +/** + * NOTE: this is not thread safe, but it can't be, either + * since it returns a pointer to static memory. + */ +char *rep_inet_ntoa(struct in_addr ip) +{ + uint8_t *p = (uint8_t *)&ip.s_addr; + static char buf[18]; + slprintf(buf, 17, "%d.%d.%d.%d", + (int)p[0], (int)p[1], (int)p[2], (int)p[3]); + return buf; +} diff --git a/ldb-2.0.8/lib/replace/inet_ntop.c b/ldb-2.0.8/lib/replace/inet_ntop.c new file mode 100644 index 0000000..fb3d8e9 --- /dev/null +++ b/ldb-2.0.8/lib/replace/inet_ntop.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#include "replace.h" +#include "system/network.h" + +#define NS_INT16SZ 2 +#define NS_IN6ADDRSZ 16 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const unsigned char *src, char *dst, + socklen_t size); + +#ifdef AF_INET6 +static const char *inet_ntop6(const unsigned char *src, char *dst, + socklen_t size); +#endif + +/* char * + * isc_net_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +rep_inet_ntop(int af, const void *src, char *dst, socklen_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#ifdef AF_INET6 + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a unsigned char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const unsigned char *src, char *dst, socklen_t size) +{ + static const char *fmt = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + size_t len; + + len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]); + if (len >= size) { + errno = ENOSPC; + return (NULL); + } + memcpy(dst, tmp, len + 1); + + return (dst); +} + +/* const char * + * isc_inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +#ifdef AF_INET6 +static const char * +inet_ntop6(const unsigned char *src, char *dst, socklen_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i, inc; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + inc = snprintf(tp, 5, "%x", words[i]); + if (inc >= 5) { + abort(); + } + tp += inc; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + memcpy(dst, tmp, tp - tmp); + return (dst); +} +#endif /* AF_INET6 */ diff --git a/ldb-2.0.8/lib/replace/inet_pton.c b/ldb-2.0.8/lib/replace/inet_pton.c new file mode 100644 index 0000000..80e4865 --- /dev/null +++ b/ldb-2.0.8/lib/replace/inet_pton.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "replace.h" +#include "system/network.h" + +#define NS_INT16SZ 2 +#define NS_INADDRSZ 4 +#define NS_IN6ADDRSZ 16 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4(const char *src, unsigned char *dst); +#ifdef AF_INET6 +static int inet_pton6(const char *src, unsigned char *dst); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +rep_inet_pton(int af, + const char *src, + void *dst) +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); +#ifdef AF_INET6 + case AF_INET6: + return (inet_pton6(src, dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + unsigned char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + unsigned int new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, NS_INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +#ifdef AF_INET6 +static int +inet_pton6(src, dst) + const char *src; + unsigned char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + unsigned int val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} +#endif diff --git a/ldb-2.0.8/lib/replace/poll.c b/ldb-2.0.8/lib/replace/poll.c new file mode 100644 index 0000000..1105617 --- /dev/null +++ b/ldb-2.0.8/lib/replace/poll.c @@ -0,0 +1,139 @@ +/* + Unix SMB/CIFS implementation. + poll.c - poll wrapper + + This file is based on code from libssh (LGPLv2.1+ at the time it + was downloaded), thus the following copyrights: + + Copyright (c) 2009-2010 by Andreas Schneider + Copyright (c) 2003-2009 by Aris Adamantiadis + Copyright (c) 2009 Aleksandar Kanchev + Copyright (C) Volker Lendecke 2011 + + ** 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 + Lesser 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 . + */ + +#include "replace.h" +#include "system/select.h" +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + + +int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + fd_set rfds, wfds, efds; + struct timeval tv, *ptv; + int max_fd; + int rc; + nfds_t i; + + if ((fds == NULL) && (nfds != 0)) { + errno = EFAULT; + return -1; + } + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + rc = 0; + max_fd = 0; + + /* compute fd_sets and find largest descriptor */ + for (i = 0; i < nfds; i++) { + if ((fds[i].fd < 0) || (fds[i].fd >= FD_SETSIZE)) { + fds[i].revents = POLLNVAL; + continue; + } + + if (fds[i].events & (POLLIN | POLLRDNORM)) { + FD_SET(fds[i].fd, &rfds); + } + if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { + FD_SET(fds[i].fd, &wfds); + } + if (fds[i].events & (POLLPRI | POLLRDBAND)) { + FD_SET(fds[i].fd, &efds); + } + if (fds[i].fd > max_fd && + (fds[i].events & (POLLIN | POLLOUT | POLLPRI | + POLLRDNORM | POLLRDBAND | + POLLWRNORM | POLLWRBAND))) { + max_fd = fds[i].fd; + } + } + + if (timeout < 0) { + ptv = NULL; + } else { + ptv = &tv; + if (timeout == 0) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + } + } + + rc = select(max_fd + 1, &rfds, &wfds, &efds, ptv); + if (rc < 0) { + return -1; + } + + for (rc = 0, i = 0; i < nfds; i++) { + if ((fds[i].fd < 0) || (fds[i].fd >= FD_SETSIZE)) { + continue; + } + + fds[i].revents = 0; + + if (FD_ISSET(fds[i].fd, &rfds)) { + int err = errno; + int available = 0; + int ret; + + /* support for POLLHUP */ + ret = ioctl(fds[i].fd, FIONREAD, &available); + if ((ret == -1) || (available == 0)) { + fds[i].revents |= POLLHUP; + } else { + fds[i].revents |= fds[i].events + & (POLLIN | POLLRDNORM); + } + + errno = err; + } + if (FD_ISSET(fds[i].fd, &wfds)) { + fds[i].revents |= fds[i].events + & (POLLOUT | POLLWRNORM | POLLWRBAND); + } + if (FD_ISSET(fds[i].fd, &efds)) { + fds[i].revents |= fds[i].events + & (POLLPRI | POLLRDBAND); + } + if (fds[i].revents & ~POLLHUP) { + rc++; + } + } + return rc; +} diff --git a/ldb-2.0.8/lib/replace/replace-test.h b/ldb-2.0.8/lib/replace/replace-test.h new file mode 100644 index 0000000..ed8e75e --- /dev/null +++ b/ldb-2.0.8/lib/replace/replace-test.h @@ -0,0 +1,9 @@ +#ifndef __LIB_REPLACE_REPLACE_TEST_H__ +#define __LIB_REPLACE_REPLACE_TEST_H__ + +int libreplace_test_strptime(void); +int test_readdir_os2_delete(void); +int getifaddrs_test(void); + +#endif /* __LIB_REPLACE_REPLACE_TEST_H__ */ + diff --git a/ldb-2.0.8/lib/replace/replace-testsuite.h b/ldb-2.0.8/lib/replace/replace-testsuite.h new file mode 100644 index 0000000..b28dbec --- /dev/null +++ b/ldb-2.0.8/lib/replace/replace-testsuite.h @@ -0,0 +1,10 @@ +#ifndef __LIB_REPLACE_REPLACE_TESTSUITE_H__ +#define __LIB_REPLACE_REPLACE_TESTSUITE_H__ + +#include +struct torture_context; + +bool torture_local_replace(struct torture_context *ctx); + +#endif /* __LIB_REPLACE_REPLACE_TESTSUITE_H__ */ + diff --git a/ldb-2.0.8/lib/replace/replace.c b/ldb-2.0.8/lib/replace/replace.c new file mode 100644 index 0000000..a14322b --- /dev/null +++ b/ldb-2.0.8/lib/replace/replace.c @@ -0,0 +1,1058 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for broken systems + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jelmer Vernooij 2005-2008 + Copyright (C) Matthieu Patou 2010 + + ** 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 + Lesser 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 . +*/ + +#include "replace.h" + +#include "system/filesys.h" +#include "system/time.h" +#include "system/network.h" +#include "system/passwd.h" +#include "system/syslog.h" +#include "system/locale.h" +#include "system/wait.h" + +#ifdef _WIN32 +#define mkdir(d,m) _mkdir(d) +#endif + +void replace_dummy(void); +void replace_dummy(void) {} + +#ifndef HAVE_FTRUNCATE + /******************************************************************* +ftruncate for operating systems that don't have it +********************************************************************/ +int rep_ftruncate(int f, off_t l) +{ +#ifdef HAVE_CHSIZE + return chsize(f,l); +#elif defined(F_FREESP) + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = l; + fl.l_type = F_WRLCK; + return fcntl(f, F_FREESP, &fl); +#else +#error "you must have a ftruncate function" +#endif +} +#endif /* HAVE_FTRUNCATE */ + + +#ifndef HAVE_STRLCPY +/* + * Like strncpy but does not 0 fill the buffer and always null + * terminates. bufsize is the size of the destination buffer. + * Returns the length of s. + */ +size_t rep_strlcpy(char *d, const char *s, size_t bufsize) +{ + size_t len = strlen(s); + size_t ret = len; + + if (bufsize <= 0) { + return 0; + } + if (len >= bufsize) { + len = bufsize - 1; + } + memcpy(d, s, len); + d[len] = 0; + return ret; +} +#endif + +#ifndef HAVE_STRLCAT +/* like strncat but does not 0 fill the buffer and always null + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ +size_t rep_strlcat(char *d, const char *s, size_t bufsize) +{ + size_t len1 = strnlen(d, bufsize); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + if (bufsize < (len1+1)) { + return ret; + } + len2 = bufsize - (len1+1); + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } + return ret; +} +#endif + +#ifndef HAVE_MKTIME +/******************************************************************* +a mktime() replacement for those who don't have it - contributed by +C.A. Lademann +Corrections by richard.kettlewell@kewill.com +********************************************************************/ + +#define MINUTE 60 +#define HOUR 60*MINUTE +#define DAY 24*HOUR +#define YEAR 365*DAY +time_t rep_mktime(struct tm *t) +{ + struct tm *u; + time_t epoch = 0; + int n; + int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + y, m, i; + + if(t->tm_year < 70) + return((time_t)-1); + + n = t->tm_year + 1900 - 1; + epoch = (t->tm_year - 70) * YEAR + + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; + + y = t->tm_year + 1900; + m = 0; + + for(i = 0; i < t->tm_mon; i++) { + epoch += mon [m] * DAY; + if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) + epoch += DAY; + + if(++m > 11) { + m = 0; + y++; + } + } + + epoch += (t->tm_mday - 1) * DAY; + epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; + + if((u = localtime(&epoch)) != NULL) { + t->tm_sec = u->tm_sec; + t->tm_min = u->tm_min; + t->tm_hour = u->tm_hour; + t->tm_mday = u->tm_mday; + t->tm_mon = u->tm_mon; + t->tm_year = u->tm_year; + t->tm_wday = u->tm_wday; + t->tm_yday = u->tm_yday; + t->tm_isdst = u->tm_isdst; + } + + return(epoch); +} +#endif /* !HAVE_MKTIME */ + + +#ifndef HAVE_INITGROUPS +/**************************************************************************** + some systems don't have an initgroups call +****************************************************************************/ +int rep_initgroups(char *name, gid_t id) +{ +#ifndef HAVE_SETGROUPS + /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ + errno = ENOSYS; + return -1; +#else /* HAVE_SETGROUPS */ + +#include + + gid_t *grouplst = NULL; + int max_gr = NGROUPS_MAX; + int ret; + int i,j; + struct group *g; + char *gr; + + if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) { + errno = ENOMEM; + return -1; + } + + grouplst[0] = id; + i = 1; + while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { + if (g->gr_gid == id) + continue; + j = 0; + gr = g->gr_mem[0]; + while (gr && (*gr != (char)NULL)) { + if (strcmp(name,gr) == 0) { + grouplst[i] = g->gr_gid; + i++; + gr = (char *)NULL; + break; + } + gr = g->gr_mem[++j]; + } + } + endgrent(); + ret = setgroups(i, grouplst); + free(grouplst); + return ret; +#endif /* HAVE_SETGROUPS */ +} +#endif /* HAVE_INITGROUPS */ + + +#ifndef HAVE_MEMMOVE +/******************************************************************* +safely copies memory, ensuring no overlap problems. +this is only used if the machine does not have its own memmove(). +this is not the fastest algorithm in town, but it will do for our +needs. +********************************************************************/ +void *rep_memmove(void *dest,const void *src,int size) +{ + unsigned long d,s; + int i; + if (dest==src || !size) return(dest); + + d = (unsigned long)dest; + s = (unsigned long)src; + + if ((d >= (s+size)) || (s >= (d+size))) { + /* no overlap */ + memcpy(dest,src,size); + return(dest); + } + + if (d < s) { + /* we can forward copy */ + if (s-d >= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=0;i= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=size-1;i>=0;i--) idest[i] = isrc[i]; + } else { + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; + } + } + return(dest); +} +#endif /* HAVE_MEMMOVE */ + +#ifndef HAVE_STRDUP +/**************************************************************************** +duplicate a string +****************************************************************************/ +char *rep_strdup(const char *s) +{ + size_t len; + char *ret; + + if (!s) return(NULL); + + len = strlen(s)+1; + ret = (char *)malloc(len); + if (!ret) return(NULL); + memcpy(ret,s,len); + return(ret); +} +#endif /* HAVE_STRDUP */ + +#ifndef HAVE_SETLINEBUF +void rep_setlinebuf(FILE *stream) +{ + setvbuf(stream, (char *)NULL, _IOLBF, 0); +} +#endif /* HAVE_SETLINEBUF */ + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG +void rep_vsyslog (int facility_priority, const char *format, va_list arglist) +{ + char *msg = NULL; + vasprintf(&msg, format, arglist); + if (!msg) + return; + syslog(facility_priority, "%s", msg); + free(msg); +} +#endif /* HAVE_SYSLOG */ +#endif /* HAVE_VSYSLOG */ + +#ifndef HAVE_STRNLEN +/** + Some platforms don't have strnlen +**/ + size_t rep_strnlen(const char *s, size_t max) +{ + size_t len; + + for (len = 0; len < max; len++) { + if (s[len] == '\0') { + break; + } + } + return len; +} +#endif + +#ifndef HAVE_STRNDUP +/** + Some platforms don't have strndup. +**/ +char *rep_strndup(const char *s, size_t n) +{ + char *ret; + + n = strnlen(s, n); + ret = malloc(n+1); + if (!ret) + return NULL; + memcpy(ret, s, n); + ret[n] = 0; + + return ret; +} +#endif + +#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4) +int rep_waitpid(pid_t pid,int *status,int options) +{ + return wait4(pid, status, options, NULL); +} +#endif + +#ifndef HAVE_SETEUID +int rep_seteuid(uid_t euid) +{ +#ifdef HAVE_SETRESUID + return setresuid(-1, euid, -1); +#else + errno = ENOSYS; + return -1; +#endif +} +#endif + +#ifndef HAVE_SETEGID +int rep_setegid(gid_t egid) +{ +#ifdef HAVE_SETRESGID + return setresgid(-1, egid, -1); +#else + errno = ENOSYS; + return -1; +#endif +} +#endif + +/******************************************************************* +os/2 also doesn't have chroot +********************************************************************/ +#ifndef HAVE_CHROOT +int rep_chroot(const char *dname) +{ + errno = ENOSYS; + return -1; +} +#endif + +/***************************************************************** + Possibly replace mkstemp if it is broken. +*****************************************************************/ + +#ifndef HAVE_SECURE_MKSTEMP +int rep_mkstemp(char *template) +{ + /* have a reasonable go at emulating it. Hope that + the system mktemp() isn't completely hopeless */ + mktemp(template); + if (template[0] == 0) + return -1; + return open(template, O_CREAT|O_EXCL|O_RDWR, 0600); +} +#endif + +#ifndef HAVE_MKDTEMP +char *rep_mkdtemp(char *template) +{ + char *dname; + + if ((dname = mktemp(template))) { + if (mkdir(dname, 0700) >= 0) { + return dname; + } + } + + return NULL; +} +#endif + +/***************************************************************** + Watch out: this is not thread safe. +*****************************************************************/ + +#ifndef HAVE_PREAD +ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return read(__fd, __buf, __nbytes); +} +#endif + +/***************************************************************** + Watch out: this is not thread safe. +*****************************************************************/ + +#ifndef HAVE_PWRITE +ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return write(__fd, __buf, __nbytes); +} +#endif + +#ifndef HAVE_STRCASESTR +char *rep_strcasestr(const char *haystack, const char *needle) +{ + const char *s; + size_t nlen = strlen(needle); + for (s=haystack;*s;s++) { + if (toupper(*needle) == toupper(*s) && + strncasecmp(s, needle, nlen) == 0) { + return (char *)((uintptr_t)s); + } + } + return NULL; +} +#endif + +#ifndef HAVE_STRSEP +char *rep_strsep(char **pps, const char *delim) +{ + char *ret = *pps; + char *p = *pps; + + if (p == NULL) { + return NULL; + } + p += strcspn(p, delim); + if (*p == '\0') { + *pps = NULL; + } else { + *p = '\0'; + *pps = p + 1; + } + return ret; +} +#endif + +#ifndef HAVE_STRTOK_R +/* based on GLIBC version, copyright Free Software Foundation */ +char *rep_strtok_r(char *s, const char *delim, char **save_ptr) +{ + char *token; + + if (s == NULL) s = *save_ptr; + + s += strspn(s, delim); + if (*s == '\0') { + *save_ptr = s; + return NULL; + } + + token = s; + s = strpbrk(token, delim); + if (s == NULL) { + *save_ptr = token + strlen(token); + } else { + *s = '\0'; + *save_ptr = s + 1; + } + + return token; +} +#endif + + +#ifndef HAVE_STRTOLL +long long int rep_strtoll(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOQ + return strtoq(str, endptr, base); +#elif defined(HAVE___STRTOLL) + return __strtoll(str, endptr, base); +#elif SIZEOF_LONG == SIZEOF_LONG_LONG + return (long long int) strtol(str, endptr, base); +#else +# error "You need a strtoll function" +#endif +} +#else +#ifdef HAVE_BSD_STRTOLL +#undef strtoll +long long int rep_strtoll(const char *str, char **endptr, int base) +{ + int saved_errno = errno; + long long int nb = strtoll(str, endptr, base); + /* With glibc EINVAL is only returned if base is not ok */ + if (errno == EINVAL) { + if (base == 0 || (base >1 && base <37)) { + /* Base was ok so it's because we were not + * able to make the convertion. + * Let's reset errno. + */ + errno = saved_errno; + } + } + return nb; +} +#endif /* HAVE_BSD_STRTOLL */ +#endif /* HAVE_STRTOLL */ + + +#ifndef HAVE_STRTOULL +unsigned long long int rep_strtoull(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOUQ + return strtouq(str, endptr, base); +#elif defined(HAVE___STRTOULL) + return __strtoull(str, endptr, base); +#elif SIZEOF_LONG == SIZEOF_LONG_LONG + return (unsigned long long int) strtoul(str, endptr, base); +#else +# error "You need a strtoull function" +#endif +} +#else +#ifdef HAVE_BSD_STRTOLL +#undef strtoull +unsigned long long int rep_strtoull(const char *str, char **endptr, int base) +{ + int saved_errno = errno; + unsigned long long int nb = strtoull(str, endptr, base); + /* With glibc EINVAL is only returned if base is not ok */ + if (errno == EINVAL) { + if (base == 0 || (base >1 && base <37)) { + /* Base was ok so it's because we were not + * able to make the convertion. + * Let's reset errno. + */ + errno = saved_errno; + } + } + return nb; +} +#endif /* HAVE_BSD_STRTOLL */ +#endif /* HAVE_STRTOULL */ + +#ifndef HAVE_SETENV +int rep_setenv(const char *name, const char *value, int overwrite) +{ + char *p; + size_t l1, l2; + int ret; + + if (!overwrite && getenv(name)) { + return 0; + } + + l1 = strlen(name); + l2 = strlen(value); + + p = malloc(l1+l2+2); + if (p == NULL) { + return -1; + } + memcpy(p, name, l1); + p[l1] = '='; + memcpy(p+l1+1, value, l2); + p[l1+l2+1] = 0; + + ret = putenv(p); + if (ret != 0) { + free(p); + } + + return ret; +} +#endif + +#ifndef HAVE_UNSETENV +int rep_unsetenv(const char *name) +{ + extern char **environ; + size_t len = strlen(name); + size_t i, count; + + if (environ == NULL || getenv(name) == NULL) { + return 0; + } + + for (i=0;environ[i];i++) /* noop */ ; + + count=i; + + for (i=0;i= needlelen) { + char *p = (char *)memchr(haystack, *(const char *)needle, + haystacklen-(needlelen-1)); + if (!p) return NULL; + if (memcmp(p, needle, needlelen) == 0) { + return p; + } + haystack = p+1; + haystacklen -= (p - (const char *)haystack) + 1; + } + return NULL; +} +#endif + +#if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF) +int rep_vdprintf(int fd, const char *format, va_list ap) +{ + char *s = NULL; + int ret; + + vasprintf(&s, format, ap); + if (s == NULL) { + errno = ENOMEM; + return -1; + } + ret = write(fd, s, strlen(s)); + free(s); + return ret; +} +#endif + +#if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF) +int rep_dprintf(int fd, const char *format, ...) +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = vdprintf(fd, format, ap); + va_end(ap); + + return ret; +} +#endif + +#ifndef HAVE_GET_CURRENT_DIR_NAME +char *rep_get_current_dir_name(void) +{ + char buf[PATH_MAX+1]; + char *p; + p = getcwd(buf, sizeof(buf)); + if (p == NULL) { + return NULL; + } + return strdup(p); +} +#endif + +#ifndef HAVE_STRERROR_R +int rep_strerror_r(int errnum, char *buf, size_t buflen) +{ + char *s = strerror(errnum); + if (strlen(s)+1 > buflen) { + errno = ERANGE; + return -1; + } + strncpy(buf, s, buflen); + return 0; +} +#elif (!defined(STRERROR_R_XSI_NOT_GNU)) +#undef strerror_r +int rep_strerror_r(int errnum, char *buf, size_t buflen) +{ + char *s = strerror_r(errnum, buf, buflen); + if (s == NULL) { + /* Shouldn't happen, should always get a string */ + return EINVAL; + } + if (s != buf) { + strlcpy(buf, s, buflen); + if (strlen(s) > buflen - 1) { + return ERANGE; + } + } + return 0; + +} +#endif + +#ifndef HAVE_CLOCK_GETTIME +int rep_clock_gettime(clockid_t clk_id, struct timespec *tp) +{ + struct timeval tval; + switch (clk_id) { + case 0: /* CLOCK_REALTIME :*/ +#if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID) + gettimeofday(&tval,NULL); +#else + gettimeofday(&tval); +#endif + tp->tv_sec = tval.tv_sec; + tp->tv_nsec = tval.tv_usec * 1000; + break; + default: + errno = EINVAL; + return -1; + } + return 0; +} +#endif + +#ifndef HAVE_MEMALIGN +void *rep_memalign( size_t align, size_t size ) +{ +#if defined(HAVE_POSIX_MEMALIGN) + void *p = NULL; + int ret = posix_memalign( &p, align, size ); + if ( ret == 0 ) + return p; + + return NULL; +#else + /* On *BSD systems memaligns doesn't exist, but memory will + * be aligned on allocations of > pagesize. */ +#if defined(SYSCONF_SC_PAGESIZE) + size_t pagesize = (size_t)sysconf(_SC_PAGESIZE); +#elif defined(HAVE_GETPAGESIZE) + size_t pagesize = (size_t)getpagesize(); +#else + size_t pagesize = (size_t)-1; +#endif + if (pagesize == (size_t)-1) { + errno = ENOSYS; + return NULL; + } + if (size < pagesize) { + size = pagesize; + } + return malloc(size); +#endif +} +#endif + +#ifndef HAVE_GETPEEREID +int rep_getpeereid(int s, uid_t *uid, gid_t *gid) +{ +#if defined(HAVE_PEERCRED) + struct ucred cred; + socklen_t cred_len = sizeof(struct ucred); + int ret; + +#undef getsockopt + ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len); + if (ret != 0) { + return -1; + } + + if (cred_len != sizeof(struct ucred)) { + errno = EINVAL; + return -1; + } + + *uid = cred.uid; + *gid = cred.gid; + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} +#endif + +#ifndef HAVE_USLEEP +int rep_usleep(useconds_t sec) +{ + struct timeval tval; + /* + * Fake it with select... + */ + tval.tv_sec = 0; + tval.tv_usec = usecs/1000; + select(0,NULL,NULL,NULL,&tval); + return 0; +} +#endif /* HAVE_USLEEP */ + +#ifndef HAVE_SETPROCTITLE +void rep_setproctitle(const char *fmt, ...) +{ +} +#endif +#ifndef HAVE_SETPROCTITLE_INIT +void rep_setproctitle_init(int argc, char *argv[], char *envp[]) +{ +} +#endif + +#ifndef HAVE_MEMSET_S +# ifndef RSIZE_MAX +# define RSIZE_MAX (SIZE_MAX >> 1) +# endif + +int rep_memset_s(void *dest, size_t destsz, int ch, size_t count) +{ + if (dest == NULL) { + return EINVAL; + } + + if (destsz > RSIZE_MAX || + count > RSIZE_MAX || + count > destsz) { + return ERANGE; + } + +#if defined(HAVE_MEMSET_EXPLICIT) + memset_explicit(dest, destsz, ch, count); +#else /* HAVE_MEMSET_EXPLICIT */ + memset(dest, ch, count); +# if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION) + /* See http://llvm.org/bugs/show_bug.cgi?id=15495 */ + __asm__ volatile("" : : "g"(dest) : "memory"); +# endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */ +#endif /* HAVE_MEMSET_EXPLICIT */ + + return 0; +} +#endif /* HAVE_MEMSET_S */ + +#ifndef HAVE_GETPROGNAME +# ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME +# define PROGNAME_SIZE 32 +static char rep_progname[PROGNAME_SIZE]; +# endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */ + +const char *rep_getprogname(void) +{ +#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME + return program_invocation_short_name; +#else /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */ + FILE *fp = NULL; + char cmdline[4096] = {0}; + char *p = NULL; + pid_t pid; + size_t nread; + int len; + int rc; + + if (rep_progname[0] != '\0') { + return rep_progname; + } + + len = snprintf(rep_progname, sizeof(rep_progname), "%s", ""); + if (len <= 0) { + return NULL; + } + + pid = getpid(); + if (pid <= 1 || pid == (pid_t)-1) { + return NULL; + } + + len = snprintf(cmdline, + sizeof(cmdline), + "/proc/%u/cmdline", + (unsigned int)pid); + if (len <= 0 || len == sizeof(cmdline)) { + return NULL; + } + + fp = fopen(cmdline, "r"); + if (fp == NULL) { + return NULL; + } + + nread = fread(cmdline, 1, sizeof(cmdline) - 1, fp); + + rc = fclose(fp); + if (rc != 0) { + return NULL; + } + + if (nread == 0) { + return NULL; + } + + cmdline[nread] = '\0'; + + p = strrchr(cmdline, '/'); + if (p != NULL) { + p++; + } else { + p = cmdline; + } + + len = strlen(p); + if (len > PROGNAME_SIZE) { + p[PROGNAME_SIZE - 1] = '\0'; + } + + (void)snprintf(rep_progname, sizeof(rep_progname), "%s", p); + + return rep_progname; +#endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */ +} +#endif /* HAVE_GETPROGNAME */ diff --git a/ldb-2.0.8/lib/replace/replace.h b/ldb-2.0.8/lib/replace/replace.h new file mode 100644 index 0000000..1658465 --- /dev/null +++ b/ldb-2.0.8/lib/replace/replace.h @@ -0,0 +1,976 @@ +/* + Unix SMB/CIFS implementation. + + macros to go along with the lib/replace/ portability layer code + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2006-2008 + Copyright (C) Jeremy Allison 2007. + + ** 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 + Lesser 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 . +*/ + +#ifndef _LIBREPLACE_REPLACE_H +#define _LIBREPLACE_REPLACE_H + +#ifndef NO_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STANDARDS_H +#include +#endif + +/* + * Needs to be defined before std*.h and string*.h are included + * As it's also needed when Python.h is the first header we + * require a global -D__STDC_WANT_LIB_EXT1__=1 + */ +#ifndef __STDC_WANT_LIB_EXT1__ +#error -D__STDC_WANT_LIB_EXT1__=1 required +#endif + +#include +#include +#include +#include + +#ifndef HAVE_DECL_EWOULDBLOCK +#define EWOULDBLOCK EAGAIN +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) +#include "win32_replace.h" +#endif + + +#ifdef HAVE_INTTYPES_H +#define __STDC_FORMAT_MACROS +#include +#elif defined(HAVE_STDINT_H) +#include +/* force off HAVE_INTTYPES_H so that roken doesn't try to include both, + which causes a warning storm on irix */ +#undef HAVE_INTTYPES_H +#endif + +#ifdef HAVE_MALLOC_H +#include +#endif + +#ifndef __PRI64_PREFIX +# if __WORDSIZE == 64 && ! defined __APPLE__ +# define __PRI64_PREFIX "l" +# else +# define __PRI64_PREFIX "ll" +# endif +#endif + +/* Decimal notation. */ +#ifndef PRId8 +# define PRId8 "d" +#endif +#ifndef PRId16 +# define PRId16 "d" +#endif +#ifndef PRId32 +# define PRId32 "d" +#endif +#ifndef PRId64 +# define PRId64 __PRI64_PREFIX "d" +#endif + +#ifndef PRIi8 +# define PRIi8 "i" +#endif +#ifndef PRIi16 +# define PRIi16 "i" +#endif +#ifndef PRIi32 +# define PRIi32 "i" +#endif +#ifndef PRIi64 +# define PRIi64 __PRI64_PREFIX "i" +#endif + +#ifndef PRIu8 +# define PRIu8 "u" +#endif +#ifndef PRIu16 +# define PRIu16 "u" +#endif +#ifndef PRIu32 +# define PRIu32 "u" +#endif +#ifndef PRIu64 +# define PRIu64 __PRI64_PREFIX "u" +#endif + +#ifndef SCNd8 +# define SCNd8 "hhd" +#endif +#ifndef SCNd16 +# define SCNd16 "hd" +#endif +#ifndef SCNd32 +# define SCNd32 "d" +#endif +#ifndef SCNd64 +# define SCNd64 __PRI64_PREFIX "d" +#endif + +#ifndef SCNi8 +# define SCNi8 "hhi" +#endif +#ifndef SCNi16 +# define SCNi16 "hi" +#endif +#ifndef SCNi32 +# define SCNi32 "i" +#endif +#ifndef SCNi64 +# define SCNi64 __PRI64_PREFIX "i" +#endif + +#ifndef SCNu8 +# define SCNu8 "hhu" +#endif +#ifndef SCNu16 +# define SCNu16 "hu" +#endif +#ifndef SCNu32 +# define SCNu32 "u" +#endif +#ifndef SCNu64 +# define SCNu64 __PRI64_PREFIX "u" +#endif + +#ifdef HAVE_BSD_STRING_H +#include +#endif + +#ifdef HAVE_BSD_UNISTD_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif + +#ifdef HAVE_SETPROCTITLE_H +#include +#endif + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_LINUX_TYPES_H +/* + * This is needed as some broken header files require this to be included early + */ +#include +#endif + +#ifndef HAVE_STRERROR +extern char *sys_errlist[]; +#define strerror(i) sys_errlist[i] +#endif + +#ifndef HAVE_ERRNO_DECL +extern int errno; +#endif + +#ifndef HAVE_STRDUP +#define strdup rep_strdup +char *rep_strdup(const char *s); +#endif + +#ifndef HAVE_MEMMOVE +#define memmove rep_memmove +void *rep_memmove(void *dest,const void *src,int size); +#endif + +#ifndef HAVE_MEMMEM +#define memmem rep_memmem +void *rep_memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); +#endif + +#ifndef HAVE_MEMALIGN +#define memalign rep_memalign +void *rep_memalign(size_t boundary, size_t size); +#endif + +#ifndef HAVE_MKTIME +#define mktime rep_mktime +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_TIMEGM +#define timegm rep_timegm +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_UTIME +#define utime rep_utime +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_UTIMES +#define utimes rep_utimes +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_STRLCPY +#define strlcpy rep_strlcpy +size_t rep_strlcpy(char *d, const char *s, size_t bufsize); +#endif + +#ifndef HAVE_STRLCAT +#define strlcat rep_strlcat +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 +char *rep_strndup(const char *s, size_t n); +#endif + +#if (defined(BROKEN_STRNLEN) || !defined(HAVE_STRNLEN)) +#undef HAVE_STRNLEN +#define strnlen rep_strnlen +size_t rep_strnlen(const char *s, size_t n); +#endif + +#if !defined(HAVE_DECL_ENVIRON) +# ifdef __APPLE__ +# include +# define environ (*_NSGetEnviron()) +# else /* __APPLE__ */ +extern char **environ; +# endif /* __APPLE */ +#endif /* !defined(HAVE_DECL_ENVIRON) */ + +#ifndef HAVE_SETENV +#define setenv rep_setenv +int rep_setenv(const char *name, const char *value, int overwrite); +#else +#ifndef HAVE_SETENV_DECL +int setenv(const char *name, const char *value, int overwrite); +#endif +#endif + +#ifndef HAVE_UNSETENV +#define unsetenv rep_unsetenv +int rep_unsetenv(const char *name); +#endif + +#ifndef HAVE_SETEUID +#define seteuid rep_seteuid +int rep_seteuid(uid_t); +#endif + +#ifndef HAVE_SETEGID +#define setegid rep_setegid +int rep_setegid(gid_t); +#endif + +#if (defined(USE_SETRESUID) && !defined(HAVE_SETRESUID_DECL)) +/* stupid glibc */ +int setresuid(uid_t ruid, uid_t euid, uid_t suid); +#endif +#if (defined(USE_SETRESUID) && !defined(HAVE_SETRESGID_DECL)) +int setresgid(gid_t rgid, gid_t egid, gid_t sgid); +#endif + +#ifndef HAVE_CHOWN +#define chown rep_chown +int rep_chown(const char *path, uid_t uid, gid_t gid); +#endif + +#ifndef HAVE_CHROOT +#define chroot rep_chroot +int rep_chroot(const char *dirname); +#endif + +#ifndef HAVE_LINK +#define link rep_link +int rep_link(const char *oldpath, const char *newpath); +#endif + +#ifndef HAVE_READLINK +#define readlink rep_readlink +ssize_t rep_readlink(const char *path, char *buf, size_t bufsize); +#endif + +#ifndef HAVE_SYMLINK +#define symlink rep_symlink +int rep_symlink(const char *oldpath, const char *newpath); +#endif + +#ifndef HAVE_REALPATH +#define realpath rep_realpath +char *rep_realpath(const char *path, char *resolved_path); +#endif + +#ifndef HAVE_LCHOWN +#define lchown rep_lchown +int rep_lchown(const char *fname,uid_t uid,gid_t gid); +#endif + +#ifdef HAVE_UNIX_H +#include +#endif + +#ifndef HAVE_SETLINEBUF +#define setlinebuf rep_setlinebuf +void rep_setlinebuf(FILE *); +#endif + +#ifndef HAVE_STRCASESTR +#define strcasestr rep_strcasestr +char *rep_strcasestr(const char *haystack, const char *needle); +#endif + +#ifndef HAVE_STRSEP +#define strsep rep_strsep +char *rep_strsep(char **pps, const char *delim); +#endif + +#ifndef HAVE_STRTOK_R +#define strtok_r rep_strtok_r +char *rep_strtok_r(char *s, const char *delim, char **save_ptr); +#endif + + + +#ifndef HAVE_STRTOLL +#define strtoll rep_strtoll +long long int rep_strtoll(const char *str, char **endptr, int base); +#else +#ifdef HAVE_BSD_STRTOLL +#define strtoll rep_strtoll +long long int rep_strtoll(const char *str, char **endptr, int base); +#endif +#endif + +#ifndef HAVE_STRTOULL +#define strtoull rep_strtoull +unsigned long long int rep_strtoull(const char *str, char **endptr, int base); +#else +#ifdef HAVE_BSD_STRTOLL /* yes, it's not HAVE_BSD_STRTOULL */ +#define strtoull rep_strtoull +unsigned long long int rep_strtoull(const char *str, char **endptr, int base); +#endif +#endif + +#ifndef HAVE_FTRUNCATE +#define ftruncate rep_ftruncate +int rep_ftruncate(int,off_t); +#endif + +#ifndef HAVE_INITGROUPS +#define initgroups rep_initgroups +int rep_initgroups(char *name, gid_t id); +#endif + +#if !defined(HAVE_BZERO) && defined(HAVE_MEMSET) +#define bzero(a,b) memset((a),'\0',(b)) +#endif + +#ifndef HAVE_DLERROR +#define dlerror rep_dlerror +char *rep_dlerror(void); +#endif + +#ifndef HAVE_DLOPEN +#define dlopen rep_dlopen +#ifdef DLOPEN_TAKES_UNSIGNED_FLAGS +void *rep_dlopen(const char *name, unsigned int flags); +#else +void *rep_dlopen(const char *name, int flags); +#endif +#endif + +#ifndef HAVE_DLSYM +#define dlsym rep_dlsym +void *rep_dlsym(void *handle, const char *symbol); +#endif + +#ifndef HAVE_DLCLOSE +#define dlclose rep_dlclose +int rep_dlclose(void *handle); +#endif + +#ifndef HAVE_SOCKETPAIR +#define socketpair rep_socketpair +/* prototype is in system/network.h */ +#endif + +#ifndef PRINTF_ATTRIBUTE +#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 + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#ifndef _DEPRECATED_ +#ifdef HAVE___ATTRIBUTE__ +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif + +#if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define vdprintf rep_vdprintf +int rep_vdprintf(int fd, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +#endif + +#if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define dprintf rep_dprintf +int rep_dprintf(int fd, const char *format, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#if !defined(HAVE_VASPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define vasprintf rep_vasprintf +int rep_vasprintf(char **ptr, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +#endif + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define snprintf rep_snprintf +int rep_snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4); +#endif + +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define vsnprintf rep_vsnprintf +int rep_vsnprintf(char *,size_t ,const char *, va_list ap) PRINTF_ATTRIBUTE(3,0); +#endif + +#if !defined(HAVE_ASPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define asprintf rep_asprintf +int rep_asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#if !defined(HAVE_C99_VSNPRINTF) +#ifdef REPLACE_BROKEN_PRINTF +/* + * We do not redefine printf by default + * as it breaks the build if system headers + * use __attribute__((format(printf, 3, 0))) + * instead of __attribute__((format(__printf__, 3, 0))) + */ +#define printf rep_printf +#endif +int rep_printf(const char *, ...) PRINTF_ATTRIBUTE(1,2); +#endif + +#if !defined(HAVE_C99_VSNPRINTF) +#define fprintf rep_fprintf +int rep_fprintf(FILE *stream, const char *, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG +#define vsyslog rep_vsyslog +void rep_vsyslog (int facility_priority, const char *format, va_list arglist) PRINTF_ATTRIBUTE(2,0); +#endif +#endif + +/* we used to use these fns, but now we have good replacements + for snprintf and vsnprintf */ +#define slprintf snprintf + + +#ifndef HAVE_VA_COPY +#undef va_copy +#ifdef HAVE___VA_COPY +#define va_copy(dest, src) __va_copy(dest, src) +#else +#define va_copy(dest, src) (dest) = (src) +#endif +#endif + +#ifndef HAVE_VOLATILE +#define volatile +#endif + +#ifndef HAVE_COMPARISON_FN_T +typedef int (*comparison_fn_t)(const void *, const void *); +#endif + +#ifndef HAVE_WORKING_STRPTIME +#define strptime rep_strptime +struct tm; +char *rep_strptime(const char *buf, const char *format, struct tm *tm); +#endif + +#ifndef HAVE_DUP2 +#define dup2 rep_dup2 +int rep_dup2(int oldfd, int newfd); +#endif + +/* Load header file for dynamic linking stuff */ +#ifdef HAVE_DLFCN_H +#include +#endif + +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif +#ifndef RTLD_NOW +#define RTLD_NOW 0 +#endif +#ifndef RTLD_GLOBAL +#define RTLD_GLOBAL 0 +#endif + +#ifndef HAVE_SECURE_MKSTEMP +#define mkstemp(path) rep_mkstemp(path) +int rep_mkstemp(char *temp); +#endif + +#ifndef HAVE_MKDTEMP +#define mkdtemp rep_mkdtemp +char *rep_mkdtemp(char *template); +#endif + +#ifndef HAVE_PREAD +#define pread rep_pread +ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset); +#define LIBREPLACE_PREAD_REPLACED 1 +#else +#define LIBREPLACE_PREAD_NOT_REPLACED 1 +#endif + +#ifndef HAVE_PWRITE +#define pwrite rep_pwrite +ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset); +#define LIBREPLACE_PWRITE_REPLACED 1 +#else +#define LIBREPLACE_PWRITE_NOT_REPLACED 1 +#endif + +#if !defined(HAVE_INET_NTOA) || defined(REPLACE_INET_NTOA) +#define inet_ntoa rep_inet_ntoa +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_INET_PTON +#define inet_pton rep_inet_pton +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_INET_NTOP +#define inet_ntop rep_inet_ntop +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_INET_ATON +#define inet_aton rep_inet_aton +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_CONNECT +#define connect rep_connect +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETHOSTBYNAME +#define gethostbyname rep_gethostbyname +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETIFADDRS +#define getifaddrs rep_getifaddrs +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_FREEIFADDRS +#define freeifaddrs rep_freeifaddrs +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GET_CURRENT_DIR_NAME +#define get_current_dir_name rep_get_current_dir_name +char *rep_get_current_dir_name(void); +#endif + +#if (!defined(HAVE_STRERROR_R) || !defined(STRERROR_R_XSI_NOT_GNU)) +#define strerror_r rep_strerror_r +int rep_strerror_r(int errnum, char *buf, size_t buflen); +#endif + +#if !defined(HAVE_CLOCK_GETTIME) +#define clock_gettime rep_clock_gettime +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +/* The extra casts work around common compiler bugs. */ +#define _TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +/* The outer cast is needed to work around a bug in Cray C 5.0.3.0. + It is necessary at least when t == time_t. */ +#define _TYPE_MINIMUM(t) ((t) (_TYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) +#define _TYPE_MAXIMUM(t) ((t) (~ (t) 0 - _TYPE_MINIMUM (t))) + +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef UINT64_MAX +#define UINT64_MAX ((uint64_t)-1) +#endif + +#ifndef INT64_MAX +#define INT64_MAX 9223372036854775807LL +#endif + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +#ifndef INT32_MAX +#define INT32_MAX _TYPE_MAXIMUM(int32_t) +#endif + +#ifdef HAVE_STDBOOL_H +#include +#endif + +#if !defined(HAVE_BOOL) +#ifdef HAVE__Bool +#define bool _Bool +#else +typedef int bool; +#endif +#endif + +#if !defined(HAVE_INTPTR_T) +typedef long long intptr_t ; +#define __intptr_t_defined +#endif + +#if !defined(HAVE_UINTPTR_T) +typedef unsigned long long uintptr_t ; +#define __uintptr_t_defined +#endif + +#if !defined(HAVE_PTRDIFF_T) +typedef unsigned long long ptrdiff_t ; +#endif + +/* + * to prevent from doing a redefine of 'bool' + * + * IRIX, HPUX, MacOS 10 and Solaris need BOOL_DEFINED + * Tru64 needs _BOOL_EXISTS + * AIX needs _BOOL,_TRUE,_FALSE + */ +#ifndef BOOL_DEFINED +#define BOOL_DEFINED +#endif +#ifndef _BOOL_EXISTS +#define _BOOL_EXISTS +#endif +#ifndef _BOOL +#define _BOOL +#endif + +#ifndef __bool_true_false_are_defined +#define __bool_true_false_are_defined +#endif + +#ifndef true +#define true (1) +#endif +#ifndef false +#define false (0) +#endif + +#ifndef _TRUE +#define _TRUE true +#endif +#ifndef _FALSE +#define _FALSE false +#endif + +#ifndef HAVE_FUNCTION_MACRO +#ifdef HAVE_func_MACRO +#define __FUNCTION__ __func__ +#else +#define __FUNCTION__ ("") +#endif +#endif + + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#if !defined(HAVE_VOLATILE) +#define volatile +#endif + +/** + this is a warning hack. The idea is to use this everywhere that we + get the "discarding const" warning from gcc. That doesn't actually + fix the problem of course, but it means that when we do get to + cleaning them up we can do it by searching the code for + discard_const. + + It also means that other error types aren't as swamped by the noise + of hundreds of const warnings, so we are more likely to notice when + we get new errors. + + Please only add more uses of this macro when you find it + _really_ hard to fix const warnings. Our aim is to eventually use + this function in only a very few places. + + Also, please call this via the discard_const_p() macro interface, as that + makes the return type safe. +*/ +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) + +/** Type-safe version of discard_const */ +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#ifndef __STRINGSTRING +#define __STRINGSTRING(x) __STRING(x) +#endif + +#ifndef __LINESTR__ +#define __LINESTR__ __STRINGSTRING(__LINE__) +#endif + +#ifndef __location__ +#define __location__ __FILE__ ":" __LINESTR__ +#endif + +/** + * Zero a structure. + */ +#define ZERO_STRUCT(x) memset_s((char *)&(x), sizeof(x), 0, sizeof(x)) + +/** + * Zero a structure given a pointer to the structure. + */ +#define ZERO_STRUCTP(x) do { \ + if ((x) != NULL) { \ + memset_s((char *)(x), sizeof(*(x)), 0, sizeof(*(x))); \ + } \ +} while(0) + +/** + * Zero a structure given a pointer to the structure - no zero check + */ +#define ZERO_STRUCTPN(x) memset_s((char *)(x), sizeof(*(x)), 0, sizeof(*(x))) + +/** + * Zero an array - note that sizeof(array) must work - ie. it must not be a + * pointer + */ +#define ZERO_ARRAY(x) memset_s((char *)(x), sizeof(x), 0, sizeof(x)) + +/** + * Zero a given len of an array + */ +#define ZERO_ARRAY_LEN(x, l) memset_s((char *)(x), (l), 0, (l)) + +/** + * Work out how many elements there are in a static array. + */ +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/** + * Pointer difference macro + */ +#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) + +#ifdef __COMPAR_FN_T +#define QSORT_CAST (__compar_fn_t) +#endif + +#ifndef QSORT_CAST +#define QSORT_CAST (int (*)(const void *, const void *)) +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#ifndef MAX_DNS_NAME_LENGTH +#define MAX_DNS_NAME_LENGTH 256 /* Actually 255 but +1 for terminating null. */ +#endif + +#ifndef HAVE_CRYPT +char *ufc_crypt(const char *key, const char *salt); +#define crypt ufc_crypt +#else +#ifdef HAVE_CRYPT_H +#include +#endif +#endif + +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#else +#ifndef likely +#define likely(x) (x) +#endif +#ifndef unlikely +#define unlikely(x) (x) +#endif +#endif + +#ifndef HAVE_FDATASYNC +#define fdatasync(fd) fsync(fd) +#elif !defined(HAVE_DECL_FDATASYNC) +int fdatasync(int ); +#endif + +/* these are used to mark symbols as local to a shared lib, or + * publicly available via the shared lib API */ +#ifndef _PUBLIC_ +#ifdef HAVE_VISIBILITY_ATTR +#define _PUBLIC_ __attribute__((visibility("default"))) +#else +#define _PUBLIC_ +#endif +#endif + +#ifndef _PRIVATE_ +#ifdef HAVE_VISIBILITY_ATTR +# define _PRIVATE_ __attribute__((visibility("hidden"))) +#else +# define _PRIVATE_ +#endif +#endif + +#ifndef HAVE_POLL +#define poll rep_poll +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETPEEREID +#define getpeereid rep_getpeereid +int rep_getpeereid(int s, uid_t *uid, gid_t *gid); +#endif + +#ifndef HAVE_USLEEP +#define usleep rep_usleep +typedef long useconds_t; +int usleep(useconds_t); +#endif + +#ifndef HAVE_SETPROCTITLE +#define setproctitle rep_setproctitle +void rep_setproctitle(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2); +#endif + +#ifndef HAVE_SETPROCTITLE_INIT +#define setproctitle_init rep_setproctitle_init +void rep_setproctitle_init(int argc, char *argv[], char *envp[]); +#endif + +#ifndef HAVE_MEMSET_S +#define memset_s rep_memset_s +int rep_memset_s(void *dest, size_t destsz, int ch, size_t count); +#endif + +#ifndef HAVE_GETPROGNAME +#define getprogname rep_getprogname +const char *rep_getprogname(void); +#endif + +#ifndef FALL_THROUGH +# ifdef HAVE_FALLTHROUGH_ATTRIBUTE +# define FALL_THROUGH __attribute__ ((fallthrough)) +# else /* HAVE_FALLTHROUGH_ATTRIBUTE */ +# define FALL_THROUGH ((void)0) +# endif /* HAVE_FALLTHROUGH_ATTRIBUTE */ +#endif /* FALL_THROUGH */ + +bool nss_wrapper_enabled(void); +bool nss_wrapper_hosts_enabled(void); +bool socket_wrapper_enabled(void); +bool uid_wrapper_enabled(void); + +/* Needed for Solaris atomic_add_XX functions. */ +#if defined(HAVE_SYS_ATOMIC_H) +#include +#endif + +#endif /* _LIBREPLACE_REPLACE_H */ diff --git a/ldb-2.0.8/lib/replace/snprintf.c b/ldb-2.0.8/lib/replace/snprintf.c new file mode 100644 index 0000000..6e4424b --- /dev/null +++ b/ldb-2.0.8/lib/replace/snprintf.c @@ -0,0 +1,1534 @@ +/* + * NOTE: If you change this file, please merge it into rsync, samba, etc. + */ + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell (papowell@astart.com) + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions + */ + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formatted the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Andrew Tridgell (tridge@samba.org) Oct 1998 + * fixed handling of %.0f + * added test for HAVE_LONG_DOUBLE + * + * tridge@samba.org, idra@samba.org, April 2001 + * got rid of fcvt code (twas buggy and made testing harder) + * added C99 semantics + * + * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 + * actually print args for %g and %e + * + * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 + * Since includes.h isn't included here, VA_COPY has to be defined here. I don't + * see any include file that is guaranteed to be here, so I'm defining it + * locally. Fixes AIX and Solaris builds. + * + * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 + * put the ifdef for HAVE_VA_COPY in one place rather than in lots of + * functions + * + * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 + * Fix usage of va_list passed as an arg. Use __va_copy before using it + * when it exists. + * + * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 + * Fix incorrect zpadlen handling in fmtfp. + * Thanks to Ollie Oldham for spotting it. + * few mods to make it easier to compile the tests. + * addedd the "Ollie" test to the floating point ones. + * + * Martin Pool (mbp@samba.org) April 2003 + * Remove NO_CONFIG_H so that the test case can be built within a source + * tree with less trouble. + * Remove unnecessary SAFE_FREE() definition. + * + * Martin Pool (mbp@samba.org) May 2003 + * Put in a prototype for dummy_snprintf() to quiet compiler warnings. + * + * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even + * if the C library has some snprintf functions already. + * + * Darren Tucker (dtucker@zip.com.au) 2005 + * Fix bug allowing read overruns of the source string with "%.*s" + * Usually harmless unless the read runs outside the process' allocation + * (eg if your malloc does guard pages) in which case it will segfault. + * From OpenSSH. Also added test for same. + * + * Simo Sorce (idra@samba.org) Jan 2006 + * + * Add support for position independent parameters + * fix fmtstr now it conforms to sprintf wrt min.max + * + **************************************************************/ + +#include "replace.h" +#include "system/locale.h" + +#ifdef TEST_SNPRINTF /* need math library headers for testing */ + +/* In test mode, we pretend that this system doesn't have any snprintf + * functions, regardless of what config.h says. */ +# undef HAVE_SNPRINTF +# undef HAVE_VSNPRINTF +# undef HAVE_C99_VSNPRINTF +# undef HAVE_ASPRINTF +# undef HAVE_VASPRINTF +# include +#endif /* TEST_SNPRINTF */ + +#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) +/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ +#include + /* make the compiler happy with an empty file */ + void dummy_snprintf(void); + void dummy_snprintf(void) {} +#endif /* HAVE_SNPRINTF, etc */ + +/* yes this really must be a ||. Don't muck with this (tridge) */ +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + +#ifdef HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +#ifdef HAVE_LONG_LONG +#define LLONG long long +#else +#define LLONG long +#endif + +#ifndef VA_COPY +#ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#else +#ifdef HAVE___VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#else +#define VA_COPY(dest, src) (dest) = (src) +#endif +#endif + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_CHAR 1 +#define DP_C_SHORT 2 +#define DP_C_LONG 3 +#define DP_C_LDOUBLE 4 +#define DP_C_LLONG 5 +#define DP_C_SIZET 6 + +/* Chunk types */ +#define CNK_FMT_STR 0 +#define CNK_INT 1 +#define CNK_OCTAL 2 +#define CNK_UINT 3 +#define CNK_HEX 4 +#define CNK_FLOAT 5 +#define CNK_CHAR 6 +#define CNK_STRING 7 +#define CNK_PTR 8 +#define CNK_NUM 9 +#define CNK_PRCNT 10 + +#define char_to_int(p) ((p)- '0') +#ifndef MAX +#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) +#endif + +struct pr_chunk { + int type; /* chunk type */ + int num; /* parameter number */ + int min; + int max; + int flags; + int cflags; + int start; + int len; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + void *pnum; + struct pr_chunk *min_star; + struct pr_chunk *max_star; + struct pr_chunk *next; +}; + +struct pr_chunk_x { + struct pr_chunk **chunks; + int num; +}; + +static int dopr(char *buffer, size_t maxlen, const char *format, + va_list args_in); +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + LLONG value, int base, int min, int max, int flags); +static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags); +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); +static struct pr_chunk *new_chunk(void); +static int add_cnk_list_entry(struct pr_chunk_x **list, + int max_num, struct pr_chunk *chunk); + +static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) +{ + char ch; + int state; + int pflag; + int pnum; + int pfirst; + size_t currlen; + va_list args; + const char *base; + struct pr_chunk *chunks = NULL; + struct pr_chunk *cnk = NULL; + struct pr_chunk_x *clist = NULL; + int max_pos; + int ret = -1; + + VA_COPY(args, args_in); + + state = DP_S_DEFAULT; + pfirst = 1; + pflag = 0; + pnum = 0; + + max_pos = 0; + base = format; + ch = *format++; + + /* retrieve the string structure as chunks */ + while (state != DP_S_DONE) { + if (ch == '\0') + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + + if (cnk) { + cnk->next = new_chunk(); + cnk = cnk->next; + } else { + cnk = new_chunk(); + } + if (!cnk) goto done; + if (!chunks) chunks = cnk; + + if (ch == '%') { + state = DP_S_FLAGS; + ch = *format++; + } else { + cnk->type = CNK_FMT_STR; + cnk->start = format - base -1; + while ((ch != '\0') && (ch != '%')) ch = *format++; + cnk->len = format - base - cnk->start -1; + } + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + cnk->flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + cnk->flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + cnk->flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + cnk->flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + cnk->flags |= DP_F_ZERO; + ch = *format++; + break; + case 'I': + /* internationalization not supported yet */ + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + cnk->min = 10 * cnk->min + char_to_int (ch); + ch = *format++; + } else if (ch == '$') { + if (!pfirst && !pflag) { + /* parameters must be all positioned or none */ + goto done; + } + if (pfirst) { + pfirst = 0; + pflag = 1; + } + if (cnk->min == 0) /* what ?? */ + goto done; + cnk->num = cnk->min; + cnk->min = 0; + ch = *format++; + } else if (ch == '*') { + if (pfirst) pfirst = 0; + cnk->min_star = new_chunk(); + if (!cnk->min_star) /* out of memory :-( */ + goto done; + cnk->min_star->type = CNK_INT; + if (pflag) { + int num; + ch = *format++; + if (!isdigit((unsigned char)ch)) { + /* parameters must be all positioned or none */ + goto done; + } + for (num = 0; isdigit((unsigned char)ch); ch = *format++) { + num = 10 * num + char_to_int(ch); + } + cnk->min_star->num = num; + if (ch != '$') /* what ?? */ + goto done; + } else { + cnk->min_star->num = ++pnum; + } + max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star); + if (max_pos == 0) /* out of memory :-( */ + goto done; + ch = *format++; + state = DP_S_DOT; + } else { + if (pfirst) pfirst = 0; + state = DP_S_DOT; + } + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (cnk->max < 0) + cnk->max = 0; + cnk->max = 10 * cnk->max + char_to_int (ch); + ch = *format++; + } else if (ch == '$') { + if (!pfirst && !pflag) { + /* parameters must be all positioned or none */ + goto done; + } + if (cnk->max <= 0) /* what ?? */ + goto done; + cnk->num = cnk->max; + cnk->max = -1; + ch = *format++; + } else if (ch == '*') { + cnk->max_star = new_chunk(); + if (!cnk->max_star) /* out of memory :-( */ + goto done; + cnk->max_star->type = CNK_INT; + if (pflag) { + int num; + ch = *format++; + if (!isdigit((unsigned char)ch)) { + /* parameters must be all positioned or none */ + goto done; + } + for (num = 0; isdigit((unsigned char)ch); ch = *format++) { + num = 10 * num + char_to_int(ch); + } + cnk->max_star->num = num; + if (ch != '$') /* what ?? */ + goto done; + } else { + cnk->max_star->num = ++pnum; + } + max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star); + if (max_pos == 0) /* out of memory :-( */ + goto done; + + ch = *format++; + state = DP_S_MOD; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cnk->cflags = DP_C_SHORT; + ch = *format++; + if (ch == 'h') { + cnk->cflags = DP_C_CHAR; + ch = *format++; + } + break; + case 'l': + cnk->cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { /* It's a long long */ + cnk->cflags = DP_C_LLONG; + ch = *format++; + } + break; + case 'j': + cnk->cflags = DP_C_LLONG; + ch = *format++; + break; + case 'L': + cnk->cflags = DP_C_LDOUBLE; + ch = *format++; + break; + case 'z': + cnk->cflags = DP_C_SIZET; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + if (cnk->num == 0) cnk->num = ++pnum; + max_pos = add_cnk_list_entry(&clist, max_pos, cnk); + if (max_pos == 0) /* out of memory :-( */ + goto done; + + switch (ch) { + case 'd': + case 'i': + cnk->type = CNK_INT; + break; + case 'o': + cnk->type = CNK_OCTAL; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'u': + cnk->type = CNK_UINT; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'X': + cnk->flags |= DP_F_UP; + case 'x': + cnk->type = CNK_HEX; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'A': + /* hex float not supported yet */ + case 'E': + case 'G': + case 'F': + cnk->flags |= DP_F_UP; + case 'a': + /* hex float not supported yet */ + case 'e': + case 'f': + case 'g': + cnk->type = CNK_FLOAT; + break; + case 'c': + cnk->type = CNK_CHAR; + break; + case 's': + cnk->type = CNK_STRING; + break; + case 'p': + cnk->type = CNK_PTR; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'n': + cnk->type = CNK_NUM; + break; + case '%': + cnk->type = CNK_PRCNT; + break; + default: + /* Unknown, bail out*/ + goto done; + } + ch = *format++; + state = DP_S_DEFAULT; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + + /* retrieve the format arguments */ + for (pnum = 0; pnum < max_pos; pnum++) { + int i; + + if (clist[pnum].num == 0) { + /* ignoring a parameter should not be permitted + * all parameters must be matched at least once + * BUT seem some system ignore this rule ... + * at least my glibc based system does --SSS + */ +#ifdef DEBUG_SNPRINTF + printf("parameter at position %d not used\n", pnum+1); +#endif + /* eat the parameter */ + va_arg (args, int); + continue; + } + for (i = 1; i < clist[pnum].num; i++) { + if (clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) { + /* nooo noo no! + * all the references to a parameter + * must be of the same type + */ + goto done; + } + } + cnk = clist[pnum].chunks[0]; + switch (cnk->type) { + case CNK_INT: + if (cnk->cflags == DP_C_SHORT) + cnk->value = va_arg (args, int); + else if (cnk->cflags == DP_C_LONG) + cnk->value = va_arg (args, long int); + else if (cnk->cflags == DP_C_LLONG) + cnk->value = va_arg (args, LLONG); + else if (cnk->cflags == DP_C_SIZET) + cnk->value = va_arg (args, ssize_t); + else + cnk->value = va_arg (args, int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_OCTAL: + case CNK_UINT: + case CNK_HEX: + if (cnk->cflags == DP_C_SHORT) + cnk->value = va_arg (args, unsigned int); + else if (cnk->cflags == DP_C_LONG) + cnk->value = (unsigned long int)va_arg (args, unsigned long int); + else if (cnk->cflags == DP_C_LLONG) + cnk->value = (LLONG)va_arg (args, unsigned LLONG); + else if (cnk->cflags == DP_C_SIZET) + cnk->value = (size_t)va_arg (args, size_t); + else + cnk->value = (unsigned int)va_arg (args, unsigned int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_FLOAT: + if (cnk->cflags == DP_C_LDOUBLE) + cnk->fvalue = va_arg (args, LDOUBLE); + else + cnk->fvalue = va_arg (args, double); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->fvalue = cnk->fvalue; + } + break; + + case CNK_CHAR: + cnk->value = va_arg (args, int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_STRING: + cnk->strvalue = va_arg (args, char *); + if (!cnk->strvalue) cnk->strvalue = "(NULL)"; + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->strvalue = cnk->strvalue; + } + break; + + case CNK_PTR: + cnk->strvalue = va_arg (args, void *); + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->strvalue = cnk->strvalue; + } + break; + + case CNK_NUM: + if (cnk->cflags == DP_C_CHAR) + cnk->pnum = va_arg (args, char *); + else if (cnk->cflags == DP_C_SHORT) + cnk->pnum = va_arg (args, short int *); + else if (cnk->cflags == DP_C_LONG) + cnk->pnum = va_arg (args, long int *); + else if (cnk->cflags == DP_C_LLONG) + cnk->pnum = va_arg (args, LLONG *); + else if (cnk->cflags == DP_C_SIZET) + cnk->pnum = va_arg (args, ssize_t *); + else + cnk->pnum = va_arg (args, int *); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->pnum = cnk->pnum; + } + break; + + case CNK_PRCNT: + break; + + default: + /* what ?? */ + goto done; + } + } + /* print out the actual string from chunks */ + currlen = 0; + cnk = chunks; + while (cnk) { + int len, min, max; + + if (cnk->min_star) min = cnk->min_star->value; + else min = cnk->min; + if (cnk->max_star) max = cnk->max_star->value; + else max = cnk->max; + + switch (cnk->type) { + + case CNK_FMT_STR: + if (maxlen != 0 && maxlen > currlen) { + if (maxlen > (currlen + cnk->len)) len = cnk->len; + else len = maxlen - currlen; + + memcpy(&(buffer[currlen]), &(base[cnk->start]), len); + } + currlen += cnk->len; + + break; + + case CNK_INT: + case CNK_UINT: + fmtint (buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags); + break; + + case CNK_OCTAL: + fmtint (buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags); + break; + + case CNK_HEX: + fmtint (buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags); + break; + + case CNK_FLOAT: + fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags); + break; + + case CNK_CHAR: + dopr_outch (buffer, &currlen, maxlen, cnk->value); + break; + + case CNK_STRING: + if (max == -1) { + max = strlen(cnk->strvalue); + } + fmtstr (buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max); + break; + + case CNK_PTR: + fmtint (buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags); + break; + + case CNK_NUM: + if (cnk->cflags == DP_C_CHAR) + *((char *)(cnk->pnum)) = (char)currlen; + else if (cnk->cflags == DP_C_SHORT) + *((short int *)(cnk->pnum)) = (short int)currlen; + else if (cnk->cflags == DP_C_LONG) + *((long int *)(cnk->pnum)) = (long int)currlen; + else if (cnk->cflags == DP_C_LLONG) + *((LLONG *)(cnk->pnum)) = (LLONG)currlen; + else if (cnk->cflags == DP_C_SIZET) + *((ssize_t *)(cnk->pnum)) = (ssize_t)currlen; + else + *((int *)(cnk->pnum)) = (int)currlen; + break; + + case CNK_PRCNT: + dopr_outch (buffer, &currlen, maxlen, '%'); + break; + + default: + /* what ?? */ + goto done; + } + cnk = cnk->next; + } + if (maxlen != 0) { + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else if (maxlen > 0) + buffer[maxlen - 1] = '\0'; + } + ret = currlen; + +done: + va_end(args); + + while (chunks) { + cnk = chunks->next; + free(chunks); + chunks = cnk; + } + if (clist) { + for (pnum = 0; pnum < max_pos; pnum++) { + if (clist[pnum].chunks) free(clist[pnum].chunks); + } + free(clist); + } + return ret; +} + +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + +#ifdef DEBUG_SNPRINTF + printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); +#endif + if (value == 0) { + value = ""; + } + + for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + while (*value && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + LLONG value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned LLONG uvalue; + 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 */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } else { + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < sizeof(convert))); + if (place == sizeof(convert)) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place); +#endif + + /* Spaces */ + while (spadlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + + if (value < 0) + result = -value; + + return result; +} + +static LDOUBLE POW10(int exp) +{ + LDOUBLE result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static LLONG ROUND(LDOUBLE value) +{ + LLONG intpart; + + intpart = (LLONG)value; + value = value - intpart; + if (value >= 0.5) intpart++; + + return intpart; +} + +/* a replacement for modf that doesn't need the math library. Should + be portable, but slow */ +static double my_modf(double x0, double *iptr) +{ + int i; + LLONG l=0; + double x = x0; + double f = 1.0; + + for (i=0;i<100;i++) { + l = (long)x; + if (l <= (x+1) && l >= (x-1)) break; + x *= 0.1; + f *= 10.0; + } + + if (i == 100) { + /* yikes! the number is beyond what we can handle. What do we do? */ + (*iptr) = 0; + return 0; + } + + if (i != 0) { + double i2; + double ret; + + ret = my_modf(x0-l*f, &i2); + (*iptr) = l*f + i2; + return ret; + } + + (*iptr) = l; + return x - (*iptr); +} + + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags) +{ + int signvalue = 0; + double ufvalue; + char iconvert[311]; + char fconvert[311]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + int idx; + double intpart; + double fracpart; + double temp; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) { + signvalue = '-'; + } else { + if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ + signvalue = '+'; + } else { + if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + +#if 0 + if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ +#endif + + /* + * Sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + + temp = ufvalue; + my_modf(temp, &intpart); + + fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); + + if (fracpart >= POW10(max)) { + intpart++; + fracpart -= POW10(max); + } + + + /* Convert integer part */ + do { + temp = intpart*0.1; + my_modf(temp, &intpart); + idx = (int) ((temp -intpart +0.05)* 10.0); + /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ + /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while (intpart && (iplace < 311)); + if (iplace == 311) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + if (fracpart) + { + do { + temp = fracpart*0.1; + my_modf(temp, &fracpart); + idx = (int) ((temp -fracpart +0.05)* 10.0); + /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ + /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while(fracpart && (fplace < 311)); + if (fplace == 311) fplace--; + } + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + +#ifdef DEBUG_SNPRINTF + printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); +#endif + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch (buffer, currlen, maxlen, '.'); + + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + } + + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) { + buffer[(*currlen)] = c; + } + (*currlen)++; +} + +static struct pr_chunk *new_chunk(void) { + struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk)); + + if (!new_c) + return NULL; + + new_c->type = 0; + new_c->num = 0; + new_c->min = 0; + new_c->min_star = NULL; + new_c->max = -1; + new_c->max_star = NULL; + new_c->flags = 0; + new_c->cflags = 0; + new_c->start = 0; + new_c->len = 0; + new_c->value = 0; + new_c->fvalue = 0; + new_c->strvalue = NULL; + new_c->pnum = NULL; + new_c->next = NULL; + + return new_c; +} + +static int add_cnk_list_entry(struct pr_chunk_x **list, + int max_num, struct pr_chunk *chunk) { + struct pr_chunk_x *l; + struct pr_chunk **c; + int max; + int cnum; + int i, pos; + + if (chunk->num > max_num) { + max = chunk->num; + + if (*list == NULL) { + l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max); + pos = 0; + } else { + l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max); + pos = max_num; + } + if (l == NULL) { + for (i = 0; i < max; i++) { + if ((*list)[i].chunks) free((*list)[i].chunks); + } + return 0; + } + for (i = pos; i < max; i++) { + l[i].chunks = NULL; + l[i].num = 0; + } + } else { + l = *list; + max = max_num; + } + + i = chunk->num - 1; + cnum = l[i].num + 1; + if (l[i].chunks == NULL) { + c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum); + } else { + c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum); + } + if (c == NULL) { + for (i = 0; i < max; i++) { + if (l[i].chunks) free(l[i].chunks); + } + return 0; + } + c[l[i].num] = chunk; + l[i].chunks = c; + l[i].num = cnum; + + *list = l; + return max; +} + + int rep_vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + return dopr(str, count, fmt, args); +} +#endif + +/* yes this really must be a ||. Don't muck with this (tridge) + * + * The logic for these two is that we need our own definition if the + * OS *either* has no definition of *sprintf, or if it does have one + * that doesn't work properly according to the autoconf test. + */ +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int rep_snprintf(char *str,size_t count,const char *fmt,...) +{ + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} +#endif + +#ifndef HAVE_C99_VSNPRINTF + int rep_printf(const char *fmt, ...) +{ + va_list ap; + int ret; + char *s; + + s = NULL; + va_start(ap, fmt); + ret = vasprintf(&s, fmt, ap); + va_end(ap); + + if (s) { + fwrite(s, 1, strlen(s), stdout); + } + free(s); + + return ret; +} +#endif + +#ifndef HAVE_C99_VSNPRINTF + int rep_fprintf(FILE *stream, const char *fmt, ...) +{ + va_list ap; + int ret; + char *s; + + s = NULL; + va_start(ap, fmt); + ret = vasprintf(&s, fmt, ap); + va_end(ap); + + if (s) { + fwrite(s, 1, strlen(s), stream); + } + free(s); + + return ret; +} +#endif + +#endif + +#if !defined(HAVE_VASPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int rep_vasprintf(char **ptr, const char *format, va_list ap) +{ + int ret; + va_list ap2; + + VA_COPY(ap2, ap); + ret = vsnprintf(NULL, 0, format, ap2); + va_end(ap2); + if (ret < 0) return ret; + + (*ptr) = (char *)malloc(ret+1); + if (!*ptr) return -1; + + VA_COPY(ap2, ap); + ret = vsnprintf(*ptr, ret+1, format, ap2); + va_end(ap2); + + return ret; +} +#endif + +#if !defined(HAVE_ASPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int rep_asprintf(char **ptr, const char *format, ...) +{ + va_list ap; + int ret; + + *ptr = NULL; + va_start(ap, format); + ret = vasprintf(ptr, format, ap); + va_end(ap); + + return ret; +} +#endif + +#ifdef TEST_SNPRINTF + + int sprintf(char *str,const char *fmt,...); + int printf(const char *fmt,...); + + int main (void) +{ + char buf1[1024]; + char buf2[1024]; + char *buf3; + char *fp_fmt[] = { + "%1.1f", + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + "%.0f", + "%f", + "%-8.8f", + "%-9.9f", + NULL + }; + double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 5.030201, 0.00205, + /* END LIST */ 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + "%d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 1234567890, 0}; + char *str_fmt[] = { + "%10.5s", + "%-10.5s", + "%5.10s", + "%-5.10s", + "%10.1s", + "%0.10s", + "%10.0s", + "%1.10s", + "%s", + "%.1s", + "%.10s", + "%10s", + NULL + }; + char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; +#ifdef HAVE_LONG_LONG + char *ll_fmt[] = { + "%llu", + NULL + }; + LLONG ll_nums[] = { 134, 91340, 341, 0203, 1234567890, 128006186140000000LL, 0}; +#endif + int x, y; + int fail = 0; + int num = 0; + int l1, l2; + char *ss_fmt[] = { + "%zd", + "%zu", + NULL + }; + size_t ss_nums[] = {134, 91340, 123456789, 0203, 1234567890, 0}; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] ; x++) { + for (y = 0; fp_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); + l2 = sprintf (buf2, fp_fmt[x], fp_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + fp_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + + for (x = 0; int_fmt[x] ; x++) { + for (y = 0; int_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); + l2 = sprintf (buf2, int_fmt[x], int_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + int_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + + for (x = 0; str_fmt[x] ; x++) { + for (y = 0; str_vals[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); + l2 = sprintf (buf2, str_fmt[x], str_vals[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + str_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + +#ifdef HAVE_LONG_LONG + for (x = 0; ll_fmt[x] ; x++) { + for (y = 0; ll_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), ll_fmt[x], ll_nums[y]); + l2 = sprintf (buf2, ll_fmt[x], ll_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + ll_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } +#endif + +#define BUFSZ 2048 + + buf1[0] = buf2[0] = '\0'; + if ((buf3 = malloc(BUFSZ)) == NULL) { + fail++; + } else { + num++; + memset(buf3, 'a', BUFSZ); + snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3); + buf1[1023] = '\0'; + if (strcmp(buf1, "a") != 0) { + printf("length limit buf1 '%s' expected 'a'\n", buf1); + fail++; + } + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); + l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); + fail++; + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); + l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); + fail++; + } + + for (x = 0; ss_fmt[x] ; x++) { + for (y = 0; ss_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), ss_fmt[x], ss_nums[y]); + l2 = sprintf (buf2, ss_fmt[x], ss_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + ss_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } +#if 0 + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890); + l2 = sprintf(buf2, "%lld", (LLONG)1234567890); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%lld", l1, buf1, l2, buf2); + fail++; + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123); + l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%Lf", l1, buf1, l2, buf2); + fail++; + } +#endif + printf ("%d tests failed out of %d.\n", fail, num); + + printf("seeing how many digits we support\n"); + { + double v0 = 0.12345678901234567890123456789012345678901; + for (x=0; x<100; x++) { + double p = pow(10, x); + double r = v0*p; + snprintf(buf1, sizeof(buf1), "%1.1f", r); + sprintf(buf2, "%1.1f", r); + if (strcmp(buf1, buf2)) { + printf("we seem to support %d digits\n", x-1); + break; + } + } + } + + return 0; +} +#endif /* TEST_SNPRINTF */ diff --git a/ldb-2.0.8/lib/replace/socket.c b/ldb-2.0.8/lib/replace/socket.c new file mode 100644 index 0000000..4cd9d2e --- /dev/null +++ b/ldb-2.0.8/lib/replace/socket.c @@ -0,0 +1,39 @@ +/* + * Unix SMB/CIFS implementation. + * + * Dummy replacements for socket functions. + * + * Copyright (C) Michael Adam 2008 + * + * ** 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 . + */ + +#include "replace.h" +#include "system/network.h" + +int rep_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + errno = ENOSYS; + return -1; +} + +struct hostent *rep_gethostbyname(const char *name) +{ + errno = ENOSYS; + return NULL; +} diff --git a/ldb-2.0.8/lib/replace/socketpair.c b/ldb-2.0.8/lib/replace/socketpair.c new file mode 100644 index 0000000..c775730 --- /dev/null +++ b/ldb-2.0.8/lib/replace/socketpair.c @@ -0,0 +1,46 @@ +/* + * Unix SMB/CIFS implementation. + * replacement routines for broken systems + * Copyright (C) Jelmer Vernooij 2006 + * Copyright (C) Michael Adam 2008 + * + * ** 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 + * Lesser 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 . + */ + +#include "replace.h" +#include "system/network.h" + +int rep_socketpair(int d, int type, int protocol, int sv[2]) +{ + if (d != AF_UNIX) { + errno = EAFNOSUPPORT; + return -1; + } + + if (protocol != 0) { + errno = EPROTONOSUPPORT; + return -1; + } + + if (type != SOCK_STREAM) { + errno = EOPNOTSUPP; + return -1; + } + + return pipe(sv); +} diff --git a/ldb-2.0.8/lib/replace/strptime.c b/ldb-2.0.8/lib/replace/strptime.c new file mode 100644 index 0000000..bbc7422 --- /dev/null +++ b/ldb-2.0.8/lib/replace/strptime.c @@ -0,0 +1,995 @@ +/* Convert a string representation of time to a time value. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + see . */ + +/* XXX This version of the implementation is not really complete. + Some of the fields cannot add information alone. But if seeing + some of them in the same format (such as year, week and weekday) + this is enough information for determining the date. */ + +#include "replace.h" +#include "system/locale.h" +#include "system/time.h" + +#ifndef __P +# if defined (__GNUC__) || (defined (__STDC__) && __STDC__) +# define __P(args) args +# else +# define __P(args) () +# endif /* GCC. */ +#endif /* Not __P. */ + +#if ! HAVE_LOCALTIME_R && ! defined localtime_r +# ifdef _LIBC +# define localtime_r __localtime_r +# else +/* Approximate localtime_r as best we can in its absence. */ +# define localtime_r my_localtime_r +static struct tm *localtime_r __P ((const time_t *, struct tm *)); +static struct tm * +localtime_r (t, tp) + const time_t *t; + struct tm *tp; +{ + struct tm *l = localtime (t); + if (! l) + return 0; + *tp = *l; + return tp; +} +# endif /* ! _LIBC */ +#endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */ + + +#define match_char(ch1, ch2) if (ch1 != ch2) return NULL +#if defined __GNUC__ && __GNUC__ >= 2 +# define match_string(cs1, s2) \ + ({ size_t len = strlen (cs1); \ + int result = strncasecmp ((cs1), (s2), len) == 0; \ + if (result) (s2) += len; \ + result; }) +#else +/* Oh come on. Get a reasonable compiler. */ +# define match_string(cs1, s2) \ + (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1)) +#endif +/* We intentionally do not use isdigit() for testing because this will + lead to problems with the wide character version. */ +#define get_number(from, to, n) \ + do { \ + int __n = n; \ + val = 0; \ + while (*rp == ' ') \ + ++rp; \ + if (*rp < '0' || *rp > '9') \ + return NULL; \ + do { \ + val *= 10; \ + val += *rp++ - '0'; \ + } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \ + if (val < from || val > to) \ + return NULL; \ + } while (0) +#ifdef _NL_CURRENT +# define get_alt_number(from, to, n) \ + ({ \ + __label__ do_normal; \ + if (*decided != raw) \ + { \ + const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \ + int __n = n; \ + int any = 0; \ + while (*rp == ' ') \ + ++rp; \ + val = 0; \ + do { \ + val *= 10; \ + while (*alts != '\0') \ + { \ + size_t len = strlen (alts); \ + if (strncasecmp (alts, rp, len) == 0) \ + break; \ + alts += len + 1; \ + ++val; \ + } \ + if (*alts == '\0') \ + { \ + if (*decided == not && ! any) \ + goto do_normal; \ + /* If we haven't read anything it's an error. */ \ + if (! any) \ + return NULL; \ + /* Correct the premature multiplication. */ \ + val /= 10; \ + break; \ + } \ + else \ + *decided = loc; \ + } while (--__n > 0 && val * 10 <= to); \ + if (val < from || val > to) \ + return NULL; \ + } \ + else \ + { \ + do_normal: \ + get_number (from, to, n); \ + } \ + 0; \ + }) +#else +# define get_alt_number(from, to, n) \ + /* We don't have the alternate representation. */ \ + get_number(from, to, n) +#endif +#define recursive(new_fmt) \ + (*(new_fmt) != '\0' \ + && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL) + + +#ifdef _LIBC +/* This is defined in locale/C-time.c in the GNU libc. */ +extern const struct locale_data _nl_C_LC_TIME; +extern const unsigned short int __mon_yday[2][13]; + +# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string) +# define ab_weekday_name \ + (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string) +# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string) +# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string) +# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string) +# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string) +# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string) +# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string) +# define HERE_T_FMT_AMPM \ + (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string) +# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string) + +# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n) +#else +static char const weekday_name[][10] = + { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" + }; +static char const ab_weekday_name[][4] = + { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; +static char const month_name[][10] = + { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + }; +static char const ab_month_name[][4] = + { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; +# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y" +# define HERE_D_FMT "%m/%d/%y" +# define HERE_AM_STR "AM" +# define HERE_PM_STR "PM" +# define HERE_T_FMT_AMPM "%I:%M:%S %p" +# define HERE_T_FMT "%H:%M:%S" + +static const unsigned short int __mon_yday[2][13] = + { + /* Normal years. */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + /* Leap years. */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } + }; +#endif + +/* Status of lookup: do we use the locale data or the raw data? */ +enum locale_status { not, loc, raw }; + + +#ifndef __isleap +/* Nonzero if YEAR is a leap year (every 4 years, + except every 100th isn't, and every 400th is). */ +# define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) +#endif + +/* Compute the day of the week. */ +static void +day_of_the_week (struct tm *tm) +{ + /* We know that January 1st 1970 was a Thursday (= 4). Compute the + the difference between this data in the one on TM and so determine + the weekday. */ + int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2); + int wday = (-473 + + (365 * (tm->tm_year - 70)) + + (corr_year / 4) + - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0) + + (((corr_year / 4) / 25) / 4) + + __mon_yday[0][tm->tm_mon] + + tm->tm_mday - 1); + tm->tm_wday = ((wday % 7) + 7) % 7; +} + +/* Compute the day of the year. */ +static void +day_of_the_year (struct tm *tm) +{ + tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon] + + (tm->tm_mday - 1)); +} + +static char * +#ifdef _LIBC +internal_function +#endif +strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm, + enum locale_status *decided, int era_cnt)); + +static char * +#ifdef _LIBC +internal_function +#endif +strptime_internal (rp, fmt, tm, decided, era_cnt) + const char *rp; + const char *fmt; + struct tm *tm; + enum locale_status *decided; + int era_cnt; +{ + int cnt; + size_t val; + int have_I, is_pm; + int century, want_century; + int want_era; + int have_wday, want_xday; + int have_yday; + int have_mon, have_mday; +#ifdef _NL_CURRENT + const char *rp_backup; + size_t num_eras; + struct era_entry *era; + + era = NULL; +#endif + + have_I = is_pm = 0; + century = -1; + want_century = 0; + want_era = 0; + + have_wday = want_xday = have_yday = have_mon = have_mday = 0; + + while (*fmt != '\0') + { + /* A white space in the format string matches 0 more or white + space in the input string. */ + if (isspace (*fmt)) + { + while (isspace (*rp)) + ++rp; + ++fmt; + continue; + } + + /* Any character but `%' must be matched by the same character + in the iput string. */ + if (*fmt != '%') + { + match_char (*fmt++, *rp++); + continue; + } + + ++fmt; +#ifndef _NL_CURRENT + /* We need this for handling the `E' modifier. */ + start_over: +#endif + +#ifdef _NL_CURRENT + /* Make back up of current processing pointer. */ + rp_backup = rp; +#endif + + switch (*fmt++) + { + case '%': + /* Match the `%' character itself. */ + match_char ('%', *rp++); + break; + case 'a': + case 'A': + /* Match day of week. */ + for (cnt = 0; cnt < 7; ++cnt) + { +#ifdef _NL_CURRENT + if (*decided !=raw) + { + if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt), + weekday_name[cnt])) + *decided = loc; + break; + } + if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), + ab_weekday_name[cnt])) + *decided = loc; + break; + } + } +#endif + if (*decided != loc + && (match_string (weekday_name[cnt], rp) + || match_string (ab_weekday_name[cnt], rp))) + { + *decided = raw; + break; + } + } + if (cnt == 7) + /* Does not match a weekday name. */ + return NULL; + tm->tm_wday = cnt; + have_wday = 1; + break; + case 'b': + case 'B': + case 'h': + /* Match month name. */ + for (cnt = 0; cnt < 12; ++cnt) + { +#ifdef _NL_CURRENT + if (*decided !=raw) + { + if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt), + month_name[cnt])) + *decided = loc; + break; + } + if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), + ab_month_name[cnt])) + *decided = loc; + break; + } + } +#endif + if (match_string (month_name[cnt], rp) + || match_string (ab_month_name[cnt], rp)) + { + *decided = raw; + break; + } + } + if (cnt == 12) + /* Does not match a month name. */ + return NULL; + tm->tm_mon = cnt; + want_xday = 1; + break; + case 'c': + /* Match locale's date and time format. */ +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (*decided == not && + strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT)) + *decided = loc; + want_xday = 1; + break; + } + *decided = raw; + } +#endif + if (!recursive (HERE_D_T_FMT)) + return NULL; + want_xday = 1; + break; + case 'C': + /* Match century number. */ +#ifdef _NL_CURRENT + match_century: +#endif + get_number (0, 99, 2); + century = val; + want_xday = 1; + break; + case 'd': + case 'e': + /* Match day of month. */ + get_number (1, 31, 2); + tm->tm_mday = val; + have_mday = 1; + want_xday = 1; + break; + case 'F': + if (!recursive ("%Y-%m-%d")) + return NULL; + want_xday = 1; + break; + case 'x': +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, D_FMT))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT)) + *decided = loc; + want_xday = 1; + break; + } + *decided = raw; + } +#endif + + FALL_THROUGH; + case 'D': + /* Match standard day format. */ + if (!recursive (HERE_D_FMT)) + return NULL; + want_xday = 1; + break; + case 'k': + case 'H': + /* Match hour in 24-hour clock. */ + get_number (0, 23, 2); + tm->tm_hour = val; + have_I = 0; + break; + case 'I': + /* Match hour in 12-hour clock. */ + get_number (1, 12, 2); + tm->tm_hour = val % 12; + have_I = 1; + break; + case 'j': + /* Match day number of year. */ + get_number (1, 366, 3); + tm->tm_yday = val - 1; + have_yday = 1; + break; + case 'm': + /* Match number of month. */ + get_number (1, 12, 2); + tm->tm_mon = val - 1; + have_mon = 1; + want_xday = 1; + break; + case 'M': + /* Match minute. */ + get_number (0, 59, 2); + tm->tm_min = val; + break; + case 'n': + case 't': + /* Match any white space. */ + while (isspace (*rp)) + ++rp; + break; + case 'p': + /* Match locale's equivalent of AM/PM. */ +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp)) + { + if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR)) + *decided = loc; + break; + } + if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp)) + { + if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR)) + *decided = loc; + is_pm = 1; + break; + } + *decided = raw; + } +#endif + if (!match_string (HERE_AM_STR, rp)) { + if (match_string (HERE_PM_STR, rp)) { + is_pm = 1; + } else { + return NULL; + } + } + break; + case 'r': +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (*decided == not && + strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM), + HERE_T_FMT_AMPM)) + *decided = loc; + break; + } + *decided = raw; + } +#endif + if (!recursive (HERE_T_FMT_AMPM)) + return NULL; + break; + case 'R': + if (!recursive ("%H:%M")) + return NULL; + break; + case 's': + { + /* The number of seconds may be very high so we cannot use + the `get_number' macro. Instead read the number + character for character and construct the result while + doing this. */ + time_t secs = 0; + if (*rp < '0' || *rp > '9') + /* We need at least one digit. */ + return NULL; + + do + { + secs *= 10; + secs += *rp++ - '0'; + } + while (*rp >= '0' && *rp <= '9'); + + if (localtime_r (&secs, tm) == NULL) + /* Error in function. */ + return NULL; + } + break; + case 'S': + get_number (0, 61, 2); + tm->tm_sec = val; + break; + case 'X': +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, T_FMT))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT)) + *decided = loc; + break; + } + *decided = raw; + } +#endif + + FALL_THROUGH; + case 'T': + if (!recursive (HERE_T_FMT)) + return NULL; + break; + case 'u': + get_number (1, 7, 1); + tm->tm_wday = val % 7; + have_wday = 1; + break; + case 'g': + get_number (0, 99, 2); + /* XXX This cannot determine any field in TM. */ + break; + case 'G': + if (*rp < '0' || *rp > '9') + return NULL; + /* XXX Ignore the number since we would need some more + information to compute a real date. */ + do + ++rp; + while (*rp >= '0' && *rp <= '9'); + break; + case 'U': + case 'V': + case 'W': + get_number (0, 53, 2); + /* XXX This cannot determine any field in TM without some + information. */ + break; + case 'w': + /* Match number of weekday. */ + get_number (0, 6, 1); + tm->tm_wday = val; + have_wday = 1; + break; + case 'y': +#ifdef _NL_CURRENT + match_year_in_century: +#endif + /* Match year within century. */ + get_number (0, 99, 2); + /* The "Year 2000: The Millennium Rollover" paper suggests that + values in the range 69-99 refer to the twentieth century. */ + tm->tm_year = val >= 69 ? val : val + 100; + /* Indicate that we want to use the century, if specified. */ + want_century = 1; + want_xday = 1; + break; + case 'Y': + /* Match year including century number. */ + get_number (0, 9999, 4); + tm->tm_year = val - 1900; + want_century = 0; + want_xday = 1; + break; + case 'Z': + /* XXX How to handle this? */ + break; + case 'E': +#ifdef _NL_CURRENT + switch (*fmt++) + { + case 'c': + /* Match locale's alternate date and time format. */ + if (*decided != raw) + { + const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT); + + if (*fmt == '\0') + fmt = _NL_CURRENT (LC_TIME, D_T_FMT); + + if (!recursive (fmt)) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (fmt, HERE_D_T_FMT)) + *decided = loc; + want_xday = 1; + break; + } + *decided = raw; + } + /* The C locale has no era information, so use the + normal representation. */ + if (!recursive (HERE_D_T_FMT)) + return NULL; + want_xday = 1; + break; + case 'C': + if (*decided != raw) + { + if (era_cnt >= 0) + { + era = _nl_select_era_entry (era_cnt); + if (match_string (era->era_name, rp)) + { + *decided = loc; + break; + } + else + return NULL; + } + else + { + num_eras = _NL_CURRENT_WORD (LC_TIME, + _NL_TIME_ERA_NUM_ENTRIES); + for (era_cnt = 0; era_cnt < (int) num_eras; + ++era_cnt, rp = rp_backup) + { + era = _nl_select_era_entry (era_cnt); + if (match_string (era->era_name, rp)) + { + *decided = loc; + break; + } + } + if (era_cnt == (int) num_eras) + { + era_cnt = -1; + if (*decided == loc) + return NULL; + } + else + break; + } + + *decided = raw; + } + /* The C locale has no era information, so use the + normal representation. */ + goto match_century; + case 'y': + if (*decided == raw) + goto match_year_in_century; + + get_number(0, 9999, 4); + tm->tm_year = val; + want_era = 1; + want_xday = 1; + break; + case 'Y': + if (*decided != raw) + { + num_eras = _NL_CURRENT_WORD (LC_TIME, + _NL_TIME_ERA_NUM_ENTRIES); + for (era_cnt = 0; era_cnt < (int) num_eras; + ++era_cnt, rp = rp_backup) + { + era = _nl_select_era_entry (era_cnt); + if (recursive (era->era_format)) + break; + } + if (era_cnt == (int) num_eras) + { + era_cnt = -1; + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + *decided = loc; + era_cnt = -1; + break; + } + + *decided = raw; + } + get_number (0, 9999, 4); + tm->tm_year = val - 1900; + want_century = 0; + want_xday = 1; + break; + case 'x': + if (*decided != raw) + { + const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT); + + if (*fmt == '\0') + fmt = _NL_CURRENT (LC_TIME, D_FMT); + + if (!recursive (fmt)) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (fmt, HERE_D_FMT)) + *decided = loc; + break; + } + *decided = raw; + } + if (!recursive (HERE_D_FMT)) + return NULL; + break; + case 'X': + if (*decided != raw) + { + const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT); + + if (*fmt == '\0') + fmt = _NL_CURRENT (LC_TIME, T_FMT); + + if (!recursive (fmt)) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (fmt, HERE_T_FMT)) + *decided = loc; + break; + } + *decided = raw; + } + if (!recursive (HERE_T_FMT)) + return NULL; + break; + default: + return NULL; + } + break; +#else + /* We have no information about the era format. Just use + the normal format. */ + if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y' + && *fmt != 'x' && *fmt != 'X') + /* This is an illegal format. */ + return NULL; + + goto start_over; +#endif + case 'O': + switch (*fmt++) + { + case 'd': + case 'e': + /* Match day of month using alternate numeric symbols. */ + get_alt_number (1, 31, 2); + tm->tm_mday = val; + have_mday = 1; + want_xday = 1; + break; + case 'H': + /* Match hour in 24-hour clock using alternate numeric + symbols. */ + get_alt_number (0, 23, 2); + tm->tm_hour = val; + have_I = 0; + break; + case 'I': + /* Match hour in 12-hour clock using alternate numeric + symbols. */ + get_alt_number (1, 12, 2); + tm->tm_hour = val - 1; + have_I = 1; + break; + case 'm': + /* Match month using alternate numeric symbols. */ + get_alt_number (1, 12, 2); + tm->tm_mon = val - 1; + have_mon = 1; + want_xday = 1; + break; + case 'M': + /* Match minutes using alternate numeric symbols. */ + get_alt_number (0, 59, 2); + tm->tm_min = val; + break; + case 'S': + /* Match seconds using alternate numeric symbols. */ + get_alt_number (0, 61, 2); + tm->tm_sec = val; + break; + case 'U': + case 'V': + case 'W': + get_alt_number (0, 53, 2); + /* XXX This cannot determine any field in TM without + further information. */ + break; + case 'w': + /* Match number of weekday using alternate numeric symbols. */ + get_alt_number (0, 6, 1); + tm->tm_wday = val; + have_wday = 1; + break; + case 'y': + /* Match year within century using alternate numeric symbols. */ + get_alt_number (0, 99, 2); + tm->tm_year = val >= 69 ? val : val + 100; + want_xday = 1; + break; + default: + return NULL; + } + break; + default: + return NULL; + } + } + + if (have_I && is_pm) + tm->tm_hour += 12; + + if (century != -1) + { + if (want_century) + tm->tm_year = tm->tm_year % 100 + (century - 19) * 100; + else + /* Only the century, but not the year. Strange, but so be it. */ + tm->tm_year = (century - 19) * 100; + } + +#ifdef _NL_CURRENT + if (era_cnt != -1) + { + era = _nl_select_era_entry(era_cnt); + if (want_era) + tm->tm_year = (era->start_date[0] + + ((tm->tm_year - era->offset) + * era->absolute_direction)); + else + /* Era start year assumed. */ + tm->tm_year = era->start_date[0]; + } + else +#endif + if (want_era) + return NULL; + + if (want_xday && !have_wday) + { + if ( !(have_mon && have_mday) && have_yday) + { + /* We don't have tm_mon and/or tm_mday, compute them. */ + int t_mon = 0; + while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday) + t_mon++; + if (!have_mon) + tm->tm_mon = t_mon - 1; + if (!have_mday) + tm->tm_mday = + (tm->tm_yday + - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1); + } + day_of_the_week (tm); + } + if (want_xday && !have_yday) + day_of_the_year (tm); + + return discard_const_p(char, rp); +} + + +char *rep_strptime(const char *buf, const char *format, struct tm *tm) +{ + enum locale_status decided; + +#ifdef _NL_CURRENT + decided = not; +#else + decided = raw; +#endif + return strptime_internal (buf, format, tm, &decided, -1); +} diff --git a/ldb-2.0.8/lib/replace/system/README b/ldb-2.0.8/lib/replace/system/README new file mode 100644 index 0000000..69a2b80 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/README @@ -0,0 +1,4 @@ +This directory contains wrappers around logical groups of system +include files. The idea is to avoid #ifdef blocks in the main code, +and instead put all the necessary conditional includes in subsystem +specific header files in this directory. diff --git a/ldb-2.0.8/lib/replace/system/aio.h b/ldb-2.0.8/lib/replace/system/aio.h new file mode 100644 index 0000000..784d77f --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/aio.h @@ -0,0 +1,32 @@ +#ifndef _system_aio_h +#define _system_aio_h +/* + Unix SMB/CIFS implementation. + + AIO system include wrappers + + Copyright (C) Andrew Tridgell 2006 + + ** 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 + Lesser 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 . +*/ + +#ifdef HAVE_LIBAIO_H +#include +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/capability.h b/ldb-2.0.8/lib/replace/system/capability.h new file mode 100644 index 0000000..44b8d51 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/capability.h @@ -0,0 +1,57 @@ +#ifndef _system_capability_h +#define _system_capability_h +/* + Unix SMB/CIFS implementation. + + capability system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . +*/ + +#ifdef HAVE_SYS_CAPABILITY_H + +#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H) +#define _I386_STATFS_H +#define _PPC_STATFS_H +#define BROKEN_REDHAT_7_STATFS_WORKAROUND +#endif + +#if defined(BROKEN_RHEL5_SYS_CAP_HEADER) && !defined(_LINUX_TYPES_H) +#define BROKEN_RHEL5_SYS_CAP_HEADER_WORKAROUND +#endif + +#ifdef HAVE_POSIX_CAPABILITIES +#include +#endif + +#ifdef BROKEN_RHEL5_SYS_CAP_HEADER_WORKAROUND +#undef _LINUX_TYPES_H +#undef BROKEN_RHEL5_SYS_CAP_HEADER_WORKAROUND +#endif + +#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND +#undef _PPC_STATFS_H +#undef _I386_STATFS_H +#undef BROKEN_REDHAT_7_STATFS_WORKAROUND +#endif + +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/dir.h b/ldb-2.0.8/lib/replace/system/dir.h new file mode 100644 index 0000000..497b5a7 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/dir.h @@ -0,0 +1,71 @@ +#ifndef _system_dir_h +#define _system_dir_h +/* + Unix SMB/CIFS implementation. + + directory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . +*/ + +#ifdef HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#ifndef HAVE_MKDIR_MODE +#define mkdir(dir, mode) mkdir(dir) +#endif + +#ifdef HAVE_LIBGEN_H +# include +#endif + +/* Test whether a file name is the "." or ".." directory entries. + * These really should be inline functions. + */ +#ifndef ISDOT +#define ISDOT(path) ( \ + *((const char *)(path)) == '.' && \ + *(((const char *)(path)) + 1) == '\0' \ + ) +#endif + +#ifndef ISDOTDOT +#define ISDOTDOT(path) ( \ + *((const char *)(path)) == '.' && \ + *(((const char *)(path)) + 1) == '.' && \ + *(((const char *)(path)) + 2) == '\0' \ + ) +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/filesys.h b/ldb-2.0.8/lib/replace/system/filesys.h new file mode 100644 index 0000000..1a8cb68 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/filesys.h @@ -0,0 +1,242 @@ +#ifndef _system_filesys_h +#define _system_filesys_h +/* + Unix SMB/CIFS implementation. + + filesystem system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + +#ifdef HAVE_MNTENT_H +#include +#endif + +#ifdef HAVE_SYS_VFS_H +#include +#endif + +#ifdef HAVE_SYS_ACL_H +#include +#endif + +#ifdef HAVE_ACL_LIBACL_H +#include +#endif + +#ifdef HAVE_SYS_FS_S5PARAM_H +#include +#endif + +#if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY) +#include +#endif + +#ifdef HAVE_SYS_STATFS_H +# include +#endif + +#ifdef HAVE_DUSTAT_H +#include +#endif + +#ifdef HAVE_SYS_STATVFS_H +#include +#endif + +#ifdef HAVE_SYS_FILIO_H +#include +#endif + +#ifdef HAVE_SYS_FILE_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#ifdef HAVE_SYS_FCNTL_H +#include +#endif +#endif + +#ifdef HAVE_SYS_MODE_H +/* apparently AIX needs this for S_ISLNK */ +#ifndef S_ISLNK +#include +#endif +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#if defined(HAVE_SYS_ATTRIBUTES_H) +#include +#elif defined(HAVE_ATTR_ATTRIBUTES_H) +#include +#endif + +/* mutually exclusive (SuSE 8.2) */ +#if defined(HAVE_ATTR_XATTR_H) +#include +#elif defined(HAVE_SYS_XATTR_H) +#include +#endif + +#ifdef HAVE_SYS_EA_H +#include +#endif + +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#ifndef XATTR_CREATE +#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +#endif + +#ifndef XATTR_REPLACE +#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ +#endif + +/* Some POSIX definitions for those without */ + +#ifndef S_IFDIR +#define S_IFDIR 0x4000 +#endif +#ifndef S_ISDIR +#define S_ISDIR(mode) ((mode & 0xF000) == S_IFDIR) +#endif +#ifndef S_IRWXU +#define S_IRWXU 00700 /* read, write, execute: owner */ +#endif +#ifndef S_IRUSR +#define S_IRUSR 00400 /* read permission: owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR 00200 /* write permission: owner */ +#endif +#ifndef S_IXUSR +#define S_IXUSR 00100 /* execute permission: owner */ +#endif +#ifndef S_IRWXG +#define S_IRWXG 00070 /* read, write, execute: group */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 00040 /* read permission: group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 00020 /* write permission: group */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 00010 /* execute permission: group */ +#endif +#ifndef S_IRWXO +#define S_IRWXO 00007 /* read, write, execute: other */ +#endif +#ifndef S_IROTH +#define S_IROTH 00004 /* read permission: other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 00002 /* write permission: other */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 00001 /* execute permission: other */ +#endif + +#ifndef O_ACCMODE +#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 256 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifdef _WIN32 +#define mkdir(d,m) _mkdir(d) +#endif + +/* + this allows us to use a uniform error handling for our xattr + wrappers +*/ +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif + + +#if !defined(HAVE_XATTR_XATTR) || defined(XATTR_ADDITIONAL_OPTIONS) + +ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t size); +#define getxattr(path, name, value, size) rep_getxattr(path, name, value, size) +/* define is in "replace.h" */ +ssize_t rep_fgetxattr (int filedes, const char *name, void *value, size_t size); +#define fgetxattr(filedes, name, value, size) rep_fgetxattr(filedes, name, value, size) +/* define is in "replace.h" */ +ssize_t rep_listxattr (const char *path, char *list, size_t size); +#define listxattr(path, list, size) rep_listxattr(path, list, size) +/* define is in "replace.h" */ +ssize_t rep_flistxattr (int filedes, char *list, size_t size); +#define flistxattr(filedes, value, size) rep_flistxattr(filedes, value, size) +/* define is in "replace.h" */ +int rep_removexattr (const char *path, const char *name); +#define removexattr(path, name) rep_removexattr(path, name) +/* define is in "replace.h" */ +int rep_fremovexattr (int filedes, const char *name); +#define fremovexattr(filedes, name) rep_fremovexattr(filedes, name) +/* define is in "replace.h" */ +int rep_setxattr (const char *path, const char *name, const void *value, size_t size, int flags); +#define setxattr(path, name, value, size, flags) rep_setxattr(path, name, value, size, flags) +/* define is in "replace.h" */ +int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags); +#define fsetxattr(filedes, name, value, size, flags) rep_fsetxattr(filedes, name, value, size, flags) +/* define is in "replace.h" */ + +#endif /* !defined(HAVE_XATTR_XATTR) || defined(XATTR_ADDITIONAL_OPTIONS) */ + +#endif diff --git a/ldb-2.0.8/lib/replace/system/glob.h b/ldb-2.0.8/lib/replace/system/glob.h new file mode 100644 index 0000000..3e23db6 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/glob.h @@ -0,0 +1,37 @@ +#ifndef _system_glob_h +#define _system_glob_h +/* + Unix SMB/CIFS implementation. + + glob system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_GLOB_H +#include +#endif + +#ifdef HAVE_FNMATCH_H +#include +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/gssapi.h b/ldb-2.0.8/lib/replace/system/gssapi.h new file mode 100644 index 0000000..d8632d7 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/gssapi.h @@ -0,0 +1,53 @@ +#ifndef _system_gssapi_h +#define _system_gssapi_h + +/* + Unix SMB/CIFS implementation. + + GSSAPI system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_GSSAPI + +#ifdef HAVE_GSSAPI_GSSAPI_EXT_H +#include +#elif defined(HAVE_GSSAPI_GSSAPI_H) +#include +#elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) +#include +#elif defined(HAVE_GSSAPI_H) +#include +#endif + +#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif + +#ifdef HAVE_GSSAPI_GSSAPI_SPNEGO_H +#include +#elif defined(HAVE_GSSAPI_SPNEGO_H) +#include +#endif + +#endif +#endif diff --git a/ldb-2.0.8/lib/replace/system/iconv.h b/ldb-2.0.8/lib/replace/system/iconv.h new file mode 100644 index 0000000..3c8a71f --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/iconv.h @@ -0,0 +1,57 @@ +#ifndef _system_iconv_h +#define _system_iconv_h +/* + Unix SMB/CIFS implementation. + + iconv memory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#if !defined(HAVE_ICONV) && defined(HAVE_ICONV_H) +#define HAVE_ICONV +#endif + +#if !defined(HAVE_GICONV) && defined(HAVE_GICONV_H) +#define HAVE_GICONV +#endif + +#if !defined(HAVE_BICONV) && defined(HAVE_BICONV_H) +#define HAVE_BICONV +#endif + +#ifdef HAVE_NATIVE_ICONV +#if defined(HAVE_ICONV) +#include +#elif defined(HAVE_GICONV) +#include +#elif defined(HAVE_BICONV) +#include +#endif +#endif /* HAVE_NATIVE_ICONV */ + +/* needed for some systems without iconv. Doesn't really matter + what error code we use */ +#ifndef EILSEQ +#define EILSEQ EIO +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/kerberos.h b/ldb-2.0.8/lib/replace/system/kerberos.h new file mode 100644 index 0000000..ebd8657 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/kerberos.h @@ -0,0 +1,41 @@ +#ifndef _system_kerberos_h +#define _system_kerberos_h + +/* + Unix SMB/CIFS implementation. + + kerberos system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_KRB5 + +#ifdef HAVE_KRB5_H +#include +#endif + +#ifdef HAVE_COM_ERR_H +#include +#endif + +#endif +#endif diff --git a/ldb-2.0.8/lib/replace/system/locale.h b/ldb-2.0.8/lib/replace/system/locale.h new file mode 100644 index 0000000..504a3bb --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/locale.h @@ -0,0 +1,42 @@ +#ifndef _system_locale_h +#define _system_locale_h + +/* + Unix SMB/CIFS implementation. + + locale include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_CTYPE_H +#include +#endif + +#ifdef HAVE_LOCALE_H +#include +#endif + +#ifdef HAVE_LANGINFO_H +#include +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/network.h b/ldb-2.0.8/lib/replace/system/network.h new file mode 100644 index 0000000..8254551 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/network.h @@ -0,0 +1,372 @@ +#ifndef _system_network_h +#define _system_network_h +/* + Unix SMB/CIFS implementation. + + networking system include wrappers + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Jelmer Vernooij 2007 + + ** 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 + Lesser 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 . + +*/ + +#ifndef LIBREPLACE_NETWORK_CHECKS +#error "AC_LIBREPLACE_NETWORK_CHECKS missing in configure" +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_UNIXSOCKET +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef HAVE_NETINET_TCP_H +#include +#endif + +/* + * The next three defines are needed to access the IPTOS_* options + * on some systems. + */ + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IN_IP_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NET_IF_H +#include +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_STROPTS_H +#include +#endif + +#ifndef HAVE_SOCKLEN_T +#define HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + +#if !defined (HAVE_INET_NTOA) || defined(REPLACE_INET_NTOA) +/* define is in "replace.h" */ +char *rep_inet_ntoa(struct in_addr ip); +#endif + +#ifndef HAVE_INET_PTON +/* define is in "replace.h" */ +int rep_inet_pton(int af, const char *src, void *dst); +#endif + +#ifndef HAVE_INET_NTOP +/* define is in "replace.h" */ +const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size); +#endif + +#ifndef HAVE_INET_ATON +/* define is in "replace.h" */ +int rep_inet_aton(const char *src, struct in_addr *dst); +#endif + +#ifndef HAVE_CONNECT +/* define is in "replace.h" */ +int rep_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +#endif + +#ifndef HAVE_GETHOSTBYNAME +/* define is in "replace.h" */ +struct hostent *rep_gethostbyname(const char *name); +#endif + +#ifdef HAVE_IFADDRS_H +#include +#endif + +#ifndef HAVE_STRUCT_IFADDRS +struct ifaddrs { + struct ifaddrs *ifa_next; /* Pointer to next struct */ + char *ifa_name; /* Interface name */ + unsigned int ifa_flags; /* Interface flags */ + struct sockaddr *ifa_addr; /* Interface address */ + struct sockaddr *ifa_netmask; /* Interface netmask */ +#undef ifa_dstaddr + struct sockaddr *ifa_dstaddr; /* P2P interface destination */ + void *ifa_data; /* Address specific data */ +}; +#endif + +#ifndef HAVE_GETIFADDRS +int rep_getifaddrs(struct ifaddrs **); +#endif + +#ifndef HAVE_FREEIFADDRS +void rep_freeifaddrs(struct ifaddrs *); +#endif + +#ifndef HAVE_SOCKETPAIR +/* define is in "replace.h" */ +int rep_socketpair(int d, int type, int protocol, int sv[2]); +#endif + +/* + * Some systems have getaddrinfo but not the + * defines needed to use it. + */ + +/* Various macros that ought to be in , but might not be */ + +#ifndef EAI_FAIL +#define EAI_BADFLAGS (-1) +#define EAI_NONAME (-2) +#define EAI_AGAIN (-3) +#define EAI_FAIL (-4) +#define EAI_FAMILY (-6) +#define EAI_SOCKTYPE (-7) +#define EAI_SERVICE (-8) +#define EAI_MEMORY (-10) +#define EAI_SYSTEM (-11) +#endif /* !EAI_FAIL */ + +#ifndef AI_PASSIVE +#define AI_PASSIVE 0x0001 +#endif + +#ifndef AI_CANONNAME +#define AI_CANONNAME 0x0002 +#endif + +#ifndef AI_NUMERICHOST +/* + * some platforms don't support AI_NUMERICHOST; define as zero if using + * the system version of getaddrinfo... + */ +#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO) +#define AI_NUMERICHOST 0 +#else +#define AI_NUMERICHOST 0x0004 +#endif +#endif + +/* + * Some of the functions in source3/lib/util_sock.c use AI_ADDRCONFIG. On QNX + * 6.3.0, this macro is defined but, if it's used, getaddrinfo will fail. This + * prevents smbd from opening any sockets. + * + * If I undefine AI_ADDRCONFIG on such systems and define it to be 0, + * this works around the issue. + */ +#ifdef __QNX__ +#include +#if _NTO_VERSION == 630 +#undef AI_ADDRCONFIG +#endif +#endif +#ifndef AI_ADDRCONFIG +/* + * logic copied from AI_NUMERICHOST + */ +#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO) +#define AI_ADDRCONFIG 0 +#else +#define AI_ADDRCONFIG 0x0020 +#endif +#endif + +#ifndef AI_NUMERICSERV +/* + * logic copied from AI_NUMERICHOST + */ +#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO) +#define AI_NUMERICSERV 0 +#else +#define AI_NUMERICSERV 0x0400 +#endif +#endif + +#ifndef NI_NUMERICHOST +#define NI_NUMERICHOST 1 +#endif + +#ifndef NI_NUMERICSERV +#define NI_NUMERICSERV 2 +#endif + +#ifndef NI_NOFQDN +#define NI_NOFQDN 4 +#endif + +#ifndef NI_NAMEREQD +#define NI_NAMEREQD 8 +#endif + +#ifndef NI_DGRAM +#define NI_DGRAM 16 +#endif + + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + +/* + * glibc on linux doesn't seem to have MSG_WAITALL + * defined. I think the kernel has it though.. + */ +#ifndef MSG_WAITALL +#define MSG_WAITALL 0 +#endif + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK 0x7f000001 +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT EINVAL +#endif + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN HOST_NAME_MAX +#endif + +#ifndef HAVE_SA_FAMILY_T +#define HAVE_SA_FAMILY_T +typedef unsigned short int sa_family_t; +#endif + +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +#define HAVE_STRUCT_SOCKADDR_STORAGE +#ifdef HAVE_STRUCT_SOCKADDR_IN6 +#define sockaddr_storage sockaddr_in6 +#define ss_family sin6_family +#define HAVE_SS_FAMILY 1 +#else /*HAVE_STRUCT_SOCKADDR_IN6*/ +#define sockaddr_storage sockaddr_in +#define ss_family sin_family +#define HAVE_SS_FAMILY 1 +#endif /*HAVE_STRUCT_SOCKADDR_IN6*/ +#endif /*HAVE_STRUCT_SOCKADDR_STORAGE*/ + +#ifndef HAVE_SS_FAMILY +#ifdef HAVE___SS_FAMILY +#define ss_family __ss_family +#define HAVE_SS_FAMILY 1 +#endif +#endif + +#ifndef IOV_MAX +# ifdef UIO_MAXIOV +# define IOV_MAX UIO_MAXIOV +# else +# ifdef __sgi + /* + * IRIX 6.5 has sysconf(_SC_IOV_MAX) + * which might return 512 or bigger + */ +# define IOV_MAX 512 +# endif +# endif +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +#define HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; +}; +#endif /* HAVE_STRUCT_ADDRINFO */ + +#if !defined(HAVE_GETADDRINFO) +#include "getaddrinfo.h" +#endif + +/* Needed for some systems that don't define it (Solaris). */ +#ifndef ifr_netmask +#define ifr_netmask ifr_addr +#endif + +/* Some old Linux systems have broken header files */ +#ifdef HAVE_IPV6 +#ifdef HAVE_LINUX_IPV6_V6ONLY_26 +#define IPV6_V6ONLY 26 +#endif /* HAVE_LINUX_IPV6_V6ONLY_26 */ +#endif /* HAVE_IPV6 */ + +#ifndef SCOPE_DELIMITER +#define SCOPE_DELIMITER '%' +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/nis.h b/ldb-2.0.8/lib/replace/system/nis.h new file mode 100644 index 0000000..7213b15 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/nis.h @@ -0,0 +1,55 @@ +/* + Unix SMB/CIFS implementation. + + nis system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . +*/ + +#ifndef _nis_passwd_h +#define _nis_passwd_h + +#if defined(HAVE_RPC_RPC_H) +/* + * Check for AUTH_ERROR define conflict with rpc/rpc.h in prot.h. + */ +#if defined(HAVE_SYS_SECURITY_H) && defined(HAVE_RPC_AUTH_ERROR_CONFLICT) +#undef AUTH_ERROR +#endif /* HAVE_SYS_SECURITY_H && HAVE_RPC_AUTH_ERROR_CONFLICT */ + +#include +#endif /* HAVE_RPC_RPC_H */ + + +#if defined (HAVE_NETGROUP) + +#if defined(HAVE_RPCSVC_YP_PROT_H) + +#include + +#endif /* HAVE_RPCSVC_YP_PROT_H */ + +#if defined(HAVE_RPCSVC_YPCLNT_H) +#include +#endif /* HAVE_RPCSVC_YPCLNT_H */ + +#endif /* HAVE_NETGROUP */ + +#endif /* _nis_passwd_h */ diff --git a/ldb-2.0.8/lib/replace/system/passwd.h b/ldb-2.0.8/lib/replace/system/passwd.h new file mode 100644 index 0000000..ecc9f60 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/passwd.h @@ -0,0 +1,92 @@ +#ifndef _system_passwd_h +#define _system_passwd_h + +/* + Unix SMB/CIFS implementation. + + passwd system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_SYS_PRIV_H +#include +#endif +#ifdef HAVE_SYS_ID_H +#include +#endif + +#ifdef HAVE_CRYPT_H +#include +#endif + +#ifdef HAVE_SHADOW_H +#include +#endif + +#ifdef HAVE_SYS_SECURITY_H +#include +#include +#define PASSWORD_LENGTH 16 +#endif /* HAVE_SYS_SECURITY_H */ + +#ifdef HAVE_GETPWANAM +#include +#include +#include +#endif + +#ifdef HAVE_COMPAT_H +#include +#endif + +#ifndef NGROUPS_MAX +#define NGROUPS_MAX 32 /* Guess... */ +#endif + +/* what is the longest significant password available on your system? + Knowing this speeds up password searches a lot */ +#ifndef PASSWORD_LENGTH +#define PASSWORD_LENGTH 8 +#endif + + +#ifndef ALLOW_CHANGE_PASSWORD +#if (defined(HAVE_TERMIOS_H) && defined(HAVE_DUP2) && defined(HAVE_SETSID)) +#define ALLOW_CHANGE_PASSWORD 1 +#endif +#endif + +#if defined(HAVE_CRYPT16) && defined(HAVE_GETAUTHUID) +#define ULTRIX_AUTH 1 +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/readline.h b/ldb-2.0.8/lib/replace/system/readline.h new file mode 100644 index 0000000..2937962 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/readline.h @@ -0,0 +1,61 @@ +#ifndef _system_readline_h +#define _system_readline_h +/* + Unix SMB/CIFS implementation. + + Readline wrappers + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_LIBREADLINE +# ifdef HAVE_READLINE_READLINE_H +# ifdef HAVE_READLINE_READLINE_WORKAROUND +# define _FUNCTION_DEF +# endif +# include +# ifdef HAVE_READLINE_HISTORY_H +# include +# endif +# else +# ifdef HAVE_READLINE_H +# include +# ifdef HAVE_HISTORY_H +# include +# endif +# else +# undef HAVE_LIBREADLINE +# endif +# endif +#endif + +#ifdef HAVE_NEW_LIBREADLINE +#ifdef HAVE_CPPFUNCTION +# define RL_COMPLETION_CAST (CPPFunction *) +#elif defined(HAVE_RL_COMPLETION_T) +# define RL_COMPLETION_CAST (rl_completion_t *) +#else +# define RL_COMPLETION_CAST +#endif +#else +/* This type is missing from libreadline<4.0 (approximately) */ +# define RL_COMPLETION_CAST +#endif /* HAVE_NEW_LIBREADLINE */ + +#endif diff --git a/ldb-2.0.8/lib/replace/system/select.h b/ldb-2.0.8/lib/replace/system/select.h new file mode 100644 index 0000000..9e945c3 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/select.h @@ -0,0 +1,81 @@ +#ifndef _system_select_h +#define _system_select_h +/* + Unix SMB/CIFS implementation. + + select system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#ifdef HAVE_SYS_EPOLL_H +#include +#endif + +#ifdef HAVE_SOLARIS_PORTS +#include +#endif + +#ifndef SELECT_CAST +#define SELECT_CAST +#endif + +#ifdef HAVE_POLL + +#include + +#else + +/* Type used for the number of file descriptors. */ +typedef unsigned long int nfds_t; + +/* Data structure describing a polling request. */ +struct pollfd +{ + int fd; /* File descriptor to poll. */ + short int events; /* Types of events poller cares about. */ + short int revents; /* Types of events that actually occurred. */ +}; + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ +#define POLLRDNORM 0x040 /* Normal data may be read. */ +#define POLLRDBAND 0x080 /* Priority data may be read. */ +#define POLLWRNORM 0x100 /* Writing now will not block. */ +#define POLLWRBAND 0x200 /* Priority data may be written. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ + +/* define is in "replace.h" */ +int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout); + +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/shmem.h b/ldb-2.0.8/lib/replace/system/shmem.h new file mode 100644 index 0000000..64fe39b --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/shmem.h @@ -0,0 +1,59 @@ +#ifndef _system_shmem_h +#define _system_shmem_h +/* + Unix SMB/CIFS implementation. + + shared memory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#if defined(HAVE_SYS_IPC_H) +#include +#endif /* HAVE_SYS_IPC_H */ + +#if defined(HAVE_SYS_SHM_H) +#include +#endif /* HAVE_SYS_SHM_H */ + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +/* NetBSD doesn't have these */ +#ifndef SHM_R +#define SHM_R 0400 +#endif + +#ifndef SHM_W +#define SHM_W 0200 +#endif + + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/syslog.h b/ldb-2.0.8/lib/replace/system/syslog.h new file mode 100644 index 0000000..104be1d --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/syslog.h @@ -0,0 +1,70 @@ +#ifndef _system_syslog_h +#define _system_syslog_h +/* + Unix SMB/CIFS implementation. + + syslog system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_SYSLOG_H +#include +#else +#ifdef HAVE_SYS_SYSLOG_H +#include +#endif +#endif + +/* For sys_adminlog(). */ +#ifndef LOG_EMERG +#define LOG_EMERG 0 /* system is unusable */ +#endif + +#ifndef LOG_ALERT +#define LOG_ALERT 1 /* action must be taken immediately */ +#endif + +#ifndef LOG_CRIT +#define LOG_CRIT 2 /* critical conditions */ +#endif + +#ifndef LOG_ERR +#define LOG_ERR 3 /* error conditions */ +#endif + +#ifndef LOG_WARNING +#define LOG_WARNING 4 /* warning conditions */ +#endif + +#ifndef LOG_NOTICE +#define LOG_NOTICE 5 /* normal but significant condition */ +#endif + +#ifndef LOG_INFO +#define LOG_INFO 6 /* informational */ +#endif + +#ifndef LOG_DEBUG +#define LOG_DEBUG 7 /* debug-level messages */ +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/terminal.h b/ldb-2.0.8/lib/replace/system/terminal.h new file mode 100644 index 0000000..9ad601a --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/terminal.h @@ -0,0 +1,46 @@ +#ifndef _system_terminal_h +#define _system_terminal_h +/* + Unix SMB/CIFS implementation. + + terminal system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef SUNOS4 +/* on SUNOS4 termios.h conflicts with sys/ioctl.h */ +#undef HAVE_TERMIOS_H +#endif + + +#if defined(HAVE_TERMIOS_H) +/* POSIX terminal handling. */ +#include +#elif defined(HAVE_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include +#elif defined(HAVE_SYS_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/threads.h b/ldb-2.0.8/lib/replace/system/threads.h new file mode 100644 index 0000000..d189ed6 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/threads.h @@ -0,0 +1,72 @@ +#ifndef _system_threads_h +#define _system_threads_h +/* + Unix SMB/CIFS implementation. + + macros to go along with the lib/replace/ portability layer code + + Copyright (C) Volker Lendecke 2012 + + ** 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 + Lesser 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 . +*/ + +#include + +#if defined(HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP) && \ + !defined(HAVE_PTHREAD_MUTEXATTR_SETROBUST) +#define pthread_mutexattr_setrobust pthread_mutexattr_setrobust_np +#endif + +#if defined(HAVE_DECL_PTHREAD_MUTEX_ROBUST_NP) && \ + !defined(HAVE_DECL_PTHREAD_MUTEX_ROBUST) +#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP +#endif + +#if defined(HAVE_PTHREAD_MUTEX_CONSISTENT_NP) && \ + !defined(HAVE_PTHREAD_MUTEX_CONSISTENT) +#define pthread_mutex_consistent pthread_mutex_consistent_np +#endif + +#ifdef HAVE_STDATOMIC_H +#include +#endif + +#ifndef HAVE_ATOMIC_THREAD_FENCE +#ifdef HAVE___ATOMIC_THREAD_FENCE +#define atomic_thread_fence(__ignore_order) __atomic_thread_fence(__ATOMIC_SEQ_CST) +#define HAVE_ATOMIC_THREAD_FENCE 1 +#endif /* HAVE___ATOMIC_THREAD_FENCE */ +#endif /* not HAVE_ATOMIC_THREAD_FENCE */ + +#ifndef HAVE_ATOMIC_THREAD_FENCE +#ifdef HAVE___SYNC_SYNCHRONIZE +#define atomic_thread_fence(__ignore_order) __sync_synchronize() +#define HAVE_ATOMIC_THREAD_FENCE 1 +#endif /* HAVE___SYNC_SYNCHRONIZE */ +#endif /* not HAVE_ATOMIC_THREAD_FENCE */ + +#ifndef HAVE_ATOMIC_THREAD_FENCE +#ifdef HAVE_ATOMIC_THREAD_FENCE_SUPPORT +#error mismatch_error_between_configure_test_and_header +#endif +/* make sure the build fails if someone uses it without checking the define */ +#define atomic_thread_fence(__order) \ + __function__atomic_thread_fence_not_available_on_this_platform__() +#endif /* not HAVE_ATOMIC_THREAD_FENCE */ + +#endif diff --git a/ldb-2.0.8/lib/replace/system/time.h b/ldb-2.0.8/lib/replace/system/time.h new file mode 100644 index 0000000..00f0d7f --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/time.h @@ -0,0 +1,99 @@ +#ifndef _system_time_h +#define _system_time_h +/* + Unix SMB/CIFS implementation. + + time system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef TIME_WITH_SYS_TIME +#include +#include +#else +#ifdef HAVE_SYS_TIME_H +#include +#else +#include +#endif +#endif + +#ifdef HAVE_UTIME_H +#include +#else +struct utimbuf { + time_t actime; /* access time */ + time_t modtime; /* modification time */ +}; +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + time_t tv_sec; /* Seconds. */ + long tv_nsec; /* Nanoseconds. */ +}; +#endif + +#ifndef HAVE_MKTIME +/* define is in "replace.h" */ +time_t rep_mktime(struct tm *t); +#endif + +#ifndef HAVE_TIMEGM +/* define is in "replace.h" */ +time_t rep_timegm(struct tm *tm); +#endif + +#ifndef HAVE_UTIME +/* define is in "replace.h" */ +int rep_utime(const char *filename, const struct utimbuf *buf); +#endif + +#ifndef HAVE_UTIMES +/* define is in "replace.h" */ +int rep_utimes(const char *filename, const struct timeval tv[2]); +#endif + +#ifndef HAVE_CLOCK_GETTIME +/* CLOCK_REALTIME is required by POSIX */ +#define CLOCK_REALTIME 0 +typedef int clockid_t; +int rep_clock_gettime(clockid_t clk_id, struct timespec *tp); +#endif +/* make sure we have a best effort CUSTOM_CLOCK_MONOTONIC we can rely on. + * + * on AIX the values of CLOCK_* are cast expressions, not integer constants, + * this prevents them from being compared against in a preprocessor directive. + * The following ...IS_* macros can be used to check which clock is in use. + */ +#if defined(CLOCK_MONOTONIC) +#define CUSTOM_CLOCK_MONOTONIC CLOCK_MONOTONIC +#define CUSTOM_CLOCK_MONOTONIC_IS_MONOTONIC +#elif defined(CLOCK_HIGHRES) +#define CUSTOM_CLOCK_MONOTONIC CLOCK_HIGHRES +#define CUSTOM_CLOCK_MONOTONIC_IS_HIGHRES +#else +#define CUSTOM_CLOCK_MONOTONIC CLOCK_REALTIME +#define CUSTOM_CLOCK_MONOTONIC_IS_REALTIME +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/wait.h b/ldb-2.0.8/lib/replace/system/wait.h new file mode 100644 index 0000000..1f5fcd9 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/wait.h @@ -0,0 +1,55 @@ +#ifndef _system_wait_h +#define _system_wait_h +/* + Unix SMB/CIFS implementation. + + waitpid system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** 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 + Lesser 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 . + +*/ + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#include + +#ifndef SIGCLD +#define SIGCLD SIGCHLD +#endif + +#ifdef HAVE_SETJMP_H +#include +#endif + +#ifdef HAVE_SYS_UCONTEXT_H +#include +#endif + +#if !defined(HAVE_SIG_ATOMIC_T_TYPE) +typedef int sig_atomic_t; +#endif + +#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4) +int rep_waitpid(pid_t pid,int *status,int options); +#endif + +#endif diff --git a/ldb-2.0.8/lib/replace/system/wscript_configure b/ldb-2.0.8/lib/replace/system/wscript_configure new file mode 100644 index 0000000..ecd9964 --- /dev/null +++ b/ldb-2.0.8/lib/replace/system/wscript_configure @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +# solaris varients of getXXent_r +conf.CHECK_C_PROTOTYPE('getpwent_r', + 'struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)', + define='SOLARIS_GETPWENT_R', headers='pwd.h') +conf.CHECK_C_PROTOTYPE('getgrent_r', + 'struct group *getgrent_r(struct group *src, char *buf, int buflen)', + define='SOLARIS_GETGRENT_R', headers='grp.h') + +# the irix varients +conf.CHECK_C_PROTOTYPE('getpwent_r', + 'struct passwd *getpwent_r(struct passwd *src, char *buf, size_t buflen)', + define='SOLARIS_GETPWENT_R', headers='pwd.h') +conf.CHECK_C_PROTOTYPE('getgrent_r', + 'struct group *getgrent_r(struct group *src, char *buf, size_t buflen)', + define='SOLARIS_GETGRENT_R', headers='grp.h') + diff --git a/ldb-2.0.8/lib/replace/tests/getifaddrs.c b/ldb-2.0.8/lib/replace/tests/getifaddrs.c new file mode 100644 index 0000000..8d575af --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/getifaddrs.c @@ -0,0 +1,105 @@ +/* + * Unix SMB/CIFS implementation. + * + * libreplace getifaddrs test + * + * Copyright (C) Michael Adam 2008 + * + * ** 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 . + */ + +#ifndef AUTOCONF_TEST +#include "replace.h" +#include "system/network.h" +#include "replace-test.h" +#endif + +#ifdef HAVE_INET_NTOP +#define rep_inet_ntop inet_ntop +#endif + +static const char *format_sockaddr(struct sockaddr *addr, + char *addrstring, + socklen_t addrlen) +{ + const char *result = NULL; + + if (addr->sa_family == AF_INET) { + result = rep_inet_ntop(AF_INET, + &((struct sockaddr_in *)addr)->sin_addr, + addrstring, + addrlen); +#ifdef HAVE_STRUCT_SOCKADDR_IN6 + } else if (addr->sa_family == AF_INET6) { + result = rep_inet_ntop(AF_INET6, + &((struct sockaddr_in6 *)addr)->sin6_addr, + addrstring, + addrlen); +#endif + } + return result; +} + +int getifaddrs_test(void) +{ + struct ifaddrs *ifs = NULL; + struct ifaddrs *ifs_head = NULL; + int ret; + + ret = getifaddrs(&ifs); + ifs_head = ifs; + if (ret != 0) { + fprintf(stderr, "getifaddrs() failed: %s\n", strerror(errno)); + return 1; + } + + while (ifs) { + printf("%-10s ", ifs->ifa_name); + if (ifs->ifa_addr != NULL) { + char addrstring[INET6_ADDRSTRLEN]; + const char *result; + + result = format_sockaddr(ifs->ifa_addr, + addrstring, + sizeof(addrstring)); + if (result != NULL) { + printf("IP=%s ", addrstring); + } + + if (ifs->ifa_netmask != NULL) { + result = format_sockaddr(ifs->ifa_netmask, + addrstring, + sizeof(addrstring)); + if (result != NULL) { + printf("NETMASK=%s", addrstring); + } + } else { + printf("AF=%d ", ifs->ifa_addr->sa_family); + } + } else { + printf(""); + } + + printf("\n"); + ifs = ifs->ifa_next; + } + + freeifaddrs(ifs_head); + + return 0; +} diff --git a/ldb-2.0.8/lib/replace/tests/incoherent_mmap.c b/ldb-2.0.8/lib/replace/tests/incoherent_mmap.c new file mode 100644 index 0000000..ee288fd --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/incoherent_mmap.c @@ -0,0 +1,83 @@ +/* In OpenBSD, if you write to a file, another process doesn't see it + * in its mmap. Returns with exit status 0 if that is the case, 1 if + * it's coherent, and other if there's a problem. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DATA "coherent.mmap" + +int main(int argc, char *argv[]) +{ + int tochild[2], toparent[2]; + int fd; + volatile unsigned char *map; + unsigned char *page; + const char *fname = argv[1]; + char c = 0; + + if (pipe(tochild) != 0 || pipe(toparent) != 0) + err(2, "Creating pipe"); + + if (!fname) + fname = DATA; + + fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0600); + if (fd < 0) + err(2, "opening %s", fname); + unlink(fname); + + switch (fork()) { + case -1: + err(2, "Fork"); + case 0: + close(tochild[1]); + close(toparent[0]); + + /* Wait for parent to create file. */ + if (read(tochild[0], &c, 1) != 1) + err(2, "reading from parent"); + + /* Alter first byte. */ + pwrite(fd, &c, 1, 0); + + if (write(toparent[1], &c, 1) != 1) + err(2, "writing to parent"); + exit(0); + + default: + close(tochild[0]); + close(toparent[1]); + + /* Create a file and mmap it. */ + page = malloc(getpagesize()); + memset(page, 0x42, getpagesize()); + if (write(fd, page, getpagesize()) != getpagesize()) + err(2, "writing first page"); + map = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0); + if (map == MAP_FAILED) + err(2, "mapping file"); + + if (*map != 0x42) + errx(2, "first byte isn't 0x42!"); + + /* Tell child to alter file. */ + if (write(tochild[1], &c, 1) != 1) + err(2, "writing to child"); + + if (read(toparent[0], &c, 1) != 1) + err(2, "reading from child"); + + if (*map) + errx(0, "mmap incoherent: first byte isn't 0."); + + exit(1); + } +} diff --git a/ldb-2.0.8/lib/replace/tests/main.c b/ldb-2.0.8/lib/replace/tests/main.c new file mode 100644 index 0000000..94264d7 --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/main.c @@ -0,0 +1,35 @@ +/* + Unix SMB/CIFS implementation. + + libreplace tests + + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "replace-testsuite.h" + +int main(void) +{ + bool ret = torture_local_replace(NULL); + if (ret) + return 0; + return -1; +} diff --git a/ldb-2.0.8/lib/replace/tests/os2_delete.c b/ldb-2.0.8/lib/replace/tests/os2_delete.c new file mode 100644 index 0000000..4b99ccf --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/os2_delete.c @@ -0,0 +1,134 @@ +/* + test readdir/unlink pattern that OS/2 uses + tridge@samba.org July 2005 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "replace-test.h" + +#define NUM_FILES 700 +#define READDIR_SIZE 100 +#define DELETE_SIZE 4 + +#define TESTDIR "test.dir" + +static int test_readdir_os2_delete_ret; + +#define FAILED(d) (printf("failure: readdir [\nFailed for %s - %d = %s\n]\n", d, errno, strerror(errno)), test_readdir_os2_delete_ret = 1) + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#ifdef _WIN32 +#define mkdir(d,m) _mkdir(d) +#endif + +static void cleanup(void) +{ + /* I'm a lazy bastard */ + if (system("rm -rf " TESTDIR)) { + FAILED("system"); + } + mkdir(TESTDIR, 0700) == 0 || FAILED("mkdir"); +} + +static void create_files(void) +{ + int i; + for (i=0;id_name); + } + + if (i == 0) { + return 0; + } + + /* delete the first few */ + for (j=0; jd_name, ".") == 0 || FAILED("match ."); + de = readdir(d); + strcmp(de->d_name, "..") == 0 || FAILED("match .."); + + while (1) { + int n = os2_delete(d); + if (n == 0) break; + total_deleted += n; + } + closedir(d); + + fprintf(stderr, "Deleted %d files of %d\n", total_deleted, NUM_FILES); + + rmdir(TESTDIR) == 0 || FAILED("rmdir"); + + if (system("rm -rf " TESTDIR) == -1) { + FAILED("system"); + } + + return test_readdir_os2_delete_ret; +} diff --git a/ldb-2.0.8/lib/replace/tests/shared_mmap.c b/ldb-2.0.8/lib/replace/tests/shared_mmap.c new file mode 100644 index 0000000..9d6e3fc --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/shared_mmap.c @@ -0,0 +1,71 @@ +/* this tests whether we can use a shared writeable mmap on a file - + as needed for the mmap variant of FAST_SHARE_MODES */ + +#if defined(HAVE_UNISTD_H) +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include + +#define DATA "conftest.mmap" + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +int main(void) +{ + int *buf; + int i; + int fd = open(DATA,O_RDWR|O_CREAT|O_TRUNC,0666); + int count=7; + + if (fd == -1) exit(1); + + for (i=0;i<10000;i++) { + write(fd,&i,sizeof(i)); + } + + close(fd); + + if (fork() == 0) { + fd = open(DATA,O_RDWR); + if (fd == -1) exit(1); + + buf = (int *)mmap(NULL, 10000*sizeof(int), + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + fd, 0); + + while (count-- && buf[9124] != 55732) sleep(1); + + if (count <= 0) exit(1); + + buf[1763] = 7268; + exit(0); + } + + fd = open(DATA,O_RDWR); + if (fd == -1) exit(1); + + buf = (int *)mmap(NULL, 10000*sizeof(int), + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + fd, 0); + + if (buf == (int *)-1) exit(1); + + buf[9124] = 55732; + + while (count-- && buf[1763] != 7268) sleep(1); + + unlink(DATA); + + if (count > 0) exit(0); + exit(1); +} diff --git a/ldb-2.0.8/lib/replace/tests/shared_mremap.c b/ldb-2.0.8/lib/replace/tests/shared_mremap.c new file mode 100644 index 0000000..08040e2 --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/shared_mremap.c @@ -0,0 +1,51 @@ +/* this tests whether we can use mremap */ + +#if defined(HAVE_UNISTD_H) +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include + +#define DATA "conftest.mmap" + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED (int *)-1 +#endif + +int main(void) +{ + int *buf; + int fd; + int err = 1; + + fd = open(DATA, O_RDWR|O_CREAT|O_TRUNC, 0666); + if (fd == -1) { + exit(1); + } + + buf = (int *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, fd, 0); + if (buf == MAP_FAILED) { + goto done; + } + + buf = mremap(buf, 0x1000, 0x2000, MREMAP_MAYMOVE); + if (buf == MAP_FAILED) { + goto done; + } + + err = 0; +done: + close(fd); + unlink(DATA); + exit(err); +} diff --git a/ldb-2.0.8/lib/replace/tests/snprintf.c b/ldb-2.0.8/lib/replace/tests/snprintf.c new file mode 100644 index 0000000..77473f0 --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/snprintf.c @@ -0,0 +1,29 @@ +void foo(const char *format, ...) +{ + va_list ap; + int len; + char buf[20]; + long long l = 1234567890; + l *= 100; + + va_start(ap, format); + len = vsnprintf(buf, 0, format, ap); + va_end(ap); + if (len != 5) exit(1); + + va_start(ap, format); + len = vsnprintf(0, 0, format, ap); + va_end(ap); + if (len != 5) exit(2); + + if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(3); + + if (snprintf(buf, 20, "%lld", l) != 12 || strcmp(buf, "123456789000") != 0) exit(4); + if (snprintf(buf, 20, "%zu", 123456789) != 9 || strcmp(buf, "123456789") != 0) exit(5); + if (snprintf(buf, 20, "%2\$d %1\$d", 3, 4) != 3 || strcmp(buf, "4 3") != 0) exit(6); + if (snprintf(buf, 20, "%s", 0) < 3) exit(7); + + printf("1"); + exit(0); +} +int main(void) { foo("hello"); } diff --git a/ldb-2.0.8/lib/replace/tests/strptime.c b/ldb-2.0.8/lib/replace/tests/strptime.c new file mode 100644 index 0000000..5bf03f5 --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/strptime.c @@ -0,0 +1,173 @@ + +#ifdef LIBREPLACE_CONFIGURE_TEST_STRPTIME + +#include +#include +#include + +#define true 1 +#define false 0 + +#ifndef __STRING +#define __STRING(x) #x +#endif + +/* make printf a no-op */ +#define printf if(0) printf + +#else /* LIBREPLACE_CONFIGURE_TEST_STRPTIME */ + +#include "replace.h" +#include "system/time.h" +#include "replace-test.h" + +#endif /* LIBREPLACE_CONFIGURE_TEST_STRPTIME */ + +int libreplace_test_strptime(void) +{ + const char *s = "20070414101546Z"; + char *ret; + struct tm t, t2; + + memset(&t, 0, sizeof(t)); + memset(&t2, 0, sizeof(t2)); + + printf("test: strptime\n"); + + ret = strptime(s, "%Y%m%d%H%M%S", &t); + if ( ret == NULL ) { + printf("failure: strptime [\n" + "returned NULL\n" + "]\n"); + return false; + } + + if ( *ret != 'Z' ) { + printf("failure: strptime [\n" + "ret doesn't point to 'Z'\n" + "]\n"); + return false; + } + + ret = strptime(s, "%Y%m%d%H%M%SZ", &t2); + if ( ret == NULL ) { + printf("failure: strptime [\n" + "returned NULL with Z\n" + "]\n"); + return false; + } + + if ( *ret != '\0' ) { + printf("failure: strptime [\n" + "ret doesn't point to '\\0'\n" + "]\n"); + return false; + } + +#define CMP_TM_ELEMENT(t1,t2,elem) \ + if (t1.elem != t2.elem) { \ + printf("failure: strptime [\n" \ + "result differs if the format string has a 'Z' at the end\n" \ + "element: %s %d != %d\n" \ + "]\n", \ + __STRING(elen), t1.elem, t2.elem); \ + return false; \ + } + + CMP_TM_ELEMENT(t,t2,tm_sec); + CMP_TM_ELEMENT(t,t2,tm_min); + CMP_TM_ELEMENT(t,t2,tm_hour); + CMP_TM_ELEMENT(t,t2,tm_mday); + CMP_TM_ELEMENT(t,t2,tm_mon); + CMP_TM_ELEMENT(t,t2,tm_year); + CMP_TM_ELEMENT(t,t2,tm_wday); + CMP_TM_ELEMENT(t,t2,tm_yday); + CMP_TM_ELEMENT(t,t2,tm_isdst); + + if (t.tm_sec != 46) { + printf("failure: strptime [\n" + "tm_sec: expected: 46, got: %d\n" + "]\n", + t.tm_sec); + return false; + } + + if (t.tm_min != 15) { + printf("failure: strptime [\n" + "tm_min: expected: 15, got: %d\n" + "]\n", + t.tm_min); + return false; + } + + if (t.tm_hour != 10) { + printf("failure: strptime [\n" + "tm_hour: expected: 10, got: %d\n" + "]\n", + t.tm_hour); + return false; + } + + if (t.tm_mday != 14) { + printf("failure: strptime [\n" + "tm_mday: expected: 14, got: %d\n" + "]\n", + t.tm_mday); + return false; + } + + if (t.tm_mon != 3) { + printf("failure: strptime [\n" + "tm_mon: expected: 3, got: %d\n" + "]\n", + t.tm_mon); + return false; + } + + if (t.tm_year != 107) { + printf("failure: strptime [\n" + "tm_year: expected: 107, got: %d\n" + "]\n", + t.tm_year); + return false; + } + + if (t.tm_wday != 6) { /* saturday */ + printf("failure: strptime [\n" + "tm_wday: expected: 6, got: %d\n" + "]\n", + t.tm_wday); + return false; + } + + if (t.tm_yday != 103) { + printf("failure: strptime [\n" + "tm_yday: expected: 103, got: %d\n" + "]\n", + t.tm_yday); + return false; + } + + /* we don't test this as it depends on the host configuration + if (t.tm_isdst != 0) { + printf("failure: strptime [\n" + "tm_isdst: expected: 0, got: %d\n" + "]\n", + t.tm_isdst); + return false; + }*/ + + printf("success: strptime\n"); + + return true; +} + +#ifdef LIBREPLACE_CONFIGURE_TEST_STRPTIME +int main (void) +{ + int ret; + ret = libreplace_test_strptime(); + if (ret == false) return 1; + return 0; +} +#endif diff --git a/ldb-2.0.8/lib/replace/tests/testsuite.c b/ldb-2.0.8/lib/replace/tests/testsuite.c new file mode 100644 index 0000000..dba545e --- /dev/null +++ b/ldb-2.0.8/lib/replace/tests/testsuite.c @@ -0,0 +1,1151 @@ +/* + Unix SMB/CIFS implementation. + + libreplace tests + + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "replace-test.h" +#include "replace-testsuite.h" + +/* + we include all the system/ include files here so that libreplace tests + them in the build farm +*/ +#include "system/capability.h" +#include "system/dir.h" +#include "system/filesys.h" +#include "system/glob.h" +#include "system/iconv.h" +#include "system/locale.h" +#include "system/network.h" +#include "system/passwd.h" +#include "system/readline.h" +#include "system/select.h" +#include "system/shmem.h" +#include "system/syslog.h" +#include "system/terminal.h" +#include "system/time.h" +#include "system/wait.h" +#include "system/aio.h" + +#define TESTFILE "testfile.dat" + + +/* + test ftruncate() function + */ +static int test_ftruncate(void) +{ + struct stat st; + int fd; + const int size = 1234; + printf("test: ftruncate\n"); + unlink(TESTFILE); + fd = open(TESTFILE, O_RDWR|O_CREAT, 0600); + if (fd == -1) { + printf("failure: ftruncate [\n" + "creating '%s' failed - %s\n]\n", TESTFILE, strerror(errno)); + return false; + } + if (ftruncate(fd, size) != 0) { + printf("failure: ftruncate [\n%s\n]\n", strerror(errno)); + close(fd); + return false; + } + if (fstat(fd, &st) != 0) { + printf("failure: ftruncate [\nfstat failed - %s\n]\n", strerror(errno)); + close(fd); + return false; + } + if (st.st_size != size) { + printf("failure: ftruncate [\ngave wrong size %d - expected %d\n]\n", + (int)st.st_size, size); + close(fd); + return false; + } + unlink(TESTFILE); + printf("success: ftruncate\n"); + close(fd); + return true; +} + +/* + test strlcpy() function. + see http://www.gratisoft.us/todd/papers/strlcpy.html + */ +static int test_strlcpy(void) +{ + char buf[4]; + const struct { + const char *src; + size_t result; + } tests[] = { + { "abc", 3 }, + { "abcdef", 6 }, + { "abcd", 4 }, + { "", 0 }, + { NULL, 0 } + }; + int i; + printf("test: strlcpy\n"); + for (i=0;tests[i].src;i++) { + if (strlcpy(buf, tests[i].src, sizeof(buf)) != tests[i].result) { + printf("failure: strlcpy [\ntest %d failed\n]\n", i); + return false; + } + } + printf("success: strlcpy\n"); + return true; +} + +static int test_strlcat(void) +{ + char tmp[10]; + printf("test: strlcat\n"); + strlcpy(tmp, "", sizeof(tmp)); + if (strlcat(tmp, "bla", 3) != 3) { + printf("failure: strlcat [\ninvalid return code\n]\n"); + return false; + } + if (strcmp(tmp, "bl") != 0) { + printf("failure: strlcat [\nexpected \"bl\", got \"%s\"\n]\n", + tmp); + return false; + } + + strlcpy(tmp, "da", sizeof(tmp)); + if (strlcat(tmp, "me", 4) != 4) { + printf("failure: strlcat [\nexpected \"dam\", got \"%s\"\n]\n", + tmp); + return false; + } + + printf("success: strlcat\n"); + return true; +} + +static int test_mktime(void) +{ + /* FIXME */ + return true; +} + +static int test_initgroups(void) +{ + /* FIXME */ + return true; +} + +static int test_memmove(void) +{ + /* FIXME */ + return true; +} + +static int test_strdup(void) +{ + char *x; + printf("test: strdup\n"); + x = strdup("bla"); + if (strcmp("bla", x) != 0) { + printf("failure: strdup [\nfailed: expected \"bla\", got \"%s\"\n]\n", + x); + return false; + } + free(x); + printf("success: strdup\n"); + return true; +} + +static int test_setlinebuf(void) +{ + printf("test: setlinebuf\n"); + setlinebuf(stdout); + printf("success: setlinebuf\n"); + return true; +} + +static int test_vsyslog(void) +{ + /* FIXME */ + return true; +} + +static int test_timegm(void) +{ + /* FIXME */ + return true; +} + +static int test_setenv(void) +{ +#define TEST_SETENV(key, value, overwrite, result) do { \ + int _ret; \ + char *_v; \ + _ret = setenv(key, value, overwrite); \ + if (_ret != 0) { \ + printf("failure: setenv [\n" \ + "setenv(%s, %s, %d) failed\n" \ + "]\n", \ + key, value, overwrite); \ + return false; \ + } \ + _v=getenv(key); \ + if (!_v) { \ + printf("failure: setenv [\n" \ + "getenv(%s) returned NULL\n" \ + "]\n", \ + key); \ + return false; \ + } \ + if (strcmp(result, _v) != 0) { \ + printf("failure: setenv [\n" \ + "getenv(%s): '%s' != '%s'\n" \ + "]\n", \ + key, result, _v); \ + return false; \ + } \ +} while(0) + +#define TEST_UNSETENV(key) do { \ + char *_v; \ + unsetenv(key); \ + _v=getenv(key); \ + if (_v) { \ + printf("failure: setenv [\n" \ + "getenv(%s): NULL != '%s'\n" \ + "]\n", \ + SETENVTEST_KEY, _v); \ + return false; \ + } \ +} while (0) + +#define SETENVTEST_KEY "SETENVTESTKEY" +#define SETENVTEST_VAL "SETENVTESTVAL" + + printf("test: setenv\n"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"1", 0, SETENVTEST_VAL"1"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"2", 0, SETENVTEST_VAL"1"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"3", 1, SETENVTEST_VAL"3"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"4", 1, SETENVTEST_VAL"4"); + TEST_UNSETENV(SETENVTEST_KEY); + TEST_UNSETENV(SETENVTEST_KEY); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"5", 0, SETENVTEST_VAL"5"); + TEST_UNSETENV(SETENVTEST_KEY); + TEST_UNSETENV(SETENVTEST_KEY); + printf("success: setenv\n"); + return true; +} + +static int test_strndup(void) +{ + char *x; + printf("test: strndup\n"); + x = strndup("bla", 0); + if (strcmp(x, "") != 0) { + printf("failure: strndup [\ninvalid\n]\n"); + return false; + } + free(x); + x = strndup("bla", 2); + if (strcmp(x, "bl") != 0) { + printf("failure: strndup [\ninvalid\n]\n"); + return false; + } + free(x); + x = strndup("bla", 10); + if (strcmp(x, "bla") != 0) { + printf("failure: strndup [\ninvalid\n]\n"); + free(x); + return false; + } + free(x); + printf("success: strndup\n"); + return true; +} + +static int test_strnlen(void) +{ + printf("test: strnlen\n"); + if (strnlen("bla", 2) != 2) { + printf("failure: strnlen [\nunexpected length\n]\n"); + return false; + } + + if (strnlen("some text\n", 0) != 0) { + printf("failure: strnlen [\nunexpected length\n]\n"); + return false; + } + + if (strnlen("some text", 20) != 9) { + printf("failure: strnlen [\nunexpected length\n]\n"); + return false; + } + + printf("success: strnlen\n"); + return true; +} + +static int test_waitpid(void) +{ + /* FIXME */ + return true; +} + +static int test_seteuid(void) +{ + /* FIXME */ + return true; +} + +static int test_setegid(void) +{ + /* FIXME */ + return true; +} + +static int test_asprintf(void) +{ + char *x; + printf("test: asprintf\n"); + if (asprintf(&x, "%d", 9) != 1) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + if (strcmp(x, "9") != 0) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + if (asprintf(&x, "dat%s", "a") != 4) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + if (strcmp(x, "data") != 0) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + printf("success: asprintf\n"); + return true; +} + +static int test_snprintf(void) +{ + char tmp[10]; + printf("test: snprintf\n"); + if (snprintf(tmp, 3, "foo%d", 9) != 4) { + printf("failure: snprintf [\nsnprintf return code failed\n]\n"); + return false; + } + + if (strcmp(tmp, "fo") != 0) { + printf("failure: snprintf [\nsnprintf failed\n]\n"); + return false; + } + + printf("success: snprintf\n"); + return true; +} + +static int test_vasprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_vsnprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_opendir(void) +{ + /* FIXME */ + return true; +} + +static int test_readdir(void) +{ + printf("test: readdir\n"); + if (test_readdir_os2_delete() != 0) { + return false; + } + printf("success: readdir\n"); + return true; +} + +static int test_telldir(void) +{ + /* FIXME */ + return true; +} + +static int test_seekdir(void) +{ + /* FIXME */ + return true; +} + +static int test_dlopen(void) +{ + /* FIXME: test dlopen, dlsym, dlclose, dlerror */ + return true; +} + + +static int test_chroot(void) +{ + /* FIXME: chroot() */ + return true; +} + +static int test_bzero(void) +{ + /* FIXME: bzero */ + return true; +} + +static int test_strerror(void) +{ + /* FIXME */ + return true; +} + +static int test_errno(void) +{ + printf("test: errno\n"); + errno = 3; + if (errno != 3) { + printf("failure: errno [\nerrno failed\n]\n"); + return false; + } + + printf("success: errno\n"); + return true; +} + +static int test_mkdtemp(void) +{ + /* FIXME */ + return true; +} + +static int test_mkstemp(void) +{ + /* FIXME */ + return true; +} + +static int test_pread(void) +{ + /* FIXME */ + return true; +} + +static int test_pwrite(void) +{ + /* FIXME */ + return true; +} + +static int test_inet_ntoa(void) +{ + /* FIXME */ + return true; +} + +#define TEST_STRTO_X(type,fmt,func,str,base,res,diff,rrnoo) do {\ + type _v; \ + char _s[64]; \ + char *_p = NULL;\ + char *_ep = NULL; \ + strlcpy(_s, str, sizeof(_s));\ + if (diff >= 0) { \ + _ep = &_s[diff]; \ + } \ + errno = 0; \ + _v = func(_s, &_p, base); \ + if (errno != rrnoo) { \ + printf("failure: %s [\n" \ + "\t%s\n" \ + "\t%s(\"%s\",%d,%d): " fmt " (=/!)= " fmt "\n" \ + "\terrno: %d != %d\n" \ + "]\n", \ + __STRING(func), __location__, __STRING(func), \ + str, diff, base, res, _v, rrnoo, errno); \ + return false; \ + } else if (_v != res) { \ + printf("failure: %s [\n" \ + "\t%s\n" \ + "\t%s(\"%s\",%d,%d): " fmt " != " fmt "\n" \ + "]\n", \ + __STRING(func), __location__, __STRING(func), \ + str, diff, base, res, _v); \ + return false; \ + } else if (_p != _ep) { \ + printf("failure: %s [\n" \ + "\t%s\n" \ + "\t%s(\"%s\",%d,%d): " fmt " (=/!)= " fmt "\n" \ + "\tptr: %p - %p = %d != %d\n" \ + "]\n", \ + __STRING(func), __location__, __STRING(func), \ + str, diff, base, res, _v, _ep, _p, (int)(diff - (_ep - _p)), diff); \ + return false; \ + } \ +} while (0) + +static int test_strtoll(void) +{ + printf("test: strtoll\n"); + +#define TEST_STRTOLL(str,base,res,diff,errnoo) TEST_STRTO_X(long long int, "%lld", strtoll,str,base,res,diff,errnoo) + + TEST_STRTOLL("15", 10, 15LL, 2, 0); + TEST_STRTOLL(" 15", 10, 15LL, 4, 0); + TEST_STRTOLL("15", 0, 15LL, 2, 0); + TEST_STRTOLL(" 15 ", 0, 15LL, 3, 0); + TEST_STRTOLL("+15", 10, 15LL, 3, 0); + TEST_STRTOLL(" +15", 10, 15LL, 5, 0); + TEST_STRTOLL("+15", 0, 15LL, 3, 0); + TEST_STRTOLL(" +15 ", 0, 15LL, 4, 0); + TEST_STRTOLL("-15", 10, -15LL, 3, 0); + TEST_STRTOLL(" -15", 10, -15LL, 5, 0); + TEST_STRTOLL("-15", 0, -15LL, 3, 0); + TEST_STRTOLL(" -15 ", 0, -15LL, 4, 0); + TEST_STRTOLL("015", 10, 15LL, 3, 0); + TEST_STRTOLL(" 015", 10, 15LL, 5, 0); + TEST_STRTOLL("015", 0, 13LL, 3, 0); + TEST_STRTOLL(" 015", 0, 13LL, 5, 0); + TEST_STRTOLL("0x15", 10, 0LL, 1, 0); + TEST_STRTOLL(" 0x15", 10, 0LL, 3, 0); + TEST_STRTOLL("0x15", 0, 21LL, 4, 0); + TEST_STRTOLL(" 0x15", 0, 21LL, 6, 0); + + TEST_STRTOLL("10", 16, 16LL, 2, 0); + TEST_STRTOLL(" 10 ", 16, 16LL, 4, 0); + TEST_STRTOLL("0x10", 16, 16LL, 4, 0); + TEST_STRTOLL("0x10", 0, 16LL, 4, 0); + TEST_STRTOLL(" 0x10 ", 0, 16LL, 5, 0); + TEST_STRTOLL("+10", 16, 16LL, 3, 0); + TEST_STRTOLL(" +10 ", 16, 16LL, 5, 0); + TEST_STRTOLL("+0x10", 16, 16LL, 5, 0); + TEST_STRTOLL("+0x10", 0, 16LL, 5, 0); + TEST_STRTOLL(" +0x10 ", 0, 16LL, 6, 0); + TEST_STRTOLL("-10", 16, -16LL, 3, 0); + TEST_STRTOLL(" -10 ", 16, -16LL, 5, 0); + TEST_STRTOLL("-0x10", 16, -16LL, 5, 0); + TEST_STRTOLL("-0x10", 0, -16LL, 5, 0); + TEST_STRTOLL(" -0x10 ", 0, -16LL, 6, 0); + TEST_STRTOLL("010", 16, 16LL, 3, 0); + TEST_STRTOLL(" 010 ", 16, 16LL, 5, 0); + TEST_STRTOLL("-010", 16, -16LL, 4, 0); + + TEST_STRTOLL("11", 8, 9LL, 2, 0); + TEST_STRTOLL("011", 8, 9LL, 3, 0); + TEST_STRTOLL("011", 0, 9LL, 3, 0); + TEST_STRTOLL("-11", 8, -9LL, 3, 0); + TEST_STRTOLL("-011", 8, -9LL, 4, 0); + TEST_STRTOLL("-011", 0, -9LL, 4, 0); + + TEST_STRTOLL("011", 8, 9LL, 3, 0); + TEST_STRTOLL("011", 0, 9LL, 3, 0); + TEST_STRTOLL("-11", 8, -9LL, 3, 0); + TEST_STRTOLL("-011", 8, -9LL, 4, 0); + TEST_STRTOLL("-011", 0, -9LL, 4, 0); + + TEST_STRTOLL("Text", 0, 0LL, 0, 0); + + TEST_STRTOLL("9223372036854775807", 10, 9223372036854775807LL, 19, 0); + TEST_STRTOLL("9223372036854775807", 0, 9223372036854775807LL, 19, 0); + TEST_STRTOLL("9223372036854775808", 0, 9223372036854775807LL, 19, ERANGE); + TEST_STRTOLL("9223372036854775808", 10, 9223372036854775807LL, 19, ERANGE); + TEST_STRTOLL("0x7FFFFFFFFFFFFFFF", 0, 9223372036854775807LL, 18, 0); + TEST_STRTOLL("0x7FFFFFFFFFFFFFFF", 16, 9223372036854775807LL, 18, 0); + TEST_STRTOLL("7FFFFFFFFFFFFFFF", 16, 9223372036854775807LL, 16, 0); + TEST_STRTOLL("0x8000000000000000", 0, 9223372036854775807LL, 18, ERANGE); + TEST_STRTOLL("0x8000000000000000", 16, 9223372036854775807LL, 18, ERANGE); + TEST_STRTOLL("80000000000000000", 16, 9223372036854775807LL, 17, ERANGE); + TEST_STRTOLL("0777777777777777777777", 0, 9223372036854775807LL, 22, 0); + TEST_STRTOLL("0777777777777777777777", 8, 9223372036854775807LL, 22, 0); + TEST_STRTOLL("777777777777777777777", 8, 9223372036854775807LL, 21, 0); + TEST_STRTOLL("01000000000000000000000", 0, 9223372036854775807LL, 23, ERANGE); + TEST_STRTOLL("01000000000000000000000", 8, 9223372036854775807LL, 23, ERANGE); + TEST_STRTOLL("1000000000000000000000", 8, 9223372036854775807LL, 22, ERANGE); + + TEST_STRTOLL("-9223372036854775808", 10, -9223372036854775807LL -1, 20, 0); + TEST_STRTOLL("-9223372036854775808", 0, -9223372036854775807LL -1, 20, 0); + TEST_STRTOLL("-9223372036854775809", 0, -9223372036854775807LL -1, 20, ERANGE); + TEST_STRTOLL("-9223372036854775809", 10, -9223372036854775807LL -1, 20, ERANGE); + TEST_STRTOLL("-0x8000000000000000", 0, -9223372036854775807LL -1, 19, 0); + TEST_STRTOLL("-0x8000000000000000", 16, -9223372036854775807LL -1, 19, 0); + TEST_STRTOLL("-8000000000000000", 16, -9223372036854775807LL -1, 17, 0); + TEST_STRTOLL("-0x8000000000000001", 0, -9223372036854775807LL -1, 19, ERANGE); + TEST_STRTOLL("-0x8000000000000001", 16, -9223372036854775807LL -1, 19, ERANGE); + TEST_STRTOLL("-80000000000000001", 16, -9223372036854775807LL -1, 18, ERANGE); + TEST_STRTOLL("-01000000000000000000000",0, -9223372036854775807LL -1, 24, 0); + TEST_STRTOLL("-01000000000000000000000",8, -9223372036854775807LL -1, 24, 0); + TEST_STRTOLL("-1000000000000000000000", 8, -9223372036854775807LL -1, 23, 0); + TEST_STRTOLL("-01000000000000000000001",0, -9223372036854775807LL -1, 24, ERANGE); + TEST_STRTOLL("-01000000000000000000001",8, -9223372036854775807LL -1, 24, ERANGE); + TEST_STRTOLL("-1000000000000000000001", 8, -9223372036854775807LL -1, 23, ERANGE); + + printf("success: strtoll\n"); + return true; +} + +static int test_strtoull(void) +{ + printf("test: strtoull\n"); + +#define TEST_STRTOULL(str,base,res,diff,errnoo) TEST_STRTO_X(long long unsigned int,"%llu",strtoull,str,base,res,diff,errnoo) + + TEST_STRTOULL("15", 10, 15LLU, 2, 0); + TEST_STRTOULL(" 15", 10, 15LLU, 4, 0); + TEST_STRTOULL("15", 0, 15LLU, 2, 0); + TEST_STRTOULL(" 15 ", 0, 15LLU, 3, 0); + TEST_STRTOULL("+15", 10, 15LLU, 3, 0); + TEST_STRTOULL(" +15", 10, 15LLU, 5, 0); + TEST_STRTOULL("+15", 0, 15LLU, 3, 0); + TEST_STRTOULL(" +15 ", 0, 15LLU, 4, 0); + TEST_STRTOULL("-15", 10, 18446744073709551601LLU, 3, 0); + TEST_STRTOULL(" -15", 10, 18446744073709551601LLU, 5, 0); + TEST_STRTOULL("-15", 0, 18446744073709551601LLU, 3, 0); + TEST_STRTOULL(" -15 ", 0, 18446744073709551601LLU, 4, 0); + TEST_STRTOULL("015", 10, 15LLU, 3, 0); + TEST_STRTOULL(" 015", 10, 15LLU, 5, 0); + TEST_STRTOULL("015", 0, 13LLU, 3, 0); + TEST_STRTOULL(" 015", 0, 13LLU, 5, 0); + TEST_STRTOULL("0x15", 10, 0LLU, 1, 0); + TEST_STRTOULL(" 0x15", 10, 0LLU, 3, 0); + TEST_STRTOULL("0x15", 0, 21LLU, 4, 0); + TEST_STRTOULL(" 0x15", 0, 21LLU, 6, 0); + + TEST_STRTOULL("10", 16, 16LLU, 2, 0); + TEST_STRTOULL(" 10 ", 16, 16LLU, 4, 0); + TEST_STRTOULL("0x10", 16, 16LLU, 4, 0); + TEST_STRTOULL("0x10", 0, 16LLU, 4, 0); + TEST_STRTOULL(" 0x10 ", 0, 16LLU, 5, 0); + TEST_STRTOULL("+10", 16, 16LLU, 3, 0); + TEST_STRTOULL(" +10 ", 16, 16LLU, 5, 0); + TEST_STRTOULL("+0x10", 16, 16LLU, 5, 0); + TEST_STRTOULL("+0x10", 0, 16LLU, 5, 0); + TEST_STRTOULL(" +0x10 ", 0, 16LLU, 6, 0); + TEST_STRTOULL("-10", 16, -16LLU, 3, 0); + TEST_STRTOULL(" -10 ", 16, -16LLU, 5, 0); + TEST_STRTOULL("-0x10", 16, -16LLU, 5, 0); + TEST_STRTOULL("-0x10", 0, -16LLU, 5, 0); + TEST_STRTOULL(" -0x10 ", 0, -16LLU, 6, 0); + TEST_STRTOULL("010", 16, 16LLU, 3, 0); + TEST_STRTOULL(" 010 ", 16, 16LLU, 5, 0); + TEST_STRTOULL("-010", 16, -16LLU, 4, 0); + + TEST_STRTOULL("11", 8, 9LLU, 2, 0); + TEST_STRTOULL("011", 8, 9LLU, 3, 0); + TEST_STRTOULL("011", 0, 9LLU, 3, 0); + TEST_STRTOULL("-11", 8, -9LLU, 3, 0); + TEST_STRTOULL("-011", 8, -9LLU, 4, 0); + TEST_STRTOULL("-011", 0, -9LLU, 4, 0); + + TEST_STRTOULL("011", 8, 9LLU, 3, 0); + TEST_STRTOULL("011", 0, 9LLU, 3, 0); + TEST_STRTOULL("-11", 8, -9LLU, 3, 0); + TEST_STRTOULL("-011", 8, -9LLU, 4, 0); + TEST_STRTOULL("-011", 0, -9LLU, 4, 0); + + TEST_STRTOULL("Text", 0, 0LLU, 0, 0); + + TEST_STRTOULL("9223372036854775807", 10, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("9223372036854775807", 0, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("9223372036854775808", 0, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("9223372036854775808", 10, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("0x7FFFFFFFFFFFFFFF", 0, 9223372036854775807LLU, 18, 0); + TEST_STRTOULL("0x7FFFFFFFFFFFFFFF", 16, 9223372036854775807LLU, 18, 0); + TEST_STRTOULL("7FFFFFFFFFFFFFFF", 16, 9223372036854775807LLU, 16, 0); + TEST_STRTOULL("0x8000000000000000", 0, 9223372036854775808LLU, 18, 0); + TEST_STRTOULL("0x8000000000000000", 16, 9223372036854775808LLU, 18, 0); + TEST_STRTOULL("8000000000000000", 16, 9223372036854775808LLU, 16, 0); + TEST_STRTOULL("0777777777777777777777", 0, 9223372036854775807LLU, 22, 0); + TEST_STRTOULL("0777777777777777777777", 8, 9223372036854775807LLU, 22, 0); + TEST_STRTOULL("777777777777777777777", 8, 9223372036854775807LLU, 21, 0); + TEST_STRTOULL("01000000000000000000000",0, 9223372036854775808LLU, 23, 0); + TEST_STRTOULL("01000000000000000000000",8, 9223372036854775808LLU, 23, 0); + TEST_STRTOULL("1000000000000000000000", 8, 9223372036854775808LLU, 22, 0); + + TEST_STRTOULL("-9223372036854775808", 10, 9223372036854775808LLU, 20, 0); + TEST_STRTOULL("-9223372036854775808", 0, 9223372036854775808LLU, 20, 0); + TEST_STRTOULL("-9223372036854775809", 0, 9223372036854775807LLU, 20, 0); + TEST_STRTOULL("-9223372036854775809", 10, 9223372036854775807LLU, 20, 0); + TEST_STRTOULL("-0x8000000000000000", 0, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("-0x8000000000000000", 16, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("-8000000000000000", 16, 9223372036854775808LLU, 17, 0); + TEST_STRTOULL("-0x8000000000000001", 0, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("-0x8000000000000001", 16, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("-8000000000000001", 16, 9223372036854775807LLU, 17, 0); + TEST_STRTOULL("-01000000000000000000000",0, 9223372036854775808LLU, 24, 0); + TEST_STRTOULL("-01000000000000000000000",8, 9223372036854775808LLU, 24, 0); + TEST_STRTOULL("-1000000000000000000000",8, 9223372036854775808LLU, 23, 0); + TEST_STRTOULL("-01000000000000000000001",0, 9223372036854775807LLU, 24, 0); + TEST_STRTOULL("-01000000000000000000001",8, 9223372036854775807LLU, 24, 0); + TEST_STRTOULL("-1000000000000000000001",8, 9223372036854775807LLU, 23, 0); + + TEST_STRTOULL("18446744073709551615", 0, 18446744073709551615LLU, 20, 0); + TEST_STRTOULL("18446744073709551615", 10, 18446744073709551615LLU, 20, 0); + TEST_STRTOULL("18446744073709551616", 0, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("18446744073709551616", 10, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("0xFFFFFFFFFFFFFFFF", 0, 18446744073709551615LLU, 18, 0); + TEST_STRTOULL("0xFFFFFFFFFFFFFFFF", 16, 18446744073709551615LLU, 18, 0); + TEST_STRTOULL("FFFFFFFFFFFFFFFF", 16, 18446744073709551615LLU, 16, 0); + TEST_STRTOULL("0x10000000000000000", 0, 18446744073709551615LLU, 19, ERANGE); + TEST_STRTOULL("0x10000000000000000", 16, 18446744073709551615LLU, 19, ERANGE); + TEST_STRTOULL("10000000000000000", 16, 18446744073709551615LLU, 17, ERANGE); + TEST_STRTOULL("01777777777777777777777",0, 18446744073709551615LLU, 23, 0); + TEST_STRTOULL("01777777777777777777777",8, 18446744073709551615LLU, 23, 0); + TEST_STRTOULL("1777777777777777777777", 8, 18446744073709551615LLU, 22, 0); + TEST_STRTOULL("02000000000000000000000",0, 18446744073709551615LLU, 23, ERANGE); + TEST_STRTOULL("02000000000000000000000",8, 18446744073709551615LLU, 23, ERANGE); + TEST_STRTOULL("2000000000000000000000", 8, 18446744073709551615LLU, 22, ERANGE); + + TEST_STRTOULL("-18446744073709551615", 0, 1LLU, 21, 0); + TEST_STRTOULL("-18446744073709551615", 10, 1LLU, 21, 0); + TEST_STRTOULL("-18446744073709551616", 0, 18446744073709551615LLU, 21, ERANGE); + TEST_STRTOULL("-18446744073709551616", 10, 18446744073709551615LLU, 21, ERANGE); + TEST_STRTOULL("-0xFFFFFFFFFFFFFFFF", 0, 1LLU, 19, 0); + TEST_STRTOULL("-0xFFFFFFFFFFFFFFFF", 16, 1LLU, 19, 0); + TEST_STRTOULL("-FFFFFFFFFFFFFFFF", 16, 1LLU, 17, 0); + TEST_STRTOULL("-0x10000000000000000", 0, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("-0x10000000000000000", 16, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("-10000000000000000", 16, 18446744073709551615LLU, 18, ERANGE); + TEST_STRTOULL("-01777777777777777777777",0, 1LLU, 24, 0); + TEST_STRTOULL("-01777777777777777777777",8, 1LLU, 24, 0); + TEST_STRTOULL("-1777777777777777777777",8, 1LLU, 23, 0); + TEST_STRTOULL("-02000000000000000000000",0, 18446744073709551615LLU, 24, ERANGE); + TEST_STRTOULL("-02000000000000000000000",8, 18446744073709551615LLU, 24, ERANGE); + TEST_STRTOULL("-2000000000000000000000",8, 18446744073709551615LLU, 23, ERANGE); + + printf("success: strtoull\n"); + return true; +} + +/* +FIXME: +Types: +bool +socklen_t +uint{8,16,32,64}_t +int{8,16,32,64}_t +intptr_t + +Constants: +PATH_NAME_MAX +UINT{16,32,64}_MAX +INT32_MAX +*/ + +static int test_va_copy(void) +{ + /* FIXME */ + return true; +} + +static int test_FUNCTION(void) +{ + printf("test: FUNCTION\n"); + if (strcmp(__FUNCTION__, "test_FUNCTION") != 0) { + printf("failure: FUNCTION [\nFUNCTION invalid\n]\n"); + return false; + } + printf("success: FUNCTION\n"); + return true; +} + +static int test_MIN(void) +{ + printf("test: MIN\n"); + if (MIN(20, 1) != 1) { + printf("failure: MIN [\nMIN invalid\n]\n"); + return false; + } + if (MIN(1, 20) != 1) { + printf("failure: MIN [\nMIN invalid\n]\n"); + return false; + } + printf("success: MIN\n"); + return true; +} + +static int test_MAX(void) +{ + printf("test: MAX\n"); + if (MAX(20, 1) != 20) { + printf("failure: MAX [\nMAX invalid\n]\n"); + return false; + } + if (MAX(1, 20) != 20) { + printf("failure: MAX [\nMAX invalid\n]\n"); + return false; + } + printf("success: MAX\n"); + return true; +} + +static int test_socketpair(void) +{ + int sock[2]; + char buf[20]; + + printf("test: socketpair\n"); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == -1) { + printf("failure: socketpair [\n" + "socketpair() failed\n" + "]\n"); + return false; + } + + if (write(sock[1], "automatisch", 12) == -1) { + printf("failure: socketpair [\n" + "write() failed: %s\n" + "]\n", strerror(errno)); + return false; + } + + if (read(sock[0], buf, 12) == -1) { + printf("failure: socketpair [\n" + "read() failed: %s\n" + "]\n", strerror(errno)); + return false; + } + + if (strcmp(buf, "automatisch") != 0) { + printf("failure: socketpair [\n" + "expected: automatisch, got: %s\n" + "]\n", buf); + return false; + } + + printf("success: socketpair\n"); + + return true; +} + +extern int libreplace_test_strptime(void); + +static int test_strptime(void) +{ + return libreplace_test_strptime(); +} + +extern int getifaddrs_test(void); + +static int test_getifaddrs(void) +{ + + printf("test: getifaddrs\n"); + + if (getifaddrs_test() != 0) { + printf("failure: getifaddrs\n"); + return false; + } + + printf("success: getifaddrs\n"); + return true; +} + +static int test_utime(void) +{ + struct utimbuf u; + struct stat st1, st2, st3; + int fd; + + printf("test: utime\n"); + unlink(TESTFILE); + + fd = open(TESTFILE, O_RDWR|O_CREAT, 0600); + if (fd == -1) { + printf("failure: utime [\n" + "creating '%s' failed - %s\n]\n", + TESTFILE, strerror(errno)); + return false; + } + + if (fstat(fd, &st1) != 0) { + printf("failure: utime [\n" + "fstat (1) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + + u.actime = st1.st_atime + 300; + u.modtime = st1.st_mtime - 300; + if (utime(TESTFILE, &u) != 0) { + printf("failure: utime [\n" + "utime(&u) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + + if (fstat(fd, &st2) != 0) { + printf("failure: utime [\n" + "fstat (2) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + + if (utime(TESTFILE, NULL) != 0) { + printf("failure: utime [\n" + "utime(NULL) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + + if (fstat(fd, &st3) != 0) { + printf("failure: utime [\n" + "fstat (3) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + +#define CMP_VAL(a,c,b) do { \ + if (a c b) { \ + printf("failure: utime [\n" \ + "%s: %s(%d) %s %s(%d)\n]\n", \ + __location__, \ + #a, (int)a, #c, #b, (int)b); \ + close(fd); \ + return false; \ + } \ +} while(0) +#define EQUAL_VAL(a,b) CMP_VAL(a,!=,b) +#define GREATER_VAL(a,b) CMP_VAL(a,<=,b) +#define LESSER_VAL(a,b) CMP_VAL(a,>=,b) + + EQUAL_VAL(st2.st_atime, st1.st_atime + 300); + EQUAL_VAL(st2.st_mtime, st1.st_mtime - 300); + LESSER_VAL(st3.st_atime, st2.st_atime); + GREATER_VAL(st3.st_mtime, st2.st_mtime); + +#undef CMP_VAL +#undef EQUAL_VAL +#undef GREATER_VAL +#undef LESSER_VAL + + unlink(TESTFILE); + printf("success: utime\n"); + close(fd); + return true; +} + +static int test_utimes(void) +{ + struct timeval tv[2]; + struct stat st1, st2; + int fd; + + printf("test: utimes\n"); + unlink(TESTFILE); + + fd = open(TESTFILE, O_RDWR|O_CREAT, 0600); + if (fd == -1) { + printf("failure: utimes [\n" + "creating '%s' failed - %s\n]\n", + TESTFILE, strerror(errno)); + return false; + } + + if (fstat(fd, &st1) != 0) { + printf("failure: utimes [\n" + "fstat (1) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + + ZERO_STRUCT(tv); + tv[0].tv_sec = st1.st_atime + 300; + tv[1].tv_sec = st1.st_mtime - 300; + if (utimes(TESTFILE, tv) != 0) { + printf("failure: utimes [\n" + "utimes(tv) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + + if (fstat(fd, &st2) != 0) { + printf("failure: utimes [\n" + "fstat (2) failed - %s\n]\n", + strerror(errno)); + close(fd); + return false; + } + +#define EQUAL_VAL(a,b) do { \ + if (a != b) { \ + printf("failure: utimes [\n" \ + "%s: %s(%d) != %s(%d)\n]\n", \ + __location__, \ + #a, (int)a, #b, (int)b); \ + close(fd); \ + return false; \ + } \ +} while(0) + + EQUAL_VAL(st2.st_atime, st1.st_atime + 300); + EQUAL_VAL(st2.st_mtime, st1.st_mtime - 300); + +#undef EQUAL_VAL + + unlink(TESTFILE); + printf("success: utimes\n"); + close(fd); + return true; +} + +static int test_memmem(void) +{ + char *s; + + printf("test: memmem\n"); + + s = (char *)memmem("foo", 3, "fo", 2); + if (strcmp(s, "foo") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + s = (char *)memmem("foo", 3, "", 0); + /* it is allowable for this to return NULL (as happens on + FreeBSD) */ + if (s && strcmp(s, "foo") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + s = (char *)memmem("foo", 4, "o", 1); + if (strcmp(s, "oo") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + s = (char *)memmem("foobarfodx", 11, "fod", 3); + if (strcmp(s, "fodx") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + printf("success: memmem\n"); + + 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) +{ + bool ret = true; + ret &= test_ftruncate(); + ret &= test_strlcpy(); + ret &= test_strlcat(); + ret &= test_mktime(); + ret &= test_initgroups(); + ret &= test_memmove(); + ret &= test_strdup(); + ret &= test_setlinebuf(); + ret &= test_vsyslog(); + ret &= test_timegm(); + ret &= test_setenv(); + ret &= test_strndup(); + ret &= test_strnlen(); + ret &= test_waitpid(); + ret &= test_seteuid(); + ret &= test_setegid(); + ret &= test_asprintf(); + ret &= test_snprintf(); + ret &= test_vasprintf(); + ret &= test_vsnprintf(); + ret &= test_opendir(); + ret &= test_readdir(); + ret &= test_telldir(); + ret &= test_seekdir(); + ret &= test_dlopen(); + ret &= test_chroot(); + ret &= test_bzero(); + ret &= test_strerror(); + ret &= test_errno(); + ret &= test_mkdtemp(); + ret &= test_mkstemp(); + ret &= test_pread(); + ret &= test_pwrite(); + ret &= test_inet_ntoa(); + ret &= test_strtoll(); + ret &= test_strtoull(); + ret &= test_va_copy(); + ret &= test_FUNCTION(); + ret &= test_MIN(); + ret &= test_MAX(); + ret &= test_socketpair(); + ret &= test_strptime(); + ret &= test_getifaddrs(); + ret &= test_utime(); + ret &= test_utimes(); + ret &= test_memmem(); + ret &= test_closefrom(); + + return ret; +} diff --git a/ldb-2.0.8/lib/replace/timegm.c b/ldb-2.0.8/lib/replace/timegm.c new file mode 100644 index 0000000..395c684 --- /dev/null +++ b/ldb-2.0.8/lib/replace/timegm.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + adapted for Samba4 by Andrew Tridgell +*/ + +#include "replace.h" +#include "system/time.h" + +static int is_leap(unsigned y) +{ + y += 1900; + return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); +} + +time_t rep_timegm(struct tm *tm) +{ + static const unsigned ndays[2][12] ={ + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + time_t res = 0; + unsigned i; + + if (tm->tm_mon > 12 || + tm->tm_mon < 0 || + tm->tm_mday > 31 || + tm->tm_min > 60 || + tm->tm_sec > 60 || + tm->tm_hour > 24) { + /* invalid tm structure */ + return 0; + } + + for (i = 70; i < tm->tm_year; ++i) + res += is_leap(i) ? 366 : 365; + + for (i = 0; i < tm->tm_mon; ++i) + res += ndays[is_leap(tm->tm_year)][i]; + res += tm->tm_mday - 1; + res *= 24; + res += tm->tm_hour; + res *= 60; + res += tm->tm_min; + res *= 60; + res += tm->tm_sec; + return res; +} diff --git a/ldb-2.0.8/lib/replace/win32_replace.h b/ldb-2.0.8/lib/replace/win32_replace.h new file mode 100644 index 0000000..9901e72 --- /dev/null +++ b/ldb-2.0.8/lib/replace/win32_replace.h @@ -0,0 +1,159 @@ +#ifndef _WIN32_REPLACE_H +#define _WIN32_REPLACE_H + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif + +/* Map BSD Socket errorcodes to the WSA errorcodes (if possible) */ + +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define ECONNREFUSED WSAECONNREFUSED +#define EINPROGRESS WSAEINPROGRESS +#define EMSGSIZE WSAEMSGSIZE +#define ENOBUFS WSAENOBUFS +#define ENOTSOCK WSAENOTSOCK +#define ENETUNREACH WSAENETUNREACH +#define ENOPROTOOPT WSAENOPROTOOPT +#define ENOTCONN WSAENOTCONN +#define ENOTSUP 134 + +/* We undefine the following constants due to conflicts with the w32api headers + * and the Windows Platform SDK/DDK. + */ + +#undef interface + +#undef ERROR_INVALID_PARAMETER +#undef ERROR_INSUFFICIENT_BUFFER +#undef ERROR_INVALID_DATATYPE + +#undef FILE_GENERIC_READ +#undef FILE_GENERIC_WRITE +#undef FILE_GENERIC_EXECUTE +#undef FILE_ATTRIBUTE_READONLY +#undef FILE_ATTRIBUTE_HIDDEN +#undef FILE_ATTRIBUTE_SYSTEM +#undef FILE_ATTRIBUTE_DIRECTORY +#undef FILE_ATTRIBUTE_ARCHIVE +#undef FILE_ATTRIBUTE_DEVICE +#undef FILE_ATTRIBUTE_NORMAL +#undef FILE_ATTRIBUTE_TEMPORARY +#undef FILE_ATTRIBUTE_REPARSE_POINT +#undef FILE_ATTRIBUTE_COMPRESSED +#undef FILE_ATTRIBUTE_OFFLINE +#undef FILE_ATTRIBUTE_ENCRYPTED +#undef FILE_FLAG_WRITE_THROUGH +#undef FILE_FLAG_NO_BUFFERING +#undef FILE_FLAG_RANDOM_ACCESS +#undef FILE_FLAG_SEQUENTIAL_SCAN +#undef FILE_FLAG_DELETE_ON_CLOSE +#undef FILE_FLAG_BACKUP_SEMANTICS +#undef FILE_FLAG_POSIX_SEMANTICS +#undef FILE_TYPE_DISK +#undef FILE_TYPE_UNKNOWN +#undef FILE_CASE_SENSITIVE_SEARCH +#undef FILE_CASE_PRESERVED_NAMES +#undef FILE_UNICODE_ON_DISK +#undef FILE_PERSISTENT_ACLS +#undef FILE_FILE_COMPRESSION +#undef FILE_VOLUME_QUOTAS +#undef FILE_VOLUME_IS_COMPRESSED +#undef FILE_NOTIFY_CHANGE_FILE_NAME +#undef FILE_NOTIFY_CHANGE_DIR_NAME +#undef FILE_NOTIFY_CHANGE_ATTRIBUTES +#undef FILE_NOTIFY_CHANGE_SIZE +#undef FILE_NOTIFY_CHANGE_LAST_WRITE +#undef FILE_NOTIFY_CHANGE_LAST_ACCESS +#undef FILE_NOTIFY_CHANGE_CREATION +#undef FILE_NOTIFY_CHANGE_EA +#undef FILE_NOTIFY_CHANGE_SECURITY +#undef FILE_NOTIFY_CHANGE_STREAM_NAME +#undef FILE_NOTIFY_CHANGE_STREAM_SIZE +#undef FILE_NOTIFY_CHANGE_STREAM_WRITE +#undef FILE_NOTIFY_CHANGE_NAME + +#undef PRINTER_ATTRIBUTE_QUEUED +#undef PRINTER_ATTRIBUTE_DIRECT +#undef PRINTER_ATTRIBUTE_DEFAULT +#undef PRINTER_ATTRIBUTE_SHARED +#undef PRINTER_ATTRIBUTE_NETWORK +#undef PRINTER_ATTRIBUTE_HIDDEN +#undef PRINTER_ATTRIBUTE_LOCAL +#undef PRINTER_ATTRIBUTE_ENABLE_DEVQ +#undef PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS +#undef PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST +#undef PRINTER_ATTRIBUTE_WORK_OFFLINE +#undef PRINTER_ATTRIBUTE_ENABLE_BIDI +#undef PRINTER_ATTRIBUTE_RAW_ONLY +#undef PRINTER_ATTRIBUTE_PUBLISHED +#undef PRINTER_ENUM_DEFAULT +#undef PRINTER_ENUM_LOCAL +#undef PRINTER_ENUM_CONNECTIONS +#undef PRINTER_ENUM_FAVORITE +#undef PRINTER_ENUM_NAME +#undef PRINTER_ENUM_REMOTE +#undef PRINTER_ENUM_SHARED +#undef PRINTER_ENUM_NETWORK +#undef PRINTER_ENUM_EXPAND +#undef PRINTER_ENUM_CONTAINER +#undef PRINTER_ENUM_ICON1 +#undef PRINTER_ENUM_ICON2 +#undef PRINTER_ENUM_ICON3 +#undef PRINTER_ENUM_ICON4 +#undef PRINTER_ENUM_ICON5 +#undef PRINTER_ENUM_ICON6 +#undef PRINTER_ENUM_ICON7 +#undef PRINTER_ENUM_ICON8 +#undef PRINTER_STATUS_PAUSED +#undef PRINTER_STATUS_ERROR +#undef PRINTER_STATUS_PENDING_DELETION +#undef PRINTER_STATUS_PAPER_JAM +#undef PRINTER_STATUS_PAPER_OUT +#undef PRINTER_STATUS_MANUAL_FEED +#undef PRINTER_STATUS_PAPER_PROBLEM +#undef PRINTER_STATUS_OFFLINE +#undef PRINTER_STATUS_IO_ACTIVE +#undef PRINTER_STATUS_BUSY +#undef PRINTER_STATUS_PRINTING +#undef PRINTER_STATUS_OUTPUT_BIN_FULL +#undef PRINTER_STATUS_NOT_AVAILABLE +#undef PRINTER_STATUS_WAITING +#undef PRINTER_STATUS_PROCESSING +#undef PRINTER_STATUS_INITIALIZING +#undef PRINTER_STATUS_WARMING_UP +#undef PRINTER_STATUS_TONER_LOW +#undef PRINTER_STATUS_NO_TONER +#undef PRINTER_STATUS_PAGE_PUNT +#undef PRINTER_STATUS_USER_INTERVENTION +#undef PRINTER_STATUS_OUT_OF_MEMORY +#undef PRINTER_STATUS_DOOR_OPEN +#undef PRINTER_STATUS_SERVER_UNKNOWN +#undef PRINTER_STATUS_POWER_SAVE + +#undef DWORD +#undef HKEY_CLASSES_ROOT +#undef HKEY_CURRENT_USER +#undef HKEY_LOCAL_MACHINE +#undef HKEY_USERS +#undef HKEY_PERFORMANCE_DATA +#undef HKEY_CURRENT_CONFIG +#undef HKEY_DYN_DATA +#undef REG_DWORD +#undef REG_QWORD + +#undef SERVICE_STATE_ALL + +#undef SE_GROUP_MANDATORY +#undef SE_GROUP_ENABLED_BY_DEFAULT +#undef SE_GROUP_ENABLED + +#endif /* _WIN32_REPLACE_H */ diff --git a/ldb-2.0.8/lib/replace/wscript b/ldb-2.0.8/lib/replace/wscript new file mode 100644 index 0000000..56e2a22 --- /dev/null +++ b/ldb-2.0.8/lib/replace/wscript @@ -0,0 +1,955 @@ +#!/usr/bin/env python + +APPNAME = 'libreplace' +VERSION = '1.2.1' + +import sys +import os + +# find the buildtools directory +top = '.' +while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5: + top = top + '/..' +sys.path.insert(0, top + '/buildtools/wafsamba') + +out = 'bin' + +import wafsamba +from wafsamba import samba_dist +from waflib import Options, Utils, Logs, Context + +samba_dist.DIST_DIRS('lib/replace buildtools:buildtools third_party/waf:third_party/waf') + +def options(opt): + opt.BUILTIN_DEFAULT('NONE') + opt.PRIVATE_EXTENSION_DEFAULT('') + opt.RECURSE('buildtools/wafsamba') + +@Utils.run_once +def configure(conf): + conf.RECURSE('buildtools/wafsamba') + + conf.env.standalone_replace = conf.IN_LAUNCH_DIR() + + conf.DEFINE('HAVE_LIBREPLACE', 1) + conf.DEFINE('LIBREPLACE_NETWORK_CHECKS', 1) + + conf.CHECK_HEADERS('linux/types.h crypt.h locale.h acl/libacl.h compat.h') + conf.CHECK_HEADERS('acl/libacl.h attr/xattr.h compat.h ctype.h dustat.h') + conf.CHECK_HEADERS('fcntl.h fnmatch.h glob.h history.h krb5.h langinfo.h') + conf.CHECK_HEADERS('libaio.h locale.h ndir.h pwd.h') + conf.CHECK_HEADERS('shadow.h sys/acl.h') + conf.CHECK_HEADERS('sys/attributes.h attr/attributes.h sys/capability.h sys/dir.h sys/epoll.h') + conf.CHECK_HEADERS('port.h') + conf.CHECK_HEADERS('sys/fcntl.h sys/filio.h sys/filsys.h sys/fs/s5param.h') + conf.CHECK_HEADERS('sys/id.h sys/ioctl.h sys/ipc.h sys/mman.h sys/mode.h sys/ndir.h sys/priv.h') + conf.CHECK_HEADERS('sys/resource.h sys/security.h sys/shm.h sys/statfs.h sys/statvfs.h sys/termio.h') + conf.CHECK_HEADERS('sys/vfs.h sys/xattr.h termio.h termios.h sys/file.h') + conf.CHECK_HEADERS('sys/ucontext.h sys/wait.h sys/stat.h') + + if not conf.CHECK_DECLS('malloc', headers='stdlib.h'): + conf.CHECK_HEADERS('malloc.h') + + conf.CHECK_HEADERS('grp.h') + conf.CHECK_HEADERS('sys/select.h setjmp.h utime.h sys/syslog.h syslog.h') + conf.CHECK_HEADERS('stdarg.h vararg.h sys/mount.h mntent.h') + conf.CHECK_HEADERS('stropts.h unix.h string.h strings.h sys/param.h limits.h') + conf.CHECK_HEADERS('''sys/socket.h netinet/in.h netdb.h arpa/inet.h netinet/in_systm.h + netinet/ip.h netinet/tcp.h netinet/in_ip.h + sys/sockio.h sys/un.h''', together=True) + conf.CHECK_HEADERS('sys/uio.h ifaddrs.h direct.h dirent.h') + conf.CHECK_HEADERS('windows.h winsock2.h ws2tcpip.h') + conf.CHECK_HEADERS('errno.h') + conf.CHECK_HEADERS('getopt.h iconv.h') + conf.CHECK_HEADERS('memory.h nss.h sasl/sasl.h') + + conf.CHECK_FUNCS_IN('inotify_init', 'inotify', checklibc=True, + headers='sys/inotify.h') + + conf.CHECK_HEADERS('security/pam_appl.h zlib.h asm/unistd.h') + conf.CHECK_HEADERS('aio.h sys/unistd.h alloca.h float.h') + + conf.SET_TARGET_TYPE('tirpc', 'EMPTY') + + if conf.CHECK_CODE( + '\n#ifndef _TIRPC_RPC_H\n#error "no tirpc headers in system path"\n#endif\n', + 'HAVE_RPC_RPC_HEADERS', + headers=['rpc/rpc.h', 'rpc/nettype.h'], + msg='Checking for tirpc rpc headers in default system path'): + if conf.CONFIG_SET('HAVE_RPC_RPC_H'): + conf.undefine('HAVE_RPC_RPC_H') + + if not conf.CONFIG_SET('HAVE_RPC_RPC_H'): + if conf.CHECK_CFG(package='libtirpc', args='--cflags --libs', + msg='Checking for libtirpc headers', + uselib_store='TIRPC'): + conf.CHECK_HEADERS('rpc/rpc.h rpc/nettype.h', lib='tirpc', together=True) + conf.SET_TARGET_TYPE('tirpc', 'SYSLIB') + if not conf.CONFIG_SET('HAVE_RPC_RPC_H'): + if conf.CHECK_CFG(package='libntirpc', args='--cflags', + msg='Checking for libntirpc headers', + uselib_store='TIRPC'): + conf.CHECK_HEADERS('rpc/rpc.h rpc/nettype.h', lib='tirpc', together=True) + conf.SET_TARGET_TYPE('tirpc', 'SYSLIB') + if not conf.CONFIG_SET('HAVE_RPC_RPC_H'): + Logs.warn('No rpc/rpc.h header found, tirpc or libntirpc missing?') + + conf.SET_TARGET_TYPE('nsl', 'EMPTY') + conf.CHECK_HEADERS('rpc/rpc.h rpcsvc/yp_prot.h', lib='tirpc') + if not conf.CONFIG_SET('HAVE_RPCSVC_YP_PROT_H'): + if conf.CHECK_CFG(package='libnsl', args='--cflags --libs', + msg='Checking for libnsl', + uselib_store='NSL'): + conf.SET_TARGET_TYPE('nsl', 'SYSLIB') + conf.CHECK_HEADERS('rpc/rpc.h rpcsvc/yp_prot.h', lib='tirpc nsl') + else: + conf.SET_TARGET_TYPE('nsl', 'SYSLIB') + conf.CHECK_HEADERS('rpcsvc/nis.h rpcsvc/ypclnt.h', lib='tirpc nsl') + + conf.CHECK_HEADERS('sys/sysctl.h') + conf.CHECK_HEADERS('sys/fileio.h sys/filesys.h sys/dustat.h sys/sysmacros.h') + conf.CHECK_HEADERS('xfs/libxfs.h netgroup.h') + + conf.CHECK_HEADERS('valgrind.h valgrind/valgrind.h') + conf.CHECK_HEADERS('valgrind/memcheck.h valgrind/helgrind.h') + conf.CHECK_HEADERS('nss_common.h nsswitch.h ns_api.h') + conf.CHECK_HEADERS('sys/extattr.h sys/ea.h sys/proplist.h sys/cdefs.h') + conf.CHECK_HEADERS('utmp.h utmpx.h lastlog.h') + conf.CHECK_HEADERS('syscall.h sys/syscall.h inttypes.h') + conf.CHECK_HEADERS('sys/atomic.h stdatomic.h') + conf.CHECK_HEADERS('libgen.h') + + if conf.CHECK_CFLAGS('-Wno-format-truncation'): + conf.define('HAVE_WNO_FORMAT_TRUNCATION', '1') + + if conf.CHECK_CFLAGS('-Wno-unused-function'): + conf.define('HAVE_WNO_UNUSED_FUNCTION', '1') + + if conf.CHECK_CFLAGS('-Wno-strict-overflow'): + conf.define('HAVE_WNO_STRICT_OVERFLOW', '1') + + # Check for process set name support + conf.CHECK_CODE(''' + #include + int main(void) { + prctl(0); + return 0; + } + ''', + 'HAVE_PRCTL', + headers='sys/prctl.h', + msg='Checking for prctl syscall') + + conf.CHECK_CODE(''' + #include + #ifdef HAVE_FCNTL_H + #include + #endif + int main(void) { int fd = open("/dev/null", O_DIRECT); } + ''', + define='HAVE_OPEN_O_DIRECT', + addmain=False, + msg='Checking for O_DIRECT flag to open(2)') + + conf.CHECK_TYPES('"long long" intptr_t uintptr_t ptrdiff_t comparison_fn_t') + conf.CHECK_TYPE('_Bool', define='HAVE__Bool') + conf.CHECK_TYPE('bool', define='HAVE_BOOL') + + conf.CHECK_TYPE('int8_t', 'char') + conf.CHECK_TYPE('uint8_t', 'unsigned char') + conf.CHECK_TYPE('int16_t', 'short') + conf.CHECK_TYPE('uint16_t', 'unsigned short') + conf.CHECK_TYPE('int32_t', 'int') + conf.CHECK_TYPE('uint32_t', 'unsigned') + conf.CHECK_TYPE('int64_t', 'long long') + conf.CHECK_TYPE('uint64_t', 'unsigned long long') + conf.CHECK_TYPE('size_t', 'unsigned int') + conf.CHECK_TYPE('ssize_t', 'int') + conf.CHECK_TYPE('ino_t', 'unsigned') + conf.CHECK_TYPE('loff_t', 'off_t') + conf.CHECK_TYPE('offset_t', 'loff_t') + conf.CHECK_TYPE('volatile int', define='HAVE_VOLATILE') + conf.CHECK_TYPE('uint_t', 'unsigned int') + conf.CHECK_TYPE('blksize_t', 'long', headers='sys/types.h sys/stat.h unistd.h') + conf.CHECK_TYPE('blkcnt_t', 'long', headers='sys/types.h sys/stat.h unistd.h') + + conf.CHECK_SIZEOF('bool char int "long long" long short size_t ssize_t') + conf.CHECK_SIZEOF('int8_t uint8_t int16_t uint16_t int32_t uint32_t int64_t uint64_t') + conf.CHECK_SIZEOF('void*', define='SIZEOF_VOID_P') + conf.CHECK_SIZEOF('off_t dev_t ino_t time_t') + + conf.CHECK_TYPES('socklen_t', headers='sys/socket.h') + conf.CHECK_TYPE_IN('struct ifaddrs', 'ifaddrs.h') + conf.CHECK_TYPE_IN('struct addrinfo', 'netdb.h') + conf.CHECK_TYPE_IN('struct sockaddr', 'sys/socket.h') + conf.CHECK_CODE('struct sockaddr_in6 x', define='HAVE_STRUCT_SOCKADDR_IN6', + headers='sys/socket.h netdb.h netinet/in.h') + conf.CHECK_TYPE_IN('struct sockaddr_storage', 'sys/socket.h') + conf.CHECK_TYPE_IN('sa_family_t', 'sys/socket.h') + + conf.CHECK_TYPE_IN('sig_atomic_t', 'signal.h', define='HAVE_SIG_ATOMIC_T_TYPE') + conf.CHECK_FUNCS('sigsetmask siggetmask sigprocmask sigblock sigaction sigset') + + # Those functions are normally available in libc + if not conf.CHECK_FUNCS(''' + inet_ntoa + inet_aton + inet_ntop + inet_pton + connect + gethostbyname + getaddrinfo + getnameinfo + freeaddrinfo + gai_strerror + socketpair''', + headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h'): + conf.CHECK_FUNCS_IN(''' + inet_ntoa + inet_aton + inet_ntop + inet_pton + connect + gethostbyname + getaddrinfo + getnameinfo + freeaddrinfo + gai_strerror + socketpair''', + 'socket nsl', + headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h') + conf.DEFINE('REPLACE_REQUIRES_LIBSOCKET_LIBNSL', 1) + + conf.CHECK_FUNCS('memset_s memset_explicit') + + conf.CHECK_CODE(''' + #include + + int main(void) + { + char buf[] = "This is some content"; + memset(buf, '\0', sizeof(buf)); __asm__ volatile("" : : "g"(&buf) : "memory"); + return 0; + } + ''', + define='HAVE_GCC_VOLATILE_MEMORY_PROTECTION', + addmain=False, + msg='Checking for volatile memory protection', + local_include=False) + + # Some old Linux systems have broken header files and + # miss the IPV6_V6ONLY define in netinet/in.h, + # but have it in linux/in6.h. + # We can't include both files so we just check if the value + # if defined and do the replacement in system/network.h + if not conf.CHECK_VARIABLE('IPV6_V6ONLY', + headers='sys/socket.h netdb.h netinet/in.h'): + conf.CHECK_CODE(''' + #include + #if (IPV6_V6ONLY != 26) + #error no IPV6_V6ONLY support on linux + #endif + int main(void) { return IPV6_V6ONLY; } + ''', + define='HAVE_LINUX_IPV6_V6ONLY_26', + addmain=False, + msg='Checking for IPV6_V6ONLY in linux/in6.h', + local_include=False) + + conf.CHECK_CODE(''' + struct sockaddr_storage sa_store; + struct addrinfo *ai = NULL; + struct in6_addr in6addr; + int idx = if_nametoindex("iface1"); + int s = socket(AF_INET6, SOCK_STREAM, 0); + int ret = getaddrinfo(NULL, NULL, NULL, &ai); + if (ret != 0) { + const char *es = gai_strerror(ret); + } + freeaddrinfo(ai); + { + int val = 1; + #ifdef HAVE_LINUX_IPV6_V6ONLY_26 + #define IPV6_V6ONLY 26 + #endif + ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (const void *)&val, sizeof(val)); + } + ''', + define='HAVE_IPV6', + lib='nsl socket', + headers='sys/socket.h netdb.h netinet/in.h net/if.h') + + if conf.CONFIG_SET('HAVE_SYS_UCONTEXT_H') and conf.CONFIG_SET('HAVE_SIGNAL_H'): + conf.CHECK_CODE(''' + ucontext_t uc; + sigaddset(&uc.uc_sigmask, SIGUSR1); + ''', + 'HAVE_UCONTEXT_T', + msg="Checking whether we have ucontext_t", + headers='signal.h sys/ucontext.h') + + # Check for atomic builtins. */ + conf.CHECK_CODE(''' + 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(''' + int32_t i; + atomic_add_32(&i, 1); + ''', + 'HAVE_ATOMIC_ADD_32', + headers='stdint.h sys/atomic.h', + msg='Checking for atomic_add_32 compiler builtin') + + # Check for thread fence. */ + tf = conf.CHECK_CODE('atomic_thread_fence(memory_order_seq_cst);', + 'HAVE_ATOMIC_THREAD_FENCE', + headers='stdatomic.h', + msg='Checking for atomic_thread_fence(memory_order_seq_cst) in stdatomic.h') + if not tf: + tf = conf.CHECK_CODE('__atomic_thread_fence(__ATOMIC_SEQ_CST);', + 'HAVE___ATOMIC_THREAD_FENCE', + msg='Checking for __atomic_thread_fence(__ATOMIC_SEQ_CST)') + if not tf: + # __sync_synchronize() is available since 2005 in gcc. + tf = conf.CHECK_CODE('__sync_synchronize();', + 'HAVE___SYNC_SYNCHRONIZE', + msg='Checking for __sync_synchronize') + if tf: + conf.DEFINE('HAVE_ATOMIC_THREAD_FENCE_SUPPORT', 1) + + conf.CHECK_CODE(''' + #define FALL_THROUGH __attribute__((fallthrough)) + + enum direction_e { + UP = 0, + DOWN, + }; + + int main(void) { + enum direction_e key = UP; + int i = 10; + int j = 0; + + switch (key) { + case UP: + i = 5; + FALL_THROUGH; + case DOWN: + j = i * 2; + break; + default: + break; + } + + if (j < i) { + return 1; + } + + return 0; + } + ''', + 'HAVE_FALLTHROUGH_ATTRIBUTE', + addmain=False, + strict=True, + cflags=['-Werror=missing-declarations'], + msg='Checking for fallthrough attribute') + + # these may be builtins, so we need the link=False strategy + conf.CHECK_FUNCS('strdup memmem printf memset memcpy memmove strcpy strncpy bzero', link=False) + + # See https://bugzilla.samba.org/show_bug.cgi?id=1097 + # + # Ported in from autoconf where it was added with this commit: + # commit 804cfb20a067b4b687089dc72a8271b3abf20f31 + # Author: Simo Sorce + # Date: Wed Aug 25 14:24:16 2004 +0000 + # r2070: Let's try to overload srnlen and strndup for AIX where they are natly broken. + + host_os = sys.platform + if host_os.rfind('aix') > -1: + conf.DEFINE('BROKEN_STRNLEN', 1) + conf.DEFINE('BROKEN_STRNDUP', 1) + + conf.CHECK_FUNCS('shl_load shl_unload shl_findsym') + conf.CHECK_FUNCS('pipe strftime srandom random srand rand usleep setbuffer') + conf.CHECK_FUNCS('lstat getpgrp utime utimes setuid seteuid setreuid setresuid setgid setegid') + conf.CHECK_FUNCS('setregid setresgid chroot strerror vsyslog setlinebuf mktime') + conf.CHECK_FUNCS('ftruncate chsize rename waitpid wait4') + conf.CHECK_FUNCS('initgroups pread pwrite strndup strcasestr strsep') + conf.CHECK_FUNCS('strtok_r mkdtemp dup2 dprintf vdprintf isatty chown lchown') + conf.CHECK_FUNCS('link readlink symlink realpath snprintf vsnprintf') + conf.CHECK_FUNCS('asprintf vasprintf setenv unsetenv strnlen strtoull __strtoull') + conf.CHECK_FUNCS('strtouq strtoll __strtoll strtoq memalign posix_memalign') + conf.CHECK_FUNCS('fmemopen') + + if conf.CONFIG_SET('HAVE_MEMALIGN'): + conf.CHECK_DECLS('memalign', headers='malloc.h') + + # glibc up to 2.3.6 had dangerously broken posix_fallocate(). DON'T USE IT. + if conf.CHECK_CODE(''' +#define _XOPEN_SOURCE 600 +#include +#if defined(__GLIBC__) && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 4)) +#error probably broken posix_fallocate +#endif +''', + '_POSIX_FALLOCATE_CAPABLE_LIBC', + msg='Checking for posix_fallocate-capable libc'): + conf.CHECK_FUNCS('posix_fallocate') + + conf.CHECK_FUNCS('prctl dirname basename') + + strlcpy_in_bsd = False + + # libbsd on some platforms provides strlcpy and strlcat + if not conf.CHECK_FUNCS('strlcpy strlcat'): + if conf.CHECK_FUNCS_IN('strlcpy strlcat', 'bsd', headers='bsd/string.h', + checklibc=True): + strlcpy_in_bsd = True + if not conf.CHECK_FUNCS('getpeereid'): + conf.CHECK_FUNCS_IN('getpeereid', 'bsd', headers='sys/types.h bsd/unistd.h') + 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('setproctitle_init'): + conf.CHECK_FUNCS_IN('setproctitle_init', '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; + int ret = getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len);''', + 'HAVE_PEERCRED', + msg="Checking whether we can use SO_PEERCRED to get socket credentials", + headers='sys/types.h sys/socket.h') + + #Some OS (ie. freebsd) return EINVAL if the convertion could not be done, it's not what we expect + #Let's detect those cases + if conf.CONFIG_SET('HAVE_STRTOLL'): + conf.CHECK_CODE(''' + long long nb = strtoll("Text", NULL, 0); + if (errno == EINVAL) { + return 0; + } else { + return 1; + } + ''', + msg="Checking correct behavior of strtoll", + headers = 'errno.h', + execute = True, + define = 'HAVE_BSD_STRTOLL', + ) + conf.CHECK_FUNCS('if_nametoindex strerror_r') + conf.CHECK_FUNCS('getdirentries getdents syslog') + conf.CHECK_FUNCS('gai_strerror get_current_dir_name') + conf.CHECK_FUNCS('timegm getifaddrs freeifaddrs mmap setgroups syscall setsid') + conf.CHECK_FUNCS('getgrent_r getgrgid_r getgrnam_r getgrouplist getpagesize') + conf.CHECK_FUNCS('getpwent_r getpwnam_r getpwuid_r epoll_create') + conf.CHECK_FUNCS('port_create') + conf.CHECK_FUNCS('getprogname') + + conf.SET_TARGET_TYPE('attr', 'EMPTY') + + xattr_headers='sys/attributes.h attr/xattr.h sys/xattr.h' + + # default to 1, we set it to 0 if we don't find any EA implementation below: + conf.DEFINE('HAVE_XATTR_SUPPORT', 1) + if conf.CHECK_FUNCS_IN('getxattr', 'attr', checklibc=True, headers=xattr_headers): + conf.DEFINE('HAVE_XATTR_XATTR', 1) + # Darwin has extra options to xattr-family functions + conf.CHECK_CODE('getxattr(NULL, NULL, NULL, 0, 0, 0)', + headers=xattr_headers, local_include=False, + define='XATTR_ADDITIONAL_OPTIONS', + msg="Checking whether xattr interface takes additional options") + elif conf.CHECK_FUNCS_IN('attr_listf', 'attr', checklibc=True, headers=xattr_headers): + conf.DEFINE('HAVE_XATTR_ATTR', 1) + elif conf.CHECK_FUNCS('extattr_list_fd'): + conf.DEFINE('HAVE_XATTR_EXTATTR', 1) + elif conf.CHECK_FUNCS('flistea'): + conf.DEFINE('HAVE_XATTR_EA', 1) + elif not conf.CHECK_FUNCS('attropen'): + conf.DEFINE('HAVE_XATTR_SUPPORT', 0) + + + conf.CHECK_FUNCS_IN('dlopen dlsym dlerror dlclose', 'dl', + checklibc=True, headers='dlfcn.h dl.h') + + conf.CHECK_C_PROTOTYPE('dlopen', 'void *dlopen(const char* filename, unsigned int flags)', + define='DLOPEN_TAKES_UNSIGNED_FLAGS', headers='dlfcn.h dl.h') + + # + # Check for clock_gettime and fdatasync + # + # First check libc to avoid linking libreplace against librt. + # + if conf.CHECK_FUNCS('fdatasync'): + # some systems are missing the declaration + conf.CHECK_DECLS('fdatasync') + else: + if conf.CHECK_FUNCS_IN('fdatasync', 'rt'): + # some systems are missing the declaration + conf.CHECK_DECLS('fdatasync') + + has_clock_gettime = False + if conf.CHECK_FUNCS('clock_gettime'): + has_clock_gettime = True + + if not has_clock_gettime: + if conf.CHECK_FUNCS_IN('clock_gettime', 'rt', checklibc=True): + has_clock_gettime = True + + if has_clock_gettime: + for c in ['CLOCK_MONOTONIC', 'CLOCK_PROCESS_CPUTIME_ID', 'CLOCK_REALTIME']: + conf.CHECK_CODE(''' + #if TIME_WITH_SYS_TIME + # include + # include + #else + # if HAVE_SYS_TIME_H + # include + # else + # include + # endif + #endif + clockid_t clk = %s''' % c, + 'HAVE_%s' % c, + msg='Checking whether the clock_gettime clock ID %s is available' % c) + + conf.CHECK_TYPE('struct timespec', headers='sys/time.h time.h') + + # these headers need to be tested as a group on freebsd + conf.CHECK_HEADERS(headers='sys/socket.h net/if.h', together=True) + conf.CHECK_HEADERS(headers='netinet/in.h arpa/nameser.h resolv.h', together=True) + conf.CHECK_FUNCS_IN('res_search', 'resolv', checklibc=True, + headers='netinet/in.h arpa/nameser.h resolv.h') + + + # try to find libintl (if --without-gettext is not given) + conf.env.intl_libs='' + if not Options.options.disable_gettext: + conf.CHECK_HEADERS('libintl.h') + conf.CHECK_LIB('intl') + conf.CHECK_DECLS('dgettext gettext bindtextdomain textdomain bind_textdomain_codeset', headers="libintl.h") + # *textdomain functions are not strictly necessary + conf.CHECK_FUNCS_IN('bindtextdomain textdomain bind_textdomain_codeset', + '', checklibc=True, headers='libintl.h') + # gettext and dgettext must exist + # on some systems (the ones with glibc, those are in libc) + if conf.CHECK_FUNCS_IN('dgettext gettext', '', checklibc=True, headers='libintl.h'): + # save for dependency definitions + conf.env.intl_libs='' + # others (e.g. FreeBSD) have separate libintl + elif conf.CHECK_FUNCS_IN('dgettext gettext', 'intl', checklibc=False, headers='libintl.h'): + # save for dependency definitions + conf.env.intl_libs='intl' + # recheck with libintl + conf.CHECK_FUNCS_IN('bindtextdomain textdomain bind_textdomain_codeset', + 'intl', checklibc=False, headers='libintl.h') + else: + # Some hosts need lib iconv for linking with lib intl + # So we try with flags just in case it helps. + oldflags = list(conf.env['EXTRA_LDFLAGS']); + conf.env['EXTRA_LDFLAGS'].extend(["-liconv"]) + conf.CHECK_FUNCS_IN('dgettext gettext bindtextdomain textdomain bind_textdomain_codeset', + 'intl', checklibc=False, headers='libintl.h') + conf.env['EXTRA_LDFLAGS'] = oldflags + if conf.env['HAVE_GETTEXT'] and conf.env['HAVE_DGETTEXT']: + # save for dependency definitions + conf.env.intl_libs='iconv intl' + + # did we find both prototypes and a library to link against? + # if not, unset the detected values (see Bug #9911) + if not (conf.env['HAVE_GETTEXT'] and conf.env['HAVE_DECL_GETTEXT']): + conf.undefine('HAVE_GETTEXT') + conf.undefine('HAVE_DECL_GETTEXT') + if not (conf.env['HAVE_DGETTEXT'] and conf.env['HAVE_DECL_DGETTEXT']): + conf.undefine('HAVE_DGETTEXT') + conf.undefine('HAVE_DECL_DGETTEXT') + + conf.CHECK_FUNCS_IN('pthread_create', 'pthread', checklibc=True, headers='pthread.h') + + PTHREAD_CFLAGS='error' + PTHREAD_LDFLAGS='error' + + if PTHREAD_LDFLAGS == 'error': + # Check if pthread_attr_init() is provided by libc first! + if conf.CHECK_FUNCS('pthread_attr_init'): + PTHREAD_CFLAGS='-D_REENTRANT' + PTHREAD_LDFLAGS='' + if PTHREAD_LDFLAGS == 'error': + if conf.CHECK_FUNCS_IN('pthread_attr_init', 'pthread'): + PTHREAD_CFLAGS='-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS' + PTHREAD_LDFLAGS='-lpthread' + if PTHREAD_LDFLAGS == 'error': + if conf.CHECK_FUNCS_IN('pthread_attr_init', 'pthreads'): + PTHREAD_CFLAGS='-D_THREAD_SAFE' + PTHREAD_LDFLAGS='-lpthreads' + if PTHREAD_LDFLAGS == 'error': + if conf.CHECK_FUNCS_IN('pthread_attr_init', 'c_r'): + PTHREAD_CFLAGS='-D_THREAD_SAFE -pthread' + PTHREAD_LDFLAGS='-pthread' + + # especially for HP-UX, where the CHECK_FUNC macro fails to test for + # pthread_attr_init. On pthread_mutex_lock it works there... + if PTHREAD_LDFLAGS == 'error': + if conf.CHECK_FUNCS_IN('pthread_mutex_lock', 'pthread'): + PTHREAD_CFLAGS='-D_REENTRANT' + PTHREAD_LDFLAGS='-lpthread' + + if PTHREAD_CFLAGS != 'error' and PTHREAD_LDFLAGS != 'error': + if conf.CONFIG_SET('replace_add_global_pthread'): + conf.ADD_CFLAGS(PTHREAD_CFLAGS) + conf.ADD_LDFLAGS(PTHREAD_LDFLAGS) + conf.CHECK_HEADERS('pthread.h') + conf.DEFINE('HAVE_PTHREAD', '1') + + if conf.CONFIG_SET('HAVE_PTHREAD'): + + conf.CHECK_FUNCS_IN('pthread_mutexattr_setrobust', 'pthread', + checklibc=True, headers='pthread.h') + if not conf.CONFIG_SET('HAVE_PTHREAD_MUTEXATTR_SETROBUST'): + conf.CHECK_FUNCS_IN('pthread_mutexattr_setrobust_np', 'pthread', + checklibc=True, headers='pthread.h') + + conf.CHECK_DECLS('PTHREAD_MUTEX_ROBUST', headers='pthread.h') + if not conf.CONFIG_SET('HAVE_DECL_PTHREAD_MUTEX_ROBUST'): + conf.CHECK_DECLS('PTHREAD_MUTEX_ROBUST_NP', headers='pthread.h') + + conf.CHECK_FUNCS_IN('pthread_mutex_consistent', 'pthread', + checklibc=True, headers='pthread.h') + if not conf.CONFIG_SET('HAVE_PTHREAD_MUTEX_CONSISTENT'): + conf.CHECK_FUNCS_IN('pthread_mutex_consistent_np', 'pthread', + checklibc=True, headers='pthread.h') + + if ((conf.CONFIG_SET('HAVE_PTHREAD_MUTEXATTR_SETROBUST') or + conf.CONFIG_SET('HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP')) and + (conf.CONFIG_SET('HAVE_DECL_PTHREAD_MUTEX_ROBUST') or + conf.CONFIG_SET('HAVE_DECL_PTHREAD_MUTEX_ROBUST_NP')) and + (conf.CONFIG_SET('HAVE_PTHREAD_MUTEX_CONSISTENT') or + conf.CONFIG_SET('HAVE_PTHREAD_MUTEX_CONSISTENT_NP'))): + conf.DEFINE('HAVE_ROBUST_MUTEXES', 1) + + # __thread is available since 2002 in gcc. + conf.CHECK_CODE(''' + __thread int tls; + + int main(void) { + return 0; + } + ''', + 'HAVE___THREAD', + addmain=False, + msg='Checking for __thread local storage') + + conf.CHECK_FUNCS_IN('crypt', 'crypt', checklibc=True) + conf.CHECK_FUNCS_IN('crypt_r', 'crypt', checklibc=True) + + conf.CHECK_VARIABLE('rl_event_hook', define='HAVE_DECL_RL_EVENT_HOOK', always=True, + headers='readline.h readline/readline.h readline/history.h') + conf.CHECK_VARIABLE('program_invocation_short_name', headers='errno.h') + + conf.CHECK_DECLS('snprintf vsnprintf asprintf vasprintf') + + conf.CHECK_DECLS('errno', headers='errno.h', reverse=True) + conf.CHECK_DECLS('EWOULDBLOCK', headers='errno.h') + conf.CHECK_DECLS('environ', reverse=True, headers='unistd.h') + conf.CHECK_DECLS('getgrent_r getpwent_r', reverse=True, headers='pwd.h grp.h') + conf.CHECK_DECLS('pread pwrite setenv setresgid setresuid', reverse=True) + + if conf.CONFIG_SET('HAVE_EPOLL_CREATE') and conf.CONFIG_SET('HAVE_SYS_EPOLL_H'): + conf.DEFINE('HAVE_EPOLL', 1) + + 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') + + conf.CHECK_FUNCS('strptime') + conf.CHECK_DECLS('strptime', headers='time.h') + conf.CHECK_CODE('''#define LIBREPLACE_CONFIGURE_TEST_STRPTIME + #include "tests/strptime.c"''', + define='HAVE_WORKING_STRPTIME', + execute=True, + addmain=False, + msg='Checking for working strptime') + + conf.CHECK_C_PROTOTYPE('gettimeofday', + 'int gettimeofday(struct timeval *tv, struct timezone *tz)', + define='HAVE_GETTIMEOFDAY_TZ', headers='sys/time.h') + + conf.CHECK_C_PROTOTYPE('gettimeofday', + 'int gettimeofday(struct timeval *tv, void *tz)', + define='HAVE_GETTIMEOFDAY_TZ_VOID', + headers='sys/time.h') + + conf.CHECK_CODE('#include "tests/snprintf.c"', + define="HAVE_C99_VSNPRINTF", + execute=True, + addmain=False, + msg="Checking for C99 vsnprintf") + + conf.CHECK_CODE('#include "tests/shared_mmap.c"', + addmain=False, add_headers=False, execute=True, + define='HAVE_SHARED_MMAP', + msg="Checking for HAVE_SHARED_MMAP") + + conf.CHECK_CODE('#include "tests/shared_mremap.c"', + addmain=False, add_headers=False, execute=True, + define='HAVE_MREMAP', + msg="Checking for HAVE_MREMAP") + + # OpenBSD (and I've heard HPUX) doesn't sync between mmap and write. + # FIXME: Anything other than a 0 or 1 exit code should abort configure! + conf.CHECK_CODE('#include "tests/incoherent_mmap.c"', + addmain=False, add_headers=False, execute=True, + define='HAVE_INCOHERENT_MMAP', + msg="Checking for HAVE_INCOHERENT_MMAP") + + conf.SAMBA_BUILD_ENV() + + conf.CHECK_CODE(''' + typedef struct {unsigned x;} FOOBAR; + #define X_FOOBAR(x) ((FOOBAR) { x }) + #define FOO_ONE X_FOOBAR(1) + FOOBAR f = FOO_ONE; + static const struct { + FOOBAR y; + } f2[] = { + {FOO_ONE} + }; + static const FOOBAR f3[] = {FOO_ONE}; + ''', + define='HAVE_IMMEDIATE_STRUCTURES') + + conf.CHECK_CODE('mkdir("foo",0777)', define='HAVE_MKDIR_MODE', headers='sys/stat.h') + + conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_mtim.tv_nsec', define='HAVE_STAT_TV_NSEC', + headers='sys/stat.h') + # we need the st_rdev test under two names + conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_rdev', + define='HAVE_STRUCT_STAT_ST_RDEV', + headers='sys/stat.h') + conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_rdev', define='HAVE_ST_RDEV', + headers='sys/stat.h') + conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_storage', 'ss_family', + headers='sys/socket.h netinet/in.h') + conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_storage', '__ss_family', + headers='sys/socket.h netinet/in.h') + + + if conf.CHECK_STRUCTURE_MEMBER('struct sockaddr', 'sa_len', + headers='sys/socket.h netinet/in.h', + define='HAVE_SOCKADDR_SA_LEN'): + # the old build system produced both defines + conf.DEFINE('HAVE_STRUCT_SOCKADDR_SA_LEN', 1) + + conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_in', 'sin_len', + headers='sys/socket.h netinet/in.h', + define='HAVE_SOCK_SIN_LEN') + + conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_in6', 'sin6_len', + headers='sys/socket.h netinet/in.h', + define='HAVE_SOCK_SIN6_LEN') + + conf.CHECK_CODE('struct sockaddr_un sunaddr; sunaddr.sun_family = AF_UNIX;', + define='HAVE_UNIXSOCKET', headers='sys/socket.h sys/un.h') + + + conf.CHECK_CODE(''' + struct stat st; + char tpl[20]="/tmp/test.XXXXXX"; + char tpl2[20]="/tmp/test.XXXXXX"; + int fd = mkstemp(tpl); + int fd2 = mkstemp(tpl2); + if (fd == -1) { + if (fd2 != -1) { + unlink(tpl2); + } + exit(1); + } + if (fd2 == -1) exit(1); + unlink(tpl); + unlink(tpl2); + if (fstat(fd, &st) != 0) exit(1); + if ((st.st_mode & 0777) != 0600) exit(1); + if (strcmp(tpl, "/tmp/test.XXXXXX") == 0) { + exit(1); + } + if (strcmp(tpl, tpl2) == 0) { + exit(1); + } + exit(0); + ''', + define='HAVE_SECURE_MKSTEMP', + execute=True, + mandatory=True) # lets see if we get a mandatory failure for this one + + # look for a method of finding the list of network interfaces + for method in ['HAVE_IFACE_GETIFADDRS', 'HAVE_IFACE_AIX', 'HAVE_IFACE_IFCONF', 'HAVE_IFACE_IFREQ']: + bsd_for_strlcpy = '' + if strlcpy_in_bsd: + bsd_for_strlcpy = ' bsd' + if conf.CHECK_CODE(''' + #define %s 1 + #define NO_CONFIG_H 1 + #define AUTOCONF_TEST 1 + #include "replace.c" + #include "inet_ntop.c" + #include "snprintf.c" + #include "getifaddrs.c" + #define getifaddrs_test main + #include "tests/getifaddrs.c" + ''' % method, + method, + lib='nsl socket' + bsd_for_strlcpy, + addmain=False, + execute=True): + break + + conf.RECURSE('system') + conf.SAMBA_CONFIG_H() + if conf.CHECK_FUNCS('strerror_r'): + # Check if strerror_r is XSI-Compatable, the default GNU implementation + # is not + conf.CHECK_CODE('int strerror_r(int errnum, char *buf, size_t buflen);', + 'STRERROR_R_XSI_NOT_GNU', + headers='string.h', addmain=False, link=False, + msg="Checking for XSI (rather than GNU) prototype for strerror_r") + + +REPLACEMENT_FUNCTIONS = { + 'replace.c': ['ftruncate', 'strlcpy', 'strlcat', 'mktime', 'initgroups', + 'memmove', 'strdup', 'setlinebuf', 'vsyslog', 'strnlen', + 'strndup', 'waitpid', 'seteuid', 'setegid', 'chroot', + 'mkstemp', 'mkdtemp', 'pread', 'pwrite', 'strcasestr', + 'strsep', 'strtok_r', 'strtoll', 'strtoull', 'setenv', 'unsetenv', + 'utime', 'utimes', 'dup2', 'chown', 'link', 'readlink', + 'symlink', 'lchown', 'realpath', 'memmem', 'vdprintf', + 'dprintf', 'get_current_dir_name', + 'strerror_r', 'clock_gettime', 'memset_s'], + 'timegm.c': ['timegm'], + # Note: C99_VSNPRINTF is not a function, but a special condition + # for replacement + 'snprintf.c': ['C99_VSNPRINTF', 'snprintf', 'vsnprintf', 'asprintf', 'vasprintf'], + # Note: WORKING_STRPTIME is not a function, but a special condition + # for replacement + 'strptime.c': ['WORKING_STRPTIME', 'strptime'], + } + + +def build(bld): + bld.RECURSE('buildtools/wafsamba') + + REPLACE_HOSTCC_SOURCE = '' + + for filename in REPLACEMENT_FUNCTIONS.keys(): + for function in REPLACEMENT_FUNCTIONS[filename]: + if not bld.CONFIG_SET('HAVE_%s' % function.upper()): + REPLACE_HOSTCC_SOURCE += ' %s' % filename + break + + extra_libs = '' + if bld.CONFIG_SET('HAVE_LIBBSD'): extra_libs += ' bsd' + if bld.CONFIG_SET('HAVE_LIBRT'): extra_libs += ' rt' + if bld.CONFIG_SET('REPLACE_REQUIRES_LIBSOCKET_LIBNSL'): extra_libs += ' socket nsl' + + bld.SAMBA_SUBSYSTEM('LIBREPLACE_HOSTCC', + REPLACE_HOSTCC_SOURCE, + use_hostcc=True, + use_global_deps=False, + cflags='-D_SAMBA_HOSTCC_', + group='compiler_libraries', + deps = extra_libs + ) + + REPLACE_SOURCE = REPLACE_HOSTCC_SOURCE + REPLACE_SOURCE += ' cwrap.c' + + if not bld.CONFIG_SET('HAVE_CRYPT'): REPLACE_SOURCE += ' crypt.c' + if not bld.CONFIG_SET('HAVE_DLOPEN'): REPLACE_SOURCE += ' dlfcn.c' + if not bld.CONFIG_SET('HAVE_POLL'): REPLACE_SOURCE += ' poll.c' + + if not bld.CONFIG_SET('HAVE_SOCKETPAIR'): REPLACE_SOURCE += ' socketpair.c' + if not bld.CONFIG_SET('HAVE_CONNECT'): REPLACE_SOURCE += ' socket.c' + if not bld.CONFIG_SET('HAVE_GETIFADDRS'): REPLACE_SOURCE += ' getifaddrs.c' + if not bld.CONFIG_SET('HAVE_GETADDRINFO'): REPLACE_SOURCE += ' getaddrinfo.c' + if not bld.CONFIG_SET('HAVE_INET_NTOA'): REPLACE_SOURCE += ' inet_ntoa.c' + if not bld.CONFIG_SET('HAVE_INET_ATON'): REPLACE_SOURCE += ' inet_aton.c' + if not bld.CONFIG_SET('HAVE_INET_NTOP'): REPLACE_SOURCE += ' inet_ntop.c' + if not bld.CONFIG_SET('HAVE_INET_PTON'): REPLACE_SOURCE += ' inet_pton.c' + 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', + # FIXME: Ideally symbols should be hidden here so they + # don't appear in the global namespace when Samba + # libraries are loaded, but this doesn't appear to work + # at the moment: + # hide_symbols=bld.BUILTIN_LIBRARY('replace'), + private_library=True, + deps='crypt dl attr' + extra_libs) + + replace_test_cflags = '' + if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): + replace_test_cflags += " -Wno-format-truncation" + bld.SAMBA_SUBSYSTEM('replace-test', + source='''tests/testsuite.c tests/strptime.c + tests/os2_delete.c tests/getifaddrs.c''', + deps='replace', + cflags=replace_test_cflags) + + bld.SAMBA_BINARY('replace_testsuite', + source='tests/main.c', + deps='replace replace-test', + install=False) + + # build replacements for stdint.h and stdbool.h if needed + bld.SAMBA_GENERATOR('replace_stdint_h', + rule='cp ${SRC} ${TGT}', + source='hdr_replace.h', + target='stdint.h', + enabled = not bld.CONFIG_SET('HAVE_STDINT_H')) + bld.SAMBA_GENERATOR('replace_stdbool_h', + rule='cp ${SRC} ${TGT}', + source='hdr_replace.h', + target='stdbool.h', + enabled = not bld.CONFIG_SET('HAVE_STDBOOL_H')) + + bld.SAMBA_SUBSYSTEM('samba_intl', source='', use_global_deps=False,deps=bld.env.intl_libs) + +def testonly(ctx): + '''run talloc testsuite''' + import samba_utils + + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') + + cmd = os.path.join(Context.g_module.out, 'replace_testsuite') + ret = samba_utils.RUN_COMMAND(cmd) + print("testsuite returned %d" % ret) + sys.exit(ret) + +# WAF doesn't build the unit tests for this, maybe because they don't link with talloc? +# This forces it +def test(ctx): + Options.commands.append('build') + Options.commands.append('testonly') + +def dist(): + '''makes a tarball for distribution''' + samba_dist.dist() diff --git a/ldb-2.0.8/lib/replace/xattr.c b/ldb-2.0.8/lib/replace/xattr.c new file mode 100644 index 0000000..2420ee1 --- /dev/null +++ b/ldb-2.0.8/lib/replace/xattr.c @@ -0,0 +1,785 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for xattr implementations + Copyright (C) Jeremy Allison 1998-2005 + Copyright (C) Timur Bakeyev 2005 + Copyright (C) Bjoern Jacke 2006-2007 + Copyright (C) Herb Lewis 2003 + Copyright (C) Andrew Bartlett 2012 + + ** 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 + Lesser 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 . +*/ + +#define UID_WRAPPER_NOT_REPLACE +#include "replace.h" +#include "system/filesys.h" +#include "system/dir.h" + +/******** Solaris EA helper function prototypes ********/ +#ifdef HAVE_ATTROPEN +#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP +static int solaris_write_xattr(int attrfd, const char *value, size_t size); +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size); +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size); +static int solaris_unlinkat(int attrdirfd, const char *name); +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode); +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode); +#endif + +/************************************************************************** + Wrappers for extented attribute calls. Based on the Linux package with + support for IRIX and (Net|Free)BSD also. Expand as other systems have them. +****************************************************************************/ + +ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t size) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return getxattr(path, name, value, size); +#else + +/* So that we do not recursivly call this function */ +#undef getxattr + int options = 0; + return getxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_XATTR_EA) + return getea(path, name, value, size); +#elif defined(HAVE_XATTR_EXTATTR) + ssize_t retval; + int attrnamespace; + const char *attrname; + + if (strncmp(name, "system.", 7) == 0) { + attrnamespace = EXTATTR_NAMESPACE_SYSTEM; + attrname = name + 7; + } else if (strncmp(name, "user.", 5) == 0) { + attrnamespace = EXTATTR_NAMESPACE_USER; + attrname = name + 5; + } else { + errno = EINVAL; + return -1; + } + + /* + * The BSD implementation has a nasty habit of silently truncating + * the returned value to the size of the buffer, so we have to check + * that the buffer is large enough to fit the returned value. + */ + if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) { + if (size == 0) { + return retval; + } else if (retval > size) { + errno = ERANGE; + return -1; + } + if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0) + return retval; + } + + return -1; +#elif defined(HAVE_XATTR_ATTR) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + if (size == 0 && retval == -1 && errno == E2BIG) { + return valuelength; + } + + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_attropen(path, name, O_RDONLY, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t rep_fgetxattr (int filedes, const char *name, void *value, size_t size) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return fgetxattr(filedes, name, value, size); +#else + +/* So that we do not recursivly call this function */ +#undef fgetxattr + int options = 0; + return fgetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_XATTR_EA) + return fgetea(filedes, name, value, size); +#elif defined(HAVE_XATTR_EXTATTR) + ssize_t retval; + int attrnamespace; + const char *attrname; + + if (strncmp(name, "system.", 7) == 0) { + attrnamespace = EXTATTR_NAMESPACE_SYSTEM; + attrname = name + 7; + } else if (strncmp(name, "user.", 5) == 0) { + attrnamespace = EXTATTR_NAMESPACE_USER; + attrname = name + 5; + } else { + errno = EINVAL; + return -1; + } + + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) { + if (size == 0) { + return retval; + } else if (retval > size) { + errno = ERANGE; + return -1; + } + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0) + return retval; + } + + return -1; +#elif defined(HAVE_XATTR_ATTR) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); + if (size == 0 && retval == -1 && errno == E2BIG) { + return valuelength; + } + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +#if defined(HAVE_XATTR_EXTATTR) + +#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1) + +static struct { + int space; + const char *name; + size_t len; +} +extattr[] = { + { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") }, + { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") }, +}; + +typedef union { + const char *path; + int filedes; +} extattr_arg; + +static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size) +{ + ssize_t list_size, total_size = 0; + int i, t, len; + char *buf; + /* Iterate through extattr(2) namespaces */ + for(t = 0; t < ARRAY_SIZE(extattr); t++) { + if (t != EXTATTR_NAMESPACE_USER && geteuid() != 0) { + /* ignore all but user namespace when we are not root, see bug 10247 */ + continue; + } + switch(type) { + case 0: + list_size = extattr_list_file(arg.path, extattr[t].space, list, size); + break; + case 1: + list_size = extattr_list_link(arg.path, extattr[t].space, list, size); + break; + case 2: + list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size); + break; + default: + errno = ENOSYS; + return -1; + } + /* Some error happend. Errno should be set by the previous call */ + if(list_size < 0) + return -1; + /* No attributes */ + if(list_size == 0) + continue; + /* XXX: Call with an empty buffer may be used to calculate + necessary buffer size. Unfortunately, we can't say, how + many attributes were returned, so here is the potential + problem with the emulation. + */ + if(list == NULL) { + /* Take the worse case of one char attribute names - + two bytes per name plus one more for sanity. + */ + total_size += list_size + (list_size/2 + 1)*extattr[t].len; + continue; + } + /* Count necessary offset to fit namespace prefixes */ + len = 0; + for(i = 0; i < list_size; i += list[i] + 1) + len += extattr[t].len; + + total_size += list_size + len; + /* Buffer is too small to fit the results */ + if(total_size > size) { + errno = ERANGE; + return -1; + } + /* Shift results back, so we can prepend prefixes */ + buf = (char *)memmove(list + len, list, list_size); + + for(i = 0; i < list_size; i += len + 1) { + len = buf[i]; + strncpy(list, extattr[t].name, extattr[t].len + 1); + list += extattr[t].len; + strncpy(list, buf + i + 1, len); + list[len] = '\0'; + list += len + 1; + } + size -= total_size; + } + return total_size; +} + +#endif + +#if defined(HAVE_XATTR_ATTR) && (defined(HAVE_SYS_ATTRIBUTES_H) || defined(HAVE_ATTR_ATTRIBUTES_H)) +static char attr_buffer[ATTR_MAX_VALUELEN]; + +static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags) +{ + int retval = 0, index; + attrlist_cursor_t *cursor = 0; + int total_size = 0; + attrlist_t * al = (attrlist_t *)attr_buffer; + attrlist_ent_t *ae; + size_t ent_size, left = size; + char *bp = list; + + while (true) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("user."); + if (left >= ent_size) { + strncpy(bp, "user.", sizeof("user.")); + strncat(bp, ae->a_name, ent_size - sizeof("user.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + if (retval == 0) { + flags |= ATTR_ROOT; + cursor = 0; + while (true) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("system."); + if (left >= ent_size) { + strncpy(bp, "system.", sizeof("system.")); + strncat(bp, ae->a_name, ent_size - sizeof("system.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + } + return (ssize_t)(retval ? retval : total_size); +} + +#endif + +ssize_t rep_listxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return listxattr(path, list, size); +#else +/* So that we do not recursivly call this function */ +#undef listxattr + int options = 0; + return listxattr(path, list, size, options); +#endif +#elif defined(HAVE_XATTR_EA) + return listea(path, list, size); +#elif defined(HAVE_XATTR_EXTATTR) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(0, arg, list, size); +#elif defined(HAVE_XATTR_ATTR) && defined(HAVE_SYS_ATTRIBUTES_H) + return irix_attr_list(path, 0, list, size, 0); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t rep_flistxattr (int filedes, char *list, size_t size) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return flistxattr(filedes, list, size); +#else +/* So that we do not recursivly call this function */ +#undef flistxattr + int options = 0; + return flistxattr(filedes, list, size, options); +#endif +#elif defined(HAVE_XATTR_EA) + return flistea(filedes, list, size); +#elif defined(HAVE_XATTR_EXTATTR) + extattr_arg arg; + arg.filedes = filedes; + return bsd_attr_list(2, arg, list, size); +#elif defined(HAVE_XATTR_ATTR) + return irix_attr_list(NULL, filedes, list, size, 0); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_removexattr (const char *path, const char *name) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return removexattr(path, name); +#else +/* So that we do not recursivly call this function */ +#undef removexattr + int options = 0; + return removexattr(path, name, options); +#endif +#elif defined(HAVE_XATTR_EA) + return removeea(path, name); +#elif defined(HAVE_XATTR_EXTATTR) + int attrnamespace; + const char *attrname; + + if (strncmp(name, "system.", 7) == 0) { + attrnamespace = EXTATTR_NAMESPACE_SYSTEM; + attrname = name + 7; + } else if (strncmp(name, "user.", 5) == 0) { + attrnamespace = EXTATTR_NAMESPACE_USER; + attrname = name + 5; + } else { + errno = EINVAL; + return -1; + } + + return extattr_delete_file(path, attrnamespace, attrname); +#elif defined(HAVE_XATTR_ATTR) + int flags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_fremovexattr (int filedes, const char *name) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return fremovexattr(filedes, name); +#else +/* So that we do not recursivly call this function */ +#undef fremovexattr + int options = 0; + return fremovexattr(filedes, name, options); +#endif +#elif defined(HAVE_XATTR_EA) + return fremoveea(filedes, name); +#elif defined(HAVE_XATTR_EXTATTR) + int attrnamespace; + const char *attrname; + + if (strncmp(name, "system.", 7) == 0) { + attrnamespace = EXTATTR_NAMESPACE_SYSTEM; + attrname = name + 7; + } else if (strncmp(name, "user.", 5) == 0) { + attrnamespace = EXTATTR_NAMESPACE_USER; + attrname = name + 5; + } else { + errno = EINVAL; + return -1; + } + + return extattr_delete_fd(filedes, attrnamespace, attrname); +#elif defined(HAVE_XATTR_ATTR) + int flags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_removef(filedes, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return setxattr(path, name, value, size, flags); +#else +/* So that we do not recursivly call this function */ +#undef setxattr + int options = 0; + return setxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_XATTR_EA) + return setea(path, name, value, size, flags); +#elif defined(HAVE_XATTR_EXTATTR) + int retval = 0; + int attrnamespace; + const char *attrname; + + if (strncmp(name, "system.", 7) == 0) { + attrnamespace = EXTATTR_NAMESPACE_SYSTEM; + attrname = name + 7; + } else if (strncmp(name, "user.", 5) == 0) { + attrnamespace = EXTATTR_NAMESPACE_USER; + attrname = name + 5; + } else { + errno = EINVAL; + return -1; + } + + if (flags) { + /* Check attribute existence */ + retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_file(path, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_XATTR_ATTR) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_XATTR_XATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return fsetxattr(filedes, name, value, size, flags); +#else +/* So that we do not recursivly call this function */ +#undef fsetxattr + int options = 0; + return fsetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_XATTR_EA) + return fsetea(filedes, name, value, size, flags); +#elif defined(HAVE_XATTR_EXTATTR) + int retval = 0; + int attrnamespace; + const char *attrname; + + if (strncmp(name, "system.", 7) == 0) { + attrnamespace = EXTATTR_NAMESPACE_SYSTEM; + attrname = name + 7; + } else if (strncmp(name, "user.", 5) == 0) { + attrnamespace = EXTATTR_NAMESPACE_USER; + attrname = name + 5; + } else { + errno = EINVAL; + return -1; + } + + if (flags) { + /* Check attribute existence */ + retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_XATTR_ATTR) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_setf(filedes, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | O_XATTR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +/************************************************************************** + helper functions for Solaris' EA support +****************************************************************************/ +#ifdef HAVE_ATTROPEN +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size) +{ + struct stat sbuf; + + if (fstat(attrfd, &sbuf) == -1) { + errno = ENOATTR; + return -1; + } + + /* This is to return the current size of the named extended attribute */ + if (size == 0) { + return sbuf.st_size; + } + + /* check size and read xattr */ + if (sbuf.st_size > size) { + errno = ERANGE; + return -1; + } + + return read(attrfd, value, sbuf.st_size); +} + +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size) +{ + ssize_t len = 0; + DIR *dirp; + struct dirent *de; + int newfd = dup(attrdirfd); + /* CAUTION: The originating file descriptor should not be + used again following the call to fdopendir(). + For that reason we dup() the file descriptor + here to make things more clear. */ + dirp = fdopendir(newfd); + + while ((de = readdir(dirp))) { + size_t listlen = strlen(de->d_name) + 1; + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { + /* we don't want "." and ".." here: */ + continue; + } + + if (size == 0) { + /* return the current size of the list of extended attribute names*/ + len += listlen; + } else { + /* check size and copy entrieÑ• + nul into list. */ + if ((len + listlen) > size) { + errno = ERANGE; + len = -1; + break; + } else { + strlcpy(list + len, de->d_name, listlen); + len += listlen; + } + } + } + + if (closedir(dirp) == -1) { + return -1; + } + return len; +} + +static int solaris_unlinkat(int attrdirfd, const char *name) +{ + if (unlinkat(attrdirfd, name, 0) == -1) { + if (errno == ENOENT) { + errno = ENOATTR; + } + return -1; + } + return 0; +} + +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode) +{ + int filedes = attropen(path, attrpath, oflag, mode); + if (filedes == -1) { + if (errno == EINVAL) { + errno = ENOTSUP; + } else { + errno = ENOATTR; + } + } + return filedes; +} + +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode) +{ + int filedes = openat(fildes, path, oflag, mode); + if (filedes == -1) { + if (errno == EINVAL) { + errno = ENOTSUP; + } else { + errno = ENOATTR; + } + } + return filedes; +} + +static int solaris_write_xattr(int attrfd, const char *value, size_t size) +{ + if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) { + return 0; + } else { + return -1; + } +} +#endif /*HAVE_ATTROPEN*/ + + diff --git a/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.6.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.6.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.6.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.7.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.7.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.7.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.8.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.8.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.0.8.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.0.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.0.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.0.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.1.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.1.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.1.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.10.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.10.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.10.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.11.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.11.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.11.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.12.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.12.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.12.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.13.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.13.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.13.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.14.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.14.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.14.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.15.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.15.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.15.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.16.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.16.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.16.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.2.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.2.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.2.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.3.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.3.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.3.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.4.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.4.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.4.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.5.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.5.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.5.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.6.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.6.sigs new file mode 100644 index 0000000..666fec0 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.7.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.7.sigs new file mode 100644 index 0000000..666fec0 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.8.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.8.sigs new file mode 100644 index 0000000..666fec0 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.9.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.9.sigs new file mode 100644 index 0000000..9d4d4d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.1.9.sigs @@ -0,0 +1,16 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.2.0.sigs b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.2.0.sigs new file mode 100644 index 0000000..62f066f --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/pytalloc-util-2.2.0.sigs @@ -0,0 +1,15 @@ +_pytalloc_check_type: int (PyObject *, const char *) +_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_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *) +pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *) +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/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.2.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.2.sigs new file mode 100644 index 0000000..6e236d5 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.2.sigs @@ -0,0 +1,62 @@ +_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_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_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.3.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.3.sigs new file mode 100644 index 0000000..6e236d5 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.3.sigs @@ -0,0 +1,62 @@ +_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_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_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.4.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.4.sigs new file mode 100644 index 0000000..6e236d5 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.4.sigs @@ -0,0 +1,62 @@ +_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_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_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.5.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.5.sigs new file mode 100644 index 0000000..6e236d5 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.5.sigs @@ -0,0 +1,62 @@ +_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_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_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.6.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.6.sigs new file mode 100644 index 0000000..6e236d5 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.6.sigs @@ -0,0 +1,62 @@ +_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_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_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.7.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.7.sigs new file mode 100644 index 0000000..6e236d5 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.7.sigs @@ -0,0 +1,62 @@ +_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_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_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.8.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.8.sigs new file mode 100644 index 0000000..15a9e95 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.0.8.sigs @@ -0,0 +1,63 @@ +_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_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.0.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.0.sigs new file mode 100644 index 0000000..eae12cc --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.0.sigs @@ -0,0 +1,64 @@ +_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.1.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.1.sigs new file mode 100644 index 0000000..eae12cc --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.1.sigs @@ -0,0 +1,64 @@ +_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.10.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.10.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.10.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.11.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.11.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.11.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.12.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.12.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.12.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.13.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.13.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.13.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.14.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.14.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.14.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.15.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.15.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.15.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.16.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.16.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.16.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.2.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.2.sigs new file mode 100644 index 0000000..eae12cc --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.2.sigs @@ -0,0 +1,64 @@ +_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.3.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.3.sigs new file mode 100644 index 0000000..eae12cc --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.3.sigs @@ -0,0 +1,64 @@ +_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_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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.4.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.4.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.4.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.5.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.5.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.5.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.6.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.6.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.7.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.7.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.8.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.8.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.9.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.9.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.1.9.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/ldb-2.0.8/lib/talloc/ABI/talloc-2.2.0.sigs b/ldb-2.0.8/lib/talloc/ABI/talloc-2.2.0.sigs new file mode 100644 index 0000000..9969ce3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/ABI/talloc-2.2.0.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/ldb-2.0.8/lib/talloc/Makefile b/ldb-2.0.8/lib/talloc/Makefile new file mode 100644 index 0000000..db2275c --- /dev/null +++ b/ldb-2.0.8/lib/talloc/Makefile @@ -0,0 +1,68 @@ +# simple makefile wrapper to run waf + +WAF_BIN=`PATH=buildtools/bin:../../buildtools/bin:$$PATH which waf` +WAF_BINARY=$(PYTHON) $(WAF_BIN) +WAF=PYTHONHASHSEED=1 WAF_MAKE=1 $(WAF_BINARY) + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: + $(WAF) test $(TEST_OPTIONS) + +testenv: + $(WAF) test --testenv $(TEST_OPTIONS) + +quicktest: + $(WAF) test --quick $(TEST_OPTIONS) + +dist: + touch .tmplock + WAFLOCK=.tmplock $(WAF) dist + +distcheck: + touch .tmplock + WAFLOCK=.tmplock $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +torture: all + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags + +pydoctor: + $(WAF) pydoctor + +bin/%:: FORCE + $(WAF) --targets=`basename $@` +FORCE: diff --git a/ldb-2.0.8/lib/talloc/NEWS b/ldb-2.0.8/lib/talloc/NEWS new file mode 100644 index 0000000..e5b3aa0 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/NEWS @@ -0,0 +1,13 @@ +1.0.1 26 May 2007 + + BUGS + + * Set name of correctly when using talloc_append_string() (metze) + + LICENSE + + * Change license of files in lib/replace to LGPL (was GPL). (jelmer) + +1.0.0 30 April 2007 + + Initial release. diff --git a/ldb-2.0.8/lib/talloc/compat/talloc_compat1.c b/ldb-2.0.8/lib/talloc/compat/talloc_compat1.c new file mode 100644 index 0000000..519e8c3 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/compat/talloc_compat1.c @@ -0,0 +1,51 @@ +/* + Samba trivial allocation library - compat functions + + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +/* + * This file contains only function to build a + * compat talloc.so.1 library on top of talloc.so.2 + */ + +#include "replace.h" +#include "talloc.h" + +void *_talloc_reference(const void *context, const void *ptr); +void *_talloc_reference(const void *context, const void *ptr) { + return _talloc_reference_loc(context, ptr, + "Called from talloc compat1 " + "_talloc_reference"); +} + +void *_talloc_steal(const void *new_ctx, const void *ptr); +void *_talloc_steal(const void *new_ctx, const void *ptr) +{ + return talloc_reparent(talloc_parent(ptr), new_ctx, ptr); +} + +#undef talloc_free +int talloc_free(void *ptr); +int talloc_free(void *ptr) +{ + return talloc_unlink(talloc_parent(ptr), ptr); +} + diff --git a/ldb-2.0.8/lib/talloc/compat/talloc_compat1.mk b/ldb-2.0.8/lib/talloc/compat/talloc_compat1.mk new file mode 100644 index 0000000..d1817f0 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/compat/talloc_compat1.mk @@ -0,0 +1,21 @@ +talloccompatdir := $(tallocdir)/compat + +TALLOC_COMPAT1_VERSION_MAJOR = 1 +TALLOC_COMPAT1_OBJ = $(talloccompatdir)/talloc_compat1.o + +TALLOC_COMPAT1_SOLIB = libtalloc-compat1-$(TALLOC_VERSION).$(SHLIBEXT) +TALLOC_COMPAT1_SONAME = libtalloc.$(SHLIBEXT).$(TALLOC_COMPAT1_VERSION_MAJOR) + +$(TALLOC_COMPAT1_SOLIB): $(TALLOC_COMPAT1_OBJ) $(TALLOC_SOLIB) + $(SHLD) $(SHLD_FLAGS) -o $@ $(TALLOC_COMPAT1_OBJ) \ + $(TALLOC_SOLIB) $(SONAMEFLAG)$(TALLOC_COMPAT1_SONAME) + +all:: $(TALLOC_COMPAT1_SOLIB) + +install:: + ${INSTALLCMD} -d $(DESTDIR)$(libdir) + ${INSTALLCMD} -m 755 $(TALLOC_COMPAT1_SOLIB) $(DESTDIR)$(libdir) + +clean:: + rm -f $(TALLOC_COMPAT1_OBJ) $(TALLOC_COMPAT1_SOLIB) + diff --git a/ldb-2.0.8/lib/talloc/configure b/ldb-2.0.8/lib/talloc/configure new file mode 100755 index 0000000..d8a8d2a --- /dev/null +++ b/ldb-2.0.8/lib/talloc/configure @@ -0,0 +1,21 @@ +#!/bin/sh + +PREVPATH=`dirname $0` + +if [ -f $PREVPATH/../../buildtools/bin/waf ]; then + WAF=../../buildtools/bin/waf +elif [ -f $PREVPATH/buildtools/bin/waf ]; then + WAF=./buildtools/bin/waf +else + echo "replace: Unable to find waf" + exit 1 +fi + +# using JOBS=1 gives maximum compatibility with +# systems like AIX which have broken threading in python +JOBS=1 +export JOBS + +cd . || exit 1 +$PYTHON $WAF configure "$@" || exit 1 +cd $PREVPATH diff --git a/ldb-2.0.8/lib/talloc/doc/context.png b/ldb-2.0.8/lib/talloc/doc/context.png new file mode 100644 index 0000000..48a6ca0 Binary files /dev/null and b/ldb-2.0.8/lib/talloc/doc/context.png differ diff --git a/ldb-2.0.8/lib/talloc/doc/context_tree.png b/ldb-2.0.8/lib/talloc/doc/context_tree.png new file mode 100644 index 0000000..9723459 Binary files /dev/null and b/ldb-2.0.8/lib/talloc/doc/context_tree.png differ diff --git a/ldb-2.0.8/lib/talloc/doc/mainpage.dox b/ldb-2.0.8/lib/talloc/doc/mainpage.dox new file mode 100644 index 0000000..ece6ccb --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/mainpage.dox @@ -0,0 +1,111 @@ +/** + * @mainpage + * + * talloc is a hierarchical, reference counted memory pool system with + * destructors. It is the core memory allocator used in Samba. + * + * @section talloc_download Download + * + * You can download the latest releases of talloc from the + * talloc directory + * on the samba public source archive. + * + * @section main-tutorial Tutorial + * + * You should start by reading @subpage libtalloc_tutorial, then reading the documentation of + * the interesting functions as you go. + + * @section talloc_bugs Discussion and bug reports + * + * talloc does not currently have its own mailing list or bug tracking system. + * For now, please use the + * samba-technical + * mailing list, and the + * Samba bugzilla + * bug tracking system. + * + * @section talloc_devel Development + * You can download the latest code either via git or rsync. + * + * To fetch via git see the following guide: + * + * Using Git for Samba Development + * + * Once you have cloned the tree switch to the master branch and cd into the + * lib/tevent directory. + * + * To fetch via rsync use this command: + * + * rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/talloc . + * + * @section talloc_preample Preamble + * + * talloc is a hierarchical, reference counted memory pool system with + * destructors. + * + * Perhaps the biggest difference from other memory pool systems is that there + * is no distinction between a "talloc context" and a "talloc pointer". Any + * pointer returned from talloc() is itself a valid talloc context. This means + * you can do this: + * + * @code + * struct foo *X = talloc(mem_ctx, struct foo); + * X->name = talloc_strdup(X, "foo"); + * @endcode + * + * The pointer X->name would be a "child" of the talloc context "X" which is + * itself a child of mem_ctx. So if you do talloc_free(mem_ctx) then it is all + * destroyed, whereas if you do talloc_free(X) then just X and X->name are + * destroyed, and if you do talloc_free(X->name) then just the name element of + * X is destroyed. + * + * If you think about this, then what this effectively gives you is an n-ary + * tree, where you can free any part of the tree with talloc_free(). + * + * If you find this confusing, then run the testsuite to watch talloc in + * action. You may also like to add your own tests to testsuite.c to clarify + * how some particular situation is handled. + * + * @section talloc_performance Performance + * + * All the additional features of talloc() over malloc() do come at a price. We + * have a simple performance test in Samba4 that measures talloc() versus + * malloc() performance, and it seems that talloc() is about 4% slower than + * malloc() on my x86 Debian Linux box. For Samba, the great reduction in code + * complexity that we get by using talloc makes this worthwhile, especially as + * the total overhead of talloc/malloc in Samba is already quite small. + * + * @section talloc_named Named blocks + * + * Every talloc chunk has a name that can be used as a dynamic type-checking + * system. If for some reason like a callback function you had to cast a + * "struct foo *" to a "void *" variable, later you can safely reassign the + * "void *" pointer to a "struct foo *" by using the talloc_get_type() or + * talloc_get_type_abort() macros. + * + * @code + * struct foo *X = talloc_get_type_abort(ptr, struct foo); + * @endcode + * + * This will abort if "ptr" does not contain a pointer that has been created + * with talloc(mem_ctx, struct foo). + * + * @section talloc_threading Multi-threading + * + * talloc itself does not deal with threads. It is thread-safe (assuming the + * underlying "malloc" is), as long as each thread uses different memory + * contexts. + * + * If two threads uses the same context then they need to synchronize in order + * to be safe. In particular: + * + * - when using talloc_enable_leak_report(), giving directly NULL as a parent + * context implicitly refers to a hidden "null context" global variable, so + * this should not be used in a multi-threaded environment without proper + * synchronization. In threaded code turn off null tracking using + * talloc_disable_null_tracking(). + * - the context returned by talloc_autofree_context() is also global so + * shouldn't be used by several threads simultaneously without + * synchronization. + * + */ diff --git a/ldb-2.0.8/lib/talloc/doc/stealing.png b/ldb-2.0.8/lib/talloc/doc/stealing.png new file mode 100644 index 0000000..8833e06 Binary files /dev/null and b/ldb-2.0.8/lib/talloc/doc/stealing.png differ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_bestpractices.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_bestpractices.dox new file mode 100644 index 0000000..3634446 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_bestpractices.dox @@ -0,0 +1,192 @@ +/** +@page libtalloc_bestpractices Chapter 7: Best practises + +The following sections contain several best practices and good manners that were +found by the Samba and +SSSD developers over the years. +These will help you to write code which is better, easier to debug and with as +few (hopefully none) memory leaks as possible. + +@section bp-hierarchy Keep the context hierarchy steady + +The talloc is a hierarchy memory allocator. The hierarchy nature is what makes +the programming more error proof. It makes the memory easier to manage and to +free. Therefore, the first thing we should have on our mind is: always project +your data structures into the talloc context hierarchy. + +That means if we have a structure, we should always use it as a parent context +for its elements. This way we will not encounter any troubles when freeing the +structure or when changing its parent. The same rule applies for arrays. + +For example, the structure user from section @ref context-hierarchy +should be created with the context hierarchy illustrated on the next image. + +@image html context_tree.png + +@section bp-tmpctx Every function should use its own context + +It is a good practice to create a temporary talloc context at the function +beginning and free the context just before the return statement. All the data +must be allocated on this context or on its children. This ensures that no +memory leaks are created as long as we do not forget to free the temporary +context. + +This pattern applies to both situations - when a function does not return any +dynamically allocated value and when it does. However, it needs a little +extension for the latter case. + +@subsection bp-tmpctx-1 Functions that do not return any dynamically allocated +value + +If the function does not return any value created on the heap, we will just obey +the aforementioned pattern. + +@code +int bar() +{ + int ret; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + /* allocate data on tmp_ctx or on its descendants */ + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} +@endcode + +@subsection bp-tmpctx-2 Functions returning dynamically allocated values + +If our function returns any dynamically allocated data, its first parameter +should always be the destination talloc context. This context serves as a parent +for the output values. But again, we will create the output values as the +descendants of the temporary context. If everything goes well, we will change +the parent of the output values from the temporary to the destination talloc +context. + +This pattern ensures that if an error occurs (e.g. I/O error or insufficient +amount of the memory), all allocated data is freed and no garbage appears on +the destination context. + +@code +int struct_foo_init(TALLOC_CTX *mem_ctx, struct foo **_foo) +{ + int ret; + struct foo *foo = NULL; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + foo = talloc_zero(tmp_ctx, struct foo); + /* ... */ + *_foo = talloc_steal(mem_ctx, foo); + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} +@endcode + +@section bp-null Allocate temporary contexts on NULL + +As it can be seen on the previous listing, instead of allocating the temporary +context directly on mem_ctx, we created a new top level context +using NULL as the parameter for talloc_new() function. +Take a look at the following example: + +@code +char *create_user_filter(TALLOC_CTX *mem_ctx, + uid_t uid, const char *username) +{ + char *filter = NULL; + char *sanitized_username = NULL; + /* tmp_ctx is a child of mem_ctx */ + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return NULL; + } + + sanitized_username = sanitize_string(tmp_ctx, username); + if (sanitized_username == NULL) { + talloc_free(tmp_ctx); + return NULL; + } + + filter = talloc_aprintf(tmp_ctx,"(|(uid=%llu)(uname=%s))", + uid, sanitized_username); + if (filter == NULL) { + return NULL; /* tmp_ctx is not freed */ (*@\label{lst:tmp-ctx-3:leak}@*) + } + + /* filter becomes a child of mem_ctx */ + filter = talloc_steal(mem_ctx, filter); + talloc_free(tmp_ctx); + return filter; +} +@endcode + +We forgot to free tmp_ctx before the return statement +in the filter == NULL condition. However, it is created as a child +of mem_ctx context and as such it will be freed as soon as the +mem_ctx is freed. Therefore, no detectable memory leak is created. + +On the other hand, we do not have any way to access the allocated data +and for all we know mem_ctx may exist for the lifetime of our +application. For these reasons this should be considered as a memory leak. How +can we detect if it is unreferenced but still attached to its parent context? +The only way is to notice the mistake in the source code. + +But if we create the temporary context as a top level context, it will not be +freed and memory diagnostic tools +(e.g. valgrind) are able to do their job. + +@section bp-pool Temporary contexts and the talloc pool + +If we want to take the advantage of the talloc pool but also keep to the +pattern introduced in the previous section, we are unable to do it directly. The +best thing to do is to create a conditional build where we can decide how do we +want to create the temporary context. For example, we can create the following +macros: + +@code +#ifdef USE_POOL_CONTEXT + #define CREATE_POOL_CTX(ctx, size) talloc_pool(ctx, size) + #define CREATE_TMP_CTX(ctx) talloc_new(ctx) +#else + #define CREATE_POOL_CTX(ctx, size) talloc_new(ctx) + #define CREATE_TMP_CTX(ctx) talloc_new(NULL) +#endif +@endcode + +Now if our application is under development, we will build it with macro +USE_POOL_CONTEXT undefined. This way, we can use memory diagnostic +utilities to detect memory leaks. + +The release version will be compiled with the macro defined. This will enable +pool contexts and therefore reduce the malloc() calls, which will +end up in a little bit faster processing. + +@code +int struct_foo_init(TALLOC_CTX *mem_ctx, struct foo **_foo) +{ + int ret; + struct foo *foo = NULL; + TALLOC_CTX *tmp_ctx = CREATE_TMP_CTX(mem_ctx); + /* ... */ +} + +errno_t handle_request(TALLOC_CTX mem_ctx) +{ + int ret; + struct foo *foo = NULL; + TALLOC_CTX *pool_ctx = CREATE_POOL_CTX(NULL, 1024); + ret = struct_foo_init(mem_ctx, &foo); + /* ... */ +} +@endcode + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_context.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_context.dox new file mode 100644 index 0000000..b8bfe26 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_context.dox @@ -0,0 +1,198 @@ +/** +@page libtalloc_context Chapter 1: Talloc context +@section context Talloc context + +The talloc context is the most important part of this library and is +responsible for every single feature of this memory allocator. It is a logical +unit which represents a memory space managed by talloc. + +From the programmer's point of view, the talloc context is completely +equivalent to a pointer that would be returned by the memory routines from the +C standard library. This means that every context that is returned from the +talloc library can be used directly in functions that do not use talloc +internally. For example we can do the following: + +@code +char *str1 = strdup("I am NOT a talloc context"); +char *str2 = talloc_strdup(NULL, "I AM a talloc context"); + +printf("%d\n", strcmp(str1, str2) == 0); + +free(str1); +talloc_free(str2); /* we can not use free() on str2 */ +@endcode + +This is possible because the context is internally handled as a special +fixed-length structure called talloc chunk. Each chunk stores context metadata +followed by the memory space requested by the programmer. When a talloc +function returns a context (pointer), it will in fact return a pointer to the user +space portion of the talloc chunk. If we to manipulate this context using +talloc functions, the talloc library transforms the user-space pointer back to +the starting address of the chunk. This is also the reason why we were unable +to use free(str2) in the previous example - because +str2 does not point at the beginning of the allocated block of +memory. This is illustrated on the next image: + +@image html context.png + +The type TALLOC_CTX is defined in talloc.h to identify a talloc context in +function parameters. However, this type is just an alias for void +and exists only for semantical reasons - thus we can differentiate between +void * (arbitrary data) and TALLOC_CTX * (talloc +context). + +@subsection metadata Context meta data + +Every talloc context carries several pieces of internal information along with +the allocated memory: + + - name - which is used in reports of context hierarchy and to simulate + a dynamic type system, + - size of the requested memory in bytes - this can be used to determine + the number of elements in arrays, + - attached destructor - which is executed just before the memory block is + about to be freed, + - references to the context + - children and parent contexts - create the hierarchical view on the + memory. + +@section context-hierarchy Hierarchy of talloc context + +Every talloc context contains information about its parent and children. Talloc +uses this information to create a hierarchical model of memory or to be more +precise, it creates an n-ary tree where each node represents a single talloc +context. The root node of the tree is referred to as a top level context - a +context without any parent. + +This approach has several advantages: + + - as a consequence of freeing a talloc context, all of its children + will be properly deallocated as well, + - the parent of a context can be changed at any time, which + results in moving the whole subtree under another node, + - it creates a more natural way of managing data structures. + +@subsection Example + +We have a structure that stores basic information about a user - his/her name, +identification number and groups he/she is a member of: + +@code +struct user { + uid_t uid; + char *username; + size_t num_groups; + char **groups; +}; +@endcode + +We will allocate this structure using talloc. The result will be the following +context tree: + +@image html context_tree.png + +@code +/* create new top level context */ +struct user *user = talloc(NULL, struct user); + +user->uid = 1000; +user->num_groups = N; + +/* make user the parent of following contexts */ +user->username = talloc_strdup(user, "Test user"); +user->groups = talloc_array(user, char*, user->num_groups); + +for (i = 0; i < user->num_groups; i++) { + /* make user->groups the parent of following context */ + user->groups[i] = talloc_asprintf(user->groups, + "Test group %d", i); +} +@endcode + +This way, we have gained a lot of additional capabilities, one of which is +very simple deallocation of the structure and all of its elements. + +With the C standard library we need first to iterate over the array of groups +and free every element separately. Then we must deallocate the array that stores +them. Next we deallocate the username and as the last step free the structure +itself. But with talloc, the only operation we need to execute is freeing the +structure context. Its descendants will be freed automatically. + +@code +talloc_free(user); +@endcode + +@section keep-hierarchy Always keep the hieararchy steady! + +The talloc is a hierarchy memory allocator. The hierarchy nature is what makes +the programming more error proof. It makes the memory easier to manage and to +free. Therefore, the first thing we should have on our mind is: always +project our data structures into the talloc context hierarchy. + +That means if we have a structure, we should always use it as a parent context +for its elements. This way we will not encounter any troubles when freeing this +structure or when changing its parent. The same rule applies for arrays. + +@section creating-context Creating a talloc context + +Here are the most important functions that create a new talloc context. + +@subsection type-safe Type-safe functions + +It allocates the size that is necessary for the given type and returns a new, +properly-casted pointer. This is the preferred way to create a new context as +we can rely on the compiler to detect type mismatches. + +The name of the context is automatically set to the name of the data type which +is used to simulate a dynamic type system. + +@code +struct user *user = talloc(ctx, struct user); + +/* initialize to default values */ +user->uid = 0; +user->name = NULL; +user->num_groups = 0; +user->groups = NULL; + +/* or we can achieve the same result with */ +struct user *user_zero = talloc_zero(ctx, struct user); +@endcode + +@subsection zero-length Zero-length contexts + +The zero-length context is basically a context without any special semantical +meaning. We can use it the same way as any other context. The only difference +is that it consists only of the meta data about the context. Therefore, it is +strictly of type TALLOC_CTX*. It is often used in cases where we +want to aggregate several data structures under one parent (zero-length) +context, such as a temporary context to contain memory needed within a single +function that is not interesting to the caller. Allocating on a zero-length +temporary context will make clean-up of the function simpler. + +@code +TALLOC_CTX *tmp_ctx = NULL; +struct foo *foo = NULL; +struct bar *bar = NULL; + +/* new zero-length top level context */ +tmp_ctx = talloc_new(NULL); +if (tmp_ctx == NULL) { + return ENOMEM; +} + +foo = talloc(tmp_ctx, struct foo); +bar = talloc(tmp_ctx, struct bar); + +/* free everything at once */ +talloc_free(tmp_ctx); +@endcode + +@subsection context-see-also See also + +- talloc_size() +- talloc_named() +- @ref talloc_array +- @ref talloc_string + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_debugging.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_debugging.dox new file mode 100644 index 0000000..aadbb0d --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_debugging.dox @@ -0,0 +1,116 @@ +/** +@page libtalloc_debugging Chapter 6: Debugging + +Although talloc makes memory management significantly easier than the C standard +library, developers are still only humans and can make mistakes. Therefore, it +can be handy to know some tools for the inspection of talloc memory usage. + +@section log-abort Talloc log and abort + +We have already encountered the abort function in section @ref dts. +In that case it was used when a type mismatch was detected. However, talloc +calls this abort function in several more situations: + +- when the provided pointer is not a valid talloc context, +- when the meta data is invalid - probably due to memory corruption, +- and when an access after free is detected. + +The third one is probably the most interesting. It can help us with detecting +an attempt to double-free a context or any other manipulation with it via +talloc functions (using it as a parent, stealing it, etc.). + +Before the context is freed talloc sets a flag in the meta data. This is then +used to detect the access after free. It basically works on the assumption that +the memory stays unchanged (at least for a while) even when it is properly +deallocated. This will work even if the memory is filled with the value +specified in TALLOC_FREE_FILL environment variable, because it +fills only the data part and leaves the meta data intact. + +Apart from the abort function, talloc uses a log function to provide additional +information to the aforementioned violations. To enable logging we shall set the +log function with one of: + +- talloc_set_log_fn() +- talloc_set_log_stderr() + +The following code is a sample output of accessing a context after it has been +freed: + +@code +talloc_set_log_stderr(); +TALLOC_CTX *ctx = talloc_new(NULL); + +talloc_free(ctx); +talloc_free(ctx); + +results in: +talloc: access after free error - first free may be at ../src/main.c:55 +Bad talloc magic value - access after free +@endcode + +Another example is an invalid context: + +@code +talloc_set_log_stderr(); +TALLOC_CTX *ctx = talloc_new(NULL); +char *str = strdup("not a talloc context"); +talloc_steal(ctx, str); + +results in: +Bad talloc magic value - unknown value +@endcode + +@section reports Memory usage reports + +Talloc can print reports of memory usage of a specified talloc context to a +file (to stdout or stderr). The report can be +simple or full. The simple report provides information only about the context +itself and its direct descendants. The full report goes recursively through the +entire context tree. See: + +- talloc_report() +- talloc_report_full() + +We will use the following code to retrieve the sample report: + +@code +struct foo { + char *str; +}; + +TALLOC_CTX *ctx = talloc_new(NULL); +char *str = talloc_strdup(ctx, "my string"); +struct foo *foo = talloc_zero(ctx, struct foo); +foo->str = talloc_strdup(foo, "I am Foo"); +char *str2 = talloc_strdup(foo, "Foo is my parent"); + +/* print full report */ +talloc_report_full(ctx, stdout); +@endcode + +It will print a full report of ctx to the standard output. +The message should be similar to: + +@code +full talloc report on 'talloc_new: ../src/main.c:82' (total 46 bytes in 5 blocks) + struct foo contains 34 bytes in 3 blocks (ref 0) 0x1495130 + Foo is my parent contains 17 bytes in 1 blocks (ref 0) 0x1495200 + I am Foo contains 9 bytes in 1 blocks (ref 0) 0x1495190 + my string contains 10 bytes in 1 blocks (ref 0) 0x14950c0 +@endcode + +We can notice in this report that something is wrong with the context containing +struct foo. We know that the structure has only one string element. +However, we can see in the report that it has two children. This indicates that +we have either violated the memory hierarchy or forgotten to free it as +temporary data. Looking into the code, we can see that "Foo is my parent" + should be attached to ctx. + +See also: + +- talloc_enable_null_tracking() +- talloc_disable_null_tracking() +- talloc_enable_leak_report() +- talloc_enable_leak_report_full() + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_destructors.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_destructors.dox new file mode 100644 index 0000000..ed06387 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_destructors.dox @@ -0,0 +1,82 @@ +/** +@page libtalloc_destructors Chapter 4: Using destructors + +@section destructors Using destructors + +Destructors are well known methods in the world of object oriented programming. +A destructor is a method of an object that is automatically run when the object +is destroyed. It is usually used to return resources taken by the object back to +the system (e.g. closing file descriptors, terminating connection to a database, +deallocating memory). + +With talloc we can take the advantage of destructors even in C. We can easily +attach our own destructor to a talloc context. When the context is freed, the +destructor will run automatically. + +To attach/detach a destructor to a talloc context use: talloc_set_destructor(). + +@section destructors-example Example + +Imagine that we have a dynamically created linked list. Before we deallocate an +element of the list, we need to make sure that we have successfully removed it +from the list. Normally, this would be done by two commands in the exact order: +remove it from the list and then free the element. With talloc, we can do this +at once by setting a destructor on the element which will remove it from the +list and talloc_free() will do the rest. + +The destructor would be: + +@code +int list_remove(void *ctx) +{ + struct list_el *el = NULL; + el = talloc_get_type_abort(ctx, struct list_el); + /* remove element from the list */ +} +@endcode + +GCC version 3 and newer can check for the types during the compilation. So if +it is our major compiler, we can use a more advanced destructor: + +@code +int list_remove(struct list_el *el) +{ + /* remove element from the list */ +} +@endcode + +Now we will assign the destructor to the list element. We can do this directly +in the function that inserts it. + +@code +struct list_el* list_insert(TALLOC_CTX *mem_ctx, + struct list_el *where, + void *ptr) +{ + struct list_el *el = talloc(mem_ctx, struct list_el); + el->data = ptr; + /* insert into list */ + + talloc_set_destructor(el, list_remove); + return el; +} +@endcode + +Because talloc is a hierarchical memory allocator, we can go a step further and +free the data with the element as well: + +@code +struct list_el* list_insert_free(TALLOC_CTX *mem_ctx, + struct list_el *where, + void *ptr) +{ + struct list_el *el = NULL; + el = list_insert(mem_ctx, where, ptr); + + talloc_steal(el, ptr); + + return el; +} +@endcode + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_dts.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_dts.dox new file mode 100644 index 0000000..75b5172 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_dts.dox @@ -0,0 +1,109 @@ +/** +@page libtalloc_dts Chapter 3: Dynamic type system + +@section dts Dynamic type system + +Generic programming in the C language is very difficult. There is no inheritance +nor templates known from object oriented languages. There is no dynamic type +system. Therefore, generic programming in this language is usually done by +type-casting a variable to void* and transferring it through +a generic function to a specialized callback as illustrated on the next listing. + +@code +void generic_function(callback_fn cb, void *pvt) +{ + /* do some stuff and call the callback */ + cb(pvt); +} + +void specific_callback(void *pvt) +{ + struct specific_struct *data; + data = (struct specific_struct*)pvt; + /* ... */ +} + +void specific_function() +{ + struct specific_struct data; + generic_function(callback, &data); +} +@endcode + +Unfortunately, the type information is lost as a result of this type cast. The +compiler cannot check the type during the compilation nor are we able to do it +at runtime. Providing an invalid data type to the callback will result in +unexpected behaviour (not necessarily a crash) of the application. This mistake +is usually hard to detect because it is not the first thing which comes the +mind. + +As we already know, every talloc context contains a name. This name is available +at any time and it can be used to determine the type of a context even if we +lose the type of a variable. + +Although the name of the context can be set to any arbitrary string, the best +way of using it to simulate the dynamic type system is to set it directly to the +type of the variable. + +It is recommended to use one of talloc() and talloc_array() (or its +variants) to create the context as they set its name to the name of the +given type automatically. + +If we have a context with such as a name, we can use two similar functions that +do both the type check and the type cast for us: + +- talloc_get_type() +- talloc_get_type_abort() + +@section dts-examples Examples + +The following example will show how generic programming with talloc is handled - +if we provide invalid data to the callback, the program will be aborted. This +is a sufficient reaction for such an error in most applications. + +@code +void foo_callback(void *pvt) +{ + struct foo *data = talloc_get_type_abort(pvt, struct foo); + /* ... */ +} + +int do_foo() +{ + struct foo *data = talloc_zero(NULL, struct foo); + /* ... */ + return generic_function(foo_callback, data); +} +@endcode + +But what if we are creating a service application that should be running for the +uptime of a server, we may want to abort the application during the development +process (to make sure the error is not overlooked) and try to recover from the +error in the customer release. This can be achieved by creating a custom abort +function with a conditional build. + +@code +void my_abort(const char *reason) +{ + fprintf(stderr, "talloc abort: %s\n", reason); +#ifdef ABORT_ON_TYPE_MISMATCH + abort(); +#endif +} +@endcode + +The usage of talloc_get_type_abort() would be then: + +@code +talloc_set_abort_fn(my_abort); + +TALLOC_CTX *ctx = talloc_new(NULL); +char *str = talloc_get_type_abort(ctx, char); +if (str == NULL) { + /* recovery code */ +} +/* talloc abort: ../src/main.c:25: Type mismatch: + name[talloc_new: ../src/main.c:24] expected[char] */ +@endcode + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_introduction.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_introduction.dox new file mode 100644 index 0000000..418c38b --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_introduction.dox @@ -0,0 +1,45 @@ +/** +@page libtalloc_tutorial The Tutorial +@section introduction Introduction + +Talloc is a hierarchical, reference counted memory pool system with destructors. +It is built atop the C standard library and it defines a set of utility +functions that altogether simplifies allocation and deallocation of data, +especially for complex structures that contain many dynamically allocated +elements such as strings and arrays. + +The main goals of this library are: removing the needs for creating a cleanup +function for every complex structure, providing a logical organization of +allocated memory blocks and reducing the likelihood of creating memory leaks in +long-running applications. All of this is achieved by allocating memory in a +hierarchical structure of talloc contexts such that deallocating one context +recursively frees all of its descendants as well. + +@section main-features Main features +- An open source project +- A hierarchical memory model +- Natural projection of data structures into the memory space +- Simplifies memory management of large data structures +- Automatic execution of a destructor before the memory is freed +- Simulates a dynamic type system +- Implements a transparent memory pool + +@section toc Table of contents: + +@subpage libtalloc_context + +@subpage libtalloc_stealing + +@subpage libtalloc_dts + +@subpage libtalloc_destructors + +@subpage libtalloc_pools + +@subpage libtalloc_debugging + +@subpage libtalloc_bestpractices + +@subpage libtalloc_threads + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_pools.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_pools.dox new file mode 100644 index 0000000..a0d1e1a --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_pools.dox @@ -0,0 +1,93 @@ +/** +@page libtalloc_pools Chapter 5: Memory pools + +@section pools Memory pools + +Allocation of a new memory is an expensive operation and large programs can +contain thousands of calls of malloc() for a single computation, where every +call allocates only a very small amount of the memory. This can result in an +undesirable slowdown of the application. We can avoid this slowdown by +decreasing the number of malloc() calls by using a memory pool. + +A memory pool is a preallocated memory space with a fixed size. If we need to +allocate new data we will take the desired amount of the memory from the pool +instead of requesting a new memory from the system. This is done by creating a +pointer that points inside the preallocated memory. Such a pool must not be +reallocated as it would change its location - pointers that were pointing +inside the pool would become invalid. Therefore, a memory pool requires a very +good estimate of the required memory space. + +The talloc library contains its own implementation of a memory pool. It is +highly transparent for the programmer. The only thing that needs to be done is +an initialization of a new pool context using talloc_pool() - +which can be used in the same way as any other context. + +Refactoring of existing code (that uses talloc) to take the advantage of a +memory pool is quite simple due to the following properties of the pool context: + +- if we are allocating data on a pool context, it takes the desired + amount of memory from the pool, +- if the context is a descendant of the pool context, it takes the space + from the pool as well, +- if the pool does not have sufficient portion of memory left, it will + create a new non-pool context, leaving the pool intact + +@code +/* allocate 1KiB in a pool */ +TALLOC_CTX *pool_ctx = talloc_pool(NULL, 1024); + +/* Take 512B from the pool, 512B is left there */ +void *ptr = talloc_size(pool_ctx, 512); + +/* 1024B > 512B, this will create new talloc chunk outside + the pool */ +void *ptr2 = talloc_size(ptr, 1024); + +/* The pool still contains 512 free bytes + * this will take 200B from them. */ +void *ptr3 = talloc_size(ptr, 200); + +/* This will destroy context 'ptr3' but the memory + * is not freed, the available space in the pool + * will increase to 512B. */ +talloc_free(ptr3); + +/* This will free memory taken by 'pool_ctx' + * and 'ptr2' as well. */ +talloc_free(pool_ctx); +@endcode + +The above given is very convenient, but there is one big issue to be kept in +mind. If the parent of a talloc pool child is changed to a parent that is +outside of this pool, the whole pool memory will not be freed until the child is +freed. For this reason we must be very careful when stealing a descendant of a +pool context. + +@code +TALLOC_CTX *mem_ctx = talloc_new(NULL); +TALLOC_CTX *pool_ctx = talloc_pool(NULL, 1024); +struct foo *foo = talloc(pool_ctx, struct foo); + +/* mem_ctx is not in the pool */ +talloc_steal(mem_ctx, foo); + +/* pool_ctx is marked as freed but the memory is not + deallocated, accessing the pool_ctx again will cause + an error */ +talloc_free(pool_ctx); + +/* This deallocates the pool_ctx. */ +talloc_free(mem_ctx); +@endcode + +It may often be better to copy the memory we want instead of stealing it to +avoid this problem. If we do not need to retain the context name (to keep the +type information), we can use talloc_memdup() to do this. + +Copying the memory out of the pool may, however, discard all the performance +boost given by the pool, depending on the size of the copied memory. Therefore, +the code should be well profiled before taking this path. In general, the +golden rule is: if we need to steal from the pool context, we should not +use a pool context. + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_stealing.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_stealing.dox new file mode 100644 index 0000000..67eae1d --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_stealing.dox @@ -0,0 +1,55 @@ +/** +@page libtalloc_stealing Chapter 2: Stealing a context + +@section stealing Stealing a context + +Talloc has the ability to change the parent of a talloc context to another +one. This operation is commonly referred to as stealing and it is one of +the most important actions performed with talloc contexts. + +Stealing a context is necessary if we want the pointer to outlive the context it +is created on. This has many possible use cases, for instance stealing a result +of a database search to an in-memory cache context, changing the parent of a +field of a generic structure to a more specific one or vice-versa. The most +common scenario, at least in Samba, is to steal output data from a function-specific +context to the output context given as an argument of that function. + +@code +struct foo { + char *a1; + char *a2; + char *a3; +}; + +struct bar { + char *wurst; + struct foo *foo; +}; + +struct foo *foo = talloc_zero(ctx, struct foo); +foo->a1 = talloc_strdup(foo, "a1"); +foo->a2 = talloc_strdup(foo, "a2"); +foo->a3 = talloc_strdup(foo, "a3"); + +struct bar *bar = talloc_zero(NULL, struct bar); +/* change parent of foo from ctx to bar */ +bar->foo = talloc_steal(bar, foo); + +/* or do the same but assign foo = NULL */ +bar->foo = talloc_move(bar, &foo); +@endcode + +The talloc_move() function is similar to the talloc_steal() function but +additionally sets the source pointer to NULL. + +In general, the source pointer itself is not changed (it only replaces the +parent in the meta data). But the common usage is that the result is +assigned to another variable, thus further accessing the pointer from the +original variable should be avoided unless it is necessary. In this case +talloc_move() is the preferred way of stealing a context. Additionally sets the +source pointer to NULL, thus.protects the pointer from being accidentally freed +and accessed using the old variable after its parent has been changed. + +@image html stealing.png + +*/ diff --git a/ldb-2.0.8/lib/talloc/doc/tutorial_threads.dox b/ldb-2.0.8/lib/talloc/doc/tutorial_threads.dox new file mode 100644 index 0000000..111bbf5 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doc/tutorial_threads.dox @@ -0,0 +1,203 @@ +/** +@page libtalloc_threads Chapter 8: Using threads with talloc + +@section Talloc and thread safety + +The talloc library is not internally thread-safe, in that accesses +to variables on a talloc context are not controlled by mutexes or +other thread-safe primitives. + +However, so long as talloc_disable_null_tracking() is called from +the main thread to disable global variable access within talloc, +then each thread can safely use its own top level talloc context +allocated off the NULL context. + +For example: + +@code +static void *thread_fn(void *arg) +{ + const char *ctx_name = (const char *)arg; + /* + * Create a new top level talloc hierarchy in + * this thread. + */ + void *top_ctx = talloc_named_const(NULL, 0, "top"); + if (top_ctx == NULL) { + return NULL; + } + sub_ctx = talloc_named_const(top_ctx, 100, ctx_name); + if (sub_ctx == NULL) { + return NULL; + } + + /* + * Do more processing/talloc calls on top_ctx + * and its children. + */ + ...... + + talloc_free(top_ctx); + return value; +} +@endcode + +is a perfectly safe use of talloc within a thread. + +The problem comes when one thread wishes to move some +memory allocated on its local top level talloc context +to another thread. Care must be taken to add data access +exclusion to prevent memory corruption. One method would +be to lock a mutex before any talloc call on each thread, +but this would push the burden of total talloc thread-safety +on the poor user of the library. + +A much easier way to transfer talloced memory between +threads is by the use of an intermediate, mutex locked, +intermediate variable. + +An example of this is below - taken from test code inside +the talloc testsuite. + +The main thread creates 1000 sub-threads, and then accepts +the transfer of some thread-talloc'ed memory onto its top +level context from each thread in turn. + +A pthread mutex and condition variable are used to +synchronize the transfer via the intermediate_ptr +variable. + +@code +/* Required sync variables. */ +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; + +/* Intermediate talloc pointer for transfer. */ +static void *intermediate_ptr; + +/* Subthread. */ +static void *thread_fn(void *arg) +{ + int ret; + const char *ctx_name = (const char *)arg; + void *sub_ctx = NULL; + /* + * Do stuff that creates a new talloc hierarchy in + * this thread. + */ + void *top_ctx = talloc_named_const(NULL, 0, "top"); + if (top_ctx == NULL) { + return NULL; + } + sub_ctx = talloc_named_const(top_ctx, 100, ctx_name); + if (sub_ctx == NULL) { + return NULL; + } + + /* + * Now transfer a pointer from our hierarchy + * onto the intermediate ptr. + */ + ret = pthread_mutex_lock(&mtx); + if (ret != 0) { + talloc_free(top_ctx); + return NULL; + } + + /* Wait for intermediate_ptr to be free. */ + while (intermediate_ptr != NULL) { + ret = pthread_cond_wait(&condvar, &mtx); + if (ret != 0) { + talloc_free(top_ctx); + return NULL; + } + } + + /* and move our memory onto it from our toplevel hierarchy. */ + intermediate_ptr = talloc_move(NULL, &sub_ctx); + + /* Tell the main thread it's ready for pickup. */ + pthread_cond_broadcast(&condvar); + pthread_mutex_unlock(&mtx); + + talloc_free(top_ctx); + return NULL; +} + +/* Main thread. */ + +#define NUM_THREADS 1000 + +static bool test_pthread_talloc_passing(void) +{ + int i; + int ret; + char str_array[NUM_THREADS][20]; + pthread_t thread_id; + void *mem_ctx; + + /* + * Important ! Null tracking breaks threaded talloc. + * It *must* be turned off. + */ + talloc_disable_null_tracking(); + + /* Main thread toplevel context. */ + mem_ctx = talloc_named_const(NULL, 0, "toplevel"); + if (mem_ctx == NULL) { + return false; + } + + /* + * Spin off NUM_THREADS threads. + * 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) { + return false; + } + ret = pthread_create(&thread_id, + NULL, + thread_fn, + str_array[i]); + if (ret != 0) { + return false; + } + } + + /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */ + for (i = 0; i < NUM_THREADS; i++) { + ret = pthread_mutex_lock(&mtx); + if (ret != 0) { + talloc_free(mem_ctx); + return false; + } + + /* Wait for intermediate_ptr to have our data. */ + while (intermediate_ptr == NULL) { + ret = pthread_cond_wait(&condvar, &mtx); + if (ret != 0) { + talloc_free(mem_ctx); + return false; + } + } + + /* and move it onto our toplevel hierarchy. */ + (void)talloc_move(mem_ctx, &intermediate_ptr); + + /* Tell the sub-threads we're ready for another. */ + pthread_cond_broadcast(&condvar); + pthread_mutex_unlock(&mtx); + } + + /* Dump the hierarchy. */ + talloc_report(mem_ctx, stdout); + talloc_free(mem_ctx); + return true; +} +@endcode +*/ diff --git a/ldb-2.0.8/lib/talloc/doxy.config b/ldb-2.0.8/lib/talloc/doxy.config new file mode 100644 index 0000000..0e27d61 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/doxy.config @@ -0,0 +1,1807 @@ +# Doxyfile 1.8.0 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = talloc + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 2.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . \ + doc + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.cpp \ + *.cc \ + *.c \ + *.h \ + *.hh \ + *.hpp \ + *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = */.git/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = doc + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = NO + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NONE + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN \ + PRINTF_ATTRIBUTE(x,y)= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/ldb-2.0.8/lib/talloc/man/talloc.3.xml b/ldb-2.0.8/lib/talloc/man/talloc.3.xml new file mode 100644 index 0000000..c51061f --- /dev/null +++ b/ldb-2.0.8/lib/talloc/man/talloc.3.xml @@ -0,0 +1,814 @@ + + + + 2015-04-10 + + talloc + 3 + Samba + System Administration tools + 4.0 + + + talloc +hierarchical reference counted memory pool system with destructors + + +#include <talloc.h> + + DESCRIPTION + + If you are used to talloc from Samba3 then please read this + carefully, as talloc has changed a lot. + + + The new talloc is a hierarchical, reference counted memory pool + system with destructors. Quite a mouthful really, but not too bad + once you get used to it. + + + Perhaps the biggest change from Samba3 is that there is no + distinction between a "talloc context" and a "talloc pointer". Any + pointer returned from talloc() is itself a valid talloc context. + This means you can do this: + + + struct foo *X = talloc(mem_ctx, struct foo); + X->name = talloc_strdup(X, "foo"); + + + and the pointer X->name + would be a "child" of the talloc context X which is itself a child of + mem_ctx. So if you do + talloc_free(mem_ctx) then + it is all destroyed, whereas if you do talloc_free(X) then just X and X->name are destroyed, and if + you do talloc_free(X->name) then just + the name element of X is + destroyed. + + + If you think about this, then what this effectively gives you is an + n-ary tree, where you can free any part of the tree with + talloc_free(). + + + If you find this confusing, then I suggest you run the testsuite program to watch talloc + in action. You may also like to add your own tests to testsuite.c to clarify how some + particular situation is handled. + + + TALLOC API + + The following is a complete guide to the talloc API. Read it all at + least twice. + + (type *)talloc(const void *ctx, type); + + The talloc() macro is the core of the talloc library. It takes a + memory ctx and a type, and returns a pointer to a new + area of memory of the given type. + + + The returned pointer is itself a talloc context, so you can use + it as the ctx argument to more + calls to talloc() if you wish. + + + The returned pointer is a "child" of the supplied context. This + means that if you talloc_free() the ctx then the new child disappears as + well. Alternatively you can free just the child. + + + The ctx argument to talloc() + can be NULL, in which case a new top level context is created. + + + void *talloc_size(const void *ctx, size_t size); + + The function talloc_size() should be used when you don't have a + convenient type to pass to talloc(). Unlike talloc(), it is not + type safe (as it returns a void *), so you are on your own for + type checking. + + + (typeof(ptr)) talloc_ptrtype(const void *ctx, ptr); + + The talloc_ptrtype() macro should be used when you have a pointer and + want to allocate memory to point at with this pointer. When compiling + with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() + and talloc_get_name() will return the current location in the source file. + and not the type. + + + int talloc_free(void *ptr); + + The talloc_free() function frees a piece of talloc memory, and + all its children. You can call talloc_free() on any pointer + returned by talloc(). + + + The return value of talloc_free() indicates success or failure, + with 0 returned for success and -1 for failure. The only + possible failure condition is if ptr had a destructor attached to it and + the destructor returned -1. See talloc_set_destructor() + for details on destructors. + + + If this pointer has an additional parent when talloc_free() is + called then the memory is not actually released, but instead the + most recently established parent is destroyed. See talloc_reference() + for details on establishing additional parents. + + + For more control on which parent is removed, see talloc_unlink(). + + + talloc_free() operates recursively on its children. + + + From the 2.0 version of talloc, as a special case, + talloc_free() is refused on pointers that have more than one + parent, as talloc would have no way of knowing which parent + should be removed. To free a pointer that has more than one + parent please use talloc_unlink(). + + + To help you find problems in your code caused by this behaviour, if + you do try and free a pointer with more than one parent then the + talloc logging function will be called to give output like this: + + + + ERROR: talloc_free with references at some_dir/source/foo.c:123 + reference at some_dir/source/other.c:325 + reference at some_dir/source/third.c:121 + + + + Please see the documentation for talloc_set_log_fn() and + talloc_set_log_stderr() for more information on talloc logging + functions. + + + void *talloc_reference(const void *ctx, const void *ptr); + + The talloc_reference() function makes ctx an additional parent of ptr. + + + The return value of talloc_reference() is always the original + pointer ptr, unless talloc ran + out of memory in creating the reference in which case it will + return NULL (each additional reference consumes around 48 bytes + of memory on intel x86 platforms). + + + If ptr is NULL, then the + function is a no-op, and simply returns NULL. + + + After creating a reference you can free it in one of the + following ways: + + + + + + you can talloc_free() any parent of the original pointer. + That will reduce the number of parents of this pointer by 1, + and will cause this pointer to be freed if it runs out of + parents. + + + + + you can talloc_free() the pointer itself if it has at maximum one + parent. This behaviour has been changed since the release of version + 2.0. Further information in the description of "talloc_free". + + + + + + For more control on which parent to remove, see talloc_unlink(). + + + int talloc_unlink(const void *ctx, void *ptr); + + The talloc_unlink() function removes a specific parent from + ptr. The ctx passed must either be a context used + in talloc_reference() with this pointer, or must be a direct + parent of ptr. + + + Note that if the parent has already been removed using + talloc_free() then this function will fail and will return -1. + Likewise, if ptr is NULL, then + the function will make no modifications and return -1. + + + Usually you can just use talloc_free() instead of + talloc_unlink(), but sometimes it is useful to have the + additional control on which parent is removed. + + + void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); + + The function talloc_set_destructor() sets the destructor for the pointer ptr. A destructor is a function that is called + when the memory used by a pointer is about to be released. The + destructor receives ptr as an + argument, and should return 0 for success and -1 for failure. + + + The destructor can do anything + it wants to, including freeing other pieces of memory. A common + use for destructors is to clean up operating system resources + (such as open file descriptors) contained in the structure the + destructor is placed on. + + + You can only place one destructor on a pointer. If you need more + than one destructor then you can create a zero-length child of + the pointer and place an additional destructor on that. + + + To remove a destructor call talloc_set_destructor() with NULL for + the destructor. + + + If your destructor attempts to talloc_free() the pointer that it + is the destructor for then talloc_free() will return -1 and the + free will be ignored. This would be a pointless operation + anyway, as the destructor is only called when the memory is just + about to go away. + + + int talloc_increase_ref_count(const void *<emphasis role="italic">ptr</emphasis>); + + The talloc_increase_ref_count(ptr) function is exactly equivalent to: + + talloc_reference(NULL, ptr); + + You can use either syntax, depending on which you think is + clearer in your code. + + + It returns 0 on success and -1 on failure. + + + size_t talloc_reference_count(const void *<emphasis role="italic">ptr</emphasis>); + + Return the number of references to the pointer. + + + void talloc_set_name(const void *ptr, const char *fmt, ...); + + Each talloc pointer has a "name". The name is used principally + for debugging purposes, although it is also possible to set and + get the name on a pointer in as a way of "marking" pointers in + your code. + + + The main use for names on pointer is for "talloc reports". See + talloc_report_depth_cb(), + talloc_report_depth_file(), + talloc_report() + talloc_report() + and talloc_report_full() + for details. Also see talloc_enable_leak_report() + and talloc_enable_leak_report_full(). + + + The talloc_set_name() function allocates memory as a child of the + pointer. It is logically equivalent to: + + talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); + + Note that multiple calls to talloc_set_name() will allocate more + memory without releasing the name. All of the memory is released + when the ptr is freed using talloc_free(). + + + void talloc_set_name_const(const void *<emphasis role="italic">ptr</emphasis>, const char *<emphasis role="italic">name</emphasis>); + + The function talloc_set_name_const() is just like + talloc_set_name(), but it takes a string constant, and is much + faster. It is extensively used by the "auto naming" macros, such + as talloc_p(). + + + This function does not allocate any memory. It just copies the + supplied pointer into the internal representation of the talloc + ptr. This means you must not pass a name pointer to memory that will + disappear before ptr is freed + with talloc_free(). + + + void *talloc_named(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...); + + The talloc_named() function creates a named talloc pointer. It + is equivalent to: + + ptr = talloc_size(ctx, size); +talloc_set_name(ptr, fmt, ....); + + void *talloc_named_const(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">name</emphasis>); + + This is equivalent to: + + ptr = talloc_size(ctx, size); +talloc_set_name_const(ptr, name); + + const char *talloc_get_name(const void *<emphasis role="italic">ptr</emphasis>); + + This returns the current name for the given talloc pointer, + ptr. See talloc_set_name() + for details. + + + void *talloc_init(const char *<emphasis role="italic">fmt</emphasis>, ...); + + This function creates a zero length named talloc context as a top + level context. It is equivalent to: + + talloc_named(NULL, 0, fmt, ...); + + void *talloc_new(void *<emphasis role="italic">ctx</emphasis>); + + This is a utility macro that creates a new memory context hanging + off an existing context, automatically naming it "talloc_new: + __location__" where __location__ is the source line it is called + from. It is particularly useful for creating a new temporary + working context. + + + (<emphasis role="italic">type</emphasis> *)talloc_realloc(const void *<emphasis role="italic">ctx</emphasis>, void *<emphasis role="italic">ptr</emphasis>, <emphasis role="italic">type</emphasis>, <emphasis role="italic">count</emphasis>); + + The talloc_realloc() macro changes the size of a talloc pointer. + It has the following equivalences: + + talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type); +talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr); + + The ctx argument is only used + if ptr is not NULL, otherwise + it is ignored. + + + talloc_realloc() returns the new pointer, or NULL on failure. + The call will fail either due to a lack of memory, or because the + pointer has more than one parent (see talloc_reference()). + + + void *talloc_realloc_size(const void *ctx, void *ptr, size_t size); + + the talloc_realloc_size() function is useful when the type is not + known so the type-safe talloc_realloc() cannot be used. + + + TYPE *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>); + + The talloc_steal() function changes the parent context of a + talloc pointer. It is typically used when the context that the + pointer is currently a child of is going to be freed and you wish + to keep the memory for a longer time. + + + The talloc_steal() function returns the pointer that you pass it. + It does not have any failure modes. + + + It is possible to produce loops in the parent/child + relationship if you are not careful with talloc_steal(). No + guarantees are provided as to your sanity or the safety of your + data if you do this. + + + Note that if you try and call talloc_steal() on a pointer that has + more than one parent then the result is ambiguous. Talloc will choose + to remove the parent that is currently indicated by talloc_parent() + and replace it with the chosen parent. You will also get a message + like this via the talloc logging functions: + + + + WARNING: talloc_steal with references at some_dir/source/foo.c:123 + reference at some_dir/source/other.c:325 + reference at some_dir/source/third.c:121 + + + + To unambiguously change the parent of a pointer please see + the + function talloc_reparent(). See + the talloc_set_log_fn() documentation for more information + on talloc logging. + + + TYPE *talloc_reparent(const void *<emphasis role="italic">old_parent</emphasis>, const void *<emphasis role="italic">new_parent</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>); + + The talloc_reparent() function changes the parent context of a talloc + pointer. It is typically used when the context that the pointer is + currently a child of is going to be freed and you wish to keep the + memory for a longer time. + + + The talloc_reparent() function returns the pointer that you pass it. It + does not have any failure modes. + + + The difference between talloc_reparent() and talloc_steal() is that + talloc_reparent() can specify which parent you wish to change. This is + useful when a pointer has multiple parents via references. + + + TYPE *talloc_move(const void *<emphasis role="italic">new_ctx</emphasis>, TYPE **<emphasis role="italic">ptr</emphasis>); + + The talloc_move() function is a wrapper around + talloc_steal() which zeros the source pointer after the + move. This avoids a potential source of bugs where a + programmer leaves a pointer in two structures, and uses the + pointer from the old structure after it has been moved to a + new one. + + + size_t talloc_total_size(const void *<emphasis role="italic">ptr</emphasis>); + + The talloc_total_size() function returns the total size in bytes + used by this pointer and all child pointers. Mostly useful for + debugging. + + + Passing NULL is allowed, but it will only give a meaningful + result if talloc_enable_leak_report() or + talloc_enable_leak_report_full() has been called. + + + size_t talloc_total_blocks(const void *<emphasis role="italic">ptr</emphasis>); + + The talloc_total_blocks() function returns the total memory block + count used by this pointer and all child pointers. Mostly useful + for debugging. + + + Passing NULL is allowed, but it will only give a meaningful + result if talloc_enable_leak_report() or + talloc_enable_leak_report_full() has been called. + + + void talloc_report(const void *ptr, FILE *f); + + The talloc_report() function prints a summary report of all + memory used by ptr. One line + of report is printed for each immediate child of ptr, showing the + total memory and number of blocks used by that child. + + + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + + + void talloc_report_full(const void *<emphasis role="italic">ptr</emphasis>, FILE *<emphasis role="italic">f</emphasis>); + + This provides a more detailed report than talloc_report(). It + will recursively print the entire tree of memory referenced by + the pointer. References in the tree are shown by giving the name + of the pointer that is referenced. + + + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + + + + + void talloc_report_depth_cb + const void *ptr + int depth + int max_depth + void (*callback)(const void *ptr, int depth, int max_depth, int is_ref, void *priv) + void *priv + + + This provides a more flexible reports than talloc_report(). It + will recursively call the callback for the entire tree of memory + referenced by the pointer. References in the tree are passed with + is_ref = 1 and the pointer that is referenced. + + + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + + + The recursion is stopped when depth >= max_depth. + max_depth = -1 means only stop at leaf nodes. + + + + + void talloc_report_depth_file + const void *ptr + int depth + int max_depth + FILE *f + + + This provides a more flexible reports than talloc_report(). It + will let you specify the depth and max_depth. + + + void talloc_enable_leak_report(void); + + This enables calling of talloc_report(NULL, stderr) when the + program exits. In Samba4 this is enabled by using the + --leak-report command line option. + + + For it to be useful, this function must be called before any + other talloc function as it establishes a "null context" that + acts as the top of the tree. If you don't call this function + first then passing NULL to talloc_report() or + talloc_report_full() won't give you the full tree printout. + + + Here is a typical talloc report: + + talloc report on 'null_context' (total 267 bytes in 15 blocks) +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +iconv(UTF8,CP850) contains 42 bytes in 2 blocks +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +iconv(CP850,UTF8) contains 42 bytes in 2 blocks +iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks +iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + + + void talloc_enable_leak_report_full(void); + + This enables calling of talloc_report_full(NULL, stderr) when the + program exits. In Samba4 this is enabled by using the + --leak-report-full command line option. + + + For it to be useful, this function must be called before any + other talloc function as it establishes a "null context" that + acts as the top of the tree. If you don't call this function + first then passing NULL to talloc_report() or + talloc_report_full() won't give you the full tree printout. + + + Here is a typical full report: + + full talloc report on 'root' (total 18 bytes in 8 blocks) +p1 contains 18 bytes in 7 blocks (ref 0) + r1 contains 13 bytes in 2 blocks (ref 0) + reference to: p2 + p2 contains 1 bytes in 1 blocks (ref 1) + x3 contains 1 bytes in 1 blocks (ref 0) + x2 contains 1 bytes in 1 blocks (ref 0) + x1 contains 1 bytes in 1 blocks (ref 0) + + + (<emphasis role="italic">type</emphasis> *)talloc_zero(const void *<emphasis role="italic">ctx</emphasis>, <emphasis role="italic">type</emphasis>); + + The talloc_zero() macro is equivalent to: + + ptr = talloc(ctx, type); +if (ptr) memset(ptr, 0, sizeof(type)); + + void *talloc_zero_size(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>) + + The talloc_zero_size() function is useful when you don't have a + known type. + + + void *talloc_memdup(const void *<emphasis role="italic">ctx</emphasis>, const void *<emphasis role="italic">p</emphasis>, size_t size); + + The talloc_memdup() function is equivalent to: + + ptr = talloc_size(ctx, size); +if (ptr) memcpy(ptr, p, size); + + char *talloc_strdup(const void *<emphasis role="italic">ctx</emphasis>, const char *<emphasis role="italic">p</emphasis>); + + The talloc_strdup() function is equivalent to: + + ptr = talloc_size(ctx, strlen(p)+1); +if (ptr) memcpy(ptr, p, strlen(p)+1); + + This function sets the name of the new pointer to the passed + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + char *talloc_strndup(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">p</emphasis>, size_t <emphasis role="italic">n</emphasis>); + + The talloc_strndup() function is the talloc equivalent of the C + library function strndup(3). + + + This function sets the name of the new pointer to the passed + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + char *talloc_vasprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, va_list <emphasis role="italic">ap</emphasis>); + + The talloc_vasprintf() function is the talloc equivalent of the C + library function vasprintf(3). + + + This function sets the name of the new pointer to the new + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + char *talloc_asprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...); + + The talloc_asprintf() function is the talloc equivalent of the C + library function asprintf(3). + + + This function sets the name of the new pointer to the passed + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + char *talloc_asprintf_append(char *s, const char *fmt, ...); + + The talloc_asprintf_append() function appends the given formatted + string to the given string. + + + This function sets the name of the new pointer to the new + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + (type *)talloc_array(const void *ctx, type, unsigned int count); + + The talloc_array() macro is equivalent to: + + (type *)talloc_size(ctx, sizeof(type) * count); + + except that it provides integer overflow protection for the + multiply, returning NULL if the multiply overflows. + + + void *talloc_array_size(const void *ctx, size_t size, unsigned int count); + + The talloc_array_size() function is useful when the type is not + known. It operates in the same way as talloc_array(), but takes a + size instead of a type. + + + (typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count); + + The talloc_ptrtype() macro should be used when you have a pointer to an array + and want to allocate memory of an array to point at with this pointer. When compiling + with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() + and talloc_get_name() will return the current location in the source file. + and not the type. + + + void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size) + + This is a non-macro version of talloc_realloc(), which is useful + as libraries sometimes want a realloc function pointer. A + realloc(3) implementation encapsulates the functionality of + malloc(3), free(3) and realloc(3) in one call, which is why it is + useful to be able to pass around a single function pointer. + + + void *talloc_autofree_context(void); + + This is a handy utility function that returns a talloc context + which will be automatically freed on program exit. This can be + used to reduce the noise in memory leak reports. + + + void *talloc_check_name(const void *ptr, const char *name); + + This function checks if a pointer has the specified name. If it does then the pointer is + returned. It it doesn't then NULL is returned. + + + (type *)talloc_get_type(const void *ptr, type); + + This macro allows you to do type checking on talloc pointers. It + is particularly useful for void* private pointers. It is + equivalent to this: + + (type *)talloc_check_name(ptr, #type) + + talloc_set_type(const void *ptr, type); + + This macro allows you to force the name of a pointer to be a + particular type. This can be + used in conjunction with talloc_get_type() to do type checking on + void* pointers. + + + It is equivalent to this: + + talloc_set_name_const(ptr, #type) + + talloc_set_log_fn(void (*log_fn)(const char *message)); + + This function sets a logging function that talloc will use for + warnings and errors. By default talloc will not print any warnings or + errors. + + + talloc_set_log_stderr(void); + + This sets the talloc log function to write log messages to stderr + + + + PERFORMANCE + + All the additional features of talloc(3) over malloc(3) do come at a + price. We have a simple performance test in Samba4 that measures + talloc() versus malloc() performance, and it seems that talloc() is + about 10% slower than malloc() on my x86 Debian Linux box. For + Samba, the great reduction in code complexity that we get by using + talloc makes this worthwhile, especially as the total overhead of + talloc/malloc in Samba is already quite small. + + + SEE ALSO + + malloc(3), strndup(3), vasprintf(3), asprintf(3), + + + + + AUTHOR + The original Samba software and related utilities were + created by Andrew Tridgell. Samba is now developed by the + Samba Team as an Open Source project similar to the way the + Linux kernel is developed. + + + + COPYRIGHT/LICENSE + + Copyright (C) Andrew Tridgell 2004 + + + This program 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 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/. + + + diff --git a/ldb-2.0.8/lib/talloc/pytalloc-util.pc.in b/ldb-2.0.8/lib/talloc/pytalloc-util.pc.in new file mode 100644 index 0000000..06f83e2 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/pytalloc-util.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: pytalloc-util@PYTHON_SO_ABI_FLAG@ +Description: Utility functions for using talloc objects with Python +Version: @TALLOC_VERSION@ +Libs: @LIB_RPATH@ -L${libdir} -lpytalloc-util@PYTHON_LIBNAME_SO_ABI_FLAG@ +Cflags: -I${includedir} +URL: http://talloc.samba.org/ diff --git a/ldb-2.0.8/lib/talloc/pytalloc.c b/ldb-2.0.8/lib/talloc/pytalloc.c new file mode 100644 index 0000000..12c7325 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/pytalloc.c @@ -0,0 +1,309 @@ +/* + Unix SMB/CIFS implementation. + Python Talloc Module + Copyright (C) Jelmer Vernooij 2010-2011 + + 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 . +*/ + +#include +#include +#include +#include "pytalloc_private.h" + +static PyTypeObject TallocObject_Type; + +/* print a talloc tree report for a talloc python object */ +static PyObject *pytalloc_report_full(PyObject *self, PyObject *args) +{ + PyObject *py_obj = Py_None; + + if (!PyArg_ParseTuple(args, "|O", &py_obj)) + return NULL; + + if (py_obj == Py_None) { + talloc_report_full(NULL, stdout); + } else { + talloc_report_full(pytalloc_get_mem_ctx(py_obj), stdout); + } + return Py_None; +} + +/* enable null tracking */ +static PyObject *pytalloc_enable_null_tracking(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + talloc_enable_null_tracking(); + return Py_None; +} + +/* return the number of talloc blocks */ +static PyObject *pytalloc_total_blocks(PyObject *self, PyObject *args) +{ + PyObject *py_obj = Py_None; + + if (!PyArg_ParseTuple(args, "|O", &py_obj)) + return NULL; + + if (py_obj == Py_None) { + return PyLong_FromLong(talloc_total_blocks(NULL)); + } + + return PyLong_FromLong(talloc_total_blocks(pytalloc_get_mem_ctx(py_obj))); +} + +static PyMethodDef talloc_methods[] = { + { "report_full", (PyCFunction)pytalloc_report_full, METH_VARARGS, + "show a talloc tree for an object"}, + { "enable_null_tracking", (PyCFunction)pytalloc_enable_null_tracking, METH_NOARGS, + "enable tracking of the NULL object"}, + { "total_blocks", (PyCFunction)pytalloc_total_blocks, METH_VARARGS, + "return talloc block count"}, + { NULL } +}; + +/** + * Default (but only slightly more useful than the default) implementation of Repr(). + */ +static PyObject *pytalloc_default_repr(PyObject *obj) +{ + pytalloc_Object *talloc_obj = (pytalloc_Object *)obj; + PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj); + + return PyUnicode_FromFormat("<%s talloc object at %p>", + type->tp_name, talloc_obj->ptr); +} + +/** + * Simple dealloc for talloc-wrapping PyObjects + */ +static void pytalloc_dealloc(PyObject* self) +{ + pytalloc_Object *obj = (pytalloc_Object *)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_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_default_cmp(PyObject *_obj1, PyObject *_obj2) +{ + pytalloc_Object *obj1 = (pytalloc_Object *)_obj1, + *obj2 = (pytalloc_Object *)_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 TallocObject_Type = { + .tp_name = "talloc.Object", + .tp_doc = "Python wrapper for a talloc-maintained object.", + .tp_basicsize = sizeof(pytalloc_Object), + .tp_dealloc = (destructor)pytalloc_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_repr = pytalloc_default_repr, +#if PY_MAJOR_VERSION >= 3 + .tp_richcompare = pytalloc_default_richcmp, +#else + .tp_compare = pytalloc_default_cmp, +#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 PyUnicode_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 +}; + +static PyTypeObject TallocGenericObject_Type = { + .tp_name = "talloc.GenericObject", + .tp_doc = "Python wrapper for a talloc-maintained object.", + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_base = &TallocBaseObject_Type, + .tp_basicsize = sizeof(pytalloc_BaseObject), +}; + +#define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "talloc", + .m_doc = MODULE_DOC, + .m_size = -1, + .m_methods = talloc_methods, +}; +#endif + +static PyObject *module_init(void); +static PyObject *module_init(void) +{ + PyObject *m; + + if (PyType_Ready(&TallocObject_Type) < 0) + return NULL; + + if (PyType_Ready(&TallocBaseObject_Type) < 0) + return NULL; + + if (PyType_Ready(&TallocGenericObject_Type) < 0) + return NULL; + +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("talloc", talloc_methods, MODULE_DOC); +#endif + if (m == NULL) + return NULL; + + Py_INCREF(&TallocObject_Type); + if (PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type)) { + goto err; + } + Py_INCREF(&TallocBaseObject_Type); + if (PyModule_AddObject(m, "BaseObject", (PyObject *)&TallocBaseObject_Type)) { + goto err; + } + Py_INCREF(&TallocGenericObject_Type); + if (PyModule_AddObject(m, "GenericObject", (PyObject *)&TallocGenericObject_Type)) { + goto err; + } + return m; + +err: + Py_DECREF(m); + return NULL; +} + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC PyInit_talloc(void); +PyMODINIT_FUNC PyInit_talloc(void) +{ + return module_init(); +} +#else +void inittalloc(void); +void inittalloc(void) +{ + module_init(); +} +#endif diff --git a/ldb-2.0.8/lib/talloc/pytalloc.h b/ldb-2.0.8/lib/talloc/pytalloc.h new file mode 100644 index 0000000..7db6c33 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/pytalloc.h @@ -0,0 +1,79 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij 2008 + + 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 . +*/ + +#ifndef _PYTALLOC_H_ +#define _PYTALLOC_H_ + +#include +#include + +typedef struct { + PyObject_HEAD + TALLOC_CTX *talloc_ctx; + void *ptr; /* eg the array element */ +} pytalloc_Object; + +/* Return the PyTypeObject for pytalloc_Object. Returns a borrowed reference. */ +PyTypeObject *pytalloc_GetObjectType(void); + +/* Return the PyTypeObject for pytalloc_BaseObject. Returns a borrowed reference. */ +PyTypeObject *pytalloc_GetBaseObjectType(void); + +/* Check whether a specific object is a talloc Object. */ +int pytalloc_Check(PyObject *); + +int pytalloc_BaseObject_check(PyObject *); + +int _pytalloc_check_type(PyObject *py_obj, const char *type_name); +#define pytalloc_check_type(py_obj, type) \ + _pytalloc_check_type((PyObject *)(py_obj), #type) + +/* 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)) + +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); +PyObject *pytalloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr); +#define pytalloc_reference(py_type, talloc_ptr) pytalloc_reference_ex(py_type, talloc_ptr, talloc_ptr) + +#define pytalloc_new(type, typeobj) pytalloc_steal(typeobj, talloc_zero(NULL, type)) + +/* + * Wrap a generic talloc pointer into a talloc.GenericObject, + * this is a subclass of talloc.BaseObject. + */ +PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr); +#define pytalloc_GenericObject_steal(talloc_ptr) \ + pytalloc_GenericObject_steal_ex(talloc_ptr, talloc_ptr) +PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr); +#define pytalloc_GenericObject_reference(talloc_ptr) \ + pytalloc_GenericObject_reference_ex(talloc_ptr, talloc_ptr) + +size_t pytalloc_BaseObject_size(void); + +int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type); + +#endif /* _PYTALLOC_H_ */ diff --git a/ldb-2.0.8/lib/talloc/pytalloc_guide.txt b/ldb-2.0.8/lib/talloc/pytalloc_guide.txt new file mode 100644 index 0000000..bd2b68c --- /dev/null +++ b/ldb-2.0.8/lib/talloc/pytalloc_guide.txt @@ -0,0 +1,252 @@ +Using talloc in Samba4 +====================== + +.. contents:: + +Jelmer Vernooij +August 2013 + +The most current version of this document is available at + http://samba.org/ftp/unpacked/talloc/pytalloc_guide.txt + +pytalloc is a small library that provides glue for wrapping +talloc-allocated objects from C in Python objects. + +What is pytalloc, and what is it not? +------------------------------------- + +pytalloc is merely a helper library - it provides a convenient base type object +for objects that wrap talloc-maintained memory in C. It won't write your +bindings for you but it will make it easier to write C bindings that involve +talloc, and take away some of the boiler plate. + +Python 3 +-------- + +pytalloc can be used with Python 3. Usage from Python extension remains +the same, but for the C utilities, the library to link to is tagged with +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_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 +in Python derive from. + +Note that you will almost never create objects of the pytalloc_Object type +itself, as they are just opaque pointers that can not be accessed from +Python. A common pattern is other objects that subclass pytalloc_Object and +rely on it for their memory management. + +Each `pytalloc_Object` wraps two core of information - a talloc context +and a pointer. The pointer is the actual data that is wrapped. The talloc +context is used for memory management purposes only; when the wrapping Python object +goes away, it unlinks the talloc context. The talloc context pointer and the ptr +can (and often do) have the same value. + +Each pytalloc_Object has a custom __repr__ implementation that +describes that it is a talloc object and the location of the +pointer it is wrapping. it also has a custom __cmp__/__eq__/__neq__ method that +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 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 *) + +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. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int pytalloc_check_type(PyObject *py_obj, type) + +Check if the object based on `pytalloc_*Object` py_obj. type should be a +C type, similar to a type passed to `talloc_get_type`. +This can be used as a check before using pytalloc_get_type() +or an alternative codepath. Returns non-zero if it is +an object of the expected type and zero otherwise. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +type *pytalloc_get_type(PyObject *py_obj, type) + +Retrieve the pointer from a `pytalloc_Object` py_obj. type should be a +C type, similar to a type passed to `talloc_get_type`. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +pytalloc_get_ptr(PyObject *py_obj) + +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 or pytalloc_BaseObject. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr) + +Create a new Python wrapping object for a talloc pointer and context, with +py_type as associated Python sub type object. This typically used +when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element. +`pytalloc_get_ptr()` can be used to get the pointer out of the object again. + +This will *not* increment the reference counter for the talloc context, +so the caller should make sure such an increment has happened. When the Python +object goes away, it will unreference the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr) + +Create a new Python wrapping object for a talloc pointer and context, with +py_type as associated Python sub type object. The pointer will also be used +as the talloc context. `pytalloc_get_type()` can be used to get +the pointer out of the object again. + +This will *not* increment the reference counter for the talloc context, +so the caller should make sure such an increment has happened. When the Python +object goes away, it will unreference the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr) + +Create a new Python wrapping object for a talloc pointer and context, with +py_type as associated Python sub type object. This typically used +when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element. +`pytalloc_get_ptr()` can be used to get the pointer out of the object again. + +This will increment the reference counter for the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_reference(PyTypeObject *py_type, void *talloc_ptr) + +Create a new Python wrapping object for a talloc pointer, with +py_type as associated Python sub type object. The pointer will also be used +as the talloc context. `pytalloc_get_type()` can be used to get +the pointer out of the object again. + +This will increment the reference counter for the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_new(type, PyTypeObject *typeobj) + +Create a new, empty pytalloc_Object with the specified Python type object. type +should be a C type, similar to talloc_new(). + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_GenericObject_steal_ex(void *ptr) + +Create a new Python wrapping object for a generic talloc pointer, +as sub type of `pytalloc_BaseObject`. This typically used +when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element. +`pytalloc_get_ptr()` can be used to get the pointer out of the object again. + +This will *not* increment the reference counter for the talloc context, +so the caller should make sure such an increment has happened. When the Python +object goes away, it will unreference the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_GenericObject_steal(void *ptr) + +Create a new Python wrapping object for a generic talloc pointer, +as sub type of `pytalloc_BaseObject`. The pointer will also be used +as the talloc context. `pytalloc_get_type()` can be used to get +the pointer out of the object again. + +This will *not* increment the reference counter for the talloc context, +so the caller should make sure such an increment has happened. When the Python +object goes away, it will unreference the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_GenericObject_reference_ex(void *ptr) + +Create a new Python wrapping object for a generic talloc pointer, +as sub type of `pytalloc_BaseObject`. This typically used +when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element. +`pytalloc_get_ptr()` can be used to get the pointer out of the object again. + +This will increment the reference counter for the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +PyObject *pytalloc_GenericObject_reference(void *ptr) + +Create a new Python wrapping object for a generic talloc pointer, +as sub type of `pytalloc_BaseObject`. The pointer will also be used +as the talloc context. `pytalloc_get_type()` can be used to get +the pointer out of the object again. + +This will increment the reference counter for the talloc context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +DEPRECATED! PyObject *pytalloc_CObject_FromTallocPtr(void *); + +Create a new pytalloc_Object for an abitrary talloc-maintained C pointer. This will +use a generic VoidPtr Python type, which just provides an opaque object in +Python. The caller is responsible for incrementing the talloc reference count before calling +this function - it will dereference the talloc pointer when it is garbage collected. + +This function is deprecated and only available on Python 2. +Use pytalloc_GenericObject_{reference,steal}[_ex]() instead. + +Debug function for talloc in Python +----------------------------------- + +The "talloc" module in Python provides a couple of functions that can be used +to debug issues with objects wrapped by pytalloc. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +report_full(obj?) + +Print a full report on a specific object or on all allocated objects by Python. +Same behaviour as the `talloc_report_full()` function that is provided by +C talloc. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +enable_null_tracking() + +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?) + +Return the talloc block count for all allocated objects or a specific object if +specified. diff --git a/ldb-2.0.8/lib/talloc/pytalloc_private.h b/ldb-2.0.8/lib/talloc/pytalloc_private.h new file mode 100644 index 0000000..b23cdfc --- /dev/null +++ b/ldb-2.0.8/lib/talloc/pytalloc_private.h @@ -0,0 +1,26 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij 2008 + Copyright (C) Andrew Bartlett 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 . +*/ + +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/ldb-2.0.8/lib/talloc/pytalloc_util.c b/ldb-2.0.8/lib/talloc/pytalloc_util.c new file mode 100644 index 0000000..7a426d6 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/pytalloc_util.c @@ -0,0 +1,333 @@ +/* + Unix SMB/CIFS implementation. + Python/Talloc glue + Copyright (C) Jelmer Vernooij 2008 + + 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 . +*/ + +#include +#include "replace.h" +#include +#include "pytalloc.h" +#include +#include "pytalloc_private.h" + +static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type, + TALLOC_CTX *mem_ctx, void *ptr, bool steal); + +_PUBLIC_ PyTypeObject *pytalloc_GetObjectType(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, "Object"); + Py_DECREF(mod); + + 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; +} + +static PyTypeObject *pytalloc_GetGenericObjectType(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, "GenericObject"); + 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) +{ + return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, true); +} + +/** + * Import an existing talloc pointer into a Python object. + */ +_PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr) +{ + return pytalloc_steal_or_reference(py_type, ptr, ptr, true); +} + + +/** + * Import an existing talloc pointer into a Python object, leaving the + * original parent, and creating a reference to the object in the python + * 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) +{ + return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, false); +} + + +/** + * Internal function that either steals or referecences the talloc + * pointer into a new talloc context. + */ +static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type, + TALLOC_CTX *mem_ctx, void *ptr, bool steal) +{ + bool ok = false; + TALLOC_CTX *talloc_ctx = NULL; + bool is_baseobject = false; + PyObject *obj = NULL; + PyTypeObject *BaseObjectType = NULL, *ObjectType = NULL; + + BaseObjectType = pytalloc_GetBaseObjectType(); + if (BaseObjectType == NULL) { + goto err; + } + ObjectType = pytalloc_GetObjectType(); + if (ObjectType == NULL) { + goto err; + } + + /* this should have been tested by caller */ + if (mem_ctx == NULL) { + return PyErr_NoMemory(); + } + + is_baseobject = PyType_IsSubtype(py_type, BaseObjectType); + if (!is_baseobject) { + if (!PyType_IsSubtype(py_type, ObjectType)) { + PyErr_SetString(PyExc_TypeError, + "Expected type based on talloc"); + return NULL; + } + } + + obj = py_type->tp_alloc(py_type, 0); + if (obj == NULL) { + goto err; + } + + talloc_ctx = talloc_new(NULL); + if (talloc_ctx == NULL) { + PyErr_NoMemory(); + goto err; + } + + if (steal) { + ok = (talloc_steal(talloc_ctx, mem_ctx) != NULL); + } else { + ok = (talloc_reference(talloc_ctx, mem_ctx) != NULL); + } + if (!ok) { + goto err; + } + talloc_set_name_const(talloc_ctx, py_type->tp_name); + + if (is_baseobject) { + pytalloc_BaseObject *ret = (pytalloc_BaseObject*)obj; + ret->talloc_ctx = talloc_ctx; + ret->talloc_ptr_ctx = mem_ctx; + ret->ptr = ptr; + } else { + pytalloc_Object *ret = (pytalloc_Object*)obj; + ret->talloc_ctx = talloc_ctx; + ret->ptr = ptr; + } + return obj; + +err: + TALLOC_FREE(talloc_ctx); + Py_XDECREF(obj); + return NULL; +} + +/* + * Wrap a generic talloc pointer into a talloc.GenericObject, + * this is a subclass of talloc.BaseObject. + */ +_PUBLIC_ PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr) +{ + PyTypeObject *tp = pytalloc_GetGenericObjectType(); + return pytalloc_steal_ex(tp, mem_ctx, ptr); +} + +/* + * Wrap a generic talloc pointer into a talloc.GenericObject, + * this is a subclass of talloc.BaseObject. + */ +_PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr) +{ + PyTypeObject *tp = pytalloc_GetGenericObjectType(); + return pytalloc_reference_ex(tp, mem_ctx, ptr); +} + +_PUBLIC_ int pytalloc_Check(PyObject *obj) +{ + PyTypeObject *tp = pytalloc_GetObjectType(); + + 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); +} + +static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name, + bool check_only, const char *function) +{ + TALLOC_CTX *mem_ctx; + void *ptr = NULL; + void *type_obj = talloc_check_name(ptr, type_name); + + mem_ctx = _pytalloc_get_mem_ctx(py_obj); + ptr = _pytalloc_get_ptr(py_obj); + + if (mem_ctx != ptr) { + if (check_only) { + return NULL; + } + + PyErr_Format(PyExc_TypeError, "%s: expected %s, " + "but the pointer is no talloc pointer, " + "pytalloc_get_ptr() would get the raw pointer.", + function, type_name); + return NULL; + } + + type_obj = talloc_check_name(ptr, type_name); + if (type_obj == NULL) { + const char *name = NULL; + + if (check_only) { + return NULL; + } + + name = talloc_get_name(ptr); + PyErr_Format(PyExc_TypeError, "%s: expected %s, got %s", + function, type_name, name); + return NULL; + } + + return ptr; +} + +_PUBLIC_ int _pytalloc_check_type(PyObject *py_obj, const char *type_name) +{ + void *ptr = NULL; + + ptr = _pytalloc_get_checked_type(py_obj, type_name, + true, /* check_only */ + "pytalloc_check_type"); + if (ptr == NULL) { + return 0; + } + + return 1; +} + +_PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name) +{ + return _pytalloc_get_checked_type(py_obj, type_name, + false, /* not check_only */ + "pytalloc_get_type"); +} + +_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) { + return -1; + } + + type->tp_base = talloc_type; + type->tp_basicsize = pytalloc_BaseObject_size(); + + return PyType_Ready(type); +} diff --git a/ldb-2.0.8/lib/talloc/talloc.c b/ldb-2.0.8/lib/talloc/talloc.c new file mode 100644 index 0000000..518ffbd --- /dev/null +++ b/ldb-2.0.8/lib/talloc/talloc.c @@ -0,0 +1,3050 @@ +/* + Samba Unix SMB/CIFS implementation. + + Samba trivial allocation library - new interface + + NOTE: Please read talloc_guide.txt for full documentation + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +/* + inspired by http://swapped.cc/halloc/ +*/ + +#include "replace.h" +#include "talloc.h" + +#ifdef HAVE_SYS_AUXV_H +#include +#endif + +#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR) +#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR" +#endif + +#if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR) +#error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR" +#endif + +/* Special macros that are no-ops except when run under Valgrind on + * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */ +#ifdef HAVE_VALGRIND_MEMCHECK_H + /* memcheck.h includes valgrind.h */ +#include +#elif defined(HAVE_VALGRIND_H) +#include +#endif + +/* use this to force every realloc to change the pointer, to stress test + code that might not cope */ +#define ALWAYS_REALLOC 0 + + +#define MAX_TALLOC_SIZE 0x10000000 + +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 +#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */ +#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */ + +/* + * Bits above this are random, used to make it harder to fake talloc + * headers during an attack. Try not to change this without good reason. + */ +#define TALLOC_FLAG_MASK 0x0F + +#define TALLOC_MAGIC_REFERENCE ((const char *)1) + +#define TALLOC_MAGIC_BASE 0xe814ec70 +#define TALLOC_MAGIC_NON_RANDOM ( \ + ~TALLOC_FLAG_MASK & ( \ + TALLOC_MAGIC_BASE + \ + (TALLOC_BUILD_VERSION_MAJOR << 24) + \ + (TALLOC_BUILD_VERSION_MINOR << 16) + \ + (TALLOC_BUILD_VERSION_RELEASE << 8))) +static unsigned int talloc_magic = TALLOC_MAGIC_NON_RANDOM; + +/* by default we abort when given a bad pointer (such as when talloc_free() is called + on a pointer that came from malloc() */ +#ifndef TALLOC_ABORT +#define TALLOC_ABORT(reason) abort() +#endif + +#ifndef discard_const_p +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) +#else +# define discard_const_p(type, ptr) ((type *)(ptr)) +#endif +#endif + +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#else +#ifndef likely +#define likely(x) (x) +#endif +#ifndef unlikely +#define unlikely(x) (x) +#endif +#endif + +/* this null_context is only used if talloc_enable_leak_report() or + talloc_enable_leak_report_full() is called, otherwise it remains + NULL +*/ +static void *null_context; +static bool talloc_report_null; +static bool talloc_report_null_full; +static void *autofree_context; + +static void talloc_setup_atexit(void); + +/* used to enable fill of memory on free, which can be useful for + * catching use after free errors when valgrind is too slow + */ +static struct { + bool initialised; + bool enabled; + uint8_t fill_value; +} talloc_fill; + +#define TALLOC_FILL_ENV "TALLOC_FREE_FILL" + +/* + * do not wipe the header, to allow the + * double-free logic to still work + */ +#define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = (_tc)->size; \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) +/* Mark the whole chunk as not accessable */ +#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \ + size_t _flen = TC_HDR_SIZE + (_tc)->size; \ + char *_fptr = (char *)(_tc); \ + VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ +} while(0) +#else +#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0) +#endif + +#define TC_INVALIDATE_FULL_CHUNK(_tc) do { \ + TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \ + TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \ +} while (0) + +#define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) +/* Mark the unused bytes not accessable */ +#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ +} while (0) +#else +#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) +#endif + +#define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \ + TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \ + TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \ +} while (0) + +#define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) +/* Mark the unused bytes as undefined */ +#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \ +} while (0) +#else +#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) +#endif + +#define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \ + TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \ + TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) +/* Mark the new bytes as undefined */ +#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \ + size_t _old_used = TC_HDR_SIZE + (_tc)->size; \ + size_t _new_used = TC_HDR_SIZE + (_new_size); \ + size_t _flen = _new_used - _old_used; \ + char *_fptr = _old_used + (char *)(_tc); \ + VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \ +} while (0) +#else +#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) +#endif + +#define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \ + TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \ +} while (0) + +struct talloc_reference_handle { + struct talloc_reference_handle *next, *prev; + void *ptr; + const char *location; +}; + +struct talloc_memlimit { + struct talloc_chunk *parent; + struct talloc_memlimit *upper; + size_t max_size; + size_t cur_size; +}; + +static inline bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size); +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 tc_memlimit_update_on_free(struct talloc_chunk *tc); + +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: + * + * + * / | \ + * / | \ + * / | \ + * + * + * The actual talloc tree is: + * + * + * | + * - - + * + * 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; + talloc_destructor_t destructor; + const char *name; + size_t size; + + /* + * limit semantics: + * if 'limit' is set it means all *new* children of the context will + * be limited to a total aggregate size ox max_size for memory + * allocations. + * cur_size is used to keep track of the current use + */ + struct talloc_memlimit *limit; + + /* + * For members of a pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool" + * is a pointer to the struct talloc_chunk of the pool that it was + * allocated from. This way children can quickly find the pool to chew + * from. + */ + struct talloc_pool_hdr *pool; +}; + +union talloc_chunk_cast_u { + uint8_t *ptr; + struct talloc_chunk *chunk; +}; + +/* 16 byte alignment seems to keep everyone happy */ +#define TC_ALIGN16(s) (((s)+15)&~15) +#define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk)) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) + +_PUBLIC_ int talloc_version_major(void) +{ + return TALLOC_VERSION_MAJOR; +} + +_PUBLIC_ int talloc_version_minor(void) +{ + return TALLOC_VERSION_MINOR; +} + +_PUBLIC_ int talloc_test_get_magic(void) +{ + return talloc_magic; +} + +static inline void _talloc_chunk_set_free(struct talloc_chunk *tc, + const char *location) +{ + /* + * Mark this memory as free, and also over-stamp the talloc + * magic with the old-style magic. + * + * Why? This tries to avoid a memory read use-after-free from + * disclosing our talloc magic, which would then allow an + * attacker to prepare a valid header and so run a destructor. + * + */ + tc->flags = TALLOC_MAGIC_NON_RANDOM | TALLOC_FLAG_FREE + | (tc->flags & TALLOC_FLAG_MASK); + + /* we mark the freed memory with where we called the free + * from. This means on a double free error we can report where + * the first free came from + */ + if (location) { + tc->name = location; + } +} + +static inline void _talloc_chunk_set_not_free(struct talloc_chunk *tc) +{ + /* + * Mark this memory as not free. + * + * Why? This is memory either in a pool (and so available for + * talloc's re-use or after the realloc(). We need to mark + * the memory as free() before any realloc() call as we can't + * write to the memory after that. + * + * We put back the normal magic instead of the 'not random' + * magic. + */ + + tc->flags = talloc_magic | + ((tc->flags & TALLOC_FLAG_MASK) & ~TALLOC_FLAG_FREE); +} + +static void (*talloc_log_fn)(const char *message); + +_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message)) +{ + talloc_log_fn = log_fn; +} + +#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE +void talloc_lib_init(void) __attribute__((constructor)); +void talloc_lib_init(void) +{ + uint32_t random_value; +#if defined(HAVE_GETAUXVAL) && defined(AT_RANDOM) + uint8_t *p; + /* + * Use the kernel-provided random values used for + * ASLR. This won't change per-exec, which is ideal for us + */ + p = (uint8_t *) getauxval(AT_RANDOM); + if (p) { + /* + * We get 16 bytes from getauxval. By calling rand(), + * a totally insecure PRNG, but one that will + * deterministically have a different value when called + * twice, we ensure that if two talloc-like libraries + * are somehow loaded in the same address space, that + * because we choose different bytes, we will keep the + * protection against collision of multiple talloc + * libs. + * + * This protection is important because the effects of + * passing a talloc pointer from one to the other may + * be very hard to determine. + */ + int offset = rand() % (16 - sizeof(random_value)); + memcpy(&random_value, p + offset, sizeof(random_value)); + } else +#endif + { + /* + * Otherwise, hope the location we are loaded in + * memory is randomised by someone else + */ + random_value = ((uintptr_t)talloc_lib_init & 0xFFFFFFFF); + } + talloc_magic = random_value & ~TALLOC_FLAG_MASK; +} +#else +#warning "No __attribute__((constructor)) support found on this platform, additional talloc security measures not available" +#endif + +static void talloc_lib_atexit(void) +{ + TALLOC_FREE(autofree_context); + + if (talloc_total_size(null_context) == 0) { + return; + } + + if (talloc_report_null_full) { + talloc_report_full(null_context, stderr); + } else if (talloc_report_null) { + talloc_report(null_context, stderr); + } +} + +static void talloc_setup_atexit(void) +{ + static bool done; + + if (done) { + return; + } + + atexit(talloc_lib_atexit); + done = true; +} + +static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +static void talloc_log(const char *fmt, ...) +{ + va_list ap; + char *message; + + if (!talloc_log_fn) { + return; + } + + va_start(ap, fmt); + message = talloc_vasprintf(NULL, fmt, ap); + va_end(ap); + + talloc_log_fn(message); + talloc_free(message); +} + +static void talloc_log_stderr(const char *message) +{ + fprintf(stderr, "%s", message); +} + +_PUBLIC_ void talloc_set_log_stderr(void) +{ + talloc_set_log_fn(talloc_log_stderr); +} + +static void (*talloc_abort_fn)(const char *reason); + +_PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason)) +{ + talloc_abort_fn = abort_fn; +} + +static void talloc_abort(const char *reason) +{ + talloc_log("%s\n", reason); + + if (!talloc_abort_fn) { + TALLOC_ABORT(reason); + } + + talloc_abort_fn(reason); +} + +static void talloc_abort_access_after_free(void) +{ + talloc_abort("Bad talloc magic value - access after free"); +} + +static void talloc_abort_unknown_value(void) +{ + talloc_abort("Bad talloc magic value - unknown value"); +} + +/* panic if we get a bad magic value */ +static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +{ + const char *pp = (const char *)ptr; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); + if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK)) != talloc_magic)) { + if ((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK)) + == (TALLOC_MAGIC_NON_RANDOM | TALLOC_FLAG_FREE)) { + talloc_log("talloc: access after free error - first free may be at %s\n", tc->name); + talloc_abort_access_after_free(); + return NULL; + } + + talloc_abort_unknown_value(); + return NULL; + } + return tc; +} + +/* hook into the front of the list */ +#define _TLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define _TLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + + +/* + return the parent chunk of a pointer +*/ +static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); + while (tc->prev) tc=tc->prev; + + return tc->parent; +} + +_PUBLIC_ void *talloc_parent(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; +} + +/* + find parents name +*/ +_PUBLIC_ const char *talloc_parent_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? tc->name : NULL; +} + +/* + A pool carries an in-pool object count count in the first 16 bytes. + bytes. This is done to support talloc_steal() to a parent outside of the + pool. The count includes the pool itself, so a talloc_free() on a pool will + only destroy the pool if the count has dropped to zero. A talloc_free() of a + pool member will reduce the count, and eventually also call free(3) on the + pool memory. + + The object count is not put into "struct talloc_chunk" because it is only + relevant for talloc pools and the alignment to 16 bytes would increase the + memory footprint of each talloc chunk by those 16 bytes. +*/ + +struct talloc_pool_hdr { + void *end; + unsigned int object_count; + size_t poolsize; +}; + +union talloc_pool_hdr_cast_u { + uint8_t *ptr; + struct talloc_pool_hdr *hdr; +}; + +#define TP_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_pool_hdr)) + +static inline struct talloc_pool_hdr *talloc_pool_from_chunk(struct talloc_chunk *c) +{ + union talloc_chunk_cast_u tcc = { .chunk = c }; + union talloc_pool_hdr_cast_u tphc = { tcc.ptr - TP_HDR_SIZE }; + return tphc.hdr; +} + +static inline struct talloc_chunk *talloc_chunk_from_pool(struct talloc_pool_hdr *h) +{ + union talloc_pool_hdr_cast_u tphc = { .hdr = h }; + union talloc_chunk_cast_u tcc = { .ptr = tphc.ptr + TP_HDR_SIZE }; + return tcc.chunk; +} + +static inline void *tc_pool_end(struct talloc_pool_hdr *pool_hdr) +{ + struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr); + return (char *)tc + TC_HDR_SIZE + pool_hdr->poolsize; +} + +static inline size_t tc_pool_space_left(struct talloc_pool_hdr *pool_hdr) +{ + return (char *)tc_pool_end(pool_hdr) - (char *)pool_hdr->end; +} + +/* If tc is inside a pool, this gives the next neighbour. */ +static inline void *tc_next_chunk(struct talloc_chunk *tc) +{ + return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size); +} + +static inline void *tc_pool_first_chunk(struct talloc_pool_hdr *pool_hdr) +{ + struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr); + return tc_next_chunk(tc); +} + +/* Mark the whole remaining pool as not accessable */ +static inline void tc_invalidate_pool(struct talloc_pool_hdr *pool_hdr) +{ + size_t flen = tc_pool_space_left(pool_hdr); + + if (unlikely(talloc_fill.enabled)) { + memset(pool_hdr->end, talloc_fill.fill_value, flen); + } + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) + VALGRIND_MAKE_MEM_NOACCESS(pool_hdr->end, flen); +#endif +} + +/* + Allocate from a pool +*/ + +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; + union talloc_chunk_cast_u tcc; + size_t space_left; + struct talloc_chunk *result; + size_t chunk_size; + + if (parent == NULL) { + return NULL; + } + + if (parent->flags & TALLOC_FLAG_POOL) { + pool_hdr = talloc_pool_from_chunk(parent); + } + else if (parent->flags & TALLOC_FLAG_POOLMEM) { + pool_hdr = parent->pool; + } + + if (pool_hdr == NULL) { + return NULL; + } + + space_left = tc_pool_space_left(pool_hdr); + + /* + * Align size to 16 bytes + */ + chunk_size = TC_ALIGN16(size + prefix_len); + + if (space_left < chunk_size) { + return NULL; + } + + tcc = (union talloc_chunk_cast_u) { + .ptr = ((uint8_t *)pool_hdr->end) + prefix_len + }; + result = tcc.chunk; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, chunk_size); +#endif + + pool_hdr->end = (void *)((char *)pool_hdr->end + chunk_size); + + result->flags = talloc_magic | TALLOC_FLAG_POOLMEM; + result->pool = pool_hdr; + + pool_hdr->object_count++; + + return result; +} + +/* + 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, + 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; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + if (unlikely(total_len < TC_HDR_SIZE)) { + return NULL; + } + + if (likely(context != NULL)) { + parent = talloc_chunk_from_ptr(context); + + if (parent->limit != NULL) { + limit = parent->limit; + } + + tc = tc_alloc_pool(parent, TC_HDR_SIZE+size, prefix_len); + } + + if (tc == NULL) { + uint8_t *ptr = NULL; + union talloc_chunk_cast_u tcc; + + /* + * Only do the memlimit check/update on actual allocation. + */ + if (!talloc_memlimit_check(limit, total_len)) { + errno = ENOMEM; + return NULL; + } + + ptr = malloc(total_len); + if (unlikely(ptr == NULL)) { + return NULL; + } + tcc = (union talloc_chunk_cast_u) { .ptr = ptr + prefix_len }; + tc = tcc.chunk; + tc->flags = talloc_magic; + tc->pool = NULL; + + talloc_memlimit_grow(limit, total_len); + } + + tc->limit = limit; + tc->size = size; + tc->destructor = NULL; + tc->child = NULL; + tc->name = NULL; + tc->refs = NULL; + + if (likely(context != NULL)) { + if (parent->child) { + parent->child->parent = NULL; + tc->next = parent->child; + tc->next->prev = tc; + } else { + tc->next = NULL; + } + tc->parent = parent; + tc->prev = NULL; + parent->child = tc; + } else { + 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, + struct talloc_chunk **tc) +{ + return __talloc_with_prefix(context, size, 0, tc); +} + +/* + * Create a talloc pool + */ + +static inline void *_talloc_pool(const void *context, size_t size) +{ + struct talloc_chunk *tc; + struct talloc_pool_hdr *pool_hdr; + void *result; + + result = __talloc_with_prefix(context, size, TP_HDR_SIZE, &tc); + + if (unlikely(result == NULL)) { + return NULL; + } + + pool_hdr = talloc_pool_from_chunk(tc); + + tc->flags |= TALLOC_FLAG_POOL; + tc->size = 0; + + pool_hdr->object_count = 1; + pool_hdr->end = result; + pool_hdr->poolsize = size; + + tc_invalidate_pool(pool_hdr); + + return result; +} + +_PUBLIC_ void *talloc_pool(const void *context, size_t size) +{ + return _talloc_pool(context, size); +} + +/* + * Create a talloc pool correctly sized for a basic size plus + * a number of subobjects whose total size is given. Essentially + * a custom allocator for talloc to reduce fragmentation. + */ + +_PUBLIC_ void *_talloc_pooled_object(const void *ctx, + size_t type_size, + const char *type_name, + unsigned num_subobjects, + size_t total_subobjects_size) +{ + size_t poolsize, subobjects_slack, tmp; + struct talloc_chunk *tc; + struct talloc_pool_hdr *pool_hdr; + void *ret; + + poolsize = type_size + total_subobjects_size; + + if ((poolsize < type_size) || (poolsize < total_subobjects_size)) { + goto overflow; + } + + if (num_subobjects == UINT_MAX) { + goto overflow; + } + num_subobjects += 1; /* the object body itself */ + + /* + * Alignment can increase the pool size by at most 15 bytes per object + * plus alignment for the object itself + */ + subobjects_slack = (TC_HDR_SIZE + TP_HDR_SIZE + 15) * num_subobjects; + if (subobjects_slack < num_subobjects) { + goto overflow; + } + + tmp = poolsize + subobjects_slack; + if ((tmp < poolsize) || (tmp < subobjects_slack)) { + goto overflow; + } + poolsize = tmp; + + ret = _talloc_pool(ctx, poolsize); + if (ret == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ret); + tc->size = type_size; + + pool_hdr = talloc_pool_from_chunk(tc); + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, type_size); +#endif + + pool_hdr->end = ((char *)pool_hdr->end + TC_ALIGN16(type_size)); + + _tc_set_name_const(tc, type_name); + return ret; + +overflow: + return NULL; +} + +/* + setup a destructor to be called on free of a pointer + the destructor should return 0 on success, or -1 on failure. + if the destructor fails then the free is failed, and the memory can + be continued to be used +*/ +_PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->destructor = destructor; +} + +/* + increase the reference count on a piece of memory. +*/ +_PUBLIC_ int talloc_increase_ref_count(const void *ptr) +{ + if (unlikely(!talloc_reference(null_context, ptr))) { + return -1; + } + return 0; +} + +/* + helper for talloc_reference() + + this is referenced by a function pointer and should not be inline +*/ +static int talloc_reference_destructor(struct talloc_reference_handle *handle) +{ + struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr); + _TLIST_REMOVE(ptr_tc->refs, handle); + return 0; +} + +/* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +static inline void _tc_set_name_const(struct talloc_chunk *tc, + const char *name) +{ + tc->name = name; +} + +/* + internal talloc_named_const() +*/ +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, &tc); + if (unlikely(ptr == NULL)) { + return NULL; + } + + _tc_set_name_const(tc, name); + + return ptr; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +_PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *handle; + if (unlikely(ptr == NULL)) return NULL; + + tc = talloc_chunk_from_ptr(ptr); + handle = (struct talloc_reference_handle *)_talloc_named_const(context, + sizeof(struct talloc_reference_handle), + TALLOC_MAGIC_REFERENCE); + if (unlikely(handle == NULL)) return NULL; + + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + handle->ptr = discard_const_p(void, ptr); + handle->location = location; + _TLIST_ADD(tc->refs, handle); + return handle->ptr; +} + +static void *_talloc_steal_internal(const void *new_ctx, const void *ptr); + +static inline void _tc_free_poolmem(struct talloc_chunk *tc, + const char *location) +{ + struct talloc_pool_hdr *pool; + struct talloc_chunk *pool_tc; + void *next_tc; + + pool = tc->pool; + pool_tc = talloc_chunk_from_pool(pool); + next_tc = tc_next_chunk(tc); + + _talloc_chunk_set_free(tc, location); + + TC_INVALIDATE_FULL_CHUNK(tc); + + if (unlikely(pool->object_count == 0)) { + talloc_abort("Pool object count zero!"); + return; + } + + pool->object_count--; + + if (unlikely(pool->object_count == 1 + && !(pool_tc->flags & TALLOC_FLAG_FREE))) { + /* + * if there is just one object left in the pool + * and pool->flags does not have TALLOC_FLAG_FREE, + * it means this is the pool itself and + * the rest is available for new objects + * again. + */ + pool->end = tc_pool_first_chunk(pool); + tc_invalidate_pool(pool); + return; + } + + if (unlikely(pool->object_count == 0)) { + /* + * we mark the freed memory with where we called the free + * from. This means on a double free error we can report where + * the first free came from + */ + pool_tc->name = location; + + if (pool_tc->flags & TALLOC_FLAG_POOLMEM) { + _tc_free_poolmem(pool_tc, location); + } else { + /* + * The tc_memlimit_update_on_free() + * call takes into account the + * prefix TP_HDR_SIZE allocated before + * the pool talloc_chunk. + */ + tc_memlimit_update_on_free(pool_tc); + TC_INVALIDATE_FULL_CHUNK(pool_tc); + free(pool); + } + return; + } + + if (pool->end == next_tc) { + /* + * if pool->pool still points to end of + * 'tc' (which is stored in the 'next_tc' variable), + * we can reclaim the memory of 'tc'. + */ + pool->end = tc; + return; + } + + /* + * Do nothing. The memory is just "wasted", waiting for the pool + * itself to be freed. + */ +} + +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 free call that takes a struct talloc_chunk *. +*/ +static inline int _tc_free_internal(struct talloc_chunk *tc, + const char *location) +{ + void *ptr_to_free; + void *ptr = TC_PTR_FROM_CHUNK(tc); + + if (unlikely(tc->refs)) { + int is_child; + /* check if this is a reference from a child or + * grandchild back to it's parent or grandparent + * + * in that case we need to remove the reference and + * call another instance of talloc_free() on the current + * pointer. + */ + is_child = talloc_is_parent(tc->refs, ptr); + _talloc_free_internal(tc->refs, location); + if (is_child) { + return _talloc_free_internal(ptr, location); + } + return -1; + } + + if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) { + /* we have a free loop - stop looping */ + return 0; + } + + 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; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + /* + * Only replace the destructor pointer if + * calling the destructor didn't modify it. + */ + if (tc->destructor == (talloc_destructor_t)-1) { + tc->destructor = d; + } + return -1; + } + tc->destructor = NULL; + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + tc->prev = tc->next = NULL; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + _tc_free_children_internal(tc, ptr, location); + + _talloc_chunk_set_free(tc, location); + + if (tc->flags & TALLOC_FLAG_POOL) { + struct talloc_pool_hdr *pool; + + pool = talloc_pool_from_chunk(tc); + + if (unlikely(pool->object_count == 0)) { + talloc_abort("Pool object count zero!"); + return 0; + } + + pool->object_count--; + + if (likely(pool->object_count != 0)) { + return 0; + } + + /* + * With object_count==0, a pool becomes a normal piece of + * memory to free. If it's allocated inside a pool, it needs + * to be freed as poolmem, else it needs to be just freed. + */ + ptr_to_free = pool; + } else { + ptr_to_free = tc; + } + + if (tc->flags & TALLOC_FLAG_POOLMEM) { + _tc_free_poolmem(tc, location); + return 0; + } + + 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); + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +static void *_talloc_steal_internal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + size_t ctx_size = 0; + + if (unlikely(!ptr)) { + return NULL; + } + + if (unlikely(new_ctx == NULL)) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->limit != NULL) { + + ctx_size = _talloc_total_limit_size(ptr, NULL, NULL); + + /* Decrement the memory limit from the source .. */ + talloc_memlimit_shrink(tc->limit->upper, ctx_size); + + if (tc->limit->parent == tc) { + tc->limit->upper = NULL; + } else { + tc->limit = NULL; + } + } + + if (unlikely(new_ctx == NULL)) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (unlikely(tc == new_tc || tc->parent == new_tc)) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + tc->prev = tc->next = NULL; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + if (tc->limit || new_tc->limit) { + ctx_size = _talloc_total_limit_size(ptr, tc->limit, + new_tc->limit); + /* .. and increment it in the destination. */ + if (new_tc->limit) { + talloc_memlimit_grow(new_tc->limit, ctx_size); + } + } + + return discard_const_p(void, ptr); +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +_PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) { + struct talloc_reference_handle *h; + + talloc_log("WARNING: talloc_steal with references at %s\n", + location); + + for (h=tc->refs; h; h=h->next) { + talloc_log("\treference at %s\n", + h->location); + } + } + +#if 0 + /* this test is probably too expensive to have on in the + normal build, but it useful for debugging */ + if (talloc_is_parent(new_ctx, ptr)) { + talloc_log("WARNING: stealing into talloc child at %s\n", location); + } +#endif + + return _talloc_steal_internal(new_ctx, ptr); +} + +/* + this is like a talloc_steal(), but you must supply the old + parent. This resolves the ambiguity in a talloc_steal() which is + called on a context that has more than one parent (via references) + + The old parent can be either a reference or a parent +*/ +_PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *h; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + if (old_parent == talloc_parent(ptr)) { + return _talloc_steal_internal(new_parent, ptr); + } + + tc = talloc_chunk_from_ptr(ptr); + for (h=tc->refs;h;h=h->next) { + if (talloc_parent(h) == old_parent) { + if (_talloc_steal_internal(new_parent, h) != h) { + return NULL; + } + return discard_const_p(void, ptr); + } + } + + /* it wasn't a parent */ + return NULL; +} + +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +static inline int talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (unlikely(context == NULL)) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *p = talloc_parent_chunk(h); + if (p == NULL) { + if (context == NULL) break; + } else if (TC_PTR_FROM_CHUNK(p) == context) { + break; + } + } + if (h == NULL) { + return -1; + } + + return _talloc_free_internal(h, __location__); +} + +/* + remove a specific parent context from a pointer. This is a more + controlled variant of talloc_free() +*/ +_PUBLIC_ int talloc_unlink(const void *context, void *ptr) +{ + struct talloc_chunk *tc_p, *new_p, *tc_c; + void *new_parent; + + if (ptr == NULL) { + return -1; + } + + if (context == NULL) { + context = null_context; + } + + if (talloc_unreference(context, ptr) == 0) { + return 0; + } + + if (context != NULL) { + tc_c = talloc_chunk_from_ptr(context); + } else { + tc_c = NULL; + } + if (tc_c != talloc_parent_chunk(ptr)) { + return -1; + } + + tc_p = talloc_chunk_from_ptr(ptr); + + if (tc_p->refs == NULL) { + return _talloc_free_internal(ptr, __location__); + } + + new_p = talloc_parent_chunk(tc_p->refs); + if (new_p) { + new_parent = TC_PTR_FROM_CHUNK(new_p); + } else { + new_parent = NULL; + } + + if (talloc_unreference(new_parent, ptr) != 0) { + return -1; + } + + _talloc_steal_internal(new_parent, ptr); + + return 0; +} + +/* + add a name to an existing pointer - va_list version +*/ +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 *tc_set_name_v(struct talloc_chunk *tc, + const char *fmt, + va_list ap) +{ + 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; +} + +/* + add a name to an existing pointer +*/ +_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 = tc_set_name_v(tc, fmt, ap); + va_end(ap); + return name; +} + + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +_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, &tc); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = tc_set_name_v(tc, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free_internal(ptr, __location__); + return NULL; + } + + return ptr; +} + +/* + return the name of a talloc ptr, or "UNNAMED" +*/ +static inline const char *__talloc_get_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) { + return ".reference"; + } + if (likely(tc->name)) { + return tc->name; + } + return "UNNAMED"; +} + +_PUBLIC_ const char *talloc_get_name(const void *ptr) +{ + return __talloc_get_name(ptr); +} + +/* + check if a pointer has the given name. If it does, return the pointer, + otherwise return NULL +*/ +_PUBLIC_ void *talloc_check_name(const void *ptr, const char *name) +{ + const char *pname; + if (unlikely(ptr == NULL)) return NULL; + pname = __talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + return NULL; +} + +static void talloc_abort_type_mismatch(const char *location, + const char *name, + const char *expected) +{ + const char *reason; + + reason = talloc_asprintf(NULL, + "%s: Type mismatch: name[%s] expected[%s]", + location, + name?name:"NULL", + expected); + if (!reason) { + reason = "Type mismatch"; + } + + talloc_abort(reason); +} + +_PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) +{ + const char *pname; + + if (unlikely(ptr == NULL)) { + talloc_abort_type_mismatch(location, NULL, name); + return NULL; + } + + pname = __talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + + talloc_abort_type_mismatch(location, pname, name); + return NULL; +} + +/* + this is for compatibility with older versions of talloc +*/ +_PUBLIC_ void *talloc_init(const char *fmt, ...) +{ + va_list ap; + void *ptr; + const char *name; + struct talloc_chunk *tc; + + ptr = __talloc(NULL, 0, &tc); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = tc_set_name_v(tc, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free_internal(ptr, __location__); + return NULL; + } + + return ptr; +} + +static inline void _tc_free_children_internal(struct talloc_chunk *tc, + void *ptr, + const char *location) +{ + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(_tc_free_internal(tc->child, location) == -1)) { + if (talloc_parent_chunk(child) != tc) { + /* + * Destructor already reparented this child. + * No further reparenting needed. + */ + continue; + } + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + _talloc_steal_internal(new_parent, child); + } + } +} + +/* + this is a replacement for the Samba3 talloc_destroy_pool functionality. It + should probably not be used in new code. It's in here to keep the talloc + code consistent across Samba 3 and 4. +*/ +_PUBLIC_ void talloc_free_children(void *ptr) +{ + struct talloc_chunk *tc_name = NULL; + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return; + } + + tc = talloc_chunk_from_ptr(ptr); + + /* we do not want to free the context name if it is a child .. */ + if (likely(tc->child)) { + for (tc_name = tc->child; tc_name; tc_name = tc_name->next) { + if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break; + } + if (tc_name) { + _TLIST_REMOVE(tc->child, tc_name); + if (tc->child) { + tc->child->parent = tc; + } + } + } + + _tc_free_children_internal(tc, ptr, __location__); + + /* .. so we put it back after all other children have been freed */ + if (tc_name) { + if (tc->child) { + tc->child->parent = NULL; + } + tc_name->parent = tc; + _TLIST_ADD(tc->child, tc_name); + } +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +_PUBLIC_ void *_talloc(const void *context, size_t size) +{ + struct talloc_chunk *tc; + return __talloc(context, size, &tc); +} + +/* + externally callable talloc_set_name_const() +*/ +_PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name) +{ + _tc_set_name_const(talloc_chunk_from_ptr(ptr), name); +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +_PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name) +{ + return _talloc_named_const(context, size, name); +} + +/* + free a talloc pointer. This also frees all child pointers of this + pointer recursively + + return 0 if the memory is actually freed, otherwise -1. The memory + will not be freed if the ref_count is > 1 or the destructor (if + any) returns non-zero +*/ +_PUBLIC_ int _talloc_free(void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs != NULL)) { + struct talloc_reference_handle *h; + + if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) { + /* in this case we do know which parent should + get this pointer, as there is really only + one parent */ + return talloc_unlink(null_context, ptr); + } + + talloc_log("ERROR: talloc_free with references at %s\n", + location); + + for (h=tc->refs; h; h=h->next) { + talloc_log("\treference at %s\n", + h->location); + } + return -1; + } + + return _talloc_free_internal(ptr, location); +} + + + +/* + A talloc version of realloc. The context argument is only used if + ptr is NULL +*/ +_PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) +{ + struct talloc_chunk *tc; + void *new_ptr; + bool malloced = false; + struct talloc_pool_hdr *pool_hdr = NULL; + size_t old_size = 0; + size_t new_size = 0; + + /* size zero is equivalent to free() */ + if (unlikely(size == 0)) { + talloc_unlink(context, ptr); + return NULL; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + /* realloc(NULL) is equivalent to malloc() */ + if (ptr == NULL) { + return _talloc_named_const(context, size, name); + } + + tc = talloc_chunk_from_ptr(ptr); + + /* don't allow realloc on referenced pointers */ + if (unlikely(tc->refs)) { + return NULL; + } + + /* don't let anybody try to realloc a talloc_pool */ + if (unlikely(tc->flags & TALLOC_FLAG_POOL)) { + return NULL; + } + + if (tc->limit && (size > tc->size)) { + if (!talloc_memlimit_check(tc->limit, (size - tc->size))) { + errno = ENOMEM; + return NULL; + } + } + + /* handle realloc inside a talloc_pool */ + if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) { + pool_hdr = tc->pool; + } + +#if (ALWAYS_REALLOC == 0) + /* don't shrink if we have less than 1k to gain */ + if (size < tc->size && tc->limit == NULL) { + if (pool_hdr) { + void *next_tc = tc_next_chunk(tc); + TC_INVALIDATE_SHRINK_CHUNK(tc, size); + tc->size = size; + if (next_tc == pool_hdr->end) { + /* note: tc->size has changed, so this works */ + pool_hdr->end = tc_next_chunk(tc); + } + return ptr; + } else if ((tc->size - size) < 1024) { + /* + * if we call TC_INVALIDATE_SHRINK_CHUNK() here + * we would need to call TC_UNDEFINE_GROW_CHUNK() + * after each realloc call, which slows down + * testing a lot :-(. + * + * That is why we only mark memory as undefined here. + */ + TC_UNDEFINE_SHRINK_CHUNK(tc, size); + + /* do not shrink if we have less than 1k to gain */ + tc->size = size; + return ptr; + } + } else if (tc->size == size) { + /* + * do not change the pointer if it is exactly + * the same size. + */ + return ptr; + } +#endif + + /* + * by resetting magic we catch users of the old memory + * + * We mark this memory as free, and also over-stamp the talloc + * magic with the old-style magic. + * + * Why? This tries to avoid a memory read use-after-free from + * disclosing our talloc magic, which would then allow an + * attacker to prepare a valid header and so run a destructor. + * + * What else? We have to re-stamp back a valid normal magic + * on this memory once realloc() is done, as it will have done + * a memcpy() into the new valid memory. We can't do this in + * reverse as that would be a real use-after-free. + */ + _talloc_chunk_set_free(tc, NULL); + +#if ALWAYS_REALLOC + if (pool_hdr) { + new_ptr = tc_alloc_pool(tc, size + TC_HDR_SIZE, 0); + pool_hdr->object_count--; + + if (new_ptr == NULL) { + new_ptr = malloc(TC_HDR_SIZE+size); + malloced = true; + new_size = size; + } + + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + TC_INVALIDATE_FULL_CHUNK(tc); + } + } else { + /* We're doing malloc then free here, so record the difference. */ + old_size = tc->size; + new_size = size; + new_ptr = malloc(size + TC_HDR_SIZE); + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE); + free(tc); + } + } +#else + if (pool_hdr) { + struct talloc_chunk *pool_tc; + void *next_tc = tc_next_chunk(tc); + size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size); + size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size); + size_t space_needed; + size_t space_left; + unsigned int chunk_count = pool_hdr->object_count; + + pool_tc = talloc_chunk_from_pool(pool_hdr); + if (!(pool_tc->flags & TALLOC_FLAG_FREE)) { + chunk_count -= 1; + } + + if (chunk_count == 1) { + /* + * optimize for the case where 'tc' is the only + * chunk in the pool. + */ + char *start = tc_pool_first_chunk(pool_hdr); + space_needed = new_chunk_size; + space_left = (char *)tc_pool_end(pool_hdr) - start; + + if (space_left >= space_needed) { + size_t old_used = TC_HDR_SIZE + tc->size; + size_t new_used = TC_HDR_SIZE + size; + new_ptr = start; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + { + /* + * The area from + * start -> tc may have + * been freed and thus been marked as + * VALGRIND_MEM_NOACCESS. Set it to + * VALGRIND_MEM_UNDEFINED so we can + * copy into it without valgrind errors. + * We can't just mark + * new_ptr -> new_ptr + old_used + * as this may overlap on top of tc, + * (which is why we use memmove, not + * memcpy below) hence the MIN. + */ + size_t undef_len = MIN((((char *)tc) - ((char *)new_ptr)),old_used); + VALGRIND_MAKE_MEM_UNDEFINED(new_ptr, undef_len); + } +#endif + + memmove(new_ptr, tc, old_used); + + tc = (struct talloc_chunk *)new_ptr; + TC_UNDEFINE_GROW_CHUNK(tc, size); + + /* + * first we do not align the pool pointer + * because we want to invalidate the padding + * too. + */ + pool_hdr->end = new_used + (char *)new_ptr; + tc_invalidate_pool(pool_hdr); + + /* now the aligned pointer */ + pool_hdr->end = new_chunk_size + (char *)new_ptr; + goto got_new_ptr; + } + + next_tc = NULL; + } + + if (new_chunk_size == old_chunk_size) { + TC_UNDEFINE_GROW_CHUNK(tc, size); + _talloc_chunk_set_not_free(tc); + tc->size = size; + return ptr; + } + + if (next_tc == pool_hdr->end) { + /* + * optimize for the case where 'tc' is the last + * chunk in the pool. + */ + space_needed = new_chunk_size - old_chunk_size; + space_left = tc_pool_space_left(pool_hdr); + + if (space_left >= space_needed) { + TC_UNDEFINE_GROW_CHUNK(tc, size); + _talloc_chunk_set_not_free(tc); + tc->size = size; + pool_hdr->end = tc_next_chunk(tc); + return ptr; + } + } + + new_ptr = tc_alloc_pool(tc, size + TC_HDR_SIZE, 0); + + if (new_ptr == NULL) { + new_ptr = malloc(TC_HDR_SIZE+size); + malloced = true; + new_size = size; + } + + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + + _tc_free_poolmem(tc, __location__ "_talloc_realloc"); + } + } + else { + /* We're doing realloc here, so record the difference. */ + old_size = tc->size; + new_size = size; + new_ptr = realloc(tc, size + TC_HDR_SIZE); + } +got_new_ptr: +#endif + if (unlikely(!new_ptr)) { + /* + * Ok, this is a strange spot. We have to put back + * the old talloc_magic and any flags, except the + * TALLOC_FLAG_FREE as this was not free'ed by the + * realloc() call after all + */ + _talloc_chunk_set_not_free(tc); + return NULL; + } + + /* + * tc is now the new value from realloc(), the old memory we + * can't access any more and was preemptively marked as + * TALLOC_FLAG_FREE before the call. Now we mark it as not + * free again + */ + tc = (struct talloc_chunk *)new_ptr; + _talloc_chunk_set_not_free(tc); + if (malloced) { + tc->flags &= ~TALLOC_FLAG_POOLMEM; + } + if (tc->parent) { + tc->parent->child = tc; + } + if (tc->child) { + tc->child->parent = tc; + } + + if (tc->prev) { + tc->prev->next = tc; + } + if (tc->next) { + tc->next->prev = tc; + } + + if (new_size > old_size) { + talloc_memlimit_grow(tc->limit, new_size - old_size); + } else if (new_size < old_size) { + talloc_memlimit_shrink(tc->limit, old_size - new_size); + } + + tc->size = size; + _tc_set_name_const(tc, name); + + return TC_PTR_FROM_CHUNK(tc); +} + +/* + a wrapper around talloc_steal() for situations where you are moving a pointer + between two structures, and want the old pointer to be set to NULL +*/ +_PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr) +{ + const void **pptr = discard_const_p(const void *,_pptr); + void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr)); + (*pptr) = NULL; + return ret; +} + +enum talloc_mem_count_type { + TOTAL_MEM_SIZE, + TOTAL_MEM_BLOCKS, + TOTAL_MEM_LIMIT, +}; + +static inline size_t _talloc_total_mem_internal(const void *ptr, + enum talloc_mem_count_type type, + struct talloc_memlimit *old_limit, + struct talloc_memlimit *new_limit) +{ + size_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (old_limit || new_limit) { + if (tc->limit && tc->limit->upper == old_limit) { + tc->limit->upper = new_limit; + } + } + + /* optimize in the memlimits case */ + if (type == TOTAL_MEM_LIMIT && + tc->limit != NULL && + tc->limit != old_limit && + tc->limit->parent == tc) { + return tc->limit->cur_size; + } + + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + if (old_limit || new_limit) { + if (old_limit == tc->limit) { + tc->limit = new_limit; + } + } + + switch (type) { + case TOTAL_MEM_SIZE: + if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) { + total = tc->size; + } + break; + case TOTAL_MEM_BLOCKS: + total++; + break; + case TOTAL_MEM_LIMIT: + if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) { + /* + * Don't count memory allocated from a pool + * when calculating limits. Only count the + * pool itself. + */ + if (!(tc->flags & TALLOC_FLAG_POOLMEM)) { + if (tc->flags & TALLOC_FLAG_POOL) { + /* + * If this is a pool, the allocated + * size is in the pool header, and + * remember to add in the prefix + * length. + */ + struct talloc_pool_hdr *pool_hdr + = talloc_pool_from_chunk(tc); + total = pool_hdr->poolsize + + TC_HDR_SIZE + + TP_HDR_SIZE; + } else { + total = tc->size + TC_HDR_SIZE; + } + } + } + break; + } + for (c = tc->child; c; c = c->next) { + total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type, + old_limit, new_limit); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + + return total; +} + +/* + return the total size of a talloc pool (subtree) +*/ +_PUBLIC_ size_t talloc_total_size(const void *ptr) +{ + return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL); +} + +/* + return the total number of blocks in a talloc pool (subtree) +*/ +_PUBLIC_ size_t talloc_total_blocks(const void *ptr) +{ + return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL); +} + +/* + return the number of external references to a pointer +*/ +_PUBLIC_ size_t talloc_reference_count(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + size_t ret = 0; + + for (h=tc->refs;h;h=h->next) { + ret++; + } + return ret; +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +_PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data) +{ + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + callback(ptr, depth, max_depth, 0, private_data); + + if (max_depth >= 0 && depth >= max_depth) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); + callback(h->ptr, depth + 1, max_depth, 1, private_data); + } else { + talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; +} + +static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f) +{ + const char *name = __talloc_get_name(ptr); + struct talloc_chunk *tc; + FILE *f = (FILE *)_f; + + if (is_ref) { + fprintf(f, "%*sreference to: %s\n", depth*4, "", name); + return; + } + + tc = talloc_chunk_from_ptr(ptr); + if (tc->limit && tc->limit->parent == tc) { + fprintf(f, "%*s%-30s is a memlimit context" + " (max_size = %lu bytes, cur_size = %lu bytes)\n", + depth*4, "", + name, + (unsigned long)tc->limit->max_size, + (unsigned long)tc->limit->cur_size); + } + + if (depth == 0) { + fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + (int)talloc_reference_count(ptr), ptr); + +#if 0 + fprintf(f, "content: "); + if (talloc_total_size(ptr)) { + int tot = talloc_total_size(ptr); + int i; + + for (i = 0; i < tot; i++) { + if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) { + fprintf(f, "%c", ((char *)ptr)[i]); + } else { + fprintf(f, "~%02x", ((char *)ptr)[i]); + } + } + } + fprintf(f, "\n"); +#endif +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +_PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) +{ + if (f) { + talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f); + fflush(f); + } +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +_PUBLIC_ void talloc_report_full(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, -1, f); +} + +/* + report on memory usage by all children of a pointer +*/ +_PUBLIC_ void talloc_report(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, 1, f); +} + +/* + enable tracking of the NULL context +*/ +_PUBLIC_ void talloc_enable_null_tracking(void) +{ + if (null_context == NULL) { + null_context = _talloc_named_const(NULL, 0, "null_context"); + if (autofree_context != NULL) { + talloc_reparent(NULL, null_context, autofree_context); + } + } +} + +/* + enable tracking of the NULL context, not moving the autofree context + into the NULL context. This is needed for the talloc testsuite +*/ +_PUBLIC_ void talloc_enable_null_tracking_no_autofree(void) +{ + if (null_context == NULL) { + null_context = _talloc_named_const(NULL, 0, "null_context"); + } +} + +/* + disable tracking of the NULL context +*/ +_PUBLIC_ void talloc_disable_null_tracking(void) +{ + if (null_context != NULL) { + /* we have to move any children onto the real NULL + context */ + struct talloc_chunk *tc, *tc2; + tc = talloc_chunk_from_ptr(null_context); + for (tc2 = tc->child; tc2; tc2=tc2->next) { + if (tc2->parent == tc) tc2->parent = NULL; + if (tc2->prev == tc) tc2->prev = NULL; + } + for (tc2 = tc->next; tc2; tc2=tc2->next) { + if (tc2->parent == tc) tc2->parent = NULL; + if (tc2->prev == tc) tc2->prev = NULL; + } + tc->child = NULL; + tc->next = NULL; + } + talloc_free(null_context); + null_context = NULL; +} + +/* + enable leak reporting on exit +*/ +_PUBLIC_ void talloc_enable_leak_report(void) +{ + talloc_enable_null_tracking(); + talloc_report_null = true; + talloc_setup_atexit(); +} + +/* + enable full leak reporting on exit +*/ +_PUBLIC_ void talloc_enable_leak_report_full(void) +{ + talloc_enable_null_tracking(); + talloc_report_null_full = true; + talloc_setup_atexit(); +} + +/* + talloc and zero memory. +*/ +_PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name) +{ + void *p = _talloc_named_const(ctx, size, name); + + if (p) { + memset(p, '\0', size); + } + + return p; +} + +/* + memdup with a talloc. +*/ +_PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) +{ + void *newp = NULL; + + if (likely(size > 0) && unlikely(p == NULL)) { + return NULL; + } + + newp = _talloc_named_const(t, size, name); + if (likely(newp != NULL) && likely(size > 0)) { + memcpy(newp, p, size); + } + + return newp; +} + +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, &tc); + if (unlikely(!ret)) return NULL; + + memcpy(ret, p, len); + ret[len] = 0; + + _tc_set_name_const(tc, ret); + return ret; +} + +/* + strdup with a talloc +*/ +_PUBLIC_ char *talloc_strdup(const void *t, const char *p) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strlen(p)); +} + +/* + strndup with a talloc +*/ +_PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strnlen(p, n)); +} + +static inline char *__talloc_strlendup_append(char *s, size_t slen, + const char *a, size_t alen) +{ + char *ret; + + ret = talloc_realloc(NULL, s, char, slen + alen + 1); + if (unlikely(!ret)) return NULL; + + /* append the string and the trailing \0 */ + memcpy(&ret[slen], a, alen); + ret[slen+alen] = 0; + + _tc_set_name_const(talloc_chunk_from_ptr(ret), ret); + return ret; +} + +/* + * Appends at the end of the string. + */ +_PUBLIC_ char *talloc_strdup_append(char *s, const char *a) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strlen(a)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +_PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strlen(a)); +} + +/* + * Appends at the end of the string. + */ +_PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n) +{ + if (unlikely(!s)) { + return talloc_strndup(NULL, a, n); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +_PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strndup(NULL, a, n); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strnlen(a, n)); +} + +#ifndef HAVE_VA_COPY +#ifdef HAVE___VA_COPY +#define va_copy(dest, src) __va_copy(dest, src) +#else +#define va_copy(dest, src) (dest) = (src) +#endif +#endif + +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 vlen; + size_t 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 */ + va_copy(ap2, ap); + vlen = vsnprintf(buf, sizeof(buf), fmt, ap2); + va_end(ap2); + if (unlikely(vlen < 0)) { + return NULL; + } + len = vlen; + if (unlikely(len + 1 < len)) { + return NULL; + } + + ret = (char *)__talloc(t, len+1, &tc); + if (unlikely(!ret)) return NULL; + + if (len < sizeof(buf)) { + memcpy(ret, buf, len+1); + } else { + va_copy(ap2, ap); + vsnprintf(ret, len+1, fmt, ap2); + va_end(ap2); + } + + _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); +} + + +/* + Perform string formatting, and return a pointer to newly allocated + memory holding the result, inside a memory pool. + */ +_PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = talloc_vasprintf(t, fmt, ap); + va_end(ap); + return ret; +} + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) + PRINTF_ATTRIBUTE(3,0); + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) +{ + ssize_t alen; + va_list ap2; + char c; + + va_copy(ap2, ap); + alen = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + + if (alen <= 0) { + /* Either the vsnprintf failed or the format resulted in + * no characters being formatted. In the former case, we + * ought to return NULL, in the latter we ought to return + * the original string. Most current callers of this + * function expect it to never return NULL. + */ + return s; + } + + s = talloc_realloc(NULL, s, char, slen + alen + 1); + if (!s) return NULL; + + va_copy(ap2, ap); + vsnprintf(s + slen, alen + 1, fmt, ap2); + va_end(ap2); + + _tc_set_name_const(talloc_chunk_from_ptr(s), s); + return s; +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Good for gradually + * accumulating output into a string buffer. Appends at the end + * of the string. + **/ +_PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +{ + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap); +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Always appends at the + * end of the talloc'ed buffer, not the end of the string. + **/ +_PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_vaslenprintf_append(s, slen, fmt, ap); +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a string buffer. + */ +_PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append(s, fmt, ap); + va_end(ap); + return s; +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a buffer. + */ +_PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append_buffer(s, fmt, ap); + va_end(ap); + return s; +} + +/* + alloc an array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_named_const(ctx, el_size * count, name); +} + +/* + alloc an zero array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_zero(ctx, el_size * count, name); +} + +/* + realloc an array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_realloc(ctx, ptr, el_size * count, name); +} + +/* + a function version of talloc_realloc(), so it can be passed as a function pointer + to libraries that want a realloc function (a realloc function encapsulates + all the basic capabilities of an allocation library, which is why this is useful) +*/ +_PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size) +{ + return _talloc_realloc(context, ptr, size, NULL); +} + + +static int talloc_autofree_destructor(void *ptr) +{ + autofree_context = NULL; + return 0; +} + +/* + return a context which will be auto-freed on exit + this is useful for reducing the noise in leak reports +*/ +_PUBLIC_ void *talloc_autofree_context(void) +{ + if (autofree_context == NULL) { + autofree_context = _talloc_named_const(NULL, 0, "autofree_context"); + talloc_set_destructor(autofree_context, talloc_autofree_destructor); + talloc_setup_atexit(); + } + return autofree_context; +} + +_PUBLIC_ size_t talloc_get_size(const void *context) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(context); + + return tc->size; +} + +/* + find a parent of this context that has the given name, if any +*/ +_PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return TC_PTR_FROM_CHUNK(tc); + } + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + return NULL; +} + +/* + show the parentage of a context +*/ +_PUBLIC_ void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", __talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", __talloc_get_name(TC_PTR_FROM_CHUNK(tc))); + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + fflush(file); +} + +/* + return 1 if ptr is a parent of context +*/ +static int _talloc_is_parent(const void *context, const void *ptr, int depth) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (depth <= 0) { + return 0; + } + if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1; + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + depth--; + } + } + return 0; +} + +/* + return 1 if ptr is a parent of context +*/ +_PUBLIC_ int talloc_is_parent(const void *context, const void *ptr) +{ + return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH); +} + +/* + return the total size of memory used by this context and all children +*/ +static inline size_t _talloc_total_limit_size(const void *ptr, + struct talloc_memlimit *old_limit, + struct talloc_memlimit *new_limit) +{ + return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT, + old_limit, new_limit); +} + +static inline bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size) +{ + struct talloc_memlimit *l; + + for (l = limit; l != NULL; l = l->upper) { + if (l->max_size != 0 && + ((l->max_size <= l->cur_size) || + (l->max_size - l->cur_size < size))) { + return false; + } + } + + return true; +} + +/* + Update memory limits when freeing a talloc_chunk. +*/ +static void tc_memlimit_update_on_free(struct talloc_chunk *tc) +{ + size_t limit_shrink_size; + + if (!tc->limit) { + return; + } + + /* + * Pool entries don't count. Only the pools + * themselves are counted as part of the memory + * limits. Note that this also takes care of + * nested pools which have both flags + * TALLOC_FLAG_POOLMEM|TALLOC_FLAG_POOL set. + */ + if (tc->flags & TALLOC_FLAG_POOLMEM) { + return; + } + + /* + * If we are part of a memory limited context hierarchy + * we need to subtract the memory used from the counters + */ + + limit_shrink_size = tc->size+TC_HDR_SIZE; + + /* + * If we're deallocating a pool, take into + * account the prefix size added for the pool. + */ + + if (tc->flags & TALLOC_FLAG_POOL) { + limit_shrink_size += TP_HDR_SIZE; + } + + talloc_memlimit_shrink(tc->limit, limit_shrink_size); + + if (tc->limit->parent == tc) { + free(tc->limit); + } + + tc->limit = NULL; +} + +/* + Increase memory limit accounting after a malloc/realloc. +*/ +static void talloc_memlimit_grow(struct talloc_memlimit *limit, + size_t size) +{ + struct talloc_memlimit *l; + + for (l = limit; l != NULL; l = l->upper) { + size_t new_cur_size = l->cur_size + size; + if (new_cur_size < l->cur_size) { + talloc_abort("logic error in talloc_memlimit_grow\n"); + return; + } + l->cur_size = new_cur_size; + } +} + +/* + Decrease memory limit accounting after a free/realloc. +*/ +static void talloc_memlimit_shrink(struct talloc_memlimit *limit, + size_t size) +{ + struct talloc_memlimit *l; + + for (l = limit; l != NULL; l = l->upper) { + if (l->cur_size < size) { + talloc_abort("logic error in talloc_memlimit_shrink\n"); + return; + } + l->cur_size = l->cur_size - size; + } +} + +_PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx); + struct talloc_memlimit *orig_limit; + struct talloc_memlimit *limit = NULL; + + if (tc->limit && tc->limit->parent == tc) { + tc->limit->max_size = max_size; + return 0; + } + orig_limit = tc->limit; + + limit = malloc(sizeof(struct talloc_memlimit)); + if (limit == NULL) { + return 1; + } + limit->parent = tc; + limit->max_size = max_size; + limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit); + + if (orig_limit) { + limit->upper = orig_limit; + } else { + limit->upper = NULL; + } + + return 0; +} diff --git a/ldb-2.0.8/lib/talloc/talloc.h b/ldb-2.0.8/lib/talloc/talloc.h new file mode 100644 index 0000000..34fe772 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/talloc.h @@ -0,0 +1,1945 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup talloc The talloc API + * + * talloc is a hierarchical, reference counted memory pool system with + * destructors. It is the core memory allocator used in Samba. + * + * @{ + */ + +#define TALLOC_VERSION_MAJOR 2 +#define TALLOC_VERSION_MINOR 2 + +int talloc_version_major(void); +int talloc_version_minor(void); +/* This is mostly useful only for testing */ +int talloc_test_get_magic(void); + +/** + * @brief Define a talloc parent type + * + * As talloc is a hierarchial memory allocator, every talloc chunk is a + * potential parent to other talloc chunks. So defining a separate type for a + * talloc chunk is not strictly necessary. TALLOC_CTX is defined nevertheless, + * as it provides an indicator for function arguments. You will frequently + * write code like + * + * @code + * struct foo *foo_create(TALLOC_CTX *mem_ctx) + * { + * struct foo *result; + * result = talloc(mem_ctx, struct foo); + * if (result == NULL) return NULL; + * ... initialize foo ... + * return result; + * } + * @endcode + * + * In this type of allocating functions it is handy to have a general + * TALLOC_CTX type to indicate which parent to put allocated structures on. + */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#ifndef __location__ +#define __TALLOC_STRING_LINE1__(s) #s +#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s) +#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__) +#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__ +#endif + +#ifndef TALLOC_DEPRECATED +#define TALLOC_DEPRECATED 0 +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** 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 + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#ifndef _DEPRECATED_ +#ifdef HAVE___ATTRIBUTE__ +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif +#ifdef DOXYGEN + +/** + * @brief Create a new talloc context. + * + * The talloc() macro is the core of the talloc library. It takes a memory + * context and a type, and returns a pointer to a new area of memory of the + * given type. + * + * The returned pointer is itself a talloc context, so you can use it as the + * context argument to more calls to talloc if you wish. + * + * The returned pointer is a "child" of the supplied context. This means that if + * you talloc_free() the context then the new child disappears as well. + * Alternatively you can free just the child. + * + * @param[in] ctx A talloc context to create a new reference on or NULL to + * create a new top level context. + * + * @param[in] type The type of memory to allocate. + * + * @return A type casted talloc context or NULL on error. + * + * @code + * unsigned int *a, *b; + * + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * @endcode + * + * @see talloc_zero + * @see talloc_array + * @see talloc_steal + * @see talloc_free + */ +void *talloc(const void *ctx, #type); +#else +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +void *_talloc(const void *context, size_t size); +#endif + +/** + * @brief Create a new top level talloc context. + * + * This function creates a zero length named talloc context as a top level + * context. It is equivalent to: + * + * @code + * talloc_named(NULL, 0, fmt, ...); + * @endcode + * @param[in] fmt Format string for the name. + * + * @param[in] ... Additional printf-style arguments. + * + * @return The allocated memory chunk, NULL on error. + * + * @see talloc_named() + */ +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); + +#ifdef DOXYGEN +/** + * @brief Free a chunk of talloc memory. + * + * The talloc_free() function frees a piece of talloc memory, and all its + * children. You can call talloc_free() on any pointer returned by + * talloc(). + * + * The return value of talloc_free() indicates success or failure, with 0 + * returned for success and -1 for failure. A possible failure condition + * is if the pointer had a destructor attached to it and the destructor + * returned -1. See talloc_set_destructor() for details on + * destructors. Likewise, if "ptr" is NULL, then the function will make + * no modifications and return -1. + * + * From version 2.0 and onwards, as a special case, talloc_free() is + * refused on pointers that have more than one parent associated, as talloc + * would have no way of knowing which parent should be removed. This is + * different from older versions in the sense that always the reference to + * the most recently established parent has been destroyed. Hence to free a + * pointer that has more than one parent please use talloc_unlink(). + * + * To help you find problems in your code caused by this behaviour, if + * you do try and free a pointer with more than one parent then the + * talloc logging function will be called to give output like this: + * + * @code + * ERROR: talloc_free with references at some_dir/source/foo.c:123 + * reference at some_dir/source/other.c:325 + * reference at some_dir/source/third.c:121 + * @endcode + * + * Please see the documentation for talloc_set_log_fn() and + * talloc_set_log_stderr() for more information on talloc logging + * functions. + * + * If TALLOC_FREE_FILL environment variable is set, + * the memory occupied by the context is filled with the value of this variable. + * The value should be a numeric representation of the character you want to + * use. + * + * talloc_free() operates recursively on its children. + * + * @param[in] ptr The chunk to be freed. + * + * @return Returns 0 on success and -1 on error. A possible + * failure condition is if the pointer had a destructor + * attached to it and the destructor returned -1. Likewise, + * if "ptr" is NULL, then the function will make no + * modifications and returns -1. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * + * talloc_free(a); // Frees a and b + * @endcode + * + * @see talloc_set_destructor() + * @see talloc_unlink() + */ +int talloc_free(void *ptr); +#else +#define talloc_free(ctx) _talloc_free(ctx, __location__) +int _talloc_free(void *ptr, const char *location); +#endif + +/** + * @brief Free a talloc chunk's children. + * + * The function walks along the list of all children of a talloc context and + * talloc_free()s only the children, not the context itself. + * + * A NULL argument is handled as no-op. + * + * @param[in] ptr The chunk that you want to free the children of + * (NULL is allowed too) + */ +void talloc_free_children(void *ptr); + +#ifdef DOXYGEN +/** + * @brief Assign a destructor function to be called when a chunk is freed. + * + * The function talloc_set_destructor() sets the "destructor" for the pointer + * "ptr". A destructor is a function that is called when the memory used by a + * pointer is about to be released. The destructor receives the pointer as an + * argument, and should return 0 for success and -1 for failure. + * + * The destructor can do anything it wants to, including freeing other pieces + * of memory. A common use for destructors is to clean up operating system + * resources (such as open file descriptors) contained in the structure the + * destructor is placed on. + * + * You can only place one destructor on a pointer. If you need more than one + * destructor then you can create a zero-length child of the pointer and place + * an additional destructor on that. + * + * To remove a destructor call talloc_set_destructor() with NULL for the + * destructor. + * + * If your destructor attempts to talloc_free() the pointer that it is the + * destructor for then talloc_free() will return -1 and the free will be + * ignored. This would be a pointless operation anyway, as the destructor is + * only called when the memory is just about to go away. + * + * @param[in] ptr The talloc chunk to add a destructor to. + * + * @param[in] destructor The destructor function to be called. NULL to remove + * it. + * + * Example: + * @code + * static int destroy_fd(int *fd) { + * close(*fd); + * return 0; + * } + * + * int *open_file(const char *filename) { + * int *fd = talloc(NULL, int); + * *fd = open(filename, O_RDONLY); + * if (*fd < 0) { + * talloc_free(fd); + * return NULL; + * } + * // Whenever they free this, we close the file. + * talloc_set_destructor(fd, destroy_fd); + * return fd; + * } + * @endcode + * + * @see talloc() + * @see talloc_free() + */ +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); + +/** + * @brief Change a talloc chunk's parent. + * + * The talloc_steal() function changes the parent context of a talloc + * pointer. It is typically used when the context that the pointer is + * currently a child of is going to be freed and you wish to keep the + * memory for a longer time. + * + * To make the changed hierarchy less error-prone, you might consider to use + * talloc_move(). + * + * If you try and call talloc_steal() on a pointer that has more than one + * parent then the result is ambiguous. Talloc will choose to remove the + * parent that is currently indicated by talloc_parent() and replace it with + * the chosen parent. You will also get a message like this via the talloc + * logging functions: + * + * @code + * WARNING: talloc_steal with references at some_dir/source/foo.c:123 + * reference at some_dir/source/other.c:325 + * reference at some_dir/source/third.c:121 + * @endcode + * + * To unambiguously change the parent of a pointer please see the function + * talloc_reparent(). See the talloc_set_log_fn() documentation for more + * information on talloc logging. + * + * @param[in] new_ctx The new parent context. + * + * @param[in] ptr The talloc chunk to move. + * + * @return Returns the pointer that you pass it. It does not have + * any failure modes. + * + * @note It is possible to produce loops in the parent/child relationship + * if you are not careful with talloc_steal(). No guarantees are provided + * as to your sanity or the safety of your data if you do this. + */ +void *talloc_steal(const void *new_ctx, const void *ptr); +#else /* DOXYGEN */ +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ + _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ + } while(0) +/* this extremely strange macro is to avoid some braindamaged warning + stupidity in gcc 4.1.x */ +#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; }) +#else /* __GNUC__ >= 3 */ +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__) +#endif /* __GNUC__ >= 3 */ +void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); +void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location); +#endif /* DOXYGEN */ + +/** + * @brief Assign a name to a talloc chunk. + * + * Each talloc pointer has a "name". The name is used principally for + * debugging purposes, although it is also possible to set and get the name on + * a pointer in as a way of "marking" pointers in your code. + * + * The main use for names on pointer is for "talloc reports". See + * talloc_report() and talloc_report_full() for details. Also see + * talloc_enable_leak_report() and talloc_enable_leak_report_full(). + * + * The talloc_set_name() function allocates memory as a child of the + * pointer. It is logically equivalent to: + * + * @code + * talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); + * @endcode + * + * @param[in] ptr The talloc chunk to assign a name to. + * + * @param[in] fmt Format string for the name. + * + * @param[in] ... Add printf-style additional arguments. + * + * @return The assigned name, NULL on error. + * + * @note Multiple calls to talloc_set_name() will allocate more memory without + * releasing the name. All of the memory is released when the ptr is freed + * using talloc_free(). + */ +const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +#ifdef DOXYGEN +/** + * @brief Change a talloc chunk's parent. + * + * This function has the same effect as talloc_steal(), and additionally sets + * the source pointer to NULL. You would use it like this: + * + * @code + * struct foo *X = talloc(tmp_ctx, struct foo); + * struct foo *Y; + * Y = talloc_move(new_ctx, &X); + * @endcode + * + * @param[in] new_ctx The new parent context. + * + * @param[in] pptr Pointer to a pointer to the talloc chunk to move. + * + * @return The pointer to the talloc chunk that moved. + * It does not have any failure modes. + * + */ +void *talloc_move(const void *new_ctx, void **pptr); +#else +#define talloc_move(ctx, pptr) (_TALLOC_TYPEOF(*(pptr)))_talloc_move((ctx),(void *)(pptr)) +void *_talloc_move(const void *new_ctx, const void *pptr); +#endif + +/** + * @brief Assign a name to a talloc chunk. + * + * The function is just like talloc_set_name(), but it takes a string constant, + * and is much faster. It is extensively used by the "auto naming" macros, such + * as talloc_p(). + * + * This function does not allocate any memory. It just copies the supplied + * pointer into the internal representation of the talloc ptr. This means you + * must not pass a name pointer to memory that will disappear before the ptr + * is freed with talloc_free(). + * + * @param[in] ptr The talloc chunk to assign a name to. + * + * @param[in] name Format string for the name. + */ +void talloc_set_name_const(const void *ptr, const char *name); + +/** + * @brief Create a named talloc chunk. + * + * The talloc_named() function creates a named talloc pointer. It is + * equivalent to: + * + * @code + * ptr = talloc_size(context, size); + * talloc_set_name(ptr, fmt, ....); + * @endcode + * + * @param[in] context The talloc context to hang the result off. + * + * @param[in] size Number of char's that you want to allocate. + * + * @param[in] fmt Format string for the name. + * + * @param[in] ... Additional printf-style arguments. + * + * @return The allocated memory chunk, NULL on error. + * + * @see talloc_set_name() + */ +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); + +/** + * @brief Basic routine to allocate a chunk of memory. + * + * This is equivalent to: + * + * @code + * ptr = talloc_size(context, size); + * talloc_set_name_const(ptr, name); + * @endcode + * + * @param[in] context The parent context. + * + * @param[in] size The number of char's that we want to allocate. + * + * @param[in] name The name the talloc block has. + * + * @return The allocated memory chunk, NULL on error. + */ +void *talloc_named_const(const void *context, size_t size, const char *name); + +#ifdef DOXYGEN +/** + * @brief Untyped allocation. + * + * The function should be used when you don't have a convenient type to pass to + * talloc(). Unlike talloc(), it is not type safe (as it returns a void *), so + * you are on your own for type checking. + * + * Best to use talloc() or talloc_array() instead. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] size Number of char's that you want to allocate. + * + * @return The allocated memory chunk, NULL on error. + * + * Example: + * @code + * void *mem = talloc_size(NULL, 100); + * @endcode + */ +void *talloc_size(const void *ctx, size_t size); +#else +#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate into a typed pointer. + * + * The talloc_ptrtype() macro should be used when you have a pointer and want + * to allocate memory to point at with this pointer. When compiling with + * gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() and + * talloc_get_name() will return the current location in the source file and + * not the type. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The pointer you want to assign the result to. + * + * @return The properly casted allocated memory chunk, NULL on + * error. + * + * Example: + * @code + * unsigned int *a = talloc_ptrtype(NULL, a); + * @endcode + */ +void *talloc_ptrtype(const void *ctx, #type); +#else +#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate a new 0-sized talloc chunk. + * + * This is a utility macro that creates a new memory context hanging off an + * existing context, automatically naming it "talloc_new: __location__" where + * __location__ is the source line it is called from. It is particularly + * useful for creating a new temporary working context. + * + * @param[in] ctx The talloc parent context. + * + * @return A new talloc chunk, NULL on error. + */ +void *talloc_new(const void *ctx); +#else +#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate a 0-initizialized structure. + * + * The macro is equivalent to: + * + * @code + * ptr = talloc(ctx, type); + * if (ptr) memset(ptr, 0, sizeof(type)); + * @endcode + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The type that we want to allocate. + * + * @return Pointer to a piece of memory, properly cast to 'type *', + * NULL on error. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc_zero(NULL, unsigned int); + * b = talloc_zero(a, unsigned int); + * @endcode + * + * @see talloc() + * @see talloc_zero_size() + * @see talloc_zero_array() + */ +void *talloc_zero(const void *ctx, #type); + +/** + * @brief Allocate untyped, 0-initialized memory. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] size Number of char's that you want to allocate. + * + * @return The allocated memory chunk. + */ +void *talloc_zero_size(const void *ctx, size_t size); +#else +#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) +void *_talloc_zero(const void *ctx, size_t size, const char *name); +#endif + +/** + * @brief Return the name of a talloc chunk. + * + * @param[in] ptr The talloc chunk. + * + * @return The current name for the given talloc pointer. + * + * @see talloc_set_name() + */ +const char *talloc_get_name(const void *ptr); + +/** + * @brief Verify that a talloc chunk carries a specified name. + * + * This function checks if a pointer has the specified name. If it does + * then the pointer is returned. + * + * @param[in] ptr The talloc chunk to check. + * + * @param[in] name The name to check against. + * + * @return The pointer if the name matches, NULL if it doesn't. + */ +void *talloc_check_name(const void *ptr, const char *name); + +/** + * @brief Get the parent chunk of a pointer. + * + * @param[in] ptr The talloc pointer to inspect. + * + * @return The talloc parent of ptr, NULL on error. + */ +void *talloc_parent(const void *ptr); + +/** + * @brief Get a talloc chunk's parent name. + * + * @param[in] ptr The talloc pointer to inspect. + * + * @return The name of ptr's parent chunk. + */ +const char *talloc_parent_name(const void *ptr); + +/** + * @brief Get the total size of a talloc chunk including its children. + * + * The function returns the total size in bytes used by this pointer and all + * child pointers. Mostly useful for debugging. + * + * Passing NULL is allowed, but it will only give a meaningful result if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() has + * been called. + * + * @param[in] ptr The talloc chunk. + * + * @return The total size. + */ +size_t talloc_total_size(const void *ptr); + +/** + * @brief Get the number of talloc chunks hanging off a chunk. + * + * The talloc_total_blocks() function returns the total memory block + * count used by this pointer and all child pointers. Mostly useful for + * debugging. + * + * Passing NULL is allowed, but it will only give a meaningful result if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() has + * been called. + * + * @param[in] ptr The talloc chunk. + * + * @return The total size. + */ +size_t talloc_total_blocks(const void *ptr); + +#ifdef DOXYGEN +/** + * @brief Duplicate a memory area into a talloc chunk. + * + * The function is equivalent to: + * + * @code + * ptr = talloc_size(ctx, size); + * if (ptr) memcpy(ptr, p, size); + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] p The memory chunk you want to duplicate. + * + * @param[in] size Number of char's that you want copy. + * + * @return The allocated memory chunk. + * + * @see talloc_size() + */ +void *talloc_memdup(const void *t, const void *p, size_t size); +#else +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Assign a type to a talloc chunk. + * + * This macro allows you to force the name of a pointer to be of a particular + * type. This can be used in conjunction with talloc_get_type() to do type + * checking on void* pointers. + * + * It is equivalent to this: + * + * @code + * talloc_set_name_const(ptr, #type) + * @endcode + * + * @param[in] ptr The talloc chunk to assign the type to. + * + * @param[in] type The type to assign. + */ +void talloc_set_type(const char *ptr, #type); + +/** + * @brief Get a typed pointer out of a talloc pointer. + * + * This macro allows you to do type checking on talloc pointers. It is + * particularly useful for void* private pointers. It is equivalent to + * this: + * + * @code + * (type *)talloc_check_name(ptr, #type) + * @endcode + * + * @param[in] ptr The talloc pointer to check. + * + * @param[in] type The type to check against. + * + * @return The properly casted pointer given by ptr, NULL on error. + */ +type *talloc_get_type(const void *ptr, #type); +#else +#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) +#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#endif + +#ifdef DOXYGEN +/** + * @brief Safely turn a void pointer into a typed pointer. + * + * This macro is used together with talloc(mem_ctx, struct foo). If you had to + * assign the talloc chunk pointer to some void pointer variable, + * talloc_get_type_abort() is the recommended way to get the convert the void + * pointer back to a typed pointer. + * + * @param[in] ptr The void pointer to convert. + * + * @param[in] type The type that this chunk contains + * + * @return The same value as ptr, type-checked and properly cast. + */ +void *talloc_get_type_abort(const void *ptr, #type); +#else +#ifdef TALLOC_GET_TYPE_ABORT_NOOP +#define talloc_get_type_abort(ptr, type) (type *)(ptr) +#else +#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) +#endif +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); +#endif + +/** + * @brief Find a parent context by name. + * + * Find a parent memory context of the current context that has the given + * name. This can be very useful in complex programs where it may be + * difficult to pass all information down to the level you need, but you + * know the structure you want is a parent of another context. + * + * @param[in] ctx The talloc chunk to start from. + * + * @param[in] name The name of the parent we look for. + * + * @return The memory context we are looking for, NULL if not + * found. + */ +void *talloc_find_parent_byname(const void *ctx, const char *name); + +#ifdef DOXYGEN +/** + * @brief Find a parent context by type. + * + * Find a parent memory context of the current context that has the given + * name. This can be very useful in complex programs where it may be + * difficult to pass all information down to the level you need, but you + * know the structure you want is a parent of another context. + * + * Like talloc_find_parent_byname() but takes a type, making it typesafe. + * + * @param[in] ptr The talloc chunk to start from. + * + * @param[in] type The type of the parent to look for. + * + * @return The memory context we are looking for, NULL if not + * found. + */ +void *talloc_find_parent_bytype(const void *ptr, #type); +#else +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) +#endif + +/** + * @brief Allocate a talloc pool. + * + * A talloc pool is a pure optimization for specific situations. In the + * release process for Samba 3.2 we found out that we had become considerably + * slower than Samba 3.0 was. Profiling showed that malloc(3) was a large CPU + * consumer in benchmarks. For Samba 3.2 we have internally converted many + * static buffers to dynamically allocated ones, so malloc(3) being beaten + * more was no surprise. But it made us slower. + * + * talloc_pool() is an optimization to call malloc(3) a lot less for the use + * pattern Samba has: The SMB protocol is mainly a request/response protocol + * where we have to allocate a certain amount of memory per request and free + * that after the SMB reply is sent to the client. + * + * talloc_pool() creates a talloc chunk that you can use as a talloc parent + * exactly as you would use any other ::TALLOC_CTX. The difference is that + * when you talloc a child of this pool, no malloc(3) is done. Instead, talloc + * just increments a pointer inside the talloc_pool. This also works + * recursively. If you use the child of the talloc pool as a parent for + * grand-children, their memory is also taken from the talloc pool. + * + * If there is not enough memory in the pool to allocate the new child, + * it will create a new talloc chunk as if the parent was a normal talloc + * context. + * + * If you talloc_free() children of a talloc pool, the memory is not given + * back to the system. Instead, free(3) is only called if the talloc_pool() + * itself is released with talloc_free(). + * + * The downside of a talloc pool is that if you talloc_move() a child of a + * talloc pool to a talloc parent outside the pool, the whole pool memory is + * not free(3)'ed until that moved chunk is also talloc_free()ed. + * + * @param[in] context The talloc context to hang the result off. + * + * @param[in] size Size of the talloc pool. + * + * @return The allocated talloc pool, NULL on error. + */ +void *talloc_pool(const void *context, size_t size); + +#ifdef DOXYGEN +/** + * @brief Allocate a talloc object as/with an additional pool. + * + * This is like talloc_pool(), but's it's more flexible + * and allows an object to be a pool for its children. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The type that we want to allocate. + * + * @param[in] num_subobjects The expected number of subobjects, which will + * be allocated within the pool. This allocates + * space for talloc_chunk headers. + * + * @param[in] total_subobjects_size The size that all subobjects can use in total. + * + * + * @return The allocated talloc object, NULL on error. + */ +void *talloc_pooled_object(const void *ctx, #type, + unsigned num_subobjects, + size_t total_subobjects_size); +#else +#define talloc_pooled_object(_ctx, _type, \ + _num_subobjects, \ + _total_subobjects_size) \ + (_type *)_talloc_pooled_object((_ctx), sizeof(_type), #_type, \ + (_num_subobjects), \ + (_total_subobjects_size)) +void *_talloc_pooled_object(const void *ctx, + size_t type_size, + const char *type_name, + unsigned num_subobjects, + size_t total_subobjects_size); +#endif + +/** + * @brief Free a talloc chunk and NULL out the pointer. + * + * TALLOC_FREE() frees a pointer and sets it to NULL. Use this if you want + * immediate feedback (i.e. crash) if you use a pointer after having free'ed + * it. + * + * @param[in] ctx The chunk to be freed. + */ +#define TALLOC_FREE(ctx) do { if (ctx != NULL) { talloc_free(ctx); ctx=NULL; } } while(0) + +/* @} ******************************************************************/ + +/** + * \defgroup talloc_ref The talloc reference function. + * @ingroup talloc + * + * This module contains the definitions around talloc references + * + * @{ + */ + +/** + * @brief Increase the reference count of a talloc chunk. + * + * The talloc_increase_ref_count(ptr) function is exactly equivalent to: + * + * @code + * talloc_reference(NULL, ptr); + * @endcode + * + * You can use either syntax, depending on which you think is clearer in + * your code. + * + * @param[in] ptr The pointer to increase the reference count. + * + * @return 0 on success, -1 on error. + */ +int talloc_increase_ref_count(const void *ptr); + +/** + * @brief Get the number of references to a talloc chunk. + * + * @param[in] ptr The pointer to retrieve the reference count from. + * + * @return The number of references. + */ +size_t talloc_reference_count(const void *ptr); + +#ifdef DOXYGEN +/** + * @brief Create an additional talloc parent to a pointer. + * + * The talloc_reference() function makes "context" an additional parent of + * ptr. Each additional reference consumes around 48 bytes of memory on intel + * x86 platforms. + * + * If ptr is NULL, then the function is a no-op, and simply returns NULL. + * + * After creating a reference you can free it in one of the following ways: + * + * - you can talloc_free() any parent of the original pointer. That + * will reduce the number of parents of this pointer by 1, and will + * cause this pointer to be freed if it runs out of parents. + * + * - you can talloc_free() the pointer itself if it has at maximum one + * parent. This behaviour has been changed since the release of version + * 2.0. Further information in the description of "talloc_free". + * + * For more control on which parent to remove, see talloc_unlink() + * @param[in] ctx The additional parent. + * + * @param[in] ptr The pointer you want to create an additional parent for. + * + * @return The original pointer 'ptr', NULL if talloc ran out of + * memory in creating the reference. + * + * @warning You should try to avoid using this interface. It turns a beautiful + * talloc-tree into a graph. It is often really hard to debug if you + * screw something up by accident. + * + * Example: + * @code + * unsigned int *a, *b, *c; + * a = talloc(NULL, unsigned int); + * b = talloc(NULL, unsigned int); + * c = talloc(a, unsigned int); + * // b also serves as a parent of c. + * talloc_reference(b, c); + * @endcode + * + * @see talloc_unlink() + */ +void *talloc_reference(const void *ctx, const void *ptr); +#else +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__) +void *_talloc_reference_loc(const void *context, const void *ptr, const char *location); +#endif + +/** + * @brief Remove a specific parent from a talloc chunk. + * + * The function removes a specific parent from ptr. The context passed must + * either be a context used in talloc_reference() with this pointer, or must be + * a direct parent of ptr. + * + * You can just use talloc_free() instead of talloc_unlink() if there + * is at maximum one parent. This behaviour has been changed since the + * release of version 2.0. Further information in the description of + * "talloc_free". + * + * @param[in] context The talloc parent to remove. + * + * @param[in] ptr The talloc ptr you want to remove the parent from. + * + * @return 0 on success, -1 on error. + * + * @note If the parent has already been removed using talloc_free() then + * this function will fail and will return -1. Likewise, if ptr is NULL, + * then the function will make no modifications and return -1. + * + * @warning You should try to avoid using this interface. It turns a beautiful + * talloc-tree into a graph. It is often really hard to debug if you + * screw something up by accident. + * + * Example: + * @code + * unsigned int *a, *b, *c; + * a = talloc(NULL, unsigned int); + * b = talloc(NULL, unsigned int); + * c = talloc(a, unsigned int); + * // b also serves as a parent of c. + * talloc_reference(b, c); + * talloc_unlink(b, c); + * @endcode + */ +int talloc_unlink(const void *context, void *ptr); + +/** + * @brief Provide a talloc context that is freed at program exit. + * + * This is a handy utility function that returns a talloc context + * which will be automatically freed on program exit. This can be used + * to reduce the noise in memory leak reports. + * + * Never use this in code that might be used in objects loaded with + * dlopen and unloaded with dlclose. talloc_autofree_context() + * internally uses atexit(3). Some platforms like modern Linux handles + * this fine, but for example FreeBSD does not deal well with dlopen() + * and atexit() used simultaneously: dlclose() does not clean up the + * list of atexit-handlers, so when the program exits the code that + * was registered from within talloc_autofree_context() is gone, the + * program crashes at exit. + * + * @return A talloc context, NULL on error. + */ +void *talloc_autofree_context(void) _DEPRECATED_; + +/** + * @brief Get the size of a talloc chunk. + * + * This function lets you know the amount of memory allocated so far by + * this context. It does NOT account for subcontext memory. + * This can be used to calculate the size of an array. + * + * @param[in] ctx The talloc chunk. + * + * @return The size of the talloc chunk. + */ +size_t talloc_get_size(const void *ctx); + +/** + * @brief Show the parentage of a context. + * + * @param[in] context The talloc context to look at. + * + * @param[in] file The output to use, a file, stdout or stderr. + */ +void talloc_show_parents(const void *context, FILE *file); + +/** + * @brief Check if a context is parent of a talloc chunk. + * + * This checks if context is referenced in the talloc hierarchy above ptr. + * + * @param[in] context The assumed talloc context. + * + * @param[in] ptr The talloc chunk to check. + * + * @return Return 1 if this is the case, 0 if not. + */ +int talloc_is_parent(const void *context, const void *ptr); + +/** + * @brief Change the parent context of a talloc pointer. + * + * The function changes the parent context of a talloc pointer. It is typically + * used when the context that the pointer is currently a child of is going to be + * freed and you wish to keep the memory for a longer time. + * + * The difference between talloc_reparent() and talloc_steal() is that + * talloc_reparent() can specify which parent you wish to change. This is + * useful when a pointer has multiple parents via references. + * + * @param[in] old_parent + * @param[in] new_parent + * @param[in] ptr + * + * @return Return the pointer you passed. It does not have any + * failure modes. + */ +void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); + +/* @} ******************************************************************/ + +/** + * @defgroup talloc_array The talloc array functions + * @ingroup talloc + * + * Talloc contains some handy helpers for handling Arrays conveniently + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief Allocate an array. + * + * The macro is equivalent to: + * + * @code + * (type *)talloc_size(ctx, sizeof(type) * count); + * @endcode + * + * except that it provides integer overflow protection for the multiply, + * returning NULL if the multiply overflows. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The type that we want to allocate. + * + * @param[in] count The number of 'type' elements you want to allocate. + * + * @return The allocated result, properly cast to 'type *', NULL on + * error. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc_zero(NULL, unsigned int); + * b = talloc_array(a, unsigned int, 100); + * @endcode + * + * @see talloc() + * @see talloc_zero_array() + */ +void *talloc_array(const void *ctx, #type, unsigned count); +#else +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate an array. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] size The size of an array element. + * + * @param[in] count The number of elements you want to allocate. + * + * @return The allocated result, NULL on error. + */ +void *talloc_array_size(const void *ctx, size_t size, unsigned count); +#else +#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate an array into a typed pointer. + * + * The macro should be used when you have a pointer to an array and want to + * allocate memory of an array to point at with this pointer. When compiling + * with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() + * and talloc_get_name() will return the current location in the source file + * and not the type. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] ptr The pointer you want to assign the result to. + * + * @param[in] count The number of elements you want to allocate. + * + * @return The allocated memory chunk, properly casted. NULL on + * error. + */ +void *talloc_array_ptrtype(const void *ctx, const void *ptr, unsigned count); +#else +#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Get the number of elements in a talloc'ed array. + * + * A talloc chunk carries its own size, so for talloc'ed arrays it is not + * necessary to store the number of elements explicitly. + * + * @param[in] ctx The allocated array. + * + * @return The number of elements in ctx. + */ +size_t talloc_array_length(const void *ctx); +#else +#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate a zero-initialized array + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The type that we want to allocate. + * + * @param[in] count The number of "type" elements you want to allocate. + * + * @return The allocated result casted to "type *", NULL on error. + * + * The talloc_zero_array() macro is equivalent to: + * + * @code + * ptr = talloc_array(ctx, type, count); + * if (ptr) memset(ptr, 0, sizeof(type) * count); + * @endcode + */ +void *talloc_zero_array(const void *ctx, #type, unsigned count); +#else +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +void *_talloc_zero_array(const void *ctx, + size_t el_size, + unsigned count, + const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Change the size of a talloc array. + * + * The macro changes the size of a talloc pointer. The 'count' argument is the + * number of elements of type 'type' that you want the resulting pointer to + * hold. + * + * talloc_realloc() has the following equivalences: + * + * @code + * talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type); + * talloc_realloc(ctx, NULL, type, N) ==> talloc_array(ctx, type, N); + * talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr); + * @endcode + * + * The "context" argument is only used if "ptr" is NULL, otherwise it is + * ignored. + * + * @param[in] ctx The parent context used if ptr is NULL. + * + * @param[in] ptr The chunk to be resized. + * + * @param[in] type The type of the array element inside ptr. + * + * @param[in] count The intended number of array elements. + * + * @return The new array, NULL on error. The call will fail either + * due to a lack of memory, or because the pointer has more + * than one parent (see talloc_reference()). + */ +void *talloc_realloc(const void *ctx, void *ptr, #type, size_t count); +#else +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Untyped realloc to change the size of a talloc array. + * + * The macro is useful when the type is not known so the typesafe + * talloc_realloc() cannot be used. + * + * @param[in] ctx The parent context used if 'ptr' is NULL. + * + * @param[in] ptr The chunk to be resized. + * + * @param[in] size The new chunk size. + * + * @return The new array, NULL on error. + */ +void *talloc_realloc_size(const void *ctx, void *ptr, size_t size); +#else +#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +#endif + +/** + * @brief Provide a function version of talloc_realloc_size. + * + * This is a non-macro version of talloc_realloc(), which is useful as + * libraries sometimes want a ralloc function pointer. A realloc() + * implementation encapsulates the functionality of malloc(), free() and + * realloc() in one call, which is why it is useful to be able to pass around + * a single function pointer. + * + * @param[in] context The parent context used if ptr is NULL. + * + * @param[in] ptr The chunk to be resized. + * + * @param[in] size The new chunk size. + * + * @return The new chunk, NULL on error. + */ +void *talloc_realloc_fn(const void *context, void *ptr, size_t size); + +/* @} ******************************************************************/ + +/** + * @defgroup talloc_string The talloc string functions. + * @ingroup talloc + * + * talloc string allocation and manipulation functions. + * @{ + */ + +/** + * @brief Duplicate a string into a talloc chunk. + * + * This function is equivalent to: + * + * @code + * ptr = talloc_size(ctx, strlen(p)+1); + * if (ptr) memcpy(ptr, p, strlen(p)+1); + * @endcode + * + * This functions sets the name of the new pointer to the passed + * string. This is equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] p The string you want to duplicate. + * + * @return The duplicated string, NULL on error. + */ +char *talloc_strdup(const void *t, const char *p); + +/** + * @brief Append a string to given string. + * + * The destination string is reallocated to take + * strlen(s) + strlen(a) + 1 characters. + * + * This functions sets the name of the new pointer to the new + * string. This is equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * If s == NULL then new context is created. + * + * @param[in] s The destination to append to. + * + * @param[in] a The string you want to append. + * + * @return The concatenated strings, NULL on error. + * + * @see talloc_strdup() + * @see talloc_strdup_append_buffer() + */ +char *talloc_strdup_append(char *s, const char *a); + +/** + * @brief Append a string to a given buffer. + * + * This is a more efficient version of talloc_strdup_append(). It determines the + * length of the destination string by the size of the talloc context. + * + * Use this very carefully as it produces a different result than + * talloc_strdup_append() when a zero character is in the middle of the + * destination string. + * + * @code + * char *str_a = talloc_strdup(NULL, "hello world"); + * char *str_b = talloc_strdup(NULL, "hello world"); + * str_a[5] = str_b[5] = '\0' + * + * char *app = talloc_strdup_append(str_a, ", hello"); + * char *buf = talloc_strdup_append_buffer(str_b, ", hello"); + * + * printf("%s\n", app); // hello, hello (app = "hello, hello") + * printf("%s\n", buf); // hello (buf = "hello\0world, hello") + * @endcode + * + * If s == NULL then new context is created. + * + * @param[in] s The destination buffer to append to. + * + * @param[in] a The string you want to append. + * + * @return The concatenated strings, NULL on error. + * + * @see talloc_strdup() + * @see talloc_strdup_append() + * @see talloc_array_length() + */ +char *talloc_strdup_append_buffer(char *s, const char *a); + +/** + * @brief Duplicate a length-limited string into a talloc chunk. + * + * This function is the talloc equivalent of the C library function strndup(3). + * + * This functions sets the name of the new pointer to the passed string. This is + * equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] p The string you want to duplicate. + * + * @param[in] n The maximum string length to duplicate. + * + * @return The duplicated string, NULL on error. + */ +char *talloc_strndup(const void *t, const char *p, size_t n); + +/** + * @brief Append at most n characters of a string to given string. + * + * The destination string is reallocated to take + * strlen(s) + strnlen(a, n) + 1 characters. + * + * This functions sets the name of the new pointer to the new + * string. This is equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * If s == NULL then new context is created. + * + * @param[in] s The destination string to append to. + * + * @param[in] a The source string you want to append. + * + * @param[in] n The number of characters you want to append from the + * string. + * + * @return The concatenated strings, NULL on error. + * + * @see talloc_strndup() + * @see talloc_strndup_append_buffer() + */ +char *talloc_strndup_append(char *s, const char *a, size_t n); + +/** + * @brief Append at most n characters of a string to given buffer + * + * This is a more efficient version of talloc_strndup_append(). It determines + * the length of the destination string by the size of the talloc context. + * + * Use this very carefully as it produces a different result than + * talloc_strndup_append() when a zero character is in the middle of the + * destination string. + * + * @code + * char *str_a = talloc_strdup(NULL, "hello world"); + * char *str_b = talloc_strdup(NULL, "hello world"); + * str_a[5] = str_b[5] = '\0' + * + * char *app = talloc_strndup_append(str_a, ", hello", 7); + * char *buf = talloc_strndup_append_buffer(str_b, ", hello", 7); + * + * printf("%s\n", app); // hello, hello (app = "hello, hello") + * printf("%s\n", buf); // hello (buf = "hello\0world, hello") + * @endcode + * + * If s == NULL then new context is created. + * + * @param[in] s The destination buffer to append to. + * + * @param[in] a The source string you want to append. + * + * @param[in] n The number of characters you want to append from the + * string. + * + * @return The concatenated strings, NULL on error. + * + * @see talloc_strndup() + * @see talloc_strndup_append() + * @see talloc_array_length() + */ +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); + +/** + * @brief Format a string given a va_list. + * + * This function is the talloc equivalent of the C library function + * vasprintf(3). + * + * This functions sets the name of the new pointer to the new string. This is + * equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] fmt The format string. + * + * @param[in] ap The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + */ +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +/** + * @brief Format a string given a va_list and append it to the given destination + * string. + * + * @param[in] s The destination string to append to. + * + * @param[in] fmt The format string. + * + * @param[in] ap The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + * + * @see talloc_vasprintf() + */ +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +/** + * @brief Format a string given a va_list and append it to the given destination + * buffer. + * + * @param[in] s The destination buffer to append to. + * + * @param[in] fmt The format string. + * + * @param[in] ap The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + * + * @see talloc_vasprintf() + */ +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +/** + * @brief Format a string. + * + * This function is the talloc equivalent of the C library function asprintf(3). + * + * This functions sets the name of the new pointer to the new string. This is + * equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] fmt The format string. + * + * @param[in] ... The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + */ +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +/** + * @brief Append a formatted string to another string. + * + * This function appends the given formatted string to the given string. Use + * this variant when the string in the current talloc buffer may have been + * truncated in length. + * + * This functions sets the name of the new pointer to the new + * string. This is equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * If s == NULL then new context is created. + * + * @param[in] s The string to append to. + * + * @param[in] fmt The format string. + * + * @param[in] ... The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + */ +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +/** + * @brief Append a formatted string to another string. + * + * This is a more efficient version of talloc_asprintf_append(). It determines + * the length of the destination string by the size of the talloc context. + * + * Use this very carefully as it produces a different result than + * talloc_asprintf_append() when a zero character is in the middle of the + * destination string. + * + * @code + * char *str_a = talloc_strdup(NULL, "hello world"); + * char *str_b = talloc_strdup(NULL, "hello world"); + * str_a[5] = str_b[5] = '\0' + * + * char *app = talloc_asprintf_append(str_a, "%s", ", hello"); + * char *buf = talloc_strdup_append_buffer(str_b, "%s", ", hello"); + * + * printf("%s\n", app); // hello, hello (app = "hello, hello") + * printf("%s\n", buf); // hello (buf = "hello\0world, hello") + * @endcode + * + * If s == NULL then new context is created. + * + * @param[in] s The string to append to + * + * @param[in] fmt The format string. + * + * @param[in] ... The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + * + * @see talloc_asprintf() + * @see talloc_asprintf_append() + */ +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +/* @} ******************************************************************/ + +/** + * @defgroup talloc_debug The talloc debugging support functions + * @ingroup talloc + * + * To aid memory debugging, talloc contains routines to inspect the currently + * allocated memory hierarchy. + * + * @{ + */ + +/** + * @brief Walk a complete talloc hierarchy. + * + * This provides a more flexible reports than talloc_report(). It + * will recursively call the callback for the entire tree of memory + * referenced by the pointer. References in the tree are passed with + * is_ref = 1 and the pointer that is referenced. + * + * You can pass NULL for the pointer, in which case a report is + * printed for the top level memory context, but only if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() + * has been called. + * + * The recursion is stopped when depth >= max_depth. + * max_depth = -1 means only stop at leaf nodes. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] depth Internal parameter to control recursion. Call with 0. + * + * @param[in] max_depth Maximum recursion level. + * + * @param[in] callback Function to be called on every chunk. + * + * @param[in] private_data Private pointer passed to callback. + */ +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data); + +/** + * @brief Print a talloc hierarchy. + * + * This provides a more flexible reports than talloc_report(). It + * will let you specify the depth and max_depth. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] depth Internal parameter to control recursion. Call with 0. + * + * @param[in] max_depth Maximum recursion level. + * + * @param[in] f The file handle to print to. + */ +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); + +/** + * @brief Print a summary report of all memory used by ptr. + * + * This provides a more detailed report than talloc_report(). It will + * recursively print the entire tree of memory referenced by the + * pointer. References in the tree are shown by giving the name of the + * pointer that is referenced. + * + * You can pass NULL for the pointer, in which case a report is printed + * for the top level memory context, but only if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() has + * been called. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] f The file handle to print to. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * fprintf(stderr, "Dumping memory tree for a:\n"); + * talloc_report_full(a, stderr); + * @endcode + * + * @see talloc_report() + */ +void talloc_report_full(const void *ptr, FILE *f); + +/** + * @brief Print a summary report of all memory used by ptr. + * + * This function prints a summary report of all memory used by ptr. One line of + * report is printed for each immediate child of ptr, showing the total memory + * and number of blocks used by that child. + * + * You can pass NULL for the pointer, in which case a report is printed + * for the top level memory context, but only if talloc_enable_leak_report() + * or talloc_enable_leak_report_full() has been called. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] f The file handle to print to. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * fprintf(stderr, "Summary of memory tree for a:\n"); + * talloc_report(a, stderr); + * @endcode + * + * @see talloc_report_full() + */ +void talloc_report(const void *ptr, FILE *f); + +/** + * @brief Enable tracking the use of NULL memory contexts. + * + * 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(); + */ +void talloc_enable_null_tracking(void); + +/** + * @brief Enable tracking the use of NULL memory contexts. + * + * 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(); + */ +void talloc_enable_null_tracking_no_autofree(void); + +/** + * @brief Disable tracking of the NULL memory context. + * + * This disables tracking of the NULL memory context. + */ +void talloc_disable_null_tracking(void); + +/** + * @brief Enable leak report when a program exits. + * + * This enables calling of talloc_report(NULL, stderr) when the program + * exits. In Samba4 this is enabled by using the --leak-report command + * line option. + * + * For it to be useful, this function must be called before any other + * talloc function as it establishes a "null context" that acts as the + * top of the tree. If you don't call this function first then passing + * NULL to talloc_report() or talloc_report_full() won't give you the + * full tree printout. + * + * Here is a typical talloc report: + * + * @code + * talloc report on 'null_context' (total 267 bytes in 15 blocks) + * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + * iconv(UTF8,CP850) contains 42 bytes in 2 blocks + * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + * iconv(CP850,UTF8) contains 42 bytes in 2 blocks + * iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks + * iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + * @endcode + */ +void talloc_enable_leak_report(void); + +/** + * @brief Enable full leak report when a program exits. + * + * This enables calling of talloc_report_full(NULL, stderr) when the + * program exits. In Samba4 this is enabled by using the + * --leak-report-full command line option. + * + * For it to be useful, this function must be called before any other + * talloc function as it establishes a "null context" that acts as the + * top of the tree. If you don't call this function first then passing + * NULL to talloc_report() or talloc_report_full() won't give you the + * full tree printout. + * + * Here is a typical full report: + * + * @code + * full talloc report on 'root' (total 18 bytes in 8 blocks) + * p1 contains 18 bytes in 7 blocks (ref 0) + * r1 contains 13 bytes in 2 blocks (ref 0) + * reference to: p2 + * p2 contains 1 bytes in 1 blocks (ref 1) + * x3 contains 1 bytes in 1 blocks (ref 0) + * x2 contains 1 bytes in 1 blocks (ref 0) + * x1 contains 1 bytes in 1 blocks (ref 0) + * @endcode + */ +void talloc_enable_leak_report_full(void); + +/** + * @brief Set a custom "abort" function that is called on serious error. + * + * The default "abort" function is abort(). + * + * The "abort" function is called when: + * + *
    + *
  • talloc_get_type_abort() fails
  • + *
  • the provided pointer is not a valid talloc context
  • + *
  • when the context meta data are invalid
  • + *
  • when access after free is detected
  • + *
+ * + * Example: + * + * @code + * void my_abort(const char *reason) + * { + * fprintf(stderr, "talloc abort: %s\n", reason); + * abort(); + * } + * + * talloc_set_abort_fn(my_abort); + * @endcode + * + * @param[in] abort_fn The new "abort" function. + * + * @see talloc_set_log_fn() + * @see talloc_get_type() + */ +void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); + +/** + * @brief Set a logging function. + * + * @param[in] log_fn The logging function. + * + * @see talloc_set_log_stderr() + * @see talloc_set_abort_fn() + */ +void talloc_set_log_fn(void (*log_fn)(const char *message)); + +/** + * @brief Set stderr as the output for logs. + * + * @see talloc_set_log_fn() + * @see talloc_set_abort_fn() + */ +void talloc_set_log_stderr(void); + +/** + * @brief Set a max memory limit for the current context hierarchy + * This affects all children of this context and constrain any + * allocation in the hierarchy to never exceed the limit set. + * The limit can be removed by setting 0 (unlimited) as the + * max_size by calling the function again on the same context. + * Memory limits can also be nested, meaning a child can have + * a stricter memory limit than a parent. + * Memory limits are enforced only at memory allocation time. + * Stealing a context into a 'limited' hierarchy properly + * updates memory usage but does *not* cause failure if the + * move causes the new parent to exceed its limits. However + * any further allocation on that hierarchy will then fail. + * + * @warning talloc memlimit functionality is deprecated. Please + * consider using cgroup memory limits instead. + * + * @param[in] ctx The talloc context to set the limit on + * @param[in] max_size The (new) max_size + */ +int talloc_set_memlimit(const void *ctx, size_t max_size) _DEPRECATED_; + +/* @} ******************************************************************/ + +#if TALLOC_DEPRECATED +#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) +#define talloc_p(ctx, type) talloc(ctx, type) +#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) +#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#define talloc_destroy(ctx) talloc_free(ctx) +#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) +#endif + +#ifndef TALLOC_MAX_DEPTH +#define TALLOC_MAX_DEPTH 10000 +#endif + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/ldb-2.0.8/lib/talloc/talloc.pc.in b/ldb-2.0.8/lib/talloc/talloc.pc.in new file mode 100644 index 0000000..437281a --- /dev/null +++ b/ldb-2.0.8/lib/talloc/talloc.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: talloc +Description: A hierarchical pool based memory system with destructors +Version: @TALLOC_VERSION@ +Libs: @LIB_RPATH@ -L${libdir} -ltalloc +Cflags: -I${includedir} +URL: http://talloc.samba.org/ diff --git a/ldb-2.0.8/lib/talloc/talloc_guide.txt b/ldb-2.0.8/lib/talloc/talloc_guide.txt new file mode 100644 index 0000000..dedda6c --- /dev/null +++ b/ldb-2.0.8/lib/talloc/talloc_guide.txt @@ -0,0 +1,768 @@ +Using talloc in Samba4 +====================== + +.. contents:: + +Andrew Tridgell +August 2009 + +The most current version of this document is available at + http://samba.org/ftp/unpacked/talloc/talloc_guide.txt + +If you are used to the "old" talloc from Samba3 before 3.0.20 then please read +this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the +Samba4 talloc has been ported back to Samba3, so this guide applies to both. + +The new talloc is a hierarchical, reference counted memory pool system +with destructors. Quite a mouthful really, but not too bad once you +get used to it. + +Perhaps the biggest change from Samba3 is that there is no distinction +between a "talloc context" and a "talloc pointer". Any pointer +returned from talloc() is itself a valid talloc context. This means +you can do this:: + + struct foo *X = talloc(mem_ctx, struct foo); + X->name = talloc_strdup(X, "foo"); + +and the pointer X->name would be a "child" of the talloc context "X" +which is itself a child of "mem_ctx". So if you do talloc_free(mem_ctx) +then it is all destroyed, whereas if you do talloc_free(X) then just X +and X->name are destroyed, and if you do talloc_free(X->name) then +just the name element of X is destroyed. + +If you think about this, then what this effectively gives you is an +n-ary tree, where you can free any part of the tree with +talloc_free(). + +If you find this confusing, then I suggest you run the testsuite to +watch talloc in action. You may also like to add your own tests to +testsuite.c to clarify how some particular situation is handled. + + +Performance +----------- + +All the additional features of talloc() over malloc() do come at a +price. We have a simple performance test in Samba4 that measures +talloc() versus malloc() performance, and it seems that talloc() is +about 4% slower than malloc() on my x86 Debian Linux box. For Samba, +the great reduction in code complexity that we get by using talloc +makes this worthwhile, especially as the total overhead of +talloc/malloc in Samba is already quite small. + + +talloc API +---------- + +The following is a complete guide to the talloc API. Read it all at +least twice. + +Multi-threading +--------------- + +talloc itself does not deal with threads. It is thread-safe (assuming +the underlying "malloc" is), as long as each thread uses different +memory contexts. +If two threads use the same context then they need to synchronize in +order to be safe. In particular: +- when using talloc_enable_leak_report(), giving directly NULL as a +parent context implicitly refers to a hidden "null context" global +variable, so this should not be used in a multi-threaded environment +without proper synchronization. In threaded code turn off null tracking using +talloc_disable_null_tracking(). ; +- the context returned by talloc_autofree_context() is also global so +shouldn't be used by several threads simultaneously without +synchronization. + +talloc and shared objects +------------------------- + +talloc can be used in shared objects. Special care needs to be taken +to never use talloc_autofree_context() in code that might be loaded +with dlopen() and unloaded with dlclose(), as talloc_autofree_context() +internally uses atexit(3). Some platforms like modern Linux handles +this fine, but for example FreeBSD does not deal well with dlopen() +and atexit() used simultaneously: dlclose() does not clean up the list +of atexit-handlers, so when the program exits the code that was +registered from within talloc_autofree_context() is gone, the program +crashes at exit. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc(const void *context, type); + +The talloc() macro is the core of the talloc library. It takes a +memory context and a type, and returns a pointer to a new area of +memory of the given type. + +The returned pointer is itself a talloc context, so you can use it as +the context argument to more calls to talloc if you wish. + +The returned pointer is a "child" of the supplied context. This means +that if you talloc_free() the context then the new child disappears as +well. Alternatively you can free just the child. + +The context argument to talloc() can be NULL, in which case a new top +level context is created. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_size(const void *context, size_t size); + +The function talloc_size() should be used when you don't have a +convenient type to pass to talloc(). Unlike talloc(), it is not type +safe (as it returns a void *), so you are on your own for type checking. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr); + +The talloc_ptrtype() macro should be used when you have a pointer and +want to allocate memory to point at with this pointer. When compiling +with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() +and talloc_get_name() will return the current location in the source file. +and not the type. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_free(void *ptr); + +The talloc_free() function frees a piece of talloc memory, and all its +children. You can call talloc_free() on any pointer returned by +talloc(). + +The return value of talloc_free() indicates success or failure, with 0 +returned for success and -1 for failure. A possible failure condition +is if the pointer had a destructor attached to it and the destructor +returned -1. See talloc_set_destructor() for details on +destructors. Likewise, if "ptr" is NULL, then the function will make +no modifications and returns -1. + +From version 2.0 and onwards, as a special case, talloc_free() is +refused on pointers that have more than one parent associated, as talloc +would have no way of knowing which parent should be removed. This is +different from older versions in the sense that always the reference to +the most recently established parent has been destroyed. Hence to free a +pointer that has more than one parent please use talloc_unlink(). + +To help you find problems in your code caused by this behaviour, if +you do try and free a pointer with more than one parent then the +talloc logging function will be called to give output like this: + + ERROR: talloc_free with references at some_dir/source/foo.c:123 + reference at some_dir/source/other.c:325 + reference at some_dir/source/third.c:121 + +Please see the documentation for talloc_set_log_fn() and +talloc_set_log_stderr() for more information on talloc logging +functions. + +talloc_free() operates recursively on its children. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_free_children(void *ptr); + +The talloc_free_children() walks along the list of all children of a +talloc context and talloc_free()s only the children, not the context +itself. + +A NULL argument is handled as no-op. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_reference(const void *context, const void *ptr); + +The talloc_reference() function makes "context" an additional parent +of "ptr". + +The return value of talloc_reference() is always the original pointer +"ptr", unless talloc ran out of memory in creating the reference in +which case it will return NULL (each additional reference consumes +around 48 bytes of memory on intel x86 platforms). + +If "ptr" is NULL, then the function is a no-op, and simply returns NULL. + +After creating a reference you can free it in one of the following +ways: + + - you can talloc_free() any parent of the original pointer. That + will reduce the number of parents of this pointer by 1, and will + cause this pointer to be freed if it runs out of parents. + + - you can talloc_free() the pointer itself if it has at maximum one + parent. This behaviour has been changed since the release of version + 2.0. Further information in the description of "talloc_free". + +For more control on which parent to remove, see talloc_unlink() + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_unlink(const void *context, void *ptr); + +The talloc_unlink() function removes a specific parent from ptr. The +context passed must either be a context used in talloc_reference() +with this pointer, or must be a direct parent of ptr. + +Note that if the parent has already been removed using talloc_free() +then this function will fail and will return -1. Likewise, if "ptr" +is NULL, then the function will make no modifications and return -1. + +You can just use talloc_free() instead of talloc_unlink() if there +is at maximum one parent. This behaviour has been changed since the +release of version 2.0. Further information in the description of +"talloc_free". + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); + +The function talloc_set_destructor() sets the "destructor" for the +pointer "ptr". A destructor is a function that is called when the +memory used by a pointer is about to be released. The destructor +receives the pointer as an argument, and should return 0 for success +and -1 for failure. + +The destructor can do anything it wants to, including freeing other +pieces of memory. A common use for destructors is to clean up +operating system resources (such as open file descriptors) contained +in the structure the destructor is placed on. + +You can only place one destructor on a pointer. If you need more than +one destructor then you can create a zero-length child of the pointer +and place an additional destructor on that. + +To remove a destructor call talloc_set_destructor() with NULL for the +destructor. + +If your destructor attempts to talloc_free() the pointer that it is +the destructor for then talloc_free() will return -1 and the free will +be ignored. This would be a pointless operation anyway, as the +destructor is only called when the memory is just about to go away. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_increase_ref_count(const void *ptr); + +The talloc_increase_ref_count(ptr) function is exactly equivalent to: + + talloc_reference(NULL, ptr); + +You can use either syntax, depending on which you think is clearer in +your code. + +It returns 0 on success and -1 on failure. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +size_t talloc_reference_count(const void *ptr); + +Return the number of references to the pointer. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_name(const void *ptr, const char *fmt, ...); + +Each talloc pointer has a "name". The name is used principally for +debugging purposes, although it is also possible to set and get the +name on a pointer in as a way of "marking" pointers in your code. + +The main use for names on pointer is for "talloc reports". See +talloc_report() and talloc_report_full() for details. Also see +talloc_enable_leak_report() and talloc_enable_leak_report_full(). + +The talloc_set_name() function allocates memory as a child of the +pointer. It is logically equivalent to: + talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); + +Note that multiple calls to talloc_set_name() will allocate more +memory without releasing the name. All of the memory is released when +the ptr is freed using talloc_free(). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_name_const(const void *ptr, const char *name); + +The function talloc_set_name_const() is just like talloc_set_name(), +but it takes a string constant, and is much faster. It is extensively +used by the "auto naming" macros, such as talloc_p(). + +This function does not allocate any memory. It just copies the +supplied pointer into the internal representation of the talloc +ptr. This means you must not pass a name pointer to memory that will +disappear before the ptr is freed with talloc_free(). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_named(const void *context, size_t size, const char *fmt, ...); + +The talloc_named() function creates a named talloc pointer. It is +equivalent to: + + ptr = talloc_size(context, size); + talloc_set_name(ptr, fmt, ....); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_named_const(const void *context, size_t size, const char *name); + +This is equivalent to:: + + ptr = talloc_size(context, size); + talloc_set_name_const(ptr, name); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +const char *talloc_get_name(const void *ptr); + +This returns the current name for the given talloc pointer. See +talloc_set_name() for details. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_init(const char *fmt, ...); + +This function creates a zero length named talloc context as a top +level context. It is equivalent to:: + + talloc_named(NULL, 0, fmt, ...); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_new(void *ctx); + +This is a utility macro that creates a new memory context hanging +off an exiting context, automatically naming it "talloc_new: __location__" +where __location__ is the source line it is called from. It is +particularly useful for creating a new temporary working context. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_realloc(const void *context, void *ptr, type, count); + +The talloc_realloc() macro changes the size of a talloc +pointer. The "count" argument is the number of elements of type "type" +that you want the resulting pointer to hold. + +talloc_realloc() has the following equivalences:: + + talloc_realloc(context, NULL, type, 1) ==> talloc(context, type); + talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N); + talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr); + +The "context" argument is only used if "ptr" is NULL, otherwise it is +ignored. + +talloc_realloc() returns the new pointer, or NULL on failure. The call +will fail either due to a lack of memory, or because the pointer has +more than one parent (see talloc_reference()). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc_size(const void *context, void *ptr, size_t size); + +the talloc_realloc_size() function is useful when the type is not +known so the typesafe talloc_realloc() cannot be used. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_steal(const void *new_ctx, const void *ptr); + +The talloc_steal() function changes the parent context of a talloc +pointer. It is typically used when the context that the pointer is +currently a child of is going to be freed and you wish to keep the +memory for a longer time. + +The talloc_steal() function returns the pointer that you pass it. It +does not have any failure modes. + +NOTE: It is possible to produce loops in the parent/child relationship +if you are not careful with talloc_steal(). No guarantees are provided +as to your sanity or the safety of your data if you do this. + +talloc_steal (new_ctx, NULL) will return NULL with no sideeffects. + +Note that if you try and call talloc_steal() on a pointer that has +more than one parent then the result is ambiguous. Talloc will choose +to remove the parent that is currently indicated by talloc_parent() +and replace it with the chosen parent. You will also get a message +like this via the talloc logging functions: + + WARNING: talloc_steal with references at some_dir/source/foo.c:123 + reference at some_dir/source/other.c:325 + reference at some_dir/source/third.c:121 + +To unambiguously change the parent of a pointer please see the +function talloc_reparent(). See the talloc_set_log_fn() documentation +for more information on talloc logging. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); + +The talloc_reparent() function changes the parent context of a talloc +pointer. It is typically used when the context that the pointer is +currently a child of is going to be freed and you wish to keep the +memory for a longer time. + +The talloc_reparent() function returns the pointer that you pass it. It +does not have any failure modes. + +The difference between talloc_reparent() and talloc_steal() is that +talloc_reparent() can specify which parent you wish to change. This is +useful when a pointer has multiple parents via references. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_parent(const void *ptr); + +The talloc_parent() function returns the current talloc parent. This +is usually the pointer under which this memory was originally created, +but it may have changed due to a talloc_steal() or talloc_reparent() + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +size_t talloc_total_size(const void *ptr); + +The talloc_total_size() function returns the total size in bytes used +by this pointer and all child pointers. Mostly useful for debugging. + +Passing NULL is allowed, but it will only give a meaningful result if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +size_t talloc_total_blocks(const void *ptr); + +The talloc_total_blocks() function returns the total memory block +count used by this pointer and all child pointers. Mostly useful for +debugging. + +Passing NULL is allowed, but it will only give a meaningful result if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *priv), + void *priv); + +This provides a more flexible reports than talloc_report(). It +will recursively call the callback for the entire tree of memory +referenced by the pointer. References in the tree are passed with +is_ref = 1 and the pointer that is referenced. + +You can pass NULL for the pointer, in which case a report is +printed for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() +has been called. + +The recursion is stopped when depth >= max_depth. +max_depth = -1 means only stop at leaf nodes. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); + +This provides a more flexible reports than talloc_report(). It +will let you specify the depth and max_depth. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report(const void *ptr, FILE *f); + +The talloc_report() function prints a summary report of all memory +used by ptr. One line of report is printed for each immediate child of +ptr, showing the total memory and number of blocks used by that child. + +You can pass NULL for the pointer, in which case a report is printed +for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report_full(const void *ptr, FILE *f); + +This provides a more detailed report than talloc_report(). It will +recursively print the entire tree of memory referenced by the +pointer. References in the tree are shown by giving the name of the +pointer that is referenced. + +You can pass NULL for the pointer, in which case a report is printed +for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_leak_report(void); + +This enables calling of talloc_report(NULL, stderr) when the program +exits. In Samba4 this is enabled by using the --leak-report command +line option. + +For it to be useful, this function must be called before any other +talloc function as it establishes a "null context" that acts as the +top of the tree. If you don't call this function first then passing +NULL to talloc_report() or talloc_report_full() won't give you the +full tree printout. + +Here is a typical talloc report: + +talloc report on 'null_context' (total 267 bytes in 15 blocks) + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + iconv(UTF8,CP850) contains 42 bytes in 2 blocks + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + iconv(CP850,UTF8) contains 42 bytes in 2 blocks + iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks + iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_leak_report_full(void); + +This enables calling of talloc_report_full(NULL, stderr) when the +program exits. In Samba4 this is enabled by using the +--leak-report-full command line option. + +For it to be useful, this function must be called before any other +talloc function as it establishes a "null context" that acts as the +top of the tree. If you don't call this function first then passing +NULL to talloc_report() or talloc_report_full() won't give you the +full tree printout. + +Here is a typical full report: + +full talloc report on 'root' (total 18 bytes in 8 blocks) + p1 contains 18 bytes in 7 blocks (ref 0) + r1 contains 13 bytes in 2 blocks (ref 0) + reference to: p2 + p2 contains 1 bytes in 1 blocks (ref 1) + x3 contains 1 bytes in 1 blocks (ref 0) + x2 contains 1 bytes in 1 blocks (ref 0) + x1 contains 1 bytes in 1 blocks (ref 0) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_null_tracking(void); + +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(); + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_disable_null_tracking(void); + +This disables tracking of the NULL memory context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_zero(const void *ctx, type); + +The talloc_zero() macro is equivalent to:: + + ptr = talloc(ctx, type); + if (ptr) memset(ptr, 0, sizeof(type)); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_zero_size(const void *ctx, size_t size) + +The talloc_zero_size() function is useful when you don't have a known type + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_memdup(const void *ctx, const void *p, size_t size); + +The talloc_memdup() function is equivalent to:: + + ptr = talloc_size(ctx, size); + if (ptr) memcpy(ptr, p, size); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_strdup(const void *ctx, const char *p); + +The talloc_strdup() function is equivalent to:: + + ptr = talloc_size(ctx, strlen(p)+1); + if (ptr) memcpy(ptr, p, strlen(p)+1); + +This functions sets the name of the new pointer to the passed +string. This is equivalent to:: + + talloc_set_name_const(ptr, ptr) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_strndup(const void *t, const char *p, size_t n); + +The talloc_strndup() function is the talloc equivalent of the C +library function strndup() + +This functions sets the name of the new pointer to the passed +string. This is equivalent to: + talloc_set_name_const(ptr, ptr) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_append_string(const void *t, char *orig, const char *append); + +The talloc_append_string() function appends the given formatted +string to the given string. + +This function sets the name of the new pointer to the new +string. This is equivalent to:: + + talloc_set_name_const(ptr, ptr) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap); + +The talloc_vasprintf() function is the talloc equivalent of the C +library function vasprintf() + +This functions sets the name of the new pointer to the new +string. This is equivalent to:: + + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_asprintf(const void *t, const char *fmt, ...); + +The talloc_asprintf() function is the talloc equivalent of the C +library function asprintf() + +This functions sets the name of the new pointer to the new +string. This is equivalent to:: + + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_asprintf_append(char *s, const char *fmt, ...); + +The talloc_asprintf_append() function appends the given formatted +string to the given string. +Use this variant when the string in the current talloc buffer may +have been truncated in length. + +This functions sets the name of the new pointer to the new +string. This is equivalent to:: + + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...); + +The talloc_asprintf_append() function appends the given formatted +string to the end of the currently allocated talloc buffer. +Use this variant when the string in the current talloc buffer has +not been changed. + +This functions sets the name of the new pointer to the new +string. This is equivalent to:: + + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +((type *)talloc_array(const void *ctx, type, unsigned int count); + +The talloc_array() macro is equivalent to:: + + (type *)talloc_size(ctx, sizeof(type) * count); + +except that it provides integer overflow protection for the multiply, +returning NULL if the multiply overflows. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_array_size(const void *ctx, size_t size, unsigned int count); + +The talloc_array_size() function is useful when the type is not +known. It operates in the same way as talloc_array(), but takes a size +instead of a type. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count); + +The talloc_ptrtype() macro should be used when you have a pointer to an array +and want to allocate memory of an array to point at with this pointer. When compiling +with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() +and talloc_get_name() will return the current location in the source file. +and not the type. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size); + +This is a non-macro version of talloc_realloc(), which is useful +as libraries sometimes want a ralloc function pointer. A realloc() +implementation encapsulates the functionality of malloc(), free() and +realloc() in one call, which is why it is useful to be able to pass +around a single function pointer. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_autofree_context(void); + +This is a handy utility function that returns a talloc context +which will be automatically freed on program exit. This can be used +to reduce the noise in memory leak reports. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_check_name(const void *ptr, const char *name); + +This function checks if a pointer has the specified name. If it does +then the pointer is returned. It it doesn't then NULL is returned. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_get_type(const void *ptr, type); + +This macro allows you to do type checking on talloc pointers. It is +particularly useful for void* private pointers. It is equivalent to +this:: + + (type *)talloc_check_name(ptr, #type) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +talloc_set_type(const void *ptr, type); + +This macro allows you to force the name of a pointer to be of a +particular type. This can be used in conjunction with +talloc_get_type() to do type checking on void* pointers. + +It is equivalent to this:: + + talloc_set_name_const(ptr, #type) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +talloc_get_size(const void *ctx); + +This function lets you know the amount of memory allocated so far by +this context. It does NOT account for subcontext memory. +This can be used to calculate the size of an array. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_find_parent_byname(const void *ctx, const char *name); + +Find a parent memory context of the current context that has the given +name. This can be very useful in complex programs where it may be +difficult to pass all information down to the level you need, but you +know the structure you want is a parent of another context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_find_parent_bytype(ctx, type); + +Like talloc_find_parent_byname() but takes a type, making it typesafe. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_log_fn(void (*log_fn)(const char *message)); + +This function sets a logging function that talloc will use for +warnings and errors. By default talloc will not print any warnings or +errors. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_log_stderr(void) + +This sets the talloc log function to write log messages to stderr. diff --git a/ldb-2.0.8/lib/talloc/talloc_testsuite.h b/ldb-2.0.8/lib/talloc/talloc_testsuite.h new file mode 100644 index 0000000..acb9701 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/talloc_testsuite.h @@ -0,0 +1,7 @@ +#ifndef __LIB_TALLOC_TALLOC_TESTSUITE_H__ +#define __LIB_TALLOC_TALLOC_TESTSUITE_H__ + +struct torture_context; +bool torture_local_talloc(struct torture_context *tctx); + +#endif diff --git a/ldb-2.0.8/lib/talloc/test_magic_differs.sh b/ldb-2.0.8/lib/talloc/test_magic_differs.sh new file mode 100755 index 0000000..1b6ba2e --- /dev/null +++ b/ldb-2.0.8/lib/talloc/test_magic_differs.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# This test ensures that two different talloc processes do not use the same +# magic value to lessen the opportunity for transferrable attacks. + +echo "test: magic differs" + +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 + +echo "success: magic differs" diff --git a/ldb-2.0.8/lib/talloc/test_magic_differs_helper.c b/ldb-2.0.8/lib/talloc/test_magic_differs_helper.c new file mode 100644 index 0000000..6798827 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/test_magic_differs_helper.c @@ -0,0 +1,12 @@ +#include +#include "talloc.h" + +/* + * This program is called by a testing shell script in order to ensure that + * if the library is loaded into different processes it uses different magic + * values in order to thwart security attacks. + */ +int main(int argc, char *argv[]) { + printf("%i\n", talloc_test_get_magic()); + return 0; +} diff --git a/ldb-2.0.8/lib/talloc/test_pytalloc.c b/ldb-2.0.8/lib/talloc/test_pytalloc.c new file mode 100644 index 0000000..6797b98 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/test_pytalloc.c @@ -0,0 +1,244 @@ +/* + Samba Unix SMB/CIFS implementation. + + C utilities for the pytalloc test suite. + Provides the "_test_pytalloc" Python module. + + NOTE: Please read talloc_guide.txt for full documentation + + Copyright (C) Petr Viktorin 2015 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +#include +#include +#include + +static PyObject *testpytalloc_new(PyTypeObject *mod, + PyObject *Py_UNUSED(ignored)) +{ + char *obj = talloc_strdup(NULL, "This is a test string");; + return pytalloc_steal(pytalloc_GetObjectType(), obj); +} + +static PyObject *testpytalloc_get_object_type(PyObject *mod, + PyObject *Py_UNUSED(ignored)) +{ + PyObject *type = (PyObject *)pytalloc_GetObjectType(); + Py_INCREF(type); + return type; +} + +static PyObject *testpytalloc_base_new(PyTypeObject *mod, + PyObject *Py_UNUSED(ignored)) +{ + 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 *Py_UNUSED(ignored)) +{ + PyObject *type = (PyObject *)pytalloc_GetBaseObjectType(); + Py_INCREF(type); + return type; +} + +static PyObject *testpytalloc_reference(PyObject *mod, PyObject *args) { + PyObject *source = NULL; + void *ptr; + + if (!PyArg_ParseTuple(args, "O!", pytalloc_GetObjectType(), &source)) + return NULL; + + 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 } +}; + +static PyTypeObject DObject_Type; + +static int dobject_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 *dobject_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, dobject_destructor); + return pytalloc_steal(&DObject_Type, obj); +} + +static PyTypeObject DObject_Type = { + .tp_name = "_test_pytalloc.DObject", + .tp_basicsize = sizeof(pytalloc_Object), + .tp_methods = NULL, + .tp_new = dobject_new, + .tp_flags = Py_TPFLAGS_DEFAULT, + .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 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "_test_pytalloc", + .m_doc = PyDoc_STR("Test utility module for pytalloc"), + .m_size = -1, + .m_methods = test_talloc_methods, +}; +#endif + +static PyObject *module_init(void); +static PyObject *module_init(void) +{ + PyObject *m; + + DObject_Type.tp_base = pytalloc_GetObjectType(); + if (PyType_Ready(&DObject_Type) < 0) { + 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 + m = Py_InitModule3("_test_pytalloc", test_talloc_methods, MODULE_DOC); +#endif + + if (m == NULL) { + return NULL; + } + + Py_INCREF(&DObject_Type); + 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; +} + + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC PyInit__test_pytalloc(void); +PyMODINIT_FUNC PyInit__test_pytalloc(void) +{ + return module_init(); +} +#else +void init_test_pytalloc(void); +void init_test_pytalloc(void) +{ + module_init(); +} +#endif diff --git a/ldb-2.0.8/lib/talloc/test_pytalloc.py b/ldb-2.0.8/lib/talloc/test_pytalloc.py new file mode 100644 index 0000000..809510f --- /dev/null +++ b/ldb-2.0.8/lib/talloc/test_pytalloc.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +# Simple tests for the talloc python bindings. +# Copyright (C) 2015 Petr Viktorin + +import unittest +import subprocess +import sys +import gc + +import talloc +import _test_pytalloc + + +def dummy_func(): + pass + + +class TallocTests(unittest.TestCase): + + def test_report_full(self): + # report_full is hardcoded to print to stdout, so use a subprocess + process = subprocess.Popen([ + sys.executable, '-c', + """if True: + import talloc, _test_pytalloc + obj = _test_pytalloc.new() + talloc.report_full(obj) + """ + ], stdout=subprocess.PIPE) + output, stderr = process.communicate() + output = str(output) + self.assertTrue("full talloc report on 'talloc.Object" in output) + self.assertTrue("This is a test string" in output) + + def test_totalblocks(self): + obj = _test_pytalloc.new() + # Two blocks: the string, and the name + self.assertEqual(talloc.total_blocks(obj), 2) + + def test_repr(self): + obj = _test_pytalloc.new() + prefix = '= obj1) + self.assertFalse(obj1 > obj1) + + def test_compare_different(self): + # object comparison is consistent + obj1, obj2 = sorted([ + _test_pytalloc.new(), + _test_pytalloc.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.Object < _test_pytalloc.DObject: + obj1 = _test_pytalloc.new() + obj2 = _test_pytalloc.DObject(dummy_func) + else: + obj2 = _test_pytalloc.new() + obj1 = _test_pytalloc.DObject(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 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_reference(self): + # Check correct lifetime of the talloc'd data with multiple references + lst = [] + obj = _test_pytalloc.DObject(lambda: lst.append('dead')) + ref = _test_pytalloc.reference(obj) + del obj + gc.collect() + self.assertEqual(lst, []) + del ref + 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/ldb-2.0.8/lib/talloc/testsuite.c b/ldb-2.0.8/lib/talloc/testsuite.c new file mode 100644 index 0000000..a76a647 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/testsuite.c @@ -0,0 +1,2169 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/time.h" +#include + +#ifdef HAVE_PTHREAD +#include +#endif + +#include +#include + +#ifdef NDEBUG +#undef NDEBUG +#endif + +#include + +#include "talloc_testsuite.h" + +static struct timeval private_timeval_current(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv; +} + +static double private_timeval_elapsed(struct timeval *tv) +{ + struct timeval tv2 = private_timeval_current(); + return (tv2.tv_sec - tv->tv_sec) + + (tv2.tv_usec - tv->tv_usec)*1.0e-6; +} + +#define torture_assert(test, expr, str) if (!(expr)) { \ + printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str); \ + return false; \ +} + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + if (arg1 == NULL && arg2 == NULL) { /* OK, both NULL == equal */ \ + } else if (arg1 == NULL || arg2 == NULL) { \ + return false; \ + } else if (strcmp(arg1, arg2)) { \ + printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc); \ + return false; \ + } + +#define CHECK_SIZE(test, ptr, tsize) do { \ + if (talloc_total_size(ptr) != (tsize)) { \ + printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \ + test, __location__, #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize); \ + talloc_report_full(ptr, stdout); \ + return false; \ + } \ +} while (0) + +#define CHECK_BLOCKS(test, ptr, tblocks) do { \ + if (talloc_total_blocks(ptr) != (tblocks)) { \ + printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, __location__, #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks); \ + talloc_report_full(ptr, stdout); \ + return false; \ + } \ +} while (0) + +#define CHECK_PARENT(test, ptr, parent) do { \ + if (talloc_parent(ptr) != (parent)) { \ + printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \ + test, __location__, #ptr, \ + talloc_parent(ptr), \ + (parent)); \ + talloc_report_full(ptr, stdout); \ + talloc_report_full(parent, stdout); \ + talloc_report_full(NULL, stdout); \ + return false; \ + } \ +} while (0) + +static unsigned int test_abort_count; + +#if 0 +static void test_abort_fn(const char *reason) +{ + printf("# test_abort_fn(%s)\n", reason); + test_abort_count++; +} + +static void test_abort_start(void) +{ + test_abort_count = 0; + talloc_set_abort_fn(test_abort_fn); +} +#endif + +static void test_abort_stop(void) +{ + test_abort_count = 0; + talloc_set_abort_fn(NULL); +} + +static void test_log_stdout(const char *message) +{ + fprintf(stdout, "%s", message); +} + +/* + test references +*/ +static bool test_ref1(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref1\n# SINGLE REFERENCE FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(p1, 1, "p2"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 2, "x2"); + talloc_named_const(p1, 3, "x3"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", ref, 1); + CHECK_BLOCKS("ref1", r1, 2); + + fprintf(stderr, "Freeing p2\n"); + talloc_unlink(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", r1, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref1", r1, 1); + + fprintf(stderr, "Freeing r1\n"); + talloc_free(r1); + talloc_report_full(NULL, stderr); + + fprintf(stderr, "Testing NULL\n"); + if (talloc_reference(root, NULL)) { + return false; + } + + CHECK_BLOCKS("ref1", root, 1); + + CHECK_SIZE("ref1", root, 0); + + talloc_free(root); + printf("success: ref1\n"); + return true; +} + +/* + test references +*/ +static bool test_ref2(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref2\n# DOUBLE REFERENCE FREE\n"); + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 2); + + fprintf(stderr, "Freeing ref\n"); + talloc_unlink(r1, ref); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 1); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", p1, 4); + CHECK_BLOCKS("ref2", r1, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref2", r1, 1); + + fprintf(stderr, "Freeing r1\n"); + talloc_free(r1); + talloc_report_full(root, stderr); + + CHECK_SIZE("ref2", root, 0); + + talloc_free(root); + printf("success: ref2\n"); + return true; +} + +/* + test references +*/ +static bool test_ref3(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref3\n# PARENT REFERENCE FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(root, 1, "p2"); + r1 = talloc_named_const(p1, 1, "r1"); + ref = talloc_reference(p2, r1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref3", p1, 2); + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); + CHECK_BLOCKS("ref3", ref, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stderr); + + CHECK_SIZE("ref3", root, 0); + + talloc_free(root); + + printf("success: ref3\n"); + return true; +} + +/* + test references +*/ +static bool test_ref4(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: ref4\n# REFERRER REFERENCE FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); + CHECK_BLOCKS("ref4", ref, 1); + CHECK_BLOCKS("ref4", r1, 2); + + fprintf(stderr, "Freeing r1\n"); + talloc_free(r1); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("ref4", p1, 4); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_SIZE("ref4", root, 0); + + talloc_free(root); + + printf("success: ref4\n"); + return true; +} + + +/* + test references +*/ +static bool test_unlink1(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("test: unlink\n# UNLINK\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(p1, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("unlink", p1, 7); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", ref, 1); + CHECK_BLOCKS("unlink", r1, 2); + + fprintf(stderr, "Unreferencing r1\n"); + talloc_unlink(r1, p2); + talloc_report_full(root, stderr); + + CHECK_BLOCKS("unlink", p1, 6); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", r1, 1); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stderr); + + CHECK_SIZE("unlink", root, 0); + + talloc_free(root); + + printf("success: unlink\n"); + return true; +} + +static int fail_destructor(void *ptr) +{ + return -1; +} + +/* + miscellaneous tests to try to get a higher test coverage percentage +*/ +static bool test_misc(void) +{ + void *root, *p1; + char *p2; + double *d; + const char *name; + + printf("test: misc\n# MISCELLANEOUS\n"); + + root = talloc_new(NULL); + + p1 = talloc_size(root, 0x7fffffff); + torture_assert("misc", !p1, "failed: large talloc allowed\n"); + + p1 = talloc_strdup(root, "foo"); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_unlink(NULL, p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_unlink(NULL, p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + p2 = talloc_strdup(p1, "foo"); + torture_assert("misc", talloc_unlink(root, p2) == -1, + "failed: talloc_unlink() of non-reference context should return -1\n"); + torture_assert("misc", talloc_unlink(p1, p2) == 0, + "failed: talloc_unlink() of parent should succeed\n"); + talloc_unlink(NULL, p1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + + name = talloc_set_name(p1, "my name is %s", "foo"); + torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo", + "failed: wrong name after talloc_set_name(my name is foo)"); + torture_assert_str_equal("misc", talloc_get_name(p1), name, + "failed: wrong name after talloc_set_name(my name is foo)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + + talloc_set_name_const(p1, NULL); + torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED", + "failed: wrong name after talloc_set_name(NULL)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + + torture_assert("misc", talloc_free(NULL) == -1, + "talloc_free(NULL) should give -1\n"); + + talloc_set_destructor(p1, fail_destructor); + torture_assert("misc", talloc_free(p1) == -1, + "Failed destructor should cause talloc_free to fail\n"); + talloc_set_destructor(p1, NULL); + + talloc_report(root, stderr); + + + p2 = (char *)talloc_zero_size(p1, 20); + torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n"); + talloc_free(p2); + + torture_assert("misc", talloc_strdup(root, NULL) == NULL, + "failed: strdup on NULL should give NULL\n"); + + p2 = talloc_strndup(p1, "foo", 2); + torture_assert("misc", strcmp("fo", p2) == 0, + "strndup doesn't work\n"); + p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd'); + torture_assert("misc", strcmp("food", p2) == 0, + "talloc_asprintf_append_buffer doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 3); + + p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world"); + torture_assert("misc", strcmp("hello world", p2) == 0, + "talloc_asprintf_append_buffer doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 3); + talloc_free(p2); + + d = talloc_array(p1, double, 0x20000000); + torture_assert("misc", !d, "failed: integer overflow not detected\n"); + + d = talloc_realloc(p1, d, double, 0x20000000); + torture_assert("misc", !d, "failed: integer overflow not detected\n"); + + talloc_free(p1); + CHECK_BLOCKS("misc", root, 1); + + p1 = talloc_named(root, 100, "%d bytes", 100); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + talloc_unlink(root, p1); + + p1 = talloc_init("%d bytes", 200); + p2 = talloc_asprintf(p1, "my test '%s'", "string"); + torture_assert_str_equal("misc", p2, "my test 'string'", + "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\""); + CHECK_BLOCKS("misc", p1, 3); + CHECK_SIZE("misc", p2, 17); + CHECK_BLOCKS("misc", root, 1); + talloc_unlink(NULL, p1); + + p1 = talloc_named_const(root, 10, "p1"); + p2 = (char *)talloc_named_const(root, 20, "p2"); + (void)talloc_reference(p1, p2); + talloc_report_full(root, stderr); + talloc_unlink(root, p2); + talloc_report_full(root, stderr); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); + talloc_unlink(p1, p2); + talloc_unlink(root, p1); + + p1 = talloc_named_const(root, 10, "p1"); + p2 = (char *)talloc_named_const(root, 20, "p2"); + (void)talloc_reference(NULL, p2); + talloc_report_full(root, stderr); + talloc_unlink(root, p2); + talloc_report_full(root, stderr); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); + talloc_unlink(NULL, p2); + talloc_unlink(root, p1); + + /* Test that talloc_unlink is a no-op */ + + torture_assert("misc", talloc_unlink(root, NULL) == -1, + "failed: talloc_unlink(root, NULL) == -1\n"); + + talloc_report(root, stderr); + talloc_report(NULL, stderr); + + CHECK_SIZE("misc", root, 0); + + talloc_free(root); + + CHECK_SIZE("misc", NULL, 0); + + talloc_enable_null_tracking_no_autofree(); + talloc_enable_leak_report(); + talloc_enable_leak_report_full(); + + printf("success: misc\n"); + + return true; +} + + +/* + test realloc +*/ +static bool test_realloc(void) +{ + void *root, *p1, *p2; + + printf("test: realloc\n# REALLOC\n"); + + root = talloc_new(NULL); + + p1 = talloc_size(root, 10); + CHECK_SIZE("realloc", p1, 10); + + p1 = talloc_realloc_size(NULL, p1, 20); + CHECK_SIZE("realloc", p1, 20); + + talloc_new(p1); + + p2 = talloc_realloc_size(p1, NULL, 30); + + talloc_new(p1); + + p2 = talloc_realloc_size(p1, p2, 40); + + CHECK_SIZE("realloc", p2, 40); + CHECK_SIZE("realloc", root, 60); + CHECK_BLOCKS("realloc", p1, 4); + + p1 = talloc_realloc_size(NULL, p1, 20); + CHECK_SIZE("realloc", p1, 60); + + talloc_increase_ref_count(p2); + torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL, + "failed: talloc_realloc() on a referenced pointer should fail\n"); + CHECK_BLOCKS("realloc", p1, 4); + + talloc_realloc_size(NULL, p2, 0); + talloc_realloc_size(NULL, p2, 0); + CHECK_BLOCKS("realloc", p1, 4); + talloc_realloc_size(p1, p2, 0); + CHECK_BLOCKS("realloc", p1, 3); + + torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL, + "failed: oversize talloc should fail\n"); + + talloc_realloc_size(NULL, p1, 0); + CHECK_BLOCKS("realloc", root, 4); + talloc_realloc_size(root, p1, 0); + CHECK_BLOCKS("realloc", root, 1); + + CHECK_SIZE("realloc", root, 0); + + talloc_free(root); + + printf("success: realloc\n"); + + return true; +} + +/* + test realloc with a child +*/ +static bool test_realloc_child(void) +{ + void *root; + struct el2 { + const char *name; + } *el2, *el2_2, *el2_3, **el_list_save; + struct el1 { + int count; + struct el2 **list, **list2, **list3; + } *el1; + + printf("test: REALLOC WITH CHILD\n"); + + root = talloc_new(NULL); + + el1 = talloc(root, struct el1); + el1->list = talloc(el1, struct el2 *); + el1->list[0] = talloc(el1->list, struct el2); + el1->list[0]->name = talloc_strdup(el1->list[0], "testing"); + + el1->list2 = talloc(el1, struct el2 *); + el1->list2[0] = talloc(el1->list2, struct el2); + el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2"); + + el1->list3 = talloc(el1, struct el2 *); + el1->list3[0] = talloc(el1->list3, struct el2); + el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2"); + + el2 = talloc(el1->list, struct 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); + + el_list_save = el1->list; + el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100); + if (el1->list == el_list_save) { + printf("failure: talloc_realloc didn't move pointer"); + return false; + } + + 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); + + /* Finally check realloc with multiple children */ + el1 = talloc_realloc(root, el1, struct el1, 100); + CHECK_PARENT("el1->list", el1->list, el1); + CHECK_PARENT("el1->list2", el1->list2, el1); + CHECK_PARENT("el1->list3", el1->list3, el1); + + talloc_free(root); + + printf("success: REALLOC WITH CHILD\n"); + return true; +} + +/* + test type checking +*/ +static bool test_type(void) +{ + void *root; + struct el1 { + int count; + }; + struct el2 { + int count; + }; + struct el1 *el1; + + printf("test: type\n# talloc type checking\n"); + + root = talloc_new(NULL); + + el1 = talloc(root, struct el1); + + el1->count = 1; + + torture_assert("type", talloc_get_type(el1, struct el1) == el1, + "type check failed on el1\n"); + torture_assert("type", talloc_get_type(el1, struct el2) == NULL, + "type check failed on el1 with el2\n"); + talloc_set_type(el1, struct el2); + torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1, + "type set failed on el1 with el2\n"); + + talloc_free(root); + + printf("success: type\n"); + return true; +} + +/* + test steal +*/ +static bool test_steal(void) +{ + void *root, *p1, *p2; + + printf("test: steal\n# STEAL\n"); + + root = talloc_new(NULL); + + p1 = talloc_array(root, char, 10); + CHECK_SIZE("steal", p1, 10); + + p2 = talloc_realloc(root, NULL, char, 20); + CHECK_SIZE("steal", p1, 10); + CHECK_SIZE("steal", root, 30); + + torture_assert("steal", talloc_steal(p1, NULL) == NULL, + "failed: stealing NULL should give NULL\n"); + + torture_assert("steal", talloc_steal(p1, p1) == p1, + "failed: stealing to ourselves is a nop\n"); + CHECK_BLOCKS("steal", root, 3); + CHECK_SIZE("steal", root, 30); + + talloc_steal(NULL, p1); + talloc_steal(NULL, p2); + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); + + talloc_free(p1); + talloc_steal(root, p2); + CHECK_BLOCKS("steal", root, 2); + CHECK_SIZE("steal", root, 20); + + talloc_free(p2); + + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); + + talloc_free(root); + + p1 = talloc_size(NULL, 3); + talloc_report_full(NULL, stderr); + CHECK_SIZE("steal", NULL, 3); + talloc_free(p1); + + printf("success: steal\n"); + return true; +} + +/* + test move +*/ +static bool test_move(void) +{ + void *root; + struct t_move { + char *p; + int *x; + } *t1, *t2; + + printf("test: move\n# MOVE\n"); + + root = talloc_new(NULL); + + t1 = talloc(root, struct t_move); + t2 = talloc(root, struct t_move); + t1->p = talloc_strdup(t1, "foo"); + t1->x = talloc(t1, int); + *t1->x = 42; + + t2->p = talloc_move(t2, &t1->p); + t2->x = talloc_move(t2, &t1->x); + torture_assert("move", t1->p == NULL && t1->x == NULL && + strcmp(t2->p, "foo") == 0 && *t2->x == 42, + "talloc move failed"); + + talloc_free(root); + + printf("success: move\n"); + + return true; +} + +/* + test talloc_realloc_fn +*/ +static bool test_realloc_fn(void) +{ + void *root, *p1; + + printf("test: realloc_fn\n# talloc_realloc_fn\n"); + + root = talloc_new(NULL); + + p1 = talloc_realloc_fn(root, NULL, 10); + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 10); + p1 = talloc_realloc_fn(root, p1, 20); + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 20); + p1 = talloc_realloc_fn(root, p1, 0); + CHECK_BLOCKS("realloc_fn", root, 1); + CHECK_SIZE("realloc_fn", root, 0); + + talloc_free(root); + + printf("success: realloc_fn\n"); + return true; +} + + +static bool test_unref_reparent(void) +{ + void *root, *p1, *p2, *c1; + + printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "orig parent"); + p2 = talloc_named_const(root, 1, "parent by reference"); + + c1 = talloc_named_const(p1, 1, "child"); + talloc_reference(p2, c1); + + CHECK_PARENT("unref_reparent", c1, p1); + + talloc_free(p1); + + CHECK_PARENT("unref_reparent", c1, p2); + + talloc_unlink(p2, c1); + + CHECK_SIZE("unref_reparent", root, 1); + + talloc_free(p2); + talloc_free(root); + + printf("success: unref_reparent\n"); + return true; +} + +/* + measure the speed of talloc versus malloc +*/ +static bool test_speed(void) +{ + void *ctx = talloc_new(NULL); + unsigned count; + const int loop = 1000; + int i; + struct timeval tv; + + printf("test: speed\n# TALLOC VS MALLOC SPEED\n"); + + tv = private_timeval_current(); + count = 0; + do { + void *p1, *p2, *p3; + for (i=0;ireq2 = talloc_strdup(req1, "req2"); + talloc_set_destructor(req1->req2, test_loop_destructor); + req1->req3 = talloc_strdup(req1, "req3"); + (void)talloc_reference(req1->req3, req1); + talloc_report_full(top, stderr); + talloc_free(parent); + talloc_report_full(top, stderr); + talloc_report_full(NULL, stderr); + talloc_free(top); + + torture_assert("loop", loop_destructor_count == 1, + "FAILED TO FIRE LOOP DESTRUCTOR\n"); + loop_destructor_count = 0; + + printf("success: loop\n"); + return true; +} + +static int realloc_parent_destructor_count; + +static int test_realloc_parent_destructor(char *ptr) +{ + realloc_parent_destructor_count++; + return 0; +} + +static bool test_realloc_on_destructor_parent(void) +{ + void *top = talloc_new(NULL); + char *parent; + char *a, *b, *C, *D; + realloc_parent_destructor_count = 0; + + printf("test: free_for_exit\n# TALLOC FREE FOR EXIT\n"); + + parent = talloc_strdup(top, "parent"); + a = talloc_strdup(parent, "a"); + b = talloc_strdup(a, "b"); + C = talloc_strdup(a, "C"); + D = talloc_strdup(b, "D"); + talloc_set_destructor(D, test_realloc_parent_destructor); + /* Capitalised ones have destructors. + * + * parent --> a -> b -> D + * -> c + */ + + a = talloc_realloc(parent, a, char, 2048); + + torture_assert("check talloc_realloc", a != NULL, "talloc_realloc failed"); + + talloc_set_destructor(C, test_realloc_parent_destructor); + /* + * parent --> a[2048] -> b -> D + * -> C + * + */ + + talloc_free(parent); + + torture_assert("check destructor realloc_parent_destructor", + realloc_parent_destructor_count == 2, + "FAILED TO FIRE free_for_exit_destructor\n"); + + + printf("success: free_for_exit\n"); + return true; +} + +static int fail_destructor_str(char *ptr) +{ + return -1; +} + +static bool test_free_parent_deny_child(void) +{ + void *top = talloc_new(NULL); + char *level1; + char *level2; + char *level3; + + printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n"); + + level1 = talloc_strdup(top, "level1"); + level2 = talloc_strdup(level1, "level2"); + level3 = talloc_strdup(level2, "level3"); + + talloc_set_destructor(level3, fail_destructor_str); + talloc_free(level1); + talloc_set_destructor(level3, NULL); + + CHECK_PARENT("free_parent_deny_child", level3, top); + + talloc_free(top); + + printf("success: free_parent_deny_child\n"); + return true; +} + +struct new_parent { + void *new_parent; + char val[20]; +}; + +static int reparenting_destructor(struct new_parent *np) +{ + talloc_set_destructor(np, NULL); + (void)talloc_move(np->new_parent, &np); + return -1; +} + +static bool test_free_parent_reparent_child(void) +{ + void *top = talloc_new(NULL); + char *level1; + char *alternate_level1; + char *level2; + struct new_parent *level3; + + printf("test: free_parent_reparent_child\n# " + "TALLOC FREE PARENT REPARENT CHILD\n"); + + level1 = talloc_strdup(top, "level1"); + alternate_level1 = talloc_strdup(top, "alternate_level1"); + level2 = talloc_strdup(level1, "level2"); + level3 = talloc(level2, struct new_parent); + level3->new_parent = alternate_level1; + memset(level3->val, 'x', sizeof(level3->val)); + + talloc_set_destructor(level3, reparenting_destructor); + talloc_free(level1); + + CHECK_PARENT("free_parent_reparent_child", + level3, alternate_level1); + + talloc_free(top); + + printf("success: free_parent_reparent_child\n"); + return true; +} + +static bool test_free_parent_reparent_child_in_pool(void) +{ + void *top = talloc_new(NULL); + char *level1; + char *alternate_level1; + char *level2; + void *pool; + struct new_parent *level3; + + printf("test: free_parent_reparent_child_in_pool\n# " + "TALLOC FREE PARENT REPARENT CHILD IN POOL\n"); + + pool = talloc_pool(top, 1024); + level1 = talloc_strdup(pool, "level1"); + alternate_level1 = talloc_strdup(top, "alternate_level1"); + level2 = talloc_strdup(level1, "level2"); + level3 = talloc(level2, struct new_parent); + level3->new_parent = alternate_level1; + memset(level3->val, 'x', sizeof(level3->val)); + + talloc_set_destructor(level3, reparenting_destructor); + talloc_free(level1); + talloc_set_destructor(level3, NULL); + + CHECK_PARENT("free_parent_reparent_child_in_pool", + level3, alternate_level1); + + /* Even freeing alternate_level1 should leave pool alone. */ + talloc_free(alternate_level1); + talloc_free(top); + + printf("success: free_parent_reparent_child_in_pool\n"); + return true; +} + + +static bool test_talloc_ptrtype(void) +{ + void *top = talloc_new(NULL); + struct struct1 { + int foo; + int bar; + } *s1, *s2, **s3, ***s4; + const char *location1; + const char *location2; + const char *location3; + const char *location4; + + printf("test: ptrtype\n# TALLOC PTRTYPE\n"); + + s1 = talloc_ptrtype(top, s1);location1 = __location__; + + if (talloc_get_size(s1) != sizeof(struct struct1)) { + printf("failure: ptrtype [\n" + "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n" + "]\n", (unsigned long)talloc_get_size(s1), + (unsigned long)sizeof(struct struct1)); + return false; + } + + if (strcmp(location1, talloc_get_name(s1)) != 0) { + printf("failure: ptrtype [\n" + "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n", + talloc_get_name(s1), location1); + return false; + } + + s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__; + + if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) { + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s2), + (unsigned long)(sizeof(struct struct1)*10)); + return false; + } + + if (strcmp(location2, talloc_get_name(s2)) != 0) { + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n", + talloc_get_name(s2), location2); + return false; + } + + s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__; + + if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) { + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s3), + (unsigned long)(sizeof(struct struct1 *)*10)); + return false; + } + + torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3), + "talloc_array_ptrtype() sets the wrong name"); + + s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__; + + if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) { + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s4), + (unsigned long)(sizeof(struct struct1 **)*10)); + return false; + } + + torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4), + "talloc_array_ptrtype() sets the wrong name"); + + talloc_free(top); + + printf("success: ptrtype\n"); + return true; +} + +static int _test_talloc_free_in_destructor(void **ptr) +{ + talloc_free(*ptr); + return 0; +} + +static bool test_talloc_free_in_destructor(void) +{ + void *level0; + void *level1; + void *level2; + void *level3; + void *level4; + void **level5; + + printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n"); + + level0 = talloc_new(NULL); + level1 = talloc_new(level0); + level2 = talloc_new(level1); + level3 = talloc_new(level2); + level4 = talloc_new(level3); + level5 = talloc(level4, void *); + + *level5 = level3; + (void)talloc_reference(level0, level3); + (void)talloc_reference(level3, level3); + (void)talloc_reference(level5, level3); + + talloc_set_destructor(level5, _test_talloc_free_in_destructor); + + talloc_free(level1); + + talloc_free(level0); + + printf("success: free_in_destructor\n"); + return true; +} + +static bool test_autofree(void) +{ +#if _SAMBA_BUILD_ < 4 + /* autofree test would kill smbtorture */ + void *p; + printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n"); + + p = talloc_autofree_context(); + talloc_free(p); + + p = talloc_autofree_context(); + talloc_free(p); + + printf("success: autofree\n"); +#endif + return true; +} + +static bool test_pool(void) +{ + void *pool; + void *p1, *p2, *p3, *p4; + void *p2_2; + + pool = talloc_pool(NULL, 1024); + + p1 = talloc_size(pool, 80); + memset(p1, 0x11, talloc_get_size(p1)); + p2 = talloc_size(pool, 20); + memset(p2, 0x11, talloc_get_size(p2)); + p3 = talloc_size(p1, 50); + memset(p3, 0x11, talloc_get_size(p3)); + p4 = talloc_size(p3, 1000); + memset(p4, 0x11, talloc_get_size(p4)); + +#if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ + p2_2 = talloc_realloc_size(pool, p2, 20+1); + torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed"); + memset(p2, 0x11, talloc_get_size(p2)); + p2_2 = talloc_realloc_size(pool, p2, 20-1); + torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); + memset(p2, 0x11, talloc_get_size(p2)); + p2_2 = talloc_realloc_size(pool, p2, 20-1); + torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); + memset(p2, 0x11, talloc_get_size(p2)); + + talloc_free(p3); + + /* this should reclaim the memory of p4 and p3 */ + p2_2 = talloc_realloc_size(pool, p2, 400); + torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed"); + memset(p2, 0x11, talloc_get_size(p2)); + + talloc_free(p1); + + /* this should reclaim the memory of p1 */ + p2_2 = talloc_realloc_size(pool, p2, 800); + torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed"); + p2 = p2_2; + memset(p2, 0x11, talloc_get_size(p2)); + + /* this should do a malloc */ + p2_2 = talloc_realloc_size(pool, p2, 1800); + torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed"); + p2 = p2_2; + memset(p2, 0x11, talloc_get_size(p2)); + + /* this should reclaim the memory from the pool */ + p3 = talloc_size(pool, 80); + torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed"); + memset(p3, 0x11, talloc_get_size(p3)); + + talloc_free(p2); + talloc_free(p3); + + p1 = talloc_size(pool, 80); + memset(p1, 0x11, talloc_get_size(p1)); + p2 = talloc_size(pool, 20); + memset(p2, 0x11, talloc_get_size(p2)); + + talloc_free(p1); + + p2_2 = talloc_realloc_size(pool, p2, 20-1); + torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); + memset(p2, 0x11, talloc_get_size(p2)); + p2_2 = talloc_realloc_size(pool, p2, 20-1); + torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed"); + memset(p2, 0x11, talloc_get_size(p2)); + + /* this should do a malloc */ + p2_2 = talloc_realloc_size(pool, p2, 1800); + torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed"); + p2 = p2_2; + memset(p2, 0x11, talloc_get_size(p2)); + + /* this should reclaim the memory from the pool */ + p3 = talloc_size(pool, 800); + torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed"); + memset(p3, 0x11, talloc_get_size(p3)); + +#endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ + + talloc_free(pool); + + return true; +} + +static bool test_pool_steal(void) +{ + void *root; + void *pool; + void *p1, *p2; + void *p1_2, *p2_2; + size_t hdr; + size_t ofs1, ofs2; + + root = talloc_new(NULL); + pool = talloc_pool(root, 1024); + + p1 = talloc_size(pool, 4 * 16); + torture_assert("pool allocate 4 * 16", p1 != NULL, "failed "); + memset(p1, 0x11, talloc_get_size(p1)); + p2 = talloc_size(pool, 4 * 16); + torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) "); + memset(p2, 0x11, talloc_get_size(p2)); + + ofs1 = PTR_DIFF(p2, p1); + hdr = ofs1 - talloc_get_size(p1); + + talloc_steal(root, p1); + talloc_steal(root, p2); + + talloc_free(pool); + + p1_2 = p1; + +#if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ + p1_2 = talloc_realloc_size(root, p1, 5 * 16); + torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed"); + memset(p1_2, 0x11, talloc_get_size(p1_2)); + ofs1 = PTR_DIFF(p1_2, p2); + ofs2 = talloc_get_size(p2) + hdr; + + torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected"); + + p2_2 = talloc_realloc_size(root, p2, 3 * 16); + torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed"); + memset(p2_2, 0x11, talloc_get_size(p2_2)); +#endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ + + talloc_free(p1_2); + + p2_2 = p2; + +#if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ + /* now we should reclaim the full pool */ + p2_2 = talloc_realloc_size(root, p2, 8 * 16); + torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected"); + p2 = p2_2; + memset(p2_2, 0x11, talloc_get_size(p2_2)); + + /* now we malloc and free the full pool space */ + p2_2 = talloc_realloc_size(root, p2, 2 * 1024); + torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected"); + memset(p2_2, 0x11, talloc_get_size(p2_2)); + +#endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */ + + talloc_free(p2_2); + + talloc_free(root); + + return true; +} + +static bool test_pool_nest(void) +{ + void *p1, *p2, *p3; + void *e = talloc_new(NULL); + + p1 = talloc_pool(NULL, 1024); + torture_assert("talloc_pool", p1 != NULL, "failed"); + + p2 = talloc_pool(p1, 500); + torture_assert("talloc_pool", p2 != NULL, "failed"); + + p3 = talloc_size(p2, 10); + + talloc_steal(e, p3); + + talloc_free(p2); + + talloc_free(p3); + + talloc_free(p1); + + return true; +} + +struct pooled { + char *s1; + char *s2; + char *s3; +}; + +static bool test_pooled_object(void) +{ + struct pooled *p; + const char *s1 = "hello"; + const char *s2 = "world"; + const char *s3 = ""; + + p = talloc_pooled_object(NULL, struct pooled, 3, + strlen(s1)+strlen(s2)+strlen(s3)+3); + + if (talloc_get_size(p) != sizeof(struct pooled)) { + return false; + } + + p->s1 = talloc_strdup(p, s1); + + TALLOC_FREE(p->s1); + p->s1 = talloc_strdup(p, s2); + TALLOC_FREE(p->s1); + + p->s1 = talloc_strdup(p, s1); + p->s2 = talloc_strdup(p, s2); + p->s3 = talloc_strdup(p, s3); + + TALLOC_FREE(p); + return true; +} + +static bool test_free_ref_null_context(void) +{ + void *p1, *p2, *p3; + int ret; + + talloc_disable_null_tracking(); + p1 = talloc_new(NULL); + p2 = talloc_new(NULL); + + p3 = talloc_reference(p2, p1); + torture_assert("reference", p3 == p1, "failed: reference on null"); + + ret = talloc_free(p1); + torture_assert("ref free with null parent", ret == 0, "failed: free with null parent"); + talloc_free(p2); + + talloc_enable_null_tracking_no_autofree(); + p1 = talloc_new(NULL); + p2 = talloc_new(NULL); + + p3 = talloc_reference(p2, p1); + torture_assert("reference", p3 == p1, "failed: reference on null"); + + ret = talloc_free(p1); + torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent"); + talloc_free(p2); + + return true; +} + +static bool test_rusty(void) +{ + void *root; + const char *p1; + + talloc_enable_null_tracking(); + root = talloc_new(NULL); + p1 = talloc_strdup(root, "foo"); + talloc_increase_ref_count(p1); + talloc_report_full(root, stdout); + talloc_free(root); + CHECK_BLOCKS("null_context", NULL, 2); + return true; +} + +static bool test_free_children(void) +{ + void *root; + char *p1, *p2; + const char *name, *name2; + + talloc_enable_null_tracking(); + root = talloc_new(NULL); + p1 = talloc_strdup(root, "foo1"); + p2 = talloc_strdup(p1, "foo2"); + (void)p2; + + talloc_set_name(p1, "%s", "testname"); + talloc_free_children(p1); + /* check its still a valid talloc ptr */ + talloc_get_size(talloc_get_name(p1)); + if (strcmp(talloc_get_name(p1), "testname") != 0) { + return false; + } + + talloc_set_name(p1, "%s", "testname"); + name = talloc_get_name(p1); + talloc_free_children(p1); + /* check its still a valid talloc ptr */ + talloc_get_size(talloc_get_name(p1)); + torture_assert("name", name == talloc_get_name(p1), "name ptr changed"); + torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0, + "wrong name"); + CHECK_BLOCKS("name1", p1, 2); + + /* note that this does not free the old child name */ + talloc_set_name_const(p1, "testname2"); + name2 = talloc_get_name(p1); + /* but this does */ + talloc_free_children(p1); + (void)name2; + torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0, + "wrong name"); + CHECK_BLOCKS("name1", p1, 1); + + talloc_report_full(root, stdout); + talloc_free(root); + return true; +} + +static bool test_memlimit(void) +{ + void *root; + char *l1, *l2, *l3, *l4, *l5, *t; + char *pool; + int i; + + printf("test: memlimit\n# MEMORY LIMITS\n"); + + printf("==== talloc_new(NULL)\n"); + root = talloc_new(NULL); + + talloc_report_full(root, stdout); + + printf("==== talloc_size(root, 2048)\n"); + l1 = talloc_size(root, 2048); + torture_assert("memlimit", l1 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_free(l1)\n"); + talloc_free(l1); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(root, level 1)\n"); + l1 = talloc_strdup(root, "level 1"); + torture_assert("memlimit", l1 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_set_memlimit(l1, 2048)\n"); + torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0, + "failed: setting memlimit should never fail\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_size(root, 2048)\n"); + l2 = talloc_size(l1, 2048); + torture_assert("memlimit", l2 == NULL, + "failed: alloc should fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(l1, level 2)\n"); + l2 = talloc_strdup(l1, "level 2"); + torture_assert("memlimit", l2 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_free(l2)\n"); + talloc_free(l2); + + talloc_report_full(root, stdout); + + printf("==== talloc_size(NULL, 2048)\n"); + l2 = talloc_size(NULL, 2048); + + talloc_report_full(root, stdout); + + printf("==== talloc_steal(l1, l2)\n"); + talloc_steal(l1, l2); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(l2, level 3)\n"); + l3 = talloc_strdup(l2, "level 3"); + torture_assert("memlimit", l3 == NULL, + "failed: alloc should fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_free(l2)\n"); + talloc_free(l2); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(NULL, level 2)\n"); + l2 = talloc_strdup(NULL, "level 2"); + talloc_steal(l1, l2); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(l2, level 3)\n"); + l3 = talloc_strdup(l2, "level 3"); + torture_assert("memlimit", l3 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_set_memlimit(l3, 1024)\n"); + torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0, + "failed: setting memlimit should never fail\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(l3, level 4)\n"); + l4 = talloc_strdup(l3, "level 4"); + torture_assert("memlimit", l4 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_set_memlimit(l4, 512)\n"); + torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0, + "failed: setting memlimit should never fail\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(l4, level 5)\n"); + l5 = talloc_strdup(l4, "level 5"); + torture_assert("memlimit", l5 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_realloc(NULL, l5, char, 600)\n"); + t = talloc_realloc(NULL, l5, char, 600); + torture_assert("memlimit", t == NULL, + "failed: alloc should fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_realloc(NULL, l5, char, 5)\n"); + l5 = talloc_realloc(NULL, l5, char, 5); + torture_assert("memlimit", l5 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(l3, level 4)\n"); + l4 = talloc_strdup(l3, "level 4"); + torture_assert("memlimit", l4 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_set_memlimit(l4, 512)\n"); + torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0, + "failed: setting memlimit should never fail\n"); + + talloc_report_full(root, stdout); + + printf("==== talloc_strdup(l4, level 5)\n"); + l5 = talloc_strdup(l4, "level 5"); + torture_assert("memlimit", l5 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + + printf("==== Make new temp context and steal l5\n"); + t = talloc_new(root); + talloc_steal(t, l5); + + talloc_report_full(root, stdout); + + printf("==== talloc_size(t, 2048)\n"); + l1 = talloc_size(t, 2048); + torture_assert("memlimit", l1 != NULL, + "failed: alloc should not fail due to memory limit\n"); + + talloc_report_full(root, stdout); + talloc_free(root); + + /* Test memlimits with pools. */ + pool = talloc_pool(NULL, 10*1024); + torture_assert("memlimit", pool != NULL, + "failed: alloc should not fail due to memory limit\n"); + talloc_set_memlimit(pool, 10*1024); + for (i = 0; i < 9; i++) { + l1 = talloc_size(pool, 1024); + torture_assert("memlimit", l1 != NULL, + "failed: alloc should not fail due to memory limit\n"); + } + /* The next alloc should fail. */ + l2 = talloc_size(pool, 1024); + torture_assert("memlimit", l2 == NULL, + "failed: alloc should fail due to memory limit\n"); + + /* Moving one of the children shouldn't change the limit, + as it's still inside the pool. */ + root = talloc_new(NULL); + talloc_steal(root, l1); + l2 = talloc_size(pool, 1024); + torture_assert("memlimit", l2 == NULL, + "failed: alloc should fail due to memory limit\n"); + + talloc_free(pool); + talloc_free(root); + printf("success: memlimit\n"); + + return true; +} + +#ifdef HAVE_PTHREAD + +#define NUM_THREADS 100 + +/* Sync variables. */ +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; +static void *intermediate_ptr; + +/* Subthread. */ +static void *thread_fn(void *arg) +{ + int ret; + const char *ctx_name = (const char *)arg; + void *sub_ctx = NULL; + /* + * Do stuff that creates a new talloc hierarchy in + * this thread. + */ + void *top_ctx = talloc_named_const(NULL, 0, "top"); + if (top_ctx == NULL) { + return NULL; + } + sub_ctx = talloc_named_const(top_ctx, 100, ctx_name); + if (sub_ctx == NULL) { + return NULL; + } + + /* + * Now transfer a pointer from our hierarchy + * onto the intermediate ptr. + */ + ret = pthread_mutex_lock(&mtx); + if (ret != 0) { + talloc_free(top_ctx); + return NULL; + } + /* Wait for intermediate_ptr to be free. */ + while (intermediate_ptr != NULL) { + ret = pthread_cond_wait(&condvar, &mtx); + if (ret != 0) { + talloc_free(top_ctx); + ret = pthread_mutex_unlock(&mtx); + assert(ret == 0); + return NULL; + } + } + + /* and move our memory onto it from our toplevel hierarchy. */ + intermediate_ptr = talloc_move(NULL, &sub_ctx); + + /* Tell the main thread it's ready for pickup. */ + pthread_cond_broadcast(&condvar); + ret = pthread_mutex_unlock(&mtx); + assert(ret == 0); + + talloc_free(top_ctx); + return NULL; +} + +/* Main thread. */ +static bool test_pthread_talloc_passing(void) +{ + int i; + int ret; + char str_array[NUM_THREADS][20]; + pthread_t thread_id; + void *mem_ctx; + + /* + * Important ! Null tracking breaks threaded talloc. + * It *must* be turned off. + */ + talloc_disable_null_tracking(); + + printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n"); + + /* Main thread toplevel context. */ + mem_ctx = talloc_named_const(NULL, 0, "toplevel"); + if (mem_ctx == NULL) { + printf("failed to create toplevel context\n"); + return false; + } + + /* + * Spin off NUM_THREADS threads. + * They will use their own toplevel contexts. + */ + for (i = 0; i < NUM_THREADS; i++) { + ret = snprintf(str_array[i], + 20, + "thread:%d", + i); + if (ret < 0) { + printf("snprintf %d failed\n", i); + return false; + } + ret = pthread_create(&thread_id, + NULL, + thread_fn, + str_array[i]); + if (ret != 0) { + printf("failed to create thread %d (%d)\n", i, ret); + return false; + } + } + + printf("Created %d threads\n", NUM_THREADS); + + /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */ + for (i = 0; i < NUM_THREADS; i++) { + ret = pthread_mutex_lock(&mtx); + if (ret != 0) { + printf("pthread_mutex_lock %d failed (%d)\n", i, ret); + talloc_free(mem_ctx); + return false; + } + + /* Wait for intermediate_ptr to have our data. */ + while (intermediate_ptr == NULL) { + ret = pthread_cond_wait(&condvar, &mtx); + if (ret != 0) { + printf("pthread_cond_wait %d failed (%d)\n", i, + ret); + talloc_free(mem_ctx); + ret = pthread_mutex_unlock(&mtx); + assert(ret == 0); + } + } + + /* and move it onto our toplevel hierarchy. */ + (void)talloc_move(mem_ctx, &intermediate_ptr); + + /* Tell the sub-threads we're ready for another. */ + pthread_cond_broadcast(&condvar); + ret = pthread_mutex_unlock(&mtx); + assert(ret == 0); + } + + CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100); +#if 1 + /* Dump the hierarchy. */ + talloc_report(mem_ctx, stdout); +#endif + talloc_free(mem_ctx); + printf("success: pthread_talloc_passing\n"); + return true; +} +#endif + +static void test_magic_protection_abort(const char *reason) +{ + /* exit with errcode 42 to communicate successful test to the parent process */ + if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) { + _exit(42); + } else { + printf("talloc aborted for an unexpected reason\n"); + } +} + +static int test_magic_protection_destructor(int *ptr) +{ + _exit(404); /* Not 42 */ +} + +static bool test_magic_protection(void) +{ + void *pool = talloc_pool(NULL, 1024); + int *p1, *p2; + pid_t pid; + int exit_status; + + printf("test: magic_protection\n"); + p1 = talloc(pool, int); + p2 = talloc(pool, int); + + /* To avoid complaints from the compiler assign values to the p1 & p2. */ + *p1 = 6; + *p2 = 9; + + 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 + * by triggering a buffer overflow in memset to overwrite the + * constructor in the next pool chunk. + * + * Real attacks would attempt to set a real destructor. + */ + memset(p1, '\0', 32); + + /* Then the attack takes effect when the memory's freed. */ + talloc_free(pool); + + /* Never reached. Make compilers happy */ + return true; + } + + while (wait(&exit_status) != pid); + + if (!WIFEXITED(exit_status)) { + printf("Child exited through unexpected abnormal means\n"); + return false; + } + if (WEXITSTATUS(exit_status) != 42) { + printf("Child exited with wrong exit status\n"); + return false; + } + if (WIFSIGNALED(exit_status)) { + printf("Child recieved unexpected signal\n"); + return false; + } + + printf("success: magic_protection\n"); + return true; +} + +static void test_magic_free_protection_abort(const char *reason) +{ + /* exit with errcode 42 to communicate successful test to the parent process */ + if (strcmp(reason, "Bad talloc magic value - access after free") == 0) { + _exit(42); + } + /* not 42 */ + _exit(404); +} + +static bool test_magic_free_protection(void) +{ + void *pool = talloc_pool(NULL, 1024); + int *p1, *p2, *p3; + pid_t pid; + int exit_status; + + printf("test: magic_free_protection\n"); + p1 = talloc(pool, int); + p2 = talloc(pool, int); + + /* To avoid complaints from the compiler assign values to the p1 & p2. */ + *p1 = 6; + *p2 = 9; + + p3 = talloc_realloc(pool, p2, int, 2048); + torture_assert("pool realloc 2048", + p3 != p2, + "failed: pointer not changed"); + + /* + * Now access the memory in the pool after the realloc(). It + * should be marked as free, so use of the old pointer should + * trigger the abort function + */ + pid = fork(); + if (pid == 0) { + talloc_set_abort_fn(test_magic_free_protection_abort); + + talloc_get_name(p2); + + /* Never reached. Make compilers happy */ + return true; + } + + while (wait(&exit_status) != pid); + + if (!WIFEXITED(exit_status)) { + printf("Child exited through unexpected abnormal means\n"); + return false; + } + if (WEXITSTATUS(exit_status) != 42) { + printf("Child exited with wrong exit status\n"); + return false; + } + if (WIFSIGNALED(exit_status)) { + printf("Child recieved unexpected signal\n"); + return false; + } + + talloc_free(pool); + + printf("success: magic_free_protection\n"); + return true; +} + +static void test_reset(void) +{ + talloc_set_log_fn(test_log_stdout); + test_abort_stop(); + talloc_disable_null_tracking(); + talloc_enable_null_tracking_no_autofree(); +} + +bool torture_local_talloc(struct torture_context *tctx) +{ + bool ret = true; + + setlinebuf(stdout); + + test_reset(); + ret &= test_pooled_object(); + test_reset(); + ret &= test_pool_nest(); + test_reset(); + ret &= test_ref1(); + test_reset(); + ret &= test_ref2(); + test_reset(); + ret &= test_ref3(); + test_reset(); + ret &= test_ref4(); + test_reset(); + ret &= test_unlink1(); + test_reset(); + ret &= test_misc(); + test_reset(); + ret &= test_realloc(); + test_reset(); + ret &= test_realloc_child(); + test_reset(); + ret &= test_steal(); + test_reset(); + ret &= test_move(); + test_reset(); + ret &= test_unref_reparent(); + test_reset(); + ret &= test_realloc_fn(); + test_reset(); + ret &= test_type(); + test_reset(); + ret &= test_lifeless(); + test_reset(); + ret &= test_loop(); + test_reset(); + ret &= test_free_parent_deny_child(); + test_reset(); + ret &= test_realloc_on_destructor_parent(); + test_reset(); + ret &= test_free_parent_reparent_child(); + test_reset(); + ret &= test_free_parent_reparent_child_in_pool(); + test_reset(); + ret &= test_talloc_ptrtype(); + test_reset(); + ret &= test_talloc_free_in_destructor(); + test_reset(); + ret &= test_pool(); + test_reset(); + ret &= test_pool_steal(); + test_reset(); + ret &= test_free_ref_null_context(); + test_reset(); + ret &= test_rusty(); + test_reset(); + ret &= test_free_children(); + test_reset(); + ret &= test_memlimit(); +#ifdef HAVE_PTHREAD + test_reset(); + ret &= test_pthread_talloc_passing(); +#endif + + + if (ret) { + test_reset(); + ret &= test_speed(); + } + test_reset(); + ret &= test_autofree(); + test_reset(); + ret &= test_magic_protection(); + test_reset(); + ret &= test_magic_free_protection(); + + test_reset(); + talloc_disable_null_tracking(); + return ret; +} diff --git a/ldb-2.0.8/lib/talloc/testsuite_main.c b/ldb-2.0.8/lib/talloc/testsuite_main.c new file mode 100644 index 0000000..50ce0f8 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/testsuite_main.c @@ -0,0 +1,36 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ + +#include "replace.h" + +#include "talloc_testsuite.h" + +int main(void) +{ + bool ret = torture_local_talloc(NULL); + if (!ret) + return -1; + return 0; +} diff --git a/ldb-2.0.8/lib/talloc/web/index.html b/ldb-2.0.8/lib/talloc/web/index.html new file mode 100644 index 0000000..388ec2c --- /dev/null +++ b/ldb-2.0.8/lib/talloc/web/index.html @@ -0,0 +1,51 @@ + + + +talloc + + + +

talloc

+ +talloc is a hierarchical pool based memory allocator with +destructors. It is the core memory allocator used in Samba, and has +made a huge difference in many aspects of Samba4 development.

+ +To get started with talloc, I would recommend you read the talloc guide. + +

Download

+You can download the latest releases of talloc from the talloc directory on the samba public +source archive. + +

Discussion and bug reports

+ +talloc does not currently have its own mailing list or bug tracking +system. For now, please use the samba-technical +mailing list, and the Samba +bugzilla bug tracking system. + +

Development

+ +You can download the latest code either via git or rsync.
+
+To fetch via git see the following guide:
+Using Git for Samba Development
+Once you have cloned the tree switch to the master branch and cd into the lib/talloc directory.
+
+To fetch via rsync use this command: + +
+  rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/talloc .
+
+ +
+ +Andrew Tridgell
+talloc AT tridgell.net +
+ + + diff --git a/ldb-2.0.8/lib/talloc/wscript b/ldb-2.0.8/lib/talloc/wscript new file mode 100644 index 0000000..eda62d1 --- /dev/null +++ b/ldb-2.0.8/lib/talloc/wscript @@ -0,0 +1,198 @@ +#!/usr/bin/env python + +APPNAME = 'talloc' +VERSION = '2.2.0' + +import os +import sys + +# find the buildtools directory +top = '.' +while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5: + top = top + '/..' +sys.path.insert(0, top + '/buildtools/wafsamba') + +out = 'bin' + +import wafsamba +from wafsamba import samba_dist, samba_utils +from waflib import Logs, Options, Context + +# setup what directories to put in a tarball +samba_dist.DIST_DIRS("""lib/talloc:. lib/replace:lib/replace +buildtools:buildtools third_party/waf:third_party/waf""") + + +def options(opt): + opt.BUILTIN_DEFAULT('replace') + opt.PRIVATE_EXTENSION_DEFAULT('talloc', noextension='talloc') + opt.RECURSE('lib/replace') + if opt.IN_LAUNCH_DIR(): + opt.add_option('--enable-talloc-compat1', + help=("Build talloc 1.x.x compat library [False]"), + action="store_true", dest='TALLOC_COMPAT1', default=False) + + +def configure(conf): + conf.RECURSE('lib/replace') + + conf.env.standalone_talloc = conf.IN_LAUNCH_DIR() + + conf.define('TALLOC_BUILD_VERSION_MAJOR', int(VERSION.split('.')[0])) + conf.define('TALLOC_BUILD_VERSION_MINOR', int(VERSION.split('.')[1])) + conf.define('TALLOC_BUILD_VERSION_RELEASE', int(VERSION.split('.')[2])) + + conf.env.TALLOC_COMPAT1 = False + if conf.env.standalone_talloc: + conf.env.TALLOC_COMPAT1 = Options.options.TALLOC_COMPAT1 + conf.env.PKGCONFIGDIR = '${LIBDIR}/pkgconfig' + conf.env.TALLOC_VERSION = VERSION + + conf.CHECK_XSLTPROC_MANPAGES() + + conf.CHECK_HEADERS('sys/auxv.h') + conf.CHECK_FUNCS('getauxval') + + conf.SAMBA_CONFIG_H() + + conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS() + + conf.SAMBA_CHECK_PYTHON() + conf.SAMBA_CHECK_PYTHON_HEADERS() + + if not conf.env.standalone_talloc: + if conf.CHECK_BUNDLED_SYSTEM_PKG('talloc', minversion=VERSION, + implied_deps='replace'): + conf.define('USING_SYSTEM_TALLOC', 1) + + if conf.env.disable_python: + using_system_pytalloc_util = False + else: + using_system_pytalloc_util = True + name = 'pytalloc-util' + conf.all_envs['default']['PYTHON_SO_ABI_FLAG'] + if not conf.CHECK_BUNDLED_SYSTEM_PKG(name, minversion=VERSION, + implied_deps='talloc replace'): + using_system_pytalloc_util = False + + if using_system_pytalloc_util: + conf.define('USING_SYSTEM_PYTALLOC_UTIL', 1) + + +def build(bld): + bld.RECURSE('lib/replace') + + if bld.env.standalone_talloc: + private_library = False + + # should we also install the symlink to libtalloc1.so here? + bld.SAMBA_LIBRARY('talloc-compat1-%s' % (VERSION), + 'compat/talloc_compat1.c', + public_deps='talloc', + soname='libtalloc.so.1', + pc_files=[], + public_headers=[], + enabled=bld.env.TALLOC_COMPAT1) + + testsuite_deps = 'talloc' + if bld.CONFIG_SET('HAVE_PTHREAD'): + testsuite_deps += ' pthread' + + bld.SAMBA_BINARY('talloc_testsuite', + 'testsuite_main.c testsuite.c', + testsuite_deps, + install=False) + + bld.SAMBA_BINARY('talloc_test_magic_differs_helper', + 'test_magic_differs_helper.c', + 'talloc', install=False) + + else: + private_library = True + + if not bld.CONFIG_SET('USING_SYSTEM_TALLOC'): + + bld.SAMBA_LIBRARY('talloc', + 'talloc.c', + deps='replace', + abi_directory='ABI', + abi_match='talloc* _talloc*', + hide_symbols=True, + vnum=VERSION, + public_headers=('' if private_library else 'talloc.h'), + pc_files='talloc.pc', + public_headers_install=not private_library, + private_library=private_library, + manpages='man/talloc.3') + + if not bld.CONFIG_SET('USING_SYSTEM_PYTALLOC_UTIL'): + name = bld.pyembed_libname('pytalloc-util') + + bld.SAMBA_LIBRARY(name, + source='pytalloc_util.c', + public_deps='talloc', + pyembed=True, + vnum=VERSION, + hide_symbols=True, + abi_directory='ABI', + abi_match='pytalloc_* _pytalloc_*', + private_library=private_library, + public_headers=('' if private_library else 'pytalloc.h'), + pc_files='pytalloc-util.pc', + enabled=bld.PYTHON_BUILD_IS_ENABLED() + ) + bld.SAMBA_PYTHON('pytalloc', + 'pytalloc.c', + deps='talloc ' + name, + enabled=bld.PYTHON_BUILD_IS_ENABLED(), + realname='talloc.so') + + bld.SAMBA_PYTHON('test_pytalloc', + 'test_pytalloc.c', + deps=name, + enabled=bld.PYTHON_BUILD_IS_ENABLED(), + realname='_test_pytalloc.so', + install=False) + + +def testonly(ctx): + '''run talloc testsuite''' + import samba_utils + + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') + + cmd = os.path.join(Context.g_module.out, 'talloc_testsuite') + ret = samba_utils.RUN_COMMAND(cmd) + print("testsuite returned %d" % ret) + magic_helper_cmd = os.path.join(Context.g_module.out, 'talloc_test_magic_differs_helper') + magic_cmd = os.path.join(Context.g_module.top, 'lib', 'talloc', + 'test_magic_differs.sh') + if not os.path.exists(magic_cmd): + magic_cmd = os.path.join(Context.g_module.top, 'test_magic_differs.sh') + + 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) + sys.exit(ret or magic_ret or pyret) + +# WAF doesn't build the unit tests for this, maybe because they don't link with talloc? +# This forces it +def test(ctx): + Options.commands.append('build') + Options.commands.append('testonly') + +def dist(): + '''makes a tarball for distribution''' + samba_dist.dist() + +def reconfigure(ctx): + '''reconfigure if config scripts have changed''' + samba_utils.reconfigure(ctx) + + +def pydoctor(ctx): + '''build python apidocs''' + cmd='PYTHONPATH=bin/python pydoctor --project-name=talloc --project-url=http://talloc.samba.org/ --make-html --docformat=restructuredtext --introspect-c-modules --add-module bin/python/talloc.*' + print("Running: %s" % cmd) + os.system(cmd) diff --git a/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.1.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.1.sigs new file mode 100644 index 0000000..84f2007 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.1.sigs @@ -0,0 +1,95 @@ +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_allrecord_lock: int (struct tdb_context *, int, enum tdb_lock_flags, bool) +tdb_allrecord_unlock: int (struct tdb_context *, int, bool) +tdb_allrecord_upgrade: int (struct tdb_context *) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, int, tdb_off_t, size_t, enum tdb_lock_flags) +tdb_brunlock: int (struct tdb_context *, int, tdb_off_t, size_t) +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_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_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +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_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +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_have_extra_locks: bool (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +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_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_needs_recovery: bool (struct tdb_context *) +tdb_nest_lock: int (struct tdb_context *, uint32_t, int, enum tdb_lock_flags) +tdb_nest_unlock: int (struct tdb_context *, uint32_t, int, bool) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +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_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_release_transaction_locks: void (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_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_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int, enum tdb_lock_flags) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_start_nonblock: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *, int) +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_unlock_record: int (struct tdb_context *, tdb_off_t) +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 *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) diff --git a/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.10.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.10.sigs new file mode 100644 index 0000000..61f6c19 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.10.sigs @@ -0,0 +1,66 @@ +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_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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.11.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.11.sigs new file mode 100644 index 0000000..d727f21 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.11.sigs @@ -0,0 +1,67 @@ +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_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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.12.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.12.sigs new file mode 100644 index 0000000..d727f21 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.12.sigs @@ -0,0 +1,67 @@ +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_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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.13.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.13.sigs new file mode 100644 index 0000000..d727f21 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.13.sigs @@ -0,0 +1,67 @@ +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_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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.2.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.2.sigs new file mode 100644 index 0000000..043790d --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.2.sigs @@ -0,0 +1,60 @@ +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_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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.3.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.3.sigs new file mode 100644 index 0000000..043790d --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.3.sigs @@ -0,0 +1,60 @@ +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_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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.4.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.4.sigs new file mode 100644 index 0000000..043790d --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.4.sigs @@ -0,0 +1,60 @@ +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_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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.5.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.5.sigs new file mode 100644 index 0000000..1e01f3b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.5.sigs @@ -0,0 +1,61 @@ +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_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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.6.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.6.sigs new file mode 100644 index 0000000..1e01f3b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.6.sigs @@ -0,0 +1,61 @@ +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_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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.7.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.7.sigs new file mode 100644 index 0000000..1e01f3b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.7.sigs @@ -0,0 +1,61 @@ +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_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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.8.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.8.sigs new file mode 100644 index 0000000..1e01f3b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.8.sigs @@ -0,0 +1,61 @@ +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_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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.9.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.9.sigs new file mode 100644 index 0000000..9e4149b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.2.9.sigs @@ -0,0 +1,62 @@ +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_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_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_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_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.0.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.0.sigs new file mode 100644 index 0000000..7d3e469 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.0.sigs @@ -0,0 +1,68 @@ +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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.1.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.1.sigs new file mode 100644 index 0000000..7d3e469 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.1.sigs @@ -0,0 +1,68 @@ +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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.10.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.10.sigs new file mode 100644 index 0000000..2545c99 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.11.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.11.sigs new file mode 100644 index 0000000..48f4278 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.12.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.12.sigs new file mode 100644 index 0000000..48f4278 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.13.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.13.sigs new file mode 100644 index 0000000..48f4278 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.13.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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.14.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.14.sigs new file mode 100644 index 0000000..61ce5e6 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.14.sigs @@ -0,0 +1,71 @@ +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_active: bool (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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.15.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.15.sigs new file mode 100644 index 0000000..61ce5e6 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.15.sigs @@ -0,0 +1,71 @@ +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_active: bool (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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.16.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.16.sigs new file mode 100644 index 0000000..61ce5e6 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.16.sigs @@ -0,0 +1,71 @@ +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_active: bool (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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.17.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.17.sigs new file mode 100644 index 0000000..e2b0427 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.17.sigs @@ -0,0 +1,73 @@ +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_active: bool (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_chain: int (struct tdb_context *, unsigned int, tdb_traverse_func, void *) +tdb_traverse_key_chain: int (struct tdb_context *, TDB_DATA, 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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.18.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.18.sigs new file mode 100644 index 0000000..e2b0427 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.18.sigs @@ -0,0 +1,73 @@ +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_active: bool (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_chain: int (struct tdb_context *, unsigned int, tdb_traverse_func, void *) +tdb_traverse_key_chain: int (struct tdb_context *, TDB_DATA, 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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.2.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.2.sigs new file mode 100644 index 0000000..7d3e469 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.2.sigs @@ -0,0 +1,68 @@ +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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.3.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.3.sigs new file mode 100644 index 0000000..7d3e469 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.3.sigs @@ -0,0 +1,68 @@ +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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.4.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.4.sigs new file mode 100644 index 0000000..7d3e469 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.4.sigs @@ -0,0 +1,68 @@ +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_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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.5.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.5.sigs new file mode 100644 index 0000000..2545c99 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.5.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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.6.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.6.sigs new file mode 100644 index 0000000..2545c99 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.6.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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.7.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.7.sigs new file mode 100644 index 0000000..2545c99 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.7.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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.8.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.8.sigs new file mode 100644 index 0000000..2545c99 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.8.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/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.9.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.3.9.sigs new file mode 100644 index 0000000..2545c99 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.0.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.0.sigs new file mode 100644 index 0000000..e2b0427 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.0.sigs @@ -0,0 +1,73 @@ +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_active: bool (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_chain: int (struct tdb_context *, unsigned int, tdb_traverse_func, void *) +tdb_traverse_key_chain: int (struct tdb_context *, TDB_DATA, 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/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.1.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.1.sigs new file mode 100644 index 0000000..e2b0427 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.1.sigs @@ -0,0 +1,73 @@ +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_active: bool (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_chain: int (struct tdb_context *, unsigned int, tdb_traverse_func, void *) +tdb_traverse_key_chain: int (struct tdb_context *, TDB_DATA, 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/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.2.sigs b/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.2.sigs new file mode 100644 index 0000000..e2b0427 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/ABI/tdb-1.4.2.sigs @@ -0,0 +1,73 @@ +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_active: bool (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_chain: int (struct tdb_context *, unsigned int, tdb_traverse_func, void *) +tdb_traverse_key_chain: int (struct tdb_context *, TDB_DATA, 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/ldb-2.0.8/lib/tdb/Makefile b/ldb-2.0.8/lib/tdb/Makefile new file mode 100644 index 0000000..8fd56c8 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/Makefile @@ -0,0 +1,68 @@ +# simple makefile wrapper to run waf + +WAF_BIN=`PATH=buildtools/bin:../../buildtools/bin:$$PATH which waf` +WAF_BINARY=$(PYTHON) $(WAF_BIN) +WAF=PYTHONHASHSEED=1 WAF_MAKE=1 $(WAF_BINARY) + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: FORCE + $(WAF) test $(TEST_OPTIONS) + +testenv: + $(WAF) test --testenv $(TEST_OPTIONS) + +quicktest: + $(WAF) test --quick $(TEST_OPTIONS) + +dist: + touch .tmplock + WAFLOCK=.tmplock $(WAF) dist + +distcheck: + touch .tmplock + WAFLOCK=.tmplock $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +torture: all + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags + +pydoctor: + $(WAF) pydoctor + +bin/%:: FORCE + $(WAF) --targets=`basename $@` +FORCE: diff --git a/ldb-2.0.8/lib/tdb/_tdb_text.py b/ldb-2.0.8/lib/tdb/_tdb_text.py new file mode 100644 index 0000000..f3caa53 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/_tdb_text.py @@ -0,0 +1,137 @@ +# Text wrapper for tdb bindings +# +# Copyright (C) 2015 Petr Viktorin +# Published under the GNU LGPLv3 or later + +import sys + +import tdb + + +class TdbTextWrapper(object): + """Text interface for a TDB file""" + + def __init__(self, tdb): + self._tdb = tdb + + @property + def raw(self): + return self._tdb + + def get(self, key): + key = key.encode('utf-8') + result = self._tdb.get(key) + if result is not None: + return result.decode('utf-8') + + def append(self, key, value): + key = key.encode('utf-8') + value = value.encode('utf-8') + self._tdb.append(key, value) + + def firstkey(self): + result = self._tdb.firstkey() + if result: + return result.decode('utf-8') + + def nextkey(self, key): + key = key.encode('utf-8') + result = self._tdb.nextkey(key) + if result is not None: + return result.decode('utf-8') + + def delete(self, key): + key = key.encode('utf-8') + self._tdb.delete(key) + + def store(self, key, value): + key = key.encode('utf-8') + value = value.encode('utf-8') + self._tdb.store(key, value) + + def __iter__(self): + for key in iter(self._tdb): + yield key.decode('utf-8') + + def __getitem__(self, key): + key = key.encode('utf-8') + result = self._tdb[key] + return result.decode('utf-8') + + def __contains__(self, key): + key = key.encode('utf-8') + return key in self._tdb + + def __repr__(self): + return '' % self._tdb + + def __setitem__(self, key, value): + key = key.encode('utf-8') + value = value.encode('utf-8') + self._tdb[key] = value + + def __delitem__(self, key): + key = key.encode('utf-8') + del self._tdb[key] + + if sys.version_info > (3, 0): + keys = __iter__ + else: + iterkeys = __iter__ + has_key = __contains__ + + +## Add wrappers for functions and getters that don't deal with text + +def _add_wrapper(name): + orig = getattr(tdb.Tdb, name) + + def wrapper(self, *args, **kwargs): + return orig(self._tdb, *args, **kwargs) + wrapper.__name__ = orig.__name__ + wrapper.__doc__ = orig.__doc__ + + setattr(TdbTextWrapper, name, wrapper) + +for name in ("transaction_cancel", + "transaction_commit", + "transaction_prepare_commit", + "transaction_start", + "reopen", + "lock_all", + "unlock_all", + "read_lock_all", + "read_unlock_all", + "close", + "add_flags", + "remove_flags", + "clear", + "repack", + "enable_seqnum", + "increment_seqnum_nonblock", + ): + _add_wrapper(name) + + +def _add_getter(name): + orig = getattr(tdb.Tdb, name) + doc = orig.__doc__ + + def getter(self): + return getattr(self._tdb, name) + + def setter(self, value): + return setattr(self._tdb, name, value) + + setattr(TdbTextWrapper, name, property(getter, setter, doc=doc)) + +for name in ("hash_size", + "map_size", + "freelist_size", + "flags", + "max_dead", + "filename", + "seqnum", + "text", + ): + _add_getter(name) diff --git a/ldb-2.0.8/lib/tdb/common/check.c b/ldb-2.0.8/lib/tdb/common/check.c new file mode 100644 index 0000000..d7741f6 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/check.c @@ -0,0 +1,489 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Rusty Russell 2009 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ +#include "tdb_private.h" + +/* Since we opened it, these shouldn't fail unless it's recent corruption. */ +static bool tdb_check_header(struct tdb_context *tdb, tdb_off_t *recovery) +{ + struct tdb_header hdr; + uint32_t h1, h2; + + if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1) + return false; + if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) + goto corrupt; + + CONVERT(hdr); + if (hdr.version != TDB_VERSION) + goto corrupt; + + if (hdr.rwlocks != 0 && + hdr.rwlocks != TDB_FEATURE_FLAG_MAGIC && + hdr.rwlocks != TDB_HASH_RWLOCK_MAGIC) + goto corrupt; + + tdb_header_hash(tdb, &h1, &h2); + if (hdr.magic1_hash && hdr.magic2_hash && + (hdr.magic1_hash != h1 || hdr.magic2_hash != h2)) + goto corrupt; + + if (hdr.hash_size == 0) + goto corrupt; + + if (hdr.hash_size != tdb->hash_size) + goto corrupt; + + if (hdr.recovery_start != 0 && + hdr.recovery_start < TDB_DATA_START(tdb->hash_size)) + goto corrupt; + + *recovery = hdr.recovery_start; + return true; + +corrupt: + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "Header is corrupt\n")); + return false; +} + +/* Generic record header check. */ +static bool tdb_check_record(struct tdb_context *tdb, + tdb_off_t off, + const struct tdb_record *rec) +{ + tdb_off_t tailer; + + /* Check rec->next: 0 or points to record offset, aligned. */ + if (rec->next > 0 && rec->next < TDB_DATA_START(tdb->hash_size)){ + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u too small next %u\n", + off, rec->next)); + goto corrupt; + } + if (rec->next + sizeof(*rec) < rec->next) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u too large next %u\n", + off, rec->next)); + goto corrupt; + } + if ((rec->next % TDB_ALIGNMENT) != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u misaligned next %u\n", + off, rec->next)); + goto corrupt; + } + if (tdb_oob(tdb, rec->next, sizeof(*rec), 0)) + goto corrupt; + + /* Check rec_len: similar to rec->next, implies next record. */ + if ((rec->rec_len % TDB_ALIGNMENT) != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u misaligned length %u\n", + off, rec->rec_len)); + goto corrupt; + } + /* Must fit tailer. */ + if (rec->rec_len < sizeof(tailer)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u too short length %u\n", + off, rec->rec_len)); + goto corrupt; + } + /* OOB allows "right at the end" access, so this works for last rec. */ + if (tdb_oob(tdb, off, sizeof(*rec)+rec->rec_len, 0)) + goto corrupt; + + /* Check tailer. */ + if (tdb_ofs_read(tdb, off+sizeof(*rec)+rec->rec_len-sizeof(tailer), + &tailer) == -1) + goto corrupt; + if (tailer != sizeof(*rec) + rec->rec_len) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u invalid tailer\n", off)); + goto corrupt; + } + + return true; + +corrupt: + tdb->ecode = TDB_ERR_CORRUPT; + return false; +} + +/* Grab some bytes: may copy if can't use mmap. + Caller has already done bounds check. */ +static TDB_DATA get_bytes(struct tdb_context *tdb, + tdb_off_t off, tdb_len_t len) +{ + TDB_DATA d; + + d.dsize = len; + + if (tdb->transaction == NULL && tdb->map_ptr != NULL) + d.dptr = (unsigned char *)tdb->map_ptr + off; + else + d.dptr = tdb_alloc_read(tdb, off, d.dsize); + return d; +} + +/* Frees data if we're not able to simply use mmap. */ +static void put_bytes(struct tdb_context *tdb, TDB_DATA d) +{ + if (tdb->transaction == NULL && tdb->map_ptr != NULL) + return; + free(d.dptr); +} + +/* We use the excellent Jenkins lookup3 hash; this is based on hash_word2. + * See: http://burtleburtle.net/bob/c/lookup3.c + */ +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) +static void hash(uint32_t key, uint32_t *pc, uint32_t *pb) +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + *pc; + c += *pb; + a += key; + c ^= b; c -= rot(b,14); + a ^= c; a -= rot(c,11); + b ^= a; b -= rot(a,25); + c ^= b; c -= rot(b,16); + a ^= c; a -= rot(c,4); + b ^= a; b -= rot(a,14); + c ^= b; c -= rot(b,24); + *pc=c; *pb=b; +} + +/* + We want to check that all free records are in the free list + (only once), and all free list entries are free records. Similarly + for each hash chain of used records. + + Doing that naively (without walking hash chains, since we want to be + linear) means keeping a list of records which have been seen in each + hash chain, and another of records pointed to (ie. next pointers + from records and the initial hash chain heads). These two lists + should be equal. This will take 8 bytes per record, and require + sorting at the end. + + So instead, we record each offset in a bitmap such a way that + recording it twice will cancel out. Since each offset should appear + exactly twice, the bitmap should be zero at the end. + + The approach was inspired by Bloom Filters (see Wikipedia). For + each value, we flip K bits in a bitmap of size N. The number of + distinct arrangements is: + + N! / (K! * (N-K)!) + + Of course, not all arrangements are actually distinct, but testing + shows this formula to be close enough. + + So, if K == 8 and N == 256, the probability of two things flipping the same + bits is 1 in 409,663,695,276,000. + + Given that ldb uses a hash size of 10000, using 32 bytes per hash chain + (320k) seems reasonable. +*/ +#define NUM_HASHES 8 +#define BITMAP_BITS 256 + +static void bit_flip(unsigned char bits[], unsigned int idx) +{ + bits[idx / CHAR_BIT] ^= (1 << (idx % CHAR_BIT)); +} + +/* We record offsets in a bitmap for the particular chain it should be in. */ +static void record_offset(unsigned char bits[], tdb_off_t off) +{ + uint32_t h1 = off, h2 = 0; + unsigned int i; + + /* We get two good hash values out of jhash2, so we use both. Then + * we keep going to produce further hash values. */ + for (i = 0; i < NUM_HASHES / 2; i++) { + hash(off, &h1, &h2); + bit_flip(bits, h1 % BITMAP_BITS); + bit_flip(bits, h2 % BITMAP_BITS); + h2++; + } +} + +/* Check that an in-use record is valid. */ +static bool tdb_check_used_record(struct tdb_context *tdb, + tdb_off_t off, + const struct tdb_record *rec, + unsigned char **hashes, + int (*check)(TDB_DATA, TDB_DATA, void *), + void *private_data) +{ + TDB_DATA key, data; + tdb_len_t len; + + if (!tdb_check_record(tdb, off, rec)) + return false; + + /* key + data + tailer must fit in record */ + len = rec->key_len; + len += rec->data_len; + if (len < rec->data_len) { + /* overflow */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "Record lengths overflow\n")); + return false; + } + len += sizeof(tdb_off_t); + if (len < sizeof(tdb_off_t)) { + /* overflow */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "Record lengths overflow\n")); + return false; + } + + if (len > rec->rec_len) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u too short for contents\n", off)); + return false; + } + + key = get_bytes(tdb, off + sizeof(*rec), rec->key_len); + if (!key.dptr) + return false; + + if (tdb->hash_fn(&key) != rec->full_hash) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %u has incorrect hash\n", off)); + goto fail_put_key; + } + + /* Mark this offset as a known value for this hash bucket. */ + record_offset(hashes[BUCKET(rec->full_hash)+1], off); + /* And similarly if the next pointer is valid. */ + if (rec->next) + record_offset(hashes[BUCKET(rec->full_hash)+1], rec->next); + + /* If they supply a check function and this record isn't dead, + get data and feed it. */ + if (check && rec->magic != TDB_DEAD_MAGIC) { + data = get_bytes(tdb, off + sizeof(*rec) + rec->key_len, + rec->data_len); + if (!data.dptr) + goto fail_put_key; + + if (check(key, data, private_data) == -1) + goto fail_put_data; + put_bytes(tdb, data); + } + + put_bytes(tdb, key); + return true; + +fail_put_data: + put_bytes(tdb, data); +fail_put_key: + put_bytes(tdb, key); + return false; +} + +/* Check that an unused record is valid. */ +static bool tdb_check_free_record(struct tdb_context *tdb, + tdb_off_t off, + const struct tdb_record *rec, + unsigned char **hashes) +{ + if (!tdb_check_record(tdb, off, rec)) + return false; + + /* Mark this offset as a known value for the free list. */ + record_offset(hashes[0], off); + /* And similarly if the next pointer is valid. */ + if (rec->next) + record_offset(hashes[0], rec->next); + return true; +} + +/* Slow, but should be very rare. */ +size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off) +{ + size_t len; + + for (len = 0; off + len < tdb->map_size; len++) { + char c; + if (tdb->methods->tdb_read(tdb, off, &c, 1, 0)) + return 0; + if (c != 0 && c != 0x42) + break; + } + return len; +} + +_PUBLIC_ int tdb_check(struct tdb_context *tdb, + int (*check)(TDB_DATA key, TDB_DATA data, void *private_data), + void *private_data) +{ + unsigned int h; + unsigned char **hashes; + tdb_off_t off, recovery_start; + struct tdb_record rec; + bool found_recovery = false; + tdb_len_t dead; + bool locked; + + /* Read-only databases use no locking at all: it's best-effort. + * We may have a write lock already, so skip that case too. */ + if (tdb->read_only || tdb->allrecord_lock.count != 0) { + locked = false; + } else { + if (tdb_lockall_read(tdb) == -1) + return -1; + locked = true; + } + + /* Make sure we know true size of the underlying file. */ + tdb_oob(tdb, tdb->map_size, 1, 1); + + /* Header must be OK: also gets us the recovery ptr, if any. */ + if (!tdb_check_header(tdb, &recovery_start)) + goto unlock; + + /* We should have the whole header, too. */ + if (tdb->map_size < TDB_DATA_START(tdb->hash_size)) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "File too short for hashes\n")); + goto unlock; + } + + /* One big malloc: pointers then bit arrays. */ + hashes = (unsigned char **)calloc( + 1, sizeof(hashes[0]) * (1+tdb->hash_size) + + BITMAP_BITS / CHAR_BIT * (1+tdb->hash_size)); + if (!hashes) { + tdb->ecode = TDB_ERR_OOM; + goto unlock; + } + + /* Initialize pointers */ + hashes[0] = (unsigned char *)(&hashes[1+tdb->hash_size]); + for (h = 1; h < 1+tdb->hash_size; h++) + hashes[h] = hashes[h-1] + BITMAP_BITS / CHAR_BIT; + + /* Freelist and hash headers are all in a row: read them. */ + for (h = 0; h < 1+tdb->hash_size; h++) { + if (tdb_ofs_read(tdb, FREELIST_TOP + h*sizeof(tdb_off_t), + &off) == -1) + goto free; + if (off) + record_offset(hashes[h], off); + } + + /* For each record, read it in and check it's ok. */ + for (off = TDB_DATA_START(tdb->hash_size); + off < tdb->map_size; + off += sizeof(rec) + rec.rec_len) { + if (tdb->methods->tdb_read(tdb, off, &rec, sizeof(rec), + DOCONV()) == -1) + goto free; + switch (rec.magic) { + case TDB_MAGIC: + case TDB_DEAD_MAGIC: + if (!tdb_check_used_record(tdb, off, &rec, hashes, + check, private_data)) + goto free; + break; + case TDB_FREE_MAGIC: + if (!tdb_check_free_record(tdb, off, &rec, hashes)) + goto free; + break; + /* If we crash after ftruncate, we can get zeroes or fill. */ + case TDB_RECOVERY_INVALID_MAGIC: + case 0x42424242: + if (recovery_start == off) { + found_recovery = true; + break; + } + dead = tdb_dead_space(tdb, off); + if (dead < sizeof(rec)) + goto corrupt; + + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Dead space at %u-%u (of %u)\n", + off, off + dead, tdb->map_size)); + rec.rec_len = dead - sizeof(rec); + break; + case TDB_RECOVERY_MAGIC: + if (recovery_start != off) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Unexpected recovery record at offset %u\n", + off)); + goto free; + } + found_recovery = true; + break; + default: ; + corrupt: + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Bad magic 0x%x at offset %u\n", + rec.magic, off)); + goto free; + } + } + + /* Now, hashes should all be empty: each record exists and is referred + * to by one other. */ + for (h = 0; h < 1+tdb->hash_size; h++) { + unsigned int i; + for (i = 0; i < BITMAP_BITS / CHAR_BIT; i++) { + if (hashes[h][i] != 0) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Hashes do not match records\n")); + goto free; + } + } + } + + /* We must have found recovery area if there was one. */ + if (recovery_start != 0 && !found_recovery) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Expected a recovery area at %u\n", + recovery_start)); + goto free; + } + + free(hashes); + if (locked) { + tdb_unlockall_read(tdb); + } + return 0; + +free: + free(hashes); +unlock: + if (locked) { + tdb_unlockall_read(tdb); + } + return -1; +} diff --git a/ldb-2.0.8/lib/tdb/common/dump.c b/ldb-2.0.8/lib/tdb/common/dump.c new file mode 100644 index 0000000..adcf591 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/dump.c @@ -0,0 +1,149 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash, + tdb_off_t offset) +{ + struct tdb_record rec; + tdb_off_t tailer_ofs, tailer; + + if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + printf("ERROR: failed to read record at %u\n", offset); + return 0; + } + + printf(" rec: hash=%d offset=0x%08x next=0x%08x rec_len=%u " + "key_len=%u data_len=%u full_hash=0x%08x magic=0x%08x\n", + hash, offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, + rec.full_hash, rec.magic); + + tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t); + + if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) { + printf("ERROR: failed to read tailer at %u\n", tailer_ofs); + return rec.next; + } + + if (tailer != rec.rec_len + sizeof(rec)) { + printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", + (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); + } + return rec.next; +} + +static int tdb_dump_chain(struct tdb_context *tdb, int i) +{ + struct tdb_chainwalk_ctx chainwalk; + tdb_off_t rec_ptr, top; + + if (i == -1) { + top = FREELIST_TOP; + } else { + top = TDB_HASH_TOP(i); + } + + if (tdb_lock(tdb, i, F_WRLCK) != 0) + return -1; + + if (tdb_ofs_read(tdb, top, &rec_ptr) == -1) + return tdb_unlock(tdb, i, F_WRLCK); + + tdb_chainwalk_init(&chainwalk, rec_ptr); + + if (rec_ptr) + printf("hash=%d\n", i); + + while (rec_ptr) { + bool ok; + rec_ptr = tdb_dump_record(tdb, i, rec_ptr); + ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr); + if (!ok) { + printf("circular hash chain %d\n", i); + break; + } + } + + return tdb_unlock(tdb, i, F_WRLCK); +} + +_PUBLIC_ void tdb_dump_all(struct tdb_context *tdb) +{ + uint32_t i; + for (i=0;ihash_size;i++) { + tdb_dump_chain(tdb, i); + } + printf("freelist:\n"); + tdb_dump_chain(tdb, -1); +} + +_PUBLIC_ int tdb_printfreelist(struct tdb_context *tdb) +{ + int ret; + long total_free = 0; + tdb_off_t offset, rec_ptr; + struct tdb_record rec; + + if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) + return ret; + + offset = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + + printf("freelist top=[0x%08x]\n", rec_ptr ); + while (rec_ptr) { + if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + if (rec.magic != TDB_FREE_MAGIC) { + printf("bad magic 0x%08x in free list\n", rec.magic); + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%u)] (end = 0x%08x)\n", + rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); + total_free += rec.rec_len; + + /* move to the next record */ + rec_ptr = rec.next; + } + printf("total rec_len = [0x%08lx (%lu)]\n", total_free, total_free); + + return tdb_unlock(tdb, -1, F_WRLCK); +} + diff --git a/ldb-2.0.8/lib/tdb/common/error.c b/ldb-2.0.8/lib/tdb/common/error.c new file mode 100644 index 0000000..478eb88 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/error.c @@ -0,0 +1,57 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +_PUBLIC_ enum TDB_ERROR tdb_error(struct tdb_context *tdb) +{ + return tdb->ecode; +} + +static struct tdb_errname { + enum TDB_ERROR ecode; const char *estring; +} emap[] = { {TDB_SUCCESS, "Success"}, + {TDB_ERR_CORRUPT, "Corrupt database"}, + {TDB_ERR_IO, "IO Error"}, + {TDB_ERR_LOCK, "Locking error"}, + {TDB_ERR_OOM, "Out of memory"}, + {TDB_ERR_EXISTS, "Record exists"}, + {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_EINVAL, "Invalid parameter"}, + {TDB_ERR_NOEXIST, "Record does not exist"}, + {TDB_ERR_RDONLY, "write not permitted"} }; + +/* Error string for the last tdb error */ +_PUBLIC_ const char *tdb_errorstr(struct tdb_context *tdb) +{ + uint32_t i; + for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) + if (tdb->ecode == emap[i].ecode) + return emap[i].estring; + return "Invalid error code"; +} + diff --git a/ldb-2.0.8/lib/tdb/common/freelist.c b/ldb-2.0.8/lib/tdb/common/freelist.c new file mode 100644 index 0000000..046c747 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/freelist.c @@ -0,0 +1,747 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +/* read a freelist record and check for simple errors */ +int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct tdb_record *rec) +{ + if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + + if (rec->magic == TDB_MAGIC) { + /* this happens when a app is showdown while deleting a record - we should + not completely fail when this happens */ + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%u - fixing\n", + rec->magic, off)); + rec->magic = TDB_FREE_MAGIC; + if (tdb_rec_write(tdb, off, rec) == -1) + return -1; + } + + if (rec->magic != TDB_FREE_MAGIC) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%u\n", + rec->magic, off)); + return -1; + } + if (tdb_oob(tdb, rec->next, sizeof(*rec), 0) != 0) + return -1; + return 0; +} + +/* update a record tailer (must hold allocation lock) */ +static int update_tailer(struct tdb_context *tdb, tdb_off_t offset, + const struct tdb_record *rec) +{ + tdb_off_t totalsize; + + /* Offset of tailer from record header */ + totalsize = sizeof(*rec) + rec->rec_len; + return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t), + &totalsize); +} + +/** + * Read the record directly on the left. + * Fail if there is no record on the left. + */ +static int read_record_on_left(struct tdb_context *tdb, tdb_off_t rec_ptr, + tdb_off_t *left_p, + struct tdb_record *left_r) +{ + tdb_off_t left_ptr; + tdb_off_t left_size; + struct tdb_record left_rec; + int ret; + + left_ptr = rec_ptr - sizeof(tdb_off_t); + + if (left_ptr <= TDB_DATA_START(tdb->hash_size)) { + /* no record on the left */ + return -1; + } + + /* Read in tailer and jump back to header */ + ret = tdb_ofs_read(tdb, left_ptr, &left_size); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + "tdb_free: left offset read failed at %u\n", left_ptr)); + return -1; + } + + /* it could be uninitialised data */ + if (left_size == 0 || left_size == TDB_PAD_U32) { + return -1; + } + + if (left_size > rec_ptr) { + return -1; + } + + left_ptr = rec_ptr - left_size; + + if (left_ptr < TDB_DATA_START(tdb->hash_size)) { + return -1; + } + + /* Now read in the left record */ + ret = tdb->methods->tdb_read(tdb, left_ptr, &left_rec, + sizeof(left_rec), DOCONV()); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + "tdb_free: left read failed at %u (%u)\n", + left_ptr, left_size)); + return -1; + } + + *left_p = left_ptr; + *left_r = left_rec; + + return 0; +} + +/** + * Merge new freelist record with the direct left neighbour. + * This assumes that left_rec represents the record + * directly to the left of right_rec and that this is + * a freelist record. + */ +static int merge_with_left_record(struct tdb_context *tdb, + tdb_off_t left_ptr, + struct tdb_record *left_rec, + struct tdb_record *right_rec) +{ + int ret; + + left_rec->rec_len += sizeof(*right_rec) + right_rec->rec_len; + + ret = tdb_rec_write(tdb, left_ptr, left_rec); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + "merge_with_left_record: update_left failed at %u\n", + left_ptr)); + return -1; + } + + ret = update_tailer(tdb, left_ptr, left_rec); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + "merge_with_left_record: update_tailer failed at %u\n", + left_ptr)); + return -1; + } + + return 0; +} + +/** + * Check whether the record left of a given freelist record is + * also a freelist record, and if so, merge the two records. + * + * Return code: + * -1 upon error + * 0 if left was not a free record + * 1 if left was free and successfully merged. + * + * The current record is handed in with pointer and fully read record. + * + * The left record pointer and struct can be retrieved as result + * in lp and lr; + */ +static int check_merge_with_left_record(struct tdb_context *tdb, + tdb_off_t rec_ptr, + struct tdb_record *rec, + tdb_off_t *lp, + struct tdb_record *lr) +{ + tdb_off_t left_ptr; + struct tdb_record left_rec; + int ret; + + ret = read_record_on_left(tdb, rec_ptr, &left_ptr, &left_rec); + if (ret != 0) { + return 0; + } + + if (left_rec.magic != TDB_FREE_MAGIC) { + return 0; + } + + /* It's free - expand to include it. */ + ret = merge_with_left_record(tdb, left_ptr, &left_rec, rec); + if (ret != 0) { + return -1; + } + + if (lp != NULL) { + *lp = left_ptr; + } + + if (lr != NULL) { + *lr = left_rec; + } + + return 1; +} + +/** + * Check whether the record left of a given freelist record is + * also a freelist record, and if so, merge the two records. + * + * Return code: + * -1 upon error + * 0 if left was not a free record + * 1 if left was free and successfully merged. + * + * In this variant, the input record is specified just as the pointer + * and is read from the database if needed. + * + * next_ptr will contain the original record's next pointer after + * successful merging (which will be lost after merging), so that + * the caller can update the last pointer. + */ +static int check_merge_ptr_with_left_record(struct tdb_context *tdb, + tdb_off_t rec_ptr, + tdb_off_t *next_ptr) +{ + tdb_off_t left_ptr; + struct tdb_record rec, left_rec; + int ret; + + ret = read_record_on_left(tdb, rec_ptr, &left_ptr, &left_rec); + if (ret != 0) { + return 0; + } + + if (left_rec.magic != TDB_FREE_MAGIC) { + return 0; + } + + /* It's free - expand to include it. */ + + ret = tdb->methods->tdb_read(tdb, rec_ptr, &rec, + sizeof(rec), DOCONV()); + if (ret != 0) { + return -1; + } + + ret = merge_with_left_record(tdb, left_ptr, &left_rec, &rec); + if (ret != 0) { + return -1; + } + + if (next_ptr != NULL) { + *next_ptr = rec.next; + } + + return 1; +} + +/** + * Add an element into the freelist. + * + * We merge the new record into the left record if it is also a + * free record, but not with the right one. This makes the + * operation O(1) instead of O(n): merging with the right record + * requires a traverse of the freelist to find the previous + * record in the free list. + * + * This prevents db traverses from being O(n^2) after a lot of deletes. + */ +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) +{ + int ret; + + /* Allocation and tailer lock */ + if (tdb_lock(tdb, -1, F_WRLCK) != 0) + return -1; + + /* set an initial tailer, so if we fail we don't leave a bogus record */ + if (update_tailer(tdb, offset, rec) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n")); + goto fail; + } + + ret = check_merge_with_left_record(tdb, offset, rec, NULL, NULL); + if (ret == -1) { + goto fail; + } + if (ret == 1) { + /* merged */ + goto done; + } + + /* Nothing to merge, prepend to free list */ + + rec->magic = TDB_FREE_MAGIC; + + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || + tdb_rec_write(tdb, offset, rec) == -1 || + tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%u\n", offset)); + goto fail; + } + +done: + /* And we're done. */ + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + + +/* + the core of tdb_allocate - called when we have decided which + free list entry to use + + Note that we try to allocate by grabbing data from the end of an existing record, + not the beginning. This is so the left merge in a free is more likely to be + able to free up the record without fragmentation + */ +static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, + tdb_len_t length, tdb_off_t rec_ptr, + struct tdb_record *rec, tdb_off_t last_ptr) +{ +#define MIN_REC_SIZE (sizeof(struct tdb_record) + sizeof(tdb_off_t) + 8) + + if (rec->rec_len < length + MIN_REC_SIZE) { + /* we have to grab the whole record */ + + /* unlink it from the previous record */ + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* mark it not free */ + rec->magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + return rec_ptr; + } + + /* we're going to just shorten the existing record */ + rec->rec_len -= (length + sizeof(*rec)); + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* and setup the new record */ + rec_ptr += sizeof(*rec) + rec->rec_len; + + memset(rec, '\0', sizeof(*rec)); + rec->rec_len = length; + rec->magic = TDB_MAGIC; + + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + return rec_ptr; +} + +/* allocate some space from the free list. The offset returned points + to a unconnected tdb_record within the database with room for at + least length bytes of total data + + 0 is returned if the space could not be allocated + */ +static tdb_off_t tdb_allocate_from_freelist( + struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec) +{ + tdb_off_t rec_ptr, last_ptr, newrec_ptr; + struct tdb_chainwalk_ctx chainwalk; + bool modified; + struct { + tdb_off_t rec_ptr, last_ptr; + tdb_len_t rec_len; + } bestfit; + float multiplier = 1.0; + bool merge_created_candidate; + + /* over-allocate to reduce fragmentation */ + length *= 1.25; + + /* Extra bytes required for tailer */ + length += sizeof(tdb_off_t); + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + again: + merge_created_candidate = false; + last_ptr = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) + return 0; + + modified = false; + tdb_chainwalk_init(&chainwalk, rec_ptr); + + bestfit.rec_ptr = 0; + bestfit.last_ptr = 0; + bestfit.rec_len = 0; + + /* + this is a best fit allocation strategy. Originally we used + a first fit strategy, but it suffered from massive fragmentation + issues when faced with a slowly increasing record size. + */ + while (rec_ptr) { + int ret; + tdb_off_t left_ptr; + struct tdb_record left_rec; + + if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) { + return 0; + } + + ret = check_merge_with_left_record(tdb, rec_ptr, rec, + &left_ptr, &left_rec); + if (ret == -1) { + return 0; + } + if (ret == 1) { + /* merged */ + rec_ptr = rec->next; + ret = tdb_ofs_write(tdb, last_ptr, &rec->next); + if (ret == -1) { + return 0; + } + + /* + * We have merged the current record into the left + * neighbour. So our traverse of the freelist will + * skip it and consider the next record in the chain. + * + * But the enlarged left neighbour may be a candidate. + * If it is, we can not directly use it, though. + * The only thing we can do and have to do here is to + * update the current best fit size in the chain if the + * current best fit is the left record. (By that we may + * worsen the best fit we already had, bit this is not a + * problem.) + * + * If the current best fit is not the left record, + * all we can do is remember the fact that a merge + * created a new candidate so that we can trigger + * a second walk of the freelist if at the end of + * the first walk we have not found any fit. + * This way we can avoid expanding the database. + */ + + if (bestfit.rec_ptr == left_ptr) { + bestfit.rec_len = left_rec.rec_len; + } + + if (left_rec.rec_len > length) { + merge_created_candidate = true; + } + + modified = true; + + continue; + } + + if (rec->rec_len >= length) { + if (bestfit.rec_ptr == 0 || + rec->rec_len < bestfit.rec_len) { + bestfit.rec_len = rec->rec_len; + bestfit.rec_ptr = rec_ptr; + bestfit.last_ptr = last_ptr; + } + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec->next; + + if (!modified) { + bool ok; + ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr); + if (!ok) { + return 0; + } + } + + /* if we've found a record that is big enough, then + stop searching if its also not too big. The + definition of 'too big' changes as we scan + through */ + if (bestfit.rec_len > 0 && + bestfit.rec_len < length * multiplier) { + break; + } + + /* this multiplier means we only extremely rarely + search more than 50 or so records. At 50 records we + accept records up to 11 times larger than what we + want */ + multiplier *= 1.05; + } + + if (bestfit.rec_ptr != 0) { + if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { + return 0; + } + + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, + rec, bestfit.last_ptr); + return newrec_ptr; + } + + if (merge_created_candidate) { + goto again; + } + + /* we didn't find enough space. See if we can expand the + database and if we can then try again */ + if (tdb_expand(tdb, length + sizeof(*rec)) == 0) + goto again; + + return 0; +} + +static bool tdb_alloc_dead( + struct tdb_context *tdb, int hash, tdb_len_t length, + tdb_off_t *rec_ptr, struct tdb_record *rec) +{ + tdb_off_t last_ptr; + + *rec_ptr = tdb_find_dead(tdb, hash, rec, length, &last_ptr); + if (*rec_ptr == 0) { + return false; + } + /* + * Unlink the record from the hash chain, it's about to be moved into + * another one. + */ + return (tdb_ofs_write(tdb, last_ptr, &rec->next) == 0); +} + +static void tdb_purge_dead(struct tdb_context *tdb, uint32_t hash) +{ + int max_dead_records = tdb->max_dead_records; + + tdb->max_dead_records = 0; + + tdb_trim_dead(tdb, hash); + + tdb->max_dead_records = max_dead_records; +} + +/* + * Chain "hash" is assumed to be locked + */ + +tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length, + struct tdb_record *rec) +{ + tdb_off_t ret; + uint32_t i; + + if (tdb->max_dead_records == 0) { + /* + * No dead records to expect anywhere. Do the blocking + * freelist lock without trying to steal from others + */ + goto blocking_freelist_allocate; + } + + /* + * The following loop tries to get the freelist lock nonblocking. If + * it gets the lock, allocate from there. If the freelist is busy, + * instead of waiting we try to steal dead records from other hash + * chains. + * + * Be aware that we do nonblocking locks on the other hash chains as + * well and fail gracefully. This way we avoid deadlocks (we block two + * hash chains, something which is pretty bad normally) + */ + + for (i=0; ihash_size; i++) { + + int list; + + list = BUCKET(hash+i); + + if (tdb_lock_nonblock(tdb, list, F_WRLCK) == 0) { + bool got_dead; + + got_dead = tdb_alloc_dead(tdb, list, length, &ret, rec); + tdb_unlock(tdb, list, F_WRLCK); + + if (got_dead) { + return ret; + } + } + + if (tdb_lock_nonblock(tdb, -1, F_WRLCK) == 0) { + /* + * Under the freelist lock take the chance to give + * back our dead records. + */ + tdb_purge_dead(tdb, hash); + + ret = tdb_allocate_from_freelist(tdb, length, rec); + tdb_unlock(tdb, -1, F_WRLCK); + return ret; + } + } + +blocking_freelist_allocate: + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + return 0; + } + /* + * Dead records can happen even if max_dead_records==0, they + * are older than the max_dead_records concept: They happen if + * tdb_delete happens concurrently with a traverse. + */ + tdb_purge_dead(tdb, hash); + ret = tdb_allocate_from_freelist(tdb, length, rec); + tdb_unlock(tdb, -1, F_WRLCK); + return ret; +} + +/** + * Merge adjacent records in the freelist. + */ +static int tdb_freelist_merge_adjacent(struct tdb_context *tdb, + int *count_records, int *count_merged) +{ + tdb_off_t cur, next; + int count = 0; + int merged = 0; + int ret; + + ret = tdb_lock(tdb, -1, F_RDLCK); + if (ret == -1) { + return -1; + } + + cur = FREELIST_TOP; + while (tdb_ofs_read(tdb, cur, &next) == 0 && next != 0) { + tdb_off_t next2; + + count++; + + ret = check_merge_ptr_with_left_record(tdb, next, &next2); + if (ret == -1) { + goto done; + } + if (ret == 1) { + /* + * merged: + * now let cur->next point to next2 instead of next + */ + + ret = tdb_ofs_write(tdb, cur, &next2); + if (ret != 0) { + goto done; + } + + next = next2; + merged++; + } + + cur = next; + } + + if (count_records != NULL) { + *count_records = count; + } + + if (count_merged != NULL) { + *count_merged = merged; + } + + ret = 0; + +done: + tdb_unlock(tdb, -1, F_RDLCK); + return ret; +} + +/** + * return the size of the freelist - no merging done + */ +static int tdb_freelist_size_no_merge(struct tdb_context *tdb) +{ + tdb_off_t ptr; + int count=0; + + if (tdb_lock(tdb, -1, F_RDLCK) == -1) { + return -1; + } + + ptr = FREELIST_TOP; + while (tdb_ofs_read(tdb, ptr, &ptr) == 0 && ptr != 0) { + count++; + } + + tdb_unlock(tdb, -1, F_RDLCK); + return count; +} + +/** + * return the size of the freelist - used to decide if we should repack + * + * As a side effect, adjacent records are merged unless the + * database is read-only, in order to reduce the fragmentation + * without repacking. + */ +_PUBLIC_ int tdb_freelist_size(struct tdb_context *tdb) +{ + + int count = 0; + + if (tdb->read_only) { + count = tdb_freelist_size_no_merge(tdb); + } else { + int ret; + ret = tdb_freelist_merge_adjacent(tdb, &count, NULL); + if (ret != 0) { + return -1; + } + } + + return count; +} diff --git a/ldb-2.0.8/lib/tdb/common/freelistcheck.c b/ldb-2.0.8/lib/tdb/common/freelistcheck.c new file mode 100644 index 0000000..2f1e6eb --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/freelistcheck.c @@ -0,0 +1,107 @@ +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Jeremy Allison 2006 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +/* Check the freelist is good and contains no loops. + Very memory intensive - only do this as a consistency + checker. Heh heh - uses an in memory tdb as the storage + for the "seen" record list. For some reason this strikes + me as extremely clever as I don't have to write another tree + data structure implementation :-). + */ + +static int seen_insert(struct tdb_context *mem_tdb, tdb_off_t rec_ptr) +{ + TDB_DATA key; + + key.dptr = (unsigned char *)&rec_ptr; + key.dsize = sizeof(rec_ptr); + return tdb_store(mem_tdb, key, tdb_null, TDB_INSERT); +} + +_PUBLIC_ int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries) +{ + struct tdb_context *mem_tdb = NULL; + struct tdb_record rec; + tdb_off_t rec_ptr, last_ptr; + int ret = -1; + + *pnum_entries = 0; + + mem_tdb = tdb_open("flval", tdb->hash_size, + TDB_INTERNAL, O_RDWR, 0600); + if (!mem_tdb) { + return -1; + } + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + tdb_close(mem_tdb); + return 0; + } + + last_ptr = FREELIST_TOP; + + /* Store the FREELIST_TOP record. */ + if (seen_insert(mem_tdb, last_ptr) == -1) { + tdb->ecode = TDB_ERR_CORRUPT; + ret = -1; + goto fail; + } + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) { + goto fail; + } + + while (rec_ptr) { + + /* If we can't store this record (we've seen it + before) then the free list has a loop and must + be corrupt. */ + + if (seen_insert(mem_tdb, rec_ptr)) { + tdb->ecode = TDB_ERR_CORRUPT; + ret = -1; + goto fail; + } + + if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) { + goto fail; + } + + /* move to the next record */ + rec_ptr = rec.next; + *pnum_entries += 1; + } + + ret = 0; + + fail: + + tdb_close(mem_tdb); + tdb_unlock(tdb, -1, F_WRLCK); + return ret; +} diff --git a/ldb-2.0.8/lib/tdb/common/hash.c b/ldb-2.0.8/lib/tdb/common/hash.c new file mode 100644 index 0000000..4de7ba9 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/hash.c @@ -0,0 +1,345 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Rusty Russell 2010 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ +#include "tdb_private.h" + +/* This is based on the hash algorithm from gdbm */ +unsigned int tdb_old_hash(TDB_DATA *key) +{ + uint32_t value; /* Used to compute the hash value. */ + uint32_t i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) + value = (value + (key->dptr[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} + +#ifndef WORDS_BIGENDIAN +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#endif + +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hash_word(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hash_word(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +*/ + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + val2 : IN: can be any 4-byte value OUT: second 32 bit hash. +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. Note that the return value is better +mixed than val2, so use that first. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; FALL_THROUGH; + case 10: c+=((uint32_t)k8[9])<<8; FALL_THROUGH; + case 9 : c+=k8[8]; FALL_THROUGH; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; FALL_THROUGH; + case 6 : b+=((uint32_t)k8[5])<<8; FALL_THROUGH; + case 5 : b+=k8[4]; FALL_THROUGH; + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; FALL_THROUGH; + case 2 : a+=((uint32_t)k8[1])<<8; FALL_THROUGH; + case 1 : a+=k8[0]; break; + case 0 : return c; + } + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; FALL_THROUGH; + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; FALL_THROUGH; + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; FALL_THROUGH; + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; FALL_THROUGH; + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; FALL_THROUGH; + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) + { + case 12: c+=((uint32_t)k[11])<<24; FALL_THROUGH; + case 11: c+=((uint32_t)k[10])<<16; FALL_THROUGH; + case 10: c+=((uint32_t)k[9])<<8; FALL_THROUGH; + case 9 : c+=k[8]; FALL_THROUGH; + case 8 : b+=((uint32_t)k[7])<<24; FALL_THROUGH; + case 7 : b+=((uint32_t)k[6])<<16; FALL_THROUGH; + case 6 : b+=((uint32_t)k[5])<<8; FALL_THROUGH; + case 5 : b+=k[4]; FALL_THROUGH; + case 4 : a+=((uint32_t)k[3])<<24; FALL_THROUGH; + case 3 : a+=((uint32_t)k[2])<<16; FALL_THROUGH; + case 2 : a+=((uint32_t)k[1])<<8; FALL_THROUGH; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + +_PUBLIC_ unsigned int tdb_jenkins_hash(TDB_DATA *key) +{ + return hashlittle(key->dptr, key->dsize); +} diff --git a/ldb-2.0.8/lib/tdb/common/io.c b/ldb-2.0.8/lib/tdb/common/io.c new file mode 100644 index 0000000..0de0dab --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/io.c @@ -0,0 +1,806 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + + +#include "tdb_private.h" + +/* + * We prepend the mutex area, so fixup offsets. See mutex.c for details. + * tdb->hdr_ofs is 0 or header.mutex_size. + * + * Note: that we only have the 4GB limit of tdb_off_t for + * tdb->map_size. The file size on disk can be 4GB + tdb->hdr_ofs! + */ + +static bool tdb_adjust_offset(struct tdb_context *tdb, off_t *off) +{ + off_t tmp = tdb->hdr_ofs + *off; + + if ((tmp < tdb->hdr_ofs) || (tmp < *off)) { + errno = EIO; + return false; + } + + *off = tmp; + return true; +} + +static ssize_t tdb_pwrite(struct tdb_context *tdb, const void *buf, + size_t count, off_t offset) +{ + ssize_t ret; + + if (!tdb_adjust_offset(tdb, &offset)) { + return -1; + } + + do { + ret = pwrite(tdb->fd, buf, count, offset); + } while ((ret == -1) && (errno == EINTR)); + + return ret; +} + +static ssize_t tdb_pread(struct tdb_context *tdb, void *buf, + size_t count, off_t offset) +{ + ssize_t ret; + + if (!tdb_adjust_offset(tdb, &offset)) { + return -1; + } + + do { + ret = pread(tdb->fd, buf, count, offset); + } while ((ret == -1) && (errno == EINTR)); + + return ret; +} + +static int tdb_ftruncate(struct tdb_context *tdb, off_t length) +{ + ssize_t ret; + + if (!tdb_adjust_offset(tdb, &length)) { + return -1; + } + + do { + ret = ftruncate(tdb->fd, length); + } while ((ret == -1) && (errno == EINTR)); + + return ret; +} + +#ifdef HAVE_POSIX_FALLOCATE +static int tdb_posix_fallocate(struct tdb_context *tdb, off_t offset, + off_t len) +{ + ssize_t ret; + + if (!tdb_adjust_offset(tdb, &offset)) { + return -1; + } + + do { + ret = posix_fallocate(tdb->fd, offset, len); + } while ((ret == -1) && (errno == EINTR)); + + return ret; +} +#endif + +static int tdb_fstat(struct tdb_context *tdb, struct stat *buf) +{ + int ret; + + ret = fstat(tdb->fd, buf); + if (ret == -1) { + return -1; + } + + if (buf->st_size < tdb->hdr_ofs) { + errno = EIO; + return -1; + } + buf->st_size -= tdb->hdr_ofs; + + return ret; +} + +/* check for an out of bounds access - if it is out of bounds then + see if the database has been expanded by someone else and expand + if necessary +*/ +static int tdb_notrans_oob( + struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) +{ + struct stat st; + if (len + off < len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob off %u len %u wrap\n", + off, len)); + } + return -1; + } + + /* + * This duplicates functionality from tdb_oob(). Don't remove: + * we still have direct callers of tdb->methods->tdb_oob() + * inside transaction.c. + */ + if (off + len <= tdb->map_size) + return 0; + if (tdb->flags & TDB_INTERNAL) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %u beyond internal malloc size %u\n", + (int)(off + len), (int)tdb->map_size)); + } + return -1; + } + + if (tdb_fstat(tdb, &st) == -1) { + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* Beware >4G files! */ + if ((tdb_off_t)st.st_size != st.st_size) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_oob len %llu too large!\n", + (long long)st.st_size)); + return -1; + } + + /* Unmap, update size, remap. We do this unconditionally, to handle + * the unusual case where the db is truncated. + * + * This can happen to a child using tdb_reopen_all(true) on a + * TDB_CLEAR_IF_FIRST tdb whose parent crashes: the next + * opener will truncate the database. */ + if (tdb_munmap(tdb) == -1) { + tdb->ecode = TDB_ERR_IO; + return -1; + } + tdb->map_size = st.st_size; + if (tdb_mmap(tdb) != 0) { + return -1; + } + + if (st.st_size < (size_t)off + len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %u beyond eof at %u\n", + (int)(off + len), (int)st.st_size)); + } + return -1; + } + return 0; +} + +/* write a lump of data at a specified offset */ +static int tdb_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + if (len == 0) { + return 0; + } + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (tdb_oob(tdb, off, len, 0) != 0) + return -1; + + if (tdb->map_ptr) { + memcpy(off + (char *)tdb->map_ptr, buf, len); + } else { +#ifdef HAVE_INCOHERENT_MMAP + tdb->ecode = TDB_ERR_IO; + return -1; +#else + ssize_t written; + + written = tdb_pwrite(tdb, buf, len, off); + + if ((written != (ssize_t)len) && (written != -1)) { + /* try once more */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_write: wrote only " + "%zi of %u bytes at %u, trying once more\n", + written, len, off)); + written = tdb_pwrite(tdb, (const char *)buf+written, + len-written, off+written); + } + if (written == -1) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %u " + "len=%u (%s)\n", off, len, strerror(errno))); + return -1; + } else if (written != (ssize_t)len) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_write: failed to " + "write %u bytes at %u in two attempts\n", + len, off)); + return -1; + } +#endif + } + return 0; +} + +/* Endian conversion: we only ever deal with 4 byte quantities */ +void *tdb_convert(void *buf, uint32_t size) +{ + uint32_t i, *p = (uint32_t *)buf; + for (i = 0; i < size / 4; i++) + p[i] = TDB_BYTEREV(p[i]); + return buf; +} + + +/* read a lump of data at a specified offset, maybe convert */ +static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + if (tdb_oob(tdb, off, len, 0) != 0) { + return -1; + } + + if (tdb->map_ptr) { + memcpy(buf, off + (char *)tdb->map_ptr, len); + } else { +#ifdef HAVE_INCOHERENT_MMAP + tdb->ecode = TDB_ERR_IO; + return -1; +#else + ssize_t ret; + + ret = tdb_pread(tdb, buf, len, off); + if (ret != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %u " + "len=%u ret=%zi (%s) map_size=%u\n", + off, len, ret, strerror(errno), + tdb->map_size)); + return -1; + } +#endif + } + if (cv) { + tdb_convert(buf, len); + } + return 0; +} + + + +/* + do an unlocked scan of the hash table heads to find the next non-zero head. The value + will then be confirmed with the lock held +*/ +static void tdb_next_hash_chain(struct tdb_context *tdb, uint32_t *chain) +{ + uint32_t h = *chain; + if (tdb->map_ptr) { + for (;h < tdb->hash_size;h++) { + if (0 != *(uint32_t *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { + break; + } + } + } else { + uint32_t off=0; + for (;h < tdb->hash_size;h++) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) { + break; + } + } + } + (*chain) = h; +} + + +int tdb_munmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + int ret; + + ret = munmap(tdb->map_ptr, tdb->map_size); + if (ret != 0) + return ret; + } +#endif + tdb->map_ptr = NULL; + return 0; +} + +/* If mmap isn't coherent, *everyone* must always mmap. */ +static bool should_mmap(const struct tdb_context *tdb) +{ +#ifdef HAVE_INCOHERENT_MMAP + return true; +#else + return !(tdb->flags & TDB_NOMMAP); +#endif +} + +int tdb_mmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (should_mmap(tdb)) { + tdb->map_ptr = mmap(NULL, tdb->map_size, + PROT_READ|(tdb->read_only? 0:PROT_WRITE), + MAP_SHARED|MAP_FILE, tdb->fd, + tdb->hdr_ofs); + + /* + * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! + */ + + if (tdb->map_ptr == MAP_FAILED) { + tdb->map_ptr = NULL; + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %u (%s)\n", + tdb->map_size, strerror(errno))); +#ifdef HAVE_INCOHERENT_MMAP + tdb->ecode = TDB_ERR_IO; + return -1; +#endif + } + } else { + tdb->map_ptr = NULL; + } +#else + tdb->map_ptr = NULL; +#endif + return 0; +} + +/* expand a file. we prefer to use ftruncate, as that is what posix + says to use for mmap expansion */ +static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) +{ + char buf[8192]; + tdb_off_t new_size; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (!tdb_add_off_t(size, addition, &new_size)) { + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write " + "overflow detected current size[%u] addition[%u]!\n", + (unsigned)size, (unsigned)addition)); + errno = ENOSPC; + return -1; + } + +#ifdef HAVE_POSIX_FALLOCATE + ret = tdb_posix_fallocate(tdb, size, addition); + if (ret == 0) { + return 0; + } + if (ret == ENOSPC) { + /* + * The Linux glibc (at least as of 2.24) fallback if + * the file system does not support fallocate does not + * reset the file size back to where it was. Also, to + * me it is unclear from the posix spec of + * posix_fallocate whether this is allowed or + * not. Better be safe than sorry and "goto fail" but + * "return -1" here, leaving the EOF pointer too + * large. + */ + goto fail; + } + + /* + * Retry the "old" way. Possibly unnecessary, but looking at + * our configure script there seem to be weird failure modes + * for posix_fallocate. See commit 3264a98ff16de, which + * probably refers to + * https://sourceware.org/bugzilla/show_bug.cgi?id=1083. + */ +#endif + + ret = tdb_ftruncate(tdb, new_size); + if (ret == -1) { + char b = 0; + ssize_t written = tdb_pwrite(tdb, &b, 1, new_size - 1); + if (written == 0) { + /* try once more, potentially revealing errno */ + written = tdb_pwrite(tdb, &b, 1, new_size - 1); + } + if (written == 0) { + /* again - give up, guessing errno */ + errno = ENOSPC; + } + if (written != 1) { + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %u failed (%s)\n", + (unsigned)new_size, strerror(errno))); + return -1; + } + } + + /* now fill the file with something. This ensures that the + file isn't sparse, which would be very bad if we ran out of + disk. This must be done with write, not via mmap */ + memset(buf, TDB_PAD_BYTE, sizeof(buf)); + while (addition) { + size_t n = addition>sizeof(buf)?sizeof(buf):addition; + ssize_t written = tdb_pwrite(tdb, buf, n, size); + if (written == 0) { + /* prevent infinite loops: try _once_ more */ + written = tdb_pwrite(tdb, buf, n, size); + } + if (written == 0) { + /* give up, trying to provide a useful errno */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write " + "returned 0 twice: giving up!\n")); + errno = ENOSPC; + goto fail; + } + if (written == -1) { + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of " + "%u bytes failed (%s)\n", (int)n, + strerror(errno))); + goto fail; + } + if (written != n) { + TDB_LOG((tdb, TDB_DEBUG_WARNING, "expand_file: wrote " + "only %zu of %zi bytes - retrying\n", written, + n)); + } + addition -= written; + size += written; + } + return 0; + +fail: + { + int err = errno; + + /* + * We're holding the freelist lock or are inside a + * transaction. Cutting the file is safe, the space we + * tried to allocate can't have been used anywhere in + * the meantime. + */ + + ret = tdb_ftruncate(tdb, size); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_WARNING, "expand_file: " + "retruncate to %ju failed\n", + (uintmax_t)size)); + } + errno = err; + } + + return -1; +} + + +/* You need 'size', this tells you how much you should expand by. */ +tdb_off_t tdb_expand_adjust(tdb_off_t map_size, tdb_off_t size, int page_size) +{ + tdb_off_t new_size, top_size, increment; + tdb_off_t max_size = UINT32_MAX - map_size; + + if (size > max_size) { + /* + * We can't round up anymore, just give back + * what we're asked for. + * + * The caller has to take care of the ENOSPC handling. + */ + return size; + } + + /* limit size in order to avoid using up huge amounts of memory for + * in memory tdbs if an oddball huge record creeps in */ + if (size > 100 * 1024) { + increment = size * 2; + } else { + increment = size * 100; + } + if (increment < size) { + goto overflow; + } + + if (!tdb_add_off_t(map_size, increment, &top_size)) { + goto overflow; + } + + /* always make room for at least top_size more records, and at + least 25% more space. if the DB is smaller than 100MiB, + otherwise grow it by 10% only. */ + if (map_size > 100 * 1024 * 1024) { + new_size = map_size * 1.10; + } else { + new_size = map_size * 1.25; + } + if (new_size < map_size) { + goto overflow; + } + + /* Round the database up to a multiple of the page size */ + new_size = MAX(top_size, new_size); + + if (new_size + page_size < new_size) { + /* There's a "+" in TDB_ALIGN that might overflow... */ + goto overflow; + } + + return TDB_ALIGN(new_size, page_size) - map_size; + +overflow: + /* + * Somewhere in between we went over 4GB. Make one big jump to + * exactly 4GB database size. + */ + return max_size; +} + +/* expand the database at least size bytes by expanding the underlying + file and doing the mmap again if necessary */ +int tdb_expand(struct tdb_context *tdb, tdb_off_t size) +{ + struct tdb_record rec; + tdb_off_t offset; + tdb_off_t new_size; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n")); + return -1; + } + + /* must know about any previous expansions by another process */ + tdb_oob(tdb, tdb->map_size, 1, 1); + + /* + * Note: that we don't care about tdb->hdr_ofs != 0 here + * + * The 4GB limitation is just related to tdb->map_size + * and the offset calculation in the records. + * + * The file on disk can be up to 4GB + tdb->hdr_ofs + */ + size = tdb_expand_adjust(tdb->map_size, size, tdb->page_size); + + if (!tdb_add_off_t(tdb->map_size, size, &new_size)) { + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_expand " + "overflow detected current map_size[%u] size[%u]!\n", + (unsigned)tdb->map_size, (unsigned)size)); + goto fail; + } + + /* form a new freelist record */ + offset = tdb->map_size; + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = size - sizeof(rec); + + if (tdb->flags & TDB_INTERNAL) { + char *new_map_ptr; + + new_map_ptr = (char *)realloc(tdb->map_ptr, new_size); + if (!new_map_ptr) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + tdb->map_ptr = new_map_ptr; + tdb->map_size = new_size; + } else { + int ret; + + /* + * expand the file itself + */ + ret = tdb->methods->tdb_expand_file(tdb, tdb->map_size, size); + if (ret != 0) { + goto fail; + } + + /* Explicitly remap: if we're in a transaction, this won't + * happen automatically! */ + tdb_munmap(tdb); + tdb->map_size = new_size; + if (tdb_mmap(tdb) != 0) { + goto fail; + } + } + + /* link it into the free list */ + if (tdb_free(tdb, offset, &rec) == -1) + goto fail; + + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + +int _tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) +{ + int ret = tdb->methods->tdb_oob(tdb, off, len, probe); + return ret; +} + +/* read/write a tdb_off_t */ +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); +} + +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + tdb_off_t off = *d; + return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); +} + + +/* read a lump of data, allocating the space for it */ +unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) +{ + unsigned char *buf; + + /* some systems don't like zero length malloc */ + + if (!(buf = (unsigned char *)malloc(len ? len : 1))) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%u (%s)\n", + len, strerror(errno))); + return NULL; + } + if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) { + SAFE_FREE(buf); + return NULL; + } + return buf; +} + +/* Give a piece of tdb data to a parser */ + +int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, + tdb_off_t offset, tdb_len_t len, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + TDB_DATA data; + int result; + + data.dsize = len; + + if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) { + /* + * Optimize by avoiding the malloc/memcpy/free, point the + * parser directly at the mmap area. + */ + if (tdb_oob(tdb, offset, len, 0) != 0) { + return -1; + } + data.dptr = offset + (unsigned char *)tdb->map_ptr; + return parser(key, data, private_data); + } + + if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) { + return -1; + } + + result = parser(key, data, private_data); + free(data.dptr); + return result; +} + +/* read/write a record */ +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) +{ + int ret; + tdb_len_t overall_len; + + if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + if (TDB_BAD_MAGIC(rec)) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%u\n", rec->magic, offset)); + return -1; + } + + overall_len = rec->key_len + rec->data_len; + if (overall_len < rec->data_len) { + /* overflow */ + return -1; + } + + if (overall_len > rec->rec_len) { + /* invalid record */ + return -1; + } + + ret = tdb_oob(tdb, offset, rec->key_len, 1); + if (ret == -1) { + return -1; + } + ret = tdb_oob(tdb, offset, rec->data_len, 1); + if (ret == -1) { + return -1; + } + ret = tdb_oob(tdb, offset, rec->rec_len, 1); + if (ret == -1) { + return -1; + } + + return tdb_oob(tdb, rec->next, sizeof(*rec), 0); +} + +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) +{ + struct tdb_record r = *rec; + return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r)); +} + +static const struct tdb_methods io_methods = { + tdb_read, + tdb_write, + tdb_next_hash_chain, + tdb_notrans_oob, + tdb_expand_file, +}; + +/* + initialise the default methods table +*/ +void tdb_io_init(struct tdb_context *tdb) +{ + tdb->methods = &io_methods; +} diff --git a/ldb-2.0.8/lib/tdb/common/lock.c b/ldb-2.0.8/lib/tdb/common/lock.c new file mode 100644 index 0000000..5fba02f --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/lock.c @@ -0,0 +1,1031 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +_PUBLIC_ void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr) +{ + tdb->interrupt_sig_ptr = ptr; +} + +static int fcntl_lock(struct tdb_context *tdb, + int rw, off_t off, off_t len, bool waitflag) +{ + struct flock fl; + int cmd; + +#ifdef USE_TDB_MUTEX_LOCKING + { + int ret; + if (tdb_mutex_lock(tdb, rw, off, len, waitflag, &ret)) { + return ret; + } + } +#endif + + fl.l_type = rw; + fl.l_whence = SEEK_SET; + fl.l_start = off; + fl.l_len = len; + fl.l_pid = 0; + + cmd = waitflag ? F_SETLKW : F_SETLK; + + return fcntl(tdb->fd, cmd, &fl); +} + +static int fcntl_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len) +{ + struct flock fl; +#if 0 /* Check they matched up locks and unlocks correctly. */ + char line[80]; + FILE *locks; + bool found = false; + + locks = fopen("/proc/locks", "r"); + + while (fgets(line, 80, locks)) { + char *p; + int type, start, l; + + /* eg. 1: FLOCK ADVISORY WRITE 2440 08:01:2180826 0 EOF */ + p = strchr(line, ':') + 1; + if (strncmp(p, " POSIX ADVISORY ", strlen(" POSIX ADVISORY "))) + continue; + p += strlen(" FLOCK ADVISORY "); + if (strncmp(p, "READ ", strlen("READ ")) == 0) + type = F_RDLCK; + else if (strncmp(p, "WRITE ", strlen("WRITE ")) == 0) + type = F_WRLCK; + else + abort(); + p += 6; + if (atoi(p) != getpid()) + continue; + p = strchr(strchr(p, ' ') + 1, ' ') + 1; + start = atoi(p); + p = strchr(p, ' ') + 1; + if (strncmp(p, "EOF", 3) == 0) + l = 0; + else + l = atoi(p) - start + 1; + + if (off == start) { + if (len != l) { + fprintf(stderr, "Len %u should be %u: %s", + (int)len, l, line); + abort(); + } + if (type != rw) { + fprintf(stderr, "Type %s wrong: %s", + rw == F_RDLCK ? "READ" : "WRITE", line); + abort(); + } + found = true; + break; + } + } + + if (!found) { + fprintf(stderr, "Unlock on %u@%u not found!\n", + (int)off, (int)len); + abort(); + } + + fclose(locks); +#endif + +#ifdef USE_TDB_MUTEX_LOCKING + { + int ret; + if (tdb_mutex_unlock(tdb, rw, off, len, &ret)) { + return ret; + } + } +#endif + + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = off; + fl.l_len = len; + fl.l_pid = 0; + + return fcntl(tdb->fd, F_SETLKW, &fl); +} + +/* + * Calculate the lock offset for a list + * + * list -1 is the freelist, otherwise a hash chain. + * + * Note that we consistently (but without real reason) lock hash chains at an + * offset that is 4 bytes below the real offset of the corresponding list head + * in the db. + * + * This is the memory layout of the hashchain array: + * + * FREELIST_TOP + 0 = freelist + * FREELIST_TOP + 4 = hashtable list 0 + * FREELIST_TOP + 8 = hashtable list 1 + * ... + * + * Otoh lock_offset computes: + * + * freelist = FREELIST_TOP - 4 + * list 0 = FREELIST_TOP + 0 + * list 1 = FREELIST_TOP + 4 + * ... + * + * Unfortunately we can't change this calculation in order to align the locking + * offset with the memory layout, as that would make the locking incompatible + * between different tdb versions. + */ +static tdb_off_t lock_offset(int list) +{ + return FREELIST_TOP + 4*list; +} + +/* a byte range locking function - return 0 on success + this functions locks/unlocks "len" byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). + + note that a len of zero means lock to end of file +*/ +int tdb_brlock(struct tdb_context *tdb, + int rw_type, tdb_off_t offset, size_t len, + enum tdb_lock_flags flags) +{ + int ret; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + if (flags & TDB_LOCK_MARK_ONLY) { + return 0; + } + + if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + do { + ret = fcntl_lock(tdb, rw_type, offset, len, + flags & TDB_LOCK_WAIT); + /* Check for a sigalarm break. */ + if (ret == -1 && errno == EINTR && + tdb->interrupt_sig_ptr && + *tdb->interrupt_sig_ptr) { + break; + } + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + tdb->ecode = TDB_ERR_LOCK; + /* Generic lock error. errno set by fcntl. + * EAGAIN is an expected return from non-blocking + * locks. */ + if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) { + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %u rw_type=%d flags=%d len=%zu\n", + tdb->fd, offset, rw_type, flags, len)); + } + return -1; + } + return 0; +} + +int tdb_brunlock(struct tdb_context *tdb, + int rw_type, tdb_off_t offset, size_t len) +{ + int ret; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + do { + ret = fcntl_unlock(tdb, rw_type, offset, len); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %u rw_type=%u len=%zu\n", + tdb->fd, offset, rw_type, len)); + } + return ret; +} + +/* + * Do a tdb_brlock in a loop. Some OSes (such as solaris) have too + * conservative deadlock detection and claim a deadlock when progress can be + * made. For those OSes we may loop for a while. + */ + +static int tdb_brlock_retry(struct tdb_context *tdb, + int rw_type, tdb_off_t offset, size_t len, + enum tdb_lock_flags flags) +{ + int count = 1000; + + while (count--) { + struct timeval tv; + int ret; + + ret = tdb_brlock(tdb, rw_type, offset, len, flags); + if (ret == 0) { + return 0; + } + if (errno != EDEADLK) { + break; + } + /* sleep for as short a time as we can - more portable than usleep() */ + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); + } + return -1; +} + +/* + upgrade a read lock to a write lock. +*/ +int tdb_allrecord_upgrade(struct tdb_context *tdb) +{ + int ret; + + if (tdb->allrecord_lock.count != 1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_allrecord_upgrade failed: count %u too high\n", + tdb->allrecord_lock.count)); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->allrecord_lock.off != 1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_allrecord_upgrade failed: already upgraded?\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb_have_mutexes(tdb)) { + ret = tdb_mutex_allrecord_upgrade(tdb); + if (ret == -1) { + goto fail; + } + ret = tdb_brlock_retry(tdb, F_WRLCK, lock_offset(tdb->hash_size), + 0, TDB_LOCK_WAIT|TDB_LOCK_PROBE); + if (ret == -1) { + tdb_mutex_allrecord_downgrade(tdb); + } + } else { + ret = tdb_brlock_retry(tdb, F_WRLCK, FREELIST_TOP, 0, + TDB_LOCK_WAIT|TDB_LOCK_PROBE); + } + + if (ret == 0) { + tdb->allrecord_lock.ltype = F_WRLCK; + tdb->allrecord_lock.off = 0; + return 0; + } +fail: + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_allrecord_upgrade failed\n")); + return -1; +} + +static struct tdb_lock_type *find_nestlock(struct tdb_context *tdb, + tdb_off_t offset) +{ + int i; + + for (i=0; inum_lockrecs; i++) { + if (tdb->lockrecs[i].off == offset) { + return &tdb->lockrecs[i]; + } + } + return NULL; +} + +/* lock an offset in the database. */ +int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype, + enum tdb_lock_flags flags) +{ + struct tdb_lock_type *new_lck; + + if (offset >= lock_offset(tdb->hash_size)) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid offset %u for ltype=%d\n", + offset, ltype)); + return -1; + } + if (tdb->flags & TDB_NOLOCK) + return 0; + + new_lck = find_nestlock(tdb, offset); + if (new_lck) { + if ((new_lck->ltype == F_RDLCK) && (ltype == F_WRLCK)) { + if (!tdb_have_mutexes(tdb)) { + int ret; + /* + * Upgrade the underlying fcntl + * lock. Mutexes don't do readlocks, + * so this only applies to fcntl + * locking. + */ + ret = tdb_brlock(tdb, ltype, offset, 1, flags); + if (ret != 0) { + return ret; + } + } + new_lck->ltype = F_WRLCK; + } + /* + * Just increment the in-memory struct, posix locks + * don't stack. + */ + new_lck->count++; + return 0; + } + + if (tdb->num_lockrecs == tdb->lockrecs_array_length) { + new_lck = (struct tdb_lock_type *)realloc( + tdb->lockrecs, + sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1)); + if (new_lck == NULL) { + errno = ENOMEM; + return -1; + } + tdb->lockrecs_array_length = tdb->num_lockrecs+1; + tdb->lockrecs = new_lck; + } + + /* Since fcntl locks don't nest, we do a lock for the first one, + and simply bump the count for future ones */ + if (tdb_brlock(tdb, ltype, offset, 1, flags)) { + return -1; + } + + new_lck = &tdb->lockrecs[tdb->num_lockrecs]; + + new_lck->off = offset; + new_lck->count = 1; + new_lck->ltype = ltype; + tdb->num_lockrecs++; + + return 0; +} + +static int tdb_lock_and_recover(struct tdb_context *tdb) +{ + int ret; + + /* We need to match locking order in transaction commit. */ + if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, TDB_LOCK_WAIT)) { + return -1; + } + + if (tdb_brlock(tdb, F_WRLCK, OPEN_LOCK, 1, TDB_LOCK_WAIT)) { + tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0); + return -1; + } + + ret = tdb_transaction_recover(tdb); + + tdb_brunlock(tdb, F_WRLCK, OPEN_LOCK, 1); + tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0); + + return ret; +} + +static bool have_data_locks(const struct tdb_context *tdb) +{ + int i; + + for (i = 0; i < tdb->num_lockrecs; i++) { + if (tdb->lockrecs[i].off >= lock_offset(-1)) + return true; + } + return false; +} + +/* + * A allrecord lock allows us to avoid per chain locks. Check if the allrecord + * lock is strong enough. + */ +static int tdb_lock_covered_by_allrecord_lock(struct tdb_context *tdb, + int ltype) +{ + if (ltype == F_RDLCK) { + /* + * The allrecord_lock is equal (F_RDLCK) or stronger + * (F_WRLCK). Pass. + */ + return 0; + } + + if (tdb->allrecord_lock.ltype == F_RDLCK) { + /* + * We ask for ltype==F_WRLCK, but the allrecord_lock + * is too weak. We can't upgrade here, so fail. + */ + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + /* + * Asking for F_WRLCK, allrecord is F_WRLCK as well. Pass. + */ + return 0; +} + +static int tdb_lock_list(struct tdb_context *tdb, int list, int ltype, + enum tdb_lock_flags waitflag) +{ + int ret; + bool check = false; + + if (tdb->allrecord_lock.count) { + return tdb_lock_covered_by_allrecord_lock(tdb, ltype); + } + + /* + * Check for recoveries: Someone might have kill -9'ed a process + * during a commit. + */ + check = !have_data_locks(tdb); + ret = tdb_nest_lock(tdb, lock_offset(list), ltype, waitflag); + + if (ret == 0 && check && tdb_needs_recovery(tdb)) { + tdb_nest_unlock(tdb, lock_offset(list), ltype, false); + + if (tdb_lock_and_recover(tdb) == -1) { + return -1; + } + return tdb_lock_list(tdb, list, ltype, waitflag); + } + return ret; +} + +/* lock a list in the database. list -1 is the alloc list */ +int tdb_lock(struct tdb_context *tdb, int list, int ltype) +{ + int ret; + + ret = tdb_lock_list(tdb, list, ltype, TDB_LOCK_WAIT); + if (ret) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d " + "ltype=%d (%s)\n", list, ltype, strerror(errno))); + } + return ret; +} + +/* lock a list in the database. list -1 is the alloc list. non-blocking lock */ +_PUBLIC_ int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype) +{ + return tdb_lock_list(tdb, list, ltype, TDB_LOCK_NOWAIT); +} + + +int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype, + bool mark_lock) +{ + int ret = -1; + struct tdb_lock_type *lck; + + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Sanity checks */ + if (offset >= lock_offset(tdb->hash_size)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: offset %u invalid (%d)\n", offset, tdb->hash_size)); + return ret; + } + + lck = find_nestlock(tdb, offset); + if ((lck == NULL) || (lck->count == 0)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); + return -1; + } + + if (lck->count > 1) { + lck->count--; + return 0; + } + + /* + * This lock has count==1 left, so we need to unlock it in the + * kernel. We don't bother with decrementing the in-memory array + * element, we're about to overwrite it with the last array element + * anyway. + */ + + if (mark_lock) { + ret = 0; + } else { + ret = tdb_brunlock(tdb, ltype, offset, 1); + } + + /* + * Shrink the array by overwriting the element just unlocked with the + * last array element. + */ + *lck = tdb->lockrecs[--tdb->num_lockrecs]; + + /* + * We don't bother with realloc when the array shrinks, but if we have + * a completely idle tdb we should get rid of the locked array. + */ + + if (ret) + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n")); + return ret; +} + +_PUBLIC_ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) +{ + /* a global lock allows us to avoid per chain locks */ + if (tdb->allrecord_lock.count) { + return tdb_lock_covered_by_allrecord_lock(tdb, ltype); + } + + return tdb_nest_unlock(tdb, lock_offset(list), ltype, false); +} + +/* + get the transaction lock + */ +int tdb_transaction_lock(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags lockflags) +{ + return tdb_nest_lock(tdb, TRANSACTION_LOCK, ltype, lockflags); +} + +/* + release the transaction lock + */ +int tdb_transaction_unlock(struct tdb_context *tdb, int ltype) +{ + return tdb_nest_unlock(tdb, TRANSACTION_LOCK, ltype, false); +} + +/* Returns 0 if all done, -1 if error, 1 if ok. */ +static int tdb_allrecord_check(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags flags, bool upgradable) +{ + /* There are no locks on read-only dbs */ + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->allrecord_lock.count && + tdb->allrecord_lock.ltype == (uint32_t)ltype) { + tdb->allrecord_lock.count++; + return 0; + } + + if (tdb->allrecord_lock.count) { + /* a global lock of a different type exists */ + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb_have_extra_locks(tdb)) { + /* can't combine global and chain locks */ + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (upgradable && ltype != F_RDLCK) { + /* tdb error: you can't upgrade a write lock! */ + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + return 1; +} + +/* We only need to lock individual bytes, but Linux merges consecutive locks + * so we lock in contiguous ranges. */ +static int tdb_chainlock_gradual(struct tdb_context *tdb, + int ltype, enum tdb_lock_flags flags, + size_t off, size_t len) +{ + int ret; + enum tdb_lock_flags nb_flags = (flags & ~TDB_LOCK_WAIT); + + if (len <= 4) { + /* Single record. Just do blocking lock. */ + return tdb_brlock(tdb, ltype, off, len, flags); + } + + /* First we try non-blocking. */ + ret = tdb_brlock(tdb, ltype, off, len, nb_flags); + if (ret == 0) { + return 0; + } + + /* Try locking first half, then second. */ + ret = tdb_chainlock_gradual(tdb, ltype, flags, off, len / 2); + if (ret == -1) + return -1; + + ret = tdb_chainlock_gradual(tdb, ltype, flags, + off + len / 2, len - len / 2); + if (ret == -1) { + tdb_brunlock(tdb, ltype, off, len / 2); + return -1; + } + return 0; +} + +/* lock/unlock entire database. It can only be upgradable if you have some + * other way of guaranteeing exclusivity (ie. transaction write lock). + * We do the locking gradually to avoid being starved by smaller locks. */ +int tdb_allrecord_lock(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags flags, bool upgradable) +{ + int ret; + + switch (tdb_allrecord_check(tdb, ltype, flags, upgradable)) { + case -1: + return -1; + case 0: + return 0; + } + + /* We cover two kinds of locks: + * 1) Normal chain locks. Taken for almost all operations. + * 2) Individual records locks. Taken after normal or free + * chain locks. + * + * It is (1) which cause the starvation problem, so we're only + * gradual for that. */ + + if (tdb_have_mutexes(tdb)) { + ret = tdb_mutex_allrecord_lock(tdb, ltype, flags); + } else { + ret = tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP, + tdb->hash_size * 4); + } + + if (ret == -1) { + return -1; + } + + /* Grab individual record locks. */ + if (tdb_brlock(tdb, ltype, lock_offset(tdb->hash_size), 0, + flags) == -1) { + if (tdb_have_mutexes(tdb)) { + tdb_mutex_allrecord_unlock(tdb); + } else { + tdb_brunlock(tdb, ltype, FREELIST_TOP, + tdb->hash_size * 4); + } + return -1; + } + + tdb->allrecord_lock.count = 1; + /* If it's upgradable, it's actually exclusive so we can treat + * it as a write lock. */ + tdb->allrecord_lock.ltype = upgradable ? F_WRLCK : ltype; + tdb->allrecord_lock.off = upgradable; + + if (tdb_needs_recovery(tdb)) { + bool mark = flags & TDB_LOCK_MARK_ONLY; + tdb_allrecord_unlock(tdb, ltype, mark); + if (mark) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_lockall_mark cannot do recovery\n")); + return -1; + } + if (tdb_lock_and_recover(tdb) == -1) { + return -1; + } + return tdb_allrecord_lock(tdb, ltype, flags, upgradable); + } + + return 0; +} + + + +/* unlock entire db */ +int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock) +{ + /* There are no locks on read-only dbs */ + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->allrecord_lock.count == 0) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + /* Upgradable locks are marked as write locks. */ + if (tdb->allrecord_lock.ltype != (uint32_t)ltype + && (!tdb->allrecord_lock.off || ltype != F_RDLCK)) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->allrecord_lock.count > 1) { + tdb->allrecord_lock.count--; + return 0; + } + + if (!mark_lock) { + int ret; + + if (tdb_have_mutexes(tdb)) { + ret = tdb_mutex_allrecord_unlock(tdb); + if (ret == 0) { + ret = tdb_brunlock(tdb, ltype, + lock_offset(tdb->hash_size), + 0); + } + } else { + ret = tdb_brunlock(tdb, ltype, FREELIST_TOP, 0); + } + + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed " + "(%s)\n", strerror(errno))); + return -1; + } + } + + tdb->allrecord_lock.count = 0; + tdb->allrecord_lock.ltype = 0; + + return 0; +} + +/* lock entire database with write lock */ +_PUBLIC_ int tdb_lockall(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall"); + return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); +} + +/* lock entire database with write lock - mark only */ +_PUBLIC_ int tdb_lockall_mark(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall_mark"); + return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_MARK_ONLY, false); +} + +/* unlock entire database with write lock - unmark only */ +_PUBLIC_ int tdb_lockall_unmark(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall_unmark"); + return tdb_allrecord_unlock(tdb, F_WRLCK, true); +} + +/* lock entire database with write lock - nonblocking varient */ +_PUBLIC_ int tdb_lockall_nonblock(struct tdb_context *tdb) +{ + int ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_NOWAIT, false); + tdb_trace_ret(tdb, "tdb_lockall_nonblock", ret); + return ret; +} + +/* unlock entire database with write lock */ +_PUBLIC_ int tdb_unlockall(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_unlockall"); + return tdb_allrecord_unlock(tdb, F_WRLCK, false); +} + +/* lock entire database with read lock */ +_PUBLIC_ int tdb_lockall_read(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall_read"); + return tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false); +} + +/* lock entire database with read lock - nonblock varient */ +_PUBLIC_ int tdb_lockall_read_nonblock(struct tdb_context *tdb) +{ + int ret = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_NOWAIT, false); + tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret); + return ret; +} + +/* unlock entire database with read lock */ +_PUBLIC_ int tdb_unlockall_read(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_unlockall_read"); + return tdb_allrecord_unlock(tdb, F_RDLCK, false); +} + +/* lock/unlock one hash chain. This is meant to be used to reduce + contention - it cannot guarantee how many records will be locked */ +_PUBLIC_ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) +{ + int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); + tdb_trace_1rec(tdb, "tdb_chainlock", key); + return ret; +} + +/* lock/unlock one hash chain, non-blocking. This is meant to be used + to reduce contention - it cannot guarantee how many records will be + locked */ +_PUBLIC_ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key) +{ + int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); + tdb_trace_1rec_ret(tdb, "tdb_chainlock_nonblock", key, ret); + return ret; +} + +/* mark a chain as locked without actually locking it. Warning! use with great caution! */ +_PUBLIC_ int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) +{ + int ret = tdb_nest_lock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))), + F_WRLCK, TDB_LOCK_MARK_ONLY); + tdb_trace_1rec(tdb, "tdb_chainlock_mark", key); + return ret; +} + +/* unmark a chain as locked without actually locking it. Warning! use with great caution! */ +_PUBLIC_ int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_trace_1rec(tdb, "tdb_chainlock_unmark", key); + return tdb_nest_unlock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))), + F_WRLCK, true); +} + +_PUBLIC_ int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_trace_1rec(tdb, "tdb_chainunlock", key); + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +_PUBLIC_ int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + int ret; + ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); + tdb_trace_1rec(tdb, "tdb_chainlock_read", key); + return ret; +} + +_PUBLIC_ int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_trace_1rec(tdb, "tdb_chainunlock_read", key); + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + +_PUBLIC_ int tdb_chainlock_read_nonblock(struct tdb_context *tdb, TDB_DATA key) +{ + int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); + tdb_trace_1rec_ret(tdb, "tdb_chainlock_read_nonblock", key, ret); + return ret; +} + +/* record lock stops delete underneath */ +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + if (tdb->allrecord_lock.count) { + return 0; + } + return off ? tdb_brlock(tdb, F_RDLCK, off, 1, TDB_LOCK_WAIT) : 0; +} + +/* + Write locks override our own fcntl readlocks, so check it here. + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + if (tdb == NULL) { + return -1; + } + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + return -1; + if (tdb->allrecord_lock.count) { + if (tdb->allrecord_lock.ltype == F_WRLCK) { + return 0; + } + return -1; + } + return tdb_brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE); +} + +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + if (tdb->allrecord_lock.count) { + return 0; + } + return tdb_brunlock(tdb, F_WRLCK, off, 1); +} + +/* fcntl locks don't stack: avoid unlocking someone else's */ +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + uint32_t count = 0; + + if (tdb->allrecord_lock.count) { + return 0; + } + + if (off == 0) + return 0; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + count++; + return (count == 1 ? tdb_brunlock(tdb, F_RDLCK, off, 1) : 0); +} + +bool tdb_have_extra_locks(struct tdb_context *tdb) +{ + unsigned int extra = tdb->num_lockrecs; + + /* A transaction holds the lock for all records. */ + if (!tdb->transaction && tdb->allrecord_lock.count) { + return true; + } + + /* We always hold the active lock if CLEAR_IF_FIRST. */ + if (find_nestlock(tdb, ACTIVE_LOCK)) { + extra--; + } + + /* In a transaction, we expect to hold the transaction lock */ + if (tdb->transaction && find_nestlock(tdb, TRANSACTION_LOCK)) { + extra--; + } + + return extra; +} + +/* The transaction code uses this to remove all locks. */ +void tdb_release_transaction_locks(struct tdb_context *tdb) +{ + int i; + unsigned int active = 0; + + if (tdb->allrecord_lock.count != 0) { + tdb_allrecord_unlock(tdb, tdb->allrecord_lock.ltype, false); + tdb->allrecord_lock.count = 0; + } + + for (i=0;inum_lockrecs;i++) { + struct tdb_lock_type *lck = &tdb->lockrecs[i]; + + /* Don't release the active lock! Copy it to first entry. */ + if (lck->off == ACTIVE_LOCK) { + tdb->lockrecs[active++] = *lck; + } else { + tdb_brunlock(tdb, lck->ltype, lck->off, 1); + } + } + tdb->num_lockrecs = active; +} + +/* Following functions are added specifically to support CTDB. */ + +/* Don't do actual fcntl locking, just mark tdb locked */ +int tdb_transaction_write_lock_mark(struct tdb_context *tdb); +_PUBLIC_ int tdb_transaction_write_lock_mark(struct tdb_context *tdb) +{ + return tdb_transaction_lock(tdb, F_WRLCK, TDB_LOCK_MARK_ONLY); +} + +/* Don't do actual fcntl unlocking, just mark tdb unlocked */ +int tdb_transaction_write_lock_unmark(struct tdb_context *tdb); +_PUBLIC_ int tdb_transaction_write_lock_unmark(struct tdb_context *tdb) +{ + return tdb_nest_unlock(tdb, TRANSACTION_LOCK, F_WRLCK, true); +} diff --git a/ldb-2.0.8/lib/tdb/common/mutex.c b/ldb-2.0.8/lib/tdb/common/mutex.c new file mode 100644 index 0000000..8a122d5 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/mutex.c @@ -0,0 +1,1077 @@ +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Volker Lendecke 2012,2013 + Copyright (C) Stefan Metzmacher 2013,2014 + Copyright (C) Michael Adam 2014 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ +#include "tdb_private.h" +#include "system/threads.h" + +#ifdef USE_TDB_MUTEX_LOCKING + +/* + * If we run with mutexes, we store the "struct tdb_mutexes" at the + * beginning of the file. We store an additional tdb_header right + * beyond the mutex area, page aligned. All the offsets within the tdb + * are relative to the area behind the mutex area. tdb->map_ptr points + * behind the mmap area as well, so the read and write path in the + * mutex case can remain unchanged. + * + * Early in the mutex development the mutexes were placed between the hash + * chain pointers and the real tdb data. This had two drawbacks: First, it + * made pointer calculations more complex. Second, we had to mmap the mutex + * area twice. One was the normal map_ptr in the tdb. This frequently changed + * from within tdb_oob. At least the Linux glibc robust mutex code assumes + * constant pointers in memory, so a constantly changing mmap area destroys + * the mutex list. So we had to mmap the first bytes of the file with a second + * mmap call. With that scheme, very weird errors happened that could be + * easily fixed by doing the mutex mmap in a second file. It seemed that + * mapping the same memory area twice does not end up in accessing the same + * physical page, looking at the mutexes in gdb it seemed that old data showed + * up after some re-mapping. To avoid a separate mutex file, the code now puts + * the real content of the tdb file after the mutex area. This way we do not + * have overlapping mmap areas, the mutex area is mmapped once and not + * changed, the tdb data area's mmap is constantly changed but does not + * overlap. + */ + +struct tdb_mutexes { + struct tdb_header hdr; + + /* protect allrecord_lock */ + pthread_mutex_t allrecord_mutex; + + /* + * F_UNLCK: free, + * F_RDLCK: shared, + * F_WRLCK: exclusive + */ + short int allrecord_lock; + + /* + * Index 0 is the freelist mutex, followed by + * one mutex per hashchain. + */ + pthread_mutex_t hashchains[1]; +}; + +bool tdb_have_mutexes(struct tdb_context *tdb) +{ + return ((tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) != 0); +} + +size_t tdb_mutex_size(struct tdb_context *tdb) +{ + size_t mutex_size; + + if (!tdb_have_mutexes(tdb)) { + return 0; + } + + mutex_size = sizeof(struct tdb_mutexes); + mutex_size += tdb->hash_size * sizeof(pthread_mutex_t); + + return TDB_ALIGN(mutex_size, tdb->page_size); +} + +/* + * Get the index for a chain mutex + */ +static bool tdb_mutex_index(struct tdb_context *tdb, off_t off, off_t len, + unsigned *idx) +{ + /* + * Weird but true: We fcntl lock 1 byte at an offset 4 bytes before + * the 4 bytes of the freelist start and the hash chain that is about + * to be locked. See lock_offset() where the freelist is -1 vs the + * "+1" in TDB_HASH_TOP(). Because the mutex array is represented in + * the tdb file itself as data, we need to adjust the offset here. + */ + const off_t freelist_lock_ofs = FREELIST_TOP - sizeof(tdb_off_t); + + if (!tdb_have_mutexes(tdb)) { + return false; + } + if (len != 1) { + /* Possibly the allrecord lock */ + return false; + } + if (off < freelist_lock_ofs) { + /* One of the special locks */ + return false; + } + if (tdb->hash_size == 0) { + /* tdb not initialized yet, called from tdb_open_ex() */ + return false; + } + if (off >= TDB_DATA_START(tdb->hash_size)) { + /* Single record lock from traverses */ + return false; + } + + /* + * Now we know it's a freelist or hash chain lock. Those are always 4 + * byte aligned. Paranoia check. + */ + if ((off % sizeof(tdb_off_t)) != 0) { + abort(); + } + + /* + * Re-index the fcntl offset into an offset into the mutex array + */ + off -= freelist_lock_ofs; /* rebase to index 0 */ + off /= sizeof(tdb_off_t); /* 0 for freelist 1-n for hashchain */ + + *idx = off; + return true; +} + +static bool tdb_have_mutex_chainlocks(struct tdb_context *tdb) +{ + size_t i; + + for (i=0; i < tdb->num_lockrecs; i++) { + bool ret; + unsigned idx; + + ret = tdb_mutex_index(tdb, + tdb->lockrecs[i].off, + tdb->lockrecs[i].count, + &idx); + if (!ret) { + continue; + } + + if (idx == 0) { + /* this is the freelist mutex */ + continue; + } + + return true; + } + + return false; +} + +static int chain_mutex_lock(pthread_mutex_t *m, bool waitflag) +{ + int ret; + + if (waitflag) { + ret = pthread_mutex_lock(m); + } else { + ret = pthread_mutex_trylock(m); + } + if (ret != EOWNERDEAD) { + return ret; + } + + /* + * For chainlocks, we don't do any cleanup (yet?) + */ + return pthread_mutex_consistent(m); +} + +static int allrecord_mutex_lock(struct tdb_mutexes *m, bool waitflag) +{ + int ret; + + if (waitflag) { + ret = pthread_mutex_lock(&m->allrecord_mutex); + } else { + ret = pthread_mutex_trylock(&m->allrecord_mutex); + } + if (ret != EOWNERDEAD) { + return ret; + } + + /* + * The allrecord lock holder died. We need to reset the allrecord_lock + * to F_UNLCK. This should also be the indication for + * tdb_needs_recovery. + */ + m->allrecord_lock = F_UNLCK; + + return pthread_mutex_consistent(&m->allrecord_mutex); +} + +bool tdb_mutex_lock(struct tdb_context *tdb, int rw, off_t off, off_t len, + bool waitflag, int *pret) +{ + struct tdb_mutexes *m = tdb->mutexes; + pthread_mutex_t *chain; + int ret; + unsigned idx; + bool allrecord_ok; + + if (!tdb_mutex_index(tdb, off, len, &idx)) { + return false; + } + chain = &m->hashchains[idx]; + +again: + ret = chain_mutex_lock(chain, waitflag); + if (ret == EBUSY) { + ret = EAGAIN; + } + if (ret != 0) { + errno = ret; + goto fail; + } + + if (idx == 0) { + /* + * This is a freelist lock, which is independent to + * the allrecord lock. So we're done once we got the + * freelist mutex. + */ + *pret = 0; + return true; + } + + if (tdb_have_mutex_chainlocks(tdb)) { + /* + * We can only check the allrecord lock once. If we do it with + * one chain mutex locked, we will deadlock with the allrecord + * locker process in the following way: We lock the first hash + * chain, we check for the allrecord lock. We keep the hash + * chain locked. Then the allrecord locker locks the + * allrecord_mutex. It walks the list of chain mutexes, + * locking them all in sequence. Meanwhile, we have the chain + * mutex locked, so the allrecord locker blocks trying to lock + * our chain mutex. Then we come in and try to lock the second + * chain lock, which in most cases will be the freelist. We + * see that the allrecord lock is locked and put ourselves on + * the allrecord_mutex. This will never be signalled though + * because the allrecord locker waits for us to give up the + * chain lock. + */ + + *pret = 0; + return true; + } + + /* + * Check if someone is has the allrecord lock: queue if so. + */ + + allrecord_ok = false; + + if (m->allrecord_lock == F_UNLCK) { + /* + * allrecord lock not taken + */ + allrecord_ok = true; + } + + if ((m->allrecord_lock == F_RDLCK) && (rw == F_RDLCK)) { + /* + * allrecord shared lock taken, but we only want to read + */ + allrecord_ok = true; + } + + if (allrecord_ok) { + *pret = 0; + return true; + } + + ret = pthread_mutex_unlock(chain); + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_unlock" + "(chain_mutex) failed: %s\n", strerror(ret))); + errno = ret; + goto fail; + } + ret = allrecord_mutex_lock(m, waitflag); + if (ret == EBUSY) { + ret = EAGAIN; + } + if (ret != 0) { + if (waitflag || (ret != EAGAIN)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_%slock" + "(allrecord_mutex) failed: %s\n", + waitflag ? "" : "try_", strerror(ret))); + } + errno = ret; + goto fail; + } + ret = pthread_mutex_unlock(&m->allrecord_mutex); + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_unlock" + "(allrecord_mutex) failed: %s\n", strerror(ret))); + errno = ret; + goto fail; + } + goto again; + +fail: + *pret = -1; + return true; +} + +bool tdb_mutex_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len, + int *pret) +{ + struct tdb_mutexes *m = tdb->mutexes; + pthread_mutex_t *chain; + int ret; + unsigned idx; + + if (!tdb_mutex_index(tdb, off, len, &idx)) { + return false; + } + chain = &m->hashchains[idx]; + + ret = pthread_mutex_unlock(chain); + if (ret == 0) { + *pret = 0; + return true; + } + errno = ret; + *pret = -1; + return true; +} + +int tdb_mutex_allrecord_lock(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags flags) +{ + struct tdb_mutexes *m = tdb->mutexes; + int ret; + uint32_t i; + bool waitflag = (flags & TDB_LOCK_WAIT); + int saved_errno; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + if (flags & TDB_LOCK_MARK_ONLY) { + return 0; + } + + ret = allrecord_mutex_lock(m, waitflag); + if (!waitflag && (ret == EBUSY)) { + errno = EAGAIN; + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + if (ret != 0) { + if (!(flags & TDB_LOCK_PROBE)) { + TDB_LOG((tdb, TDB_DEBUG_TRACE, + "allrecord_mutex_lock() failed: %s\n", + strerror(ret))); + } + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (m->allrecord_lock != F_UNLCK) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "allrecord_lock == %d\n", + (int)m->allrecord_lock)); + goto fail_unlock_allrecord_mutex; + } + m->allrecord_lock = (ltype == F_RDLCK) ? F_RDLCK : F_WRLCK; + + for (i=0; ihash_size; i++) { + + /* ignore hashchains[0], the freelist */ + pthread_mutex_t *chain = &m->hashchains[i+1]; + + ret = chain_mutex_lock(chain, waitflag); + if (!waitflag && (ret == EBUSY)) { + errno = EAGAIN; + goto fail_unroll_allrecord_lock; + } + if (ret != 0) { + if (!(flags & TDB_LOCK_PROBE)) { + TDB_LOG((tdb, TDB_DEBUG_TRACE, + "chain_mutex_lock() failed: %s\n", + strerror(ret))); + } + errno = ret; + goto fail_unroll_allrecord_lock; + } + + ret = pthread_mutex_unlock(chain); + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_unlock" + "(chainlock) failed: %s\n", strerror(ret))); + errno = ret; + goto fail_unroll_allrecord_lock; + } + } + /* + * We leave this routine with m->allrecord_mutex locked + */ + return 0; + +fail_unroll_allrecord_lock: + m->allrecord_lock = F_UNLCK; + +fail_unlock_allrecord_mutex: + saved_errno = errno; + ret = pthread_mutex_unlock(&m->allrecord_mutex); + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_unlock" + "(allrecord_mutex) failed: %s\n", strerror(ret))); + } + errno = saved_errno; + tdb->ecode = TDB_ERR_LOCK; + return -1; +} + +int tdb_mutex_allrecord_upgrade(struct tdb_context *tdb) +{ + struct tdb_mutexes *m = tdb->mutexes; + int ret; + uint32_t i; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + /* + * Our only caller tdb_allrecord_upgrade() + * garantees that we already own the allrecord lock. + * + * Which means m->allrecord_mutex is still locked by us. + */ + + if (m->allrecord_lock != F_RDLCK) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "allrecord_lock == %d\n", + (int)m->allrecord_lock)); + return -1; + } + + m->allrecord_lock = F_WRLCK; + + for (i=0; ihash_size; i++) { + + /* ignore hashchains[0], the freelist */ + pthread_mutex_t *chain = &m->hashchains[i+1]; + + ret = chain_mutex_lock(chain, true); + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_lock" + "(chainlock) failed: %s\n", strerror(ret))); + goto fail_unroll_allrecord_lock; + } + + ret = pthread_mutex_unlock(chain); + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_unlock" + "(chainlock) failed: %s\n", strerror(ret))); + goto fail_unroll_allrecord_lock; + } + } + + return 0; + +fail_unroll_allrecord_lock: + m->allrecord_lock = F_RDLCK; + tdb->ecode = TDB_ERR_LOCK; + return -1; +} + +void tdb_mutex_allrecord_downgrade(struct tdb_context *tdb) +{ + struct tdb_mutexes *m = tdb->mutexes; + + /* + * Our only caller tdb_allrecord_upgrade() (in the error case) + * garantees that we already own the allrecord lock. + * + * Which means m->allrecord_mutex is still locked by us. + */ + + if (m->allrecord_lock != F_WRLCK) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "allrecord_lock == %d\n", + (int)m->allrecord_lock)); + return; + } + + m->allrecord_lock = F_RDLCK; + return; +} + + +int tdb_mutex_allrecord_unlock(struct tdb_context *tdb) +{ + struct tdb_mutexes *m = tdb->mutexes; + short old; + int ret; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + /* + * Our only callers tdb_allrecord_unlock() and + * tdb_allrecord_lock() (in the error path) + * garantee that we already own the allrecord lock. + * + * Which means m->allrecord_mutex is still locked by us. + */ + + if ((m->allrecord_lock != F_RDLCK) && (m->allrecord_lock != F_WRLCK)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "allrecord_lock == %d\n", + (int)m->allrecord_lock)); + return -1; + } + + old = m->allrecord_lock; + m->allrecord_lock = F_UNLCK; + + ret = pthread_mutex_unlock(&m->allrecord_mutex); + if (ret != 0) { + m->allrecord_lock = old; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "pthread_mutex_unlock" + "(allrecord_mutex) failed: %s\n", strerror(ret))); + return -1; + } + return 0; +} + +int tdb_mutex_init(struct tdb_context *tdb) +{ + struct tdb_mutexes *m; + pthread_mutexattr_t ma; + int i, ret; + + ret = tdb_mutex_mmap(tdb); + if (ret == -1) { + return -1; + } + m = tdb->mutexes; + + ret = pthread_mutexattr_init(&ma); + if (ret != 0) { + goto fail_munmap; + } + ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); + if (ret != 0) { + goto fail; + } + ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); + if (ret != 0) { + goto fail; + } + ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); + if (ret != 0) { + goto fail; + } + + for (i=0; ihash_size+1; i++) { + pthread_mutex_t *chain = &m->hashchains[i]; + + ret = pthread_mutex_init(chain, &ma); + if (ret != 0) { + goto fail; + } + } + + m->allrecord_lock = F_UNLCK; + + ret = pthread_mutex_init(&m->allrecord_mutex, &ma); + if (ret != 0) { + goto fail; + } + ret = 0; +fail: + pthread_mutexattr_destroy(&ma); +fail_munmap: + + if (ret == 0) { + return 0; + } + + tdb_mutex_munmap(tdb); + + errno = ret; + return -1; +} + +int tdb_mutex_mmap(struct tdb_context *tdb) +{ + size_t len; + void *ptr; + + len = tdb_mutex_size(tdb); + if (len == 0) { + 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) { + return -1; + } + tdb->mutexes = (struct tdb_mutexes *)ptr; + + return 0; +} + +int tdb_mutex_munmap(struct tdb_context *tdb) +{ + size_t len; + int ret; + + len = tdb_mutex_size(tdb); + if (len == 0) { + return 0; + } + + ret = munmap(tdb->mutexes, len); + if (ret == -1) { + return -1; + } + tdb->mutexes = NULL; + + return 0; +} + +static bool tdb_mutex_locking_cached; + +static bool tdb_mutex_locking_supported(void) +{ + pthread_mutexattr_t ma; + pthread_mutex_t m; + int ret; + static bool initialized; + + if (initialized) { + return tdb_mutex_locking_cached; + } + + initialized = true; + + ret = pthread_mutexattr_init(&ma); + if (ret != 0) { + return false; + } + ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); + if (ret != 0) { + goto cleanup_ma; + } + ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); + if (ret != 0) { + goto cleanup_ma; + } + ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); + if (ret != 0) { + goto cleanup_ma; + } + ret = pthread_mutex_init(&m, &ma); + if (ret != 0) { + goto cleanup_ma; + } + ret = pthread_mutex_lock(&m); + if (ret != 0) { + goto cleanup_m; + } + /* + * This makes sure we have real mutexes + * from a threading library instead of just + * stubs from libc. + */ + ret = pthread_mutex_lock(&m); + if (ret != EDEADLK) { + goto cleanup_lock; + } + ret = pthread_mutex_unlock(&m); + if (ret != 0) { + goto cleanup_m; + } + + tdb_mutex_locking_cached = true; + goto cleanup_m; + +cleanup_lock: + pthread_mutex_unlock(&m); +cleanup_m: + pthread_mutex_destroy(&m); +cleanup_ma: + pthread_mutexattr_destroy(&ma); + return tdb_mutex_locking_cached; +} + +static void (*tdb_robust_mutext_old_handler)(int) = SIG_ERR; +static pid_t tdb_robust_mutex_pid = -1; + +static bool tdb_robust_mutex_setup_sigchild(void (*handler)(int), + void (**p_old_handler)(int)) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + memset(&act, '\0', sizeof(act)); + + act.sa_handler = handler; +#ifdef SA_RESTART + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask, SIGCHLD); + sigaction(SIGCHLD, &act, &oldact); + if (p_old_handler) { + *p_old_handler = oldact.sa_handler; + } + return true; +#else /* !HAVE_SIGACTION */ + return false; +#endif +} + +static void tdb_robust_mutex_handler(int sig) +{ + pid_t child_pid = tdb_robust_mutex_pid; + + if (child_pid != -1) { + pid_t pid; + + pid = waitpid(child_pid, NULL, WNOHANG); + if (pid == -1) { + switch (errno) { + case ECHILD: + tdb_robust_mutex_pid = -1; + return; + + default: + return; + } + } + if (pid == child_pid) { + tdb_robust_mutex_pid = -1; + return; + } + } + + if (tdb_robust_mutext_old_handler == SIG_DFL) { + return; + } + if (tdb_robust_mutext_old_handler == SIG_IGN) { + return; + } + if (tdb_robust_mutext_old_handler == SIG_ERR) { + return; + } + + tdb_robust_mutext_old_handler(sig); +} + +static void tdb_robust_mutex_wait_for_child(pid_t *child_pid) +{ + int options = WNOHANG; + + if (*child_pid == -1) { + return; + } + + while (tdb_robust_mutex_pid > 0) { + pid_t pid; + + /* + * First we try with WNOHANG, as the process might not exist + * anymore. Once we've sent SIGKILL we block waiting for the + * exit. + */ + pid = waitpid(*child_pid, NULL, options); + if (pid == -1) { + if (errno == EINTR) { + continue; + } else if (errno == ECHILD) { + break; + } else { + abort(); + } + } + if (pid == *child_pid) { + break; + } + + kill(*child_pid, SIGKILL); + options = 0; + } + + tdb_robust_mutex_pid = -1; + *child_pid = -1; +} + +_PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void) +{ + void *ptr = NULL; + pthread_mutex_t *m = NULL; + pthread_mutexattr_t ma; + int ret = 1; + int pipe_down[2] = { -1, -1 }; + int pipe_up[2] = { -1, -1 }; + ssize_t nread; + char c = 0; + bool ok; + static bool initialized; + pid_t saved_child_pid = -1; + bool cleanup_ma = false; + + if (initialized) { + return tdb_mutex_locking_cached; + } + + initialized = true; + + ok = tdb_mutex_locking_supported(); + if (!ok) { + return false; + } + + tdb_mutex_locking_cached = false; + + ptr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, + MAP_SHARED|MAP_ANON, -1 /* fd */, 0); + if (ptr == MAP_FAILED) { + return false; + } + + ret = pipe(pipe_down); + if (ret != 0) { + goto cleanup; + } + ret = pipe(pipe_up); + if (ret != 0) { + goto cleanup; + } + + ret = pthread_mutexattr_init(&ma); + if (ret != 0) { + goto cleanup; + } + cleanup_ma = true; + ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); + if (ret != 0) { + goto cleanup; + } + ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); + if (ret != 0) { + goto cleanup; + } + ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); + if (ret != 0) { + goto cleanup; + } + ret = pthread_mutex_init(ptr, &ma); + if (ret != 0) { + goto cleanup; + } + m = (pthread_mutex_t *)ptr; + + if (tdb_robust_mutex_setup_sigchild(tdb_robust_mutex_handler, + &tdb_robust_mutext_old_handler) == false) { + goto cleanup; + } + + tdb_robust_mutex_pid = fork(); + saved_child_pid = tdb_robust_mutex_pid; + if (tdb_robust_mutex_pid == 0) { + size_t nwritten; + close(pipe_down[1]); + close(pipe_up[0]); + ret = pthread_mutex_lock(m); + nwritten = write(pipe_up[1], &ret, sizeof(ret)); + if (nwritten != sizeof(ret)) { + _exit(1); + } + if (ret != 0) { + _exit(1); + } + nread = read(pipe_down[0], &c, 1); + if (nread != 1) { + _exit(1); + } + /* leave locked */ + _exit(0); + } + if (tdb_robust_mutex_pid == -1) { + goto cleanup; + } + close(pipe_down[0]); + pipe_down[0] = -1; + close(pipe_up[1]); + pipe_up[1] = -1; + + nread = read(pipe_up[0], &ret, sizeof(ret)); + if (nread != sizeof(ret)) { + goto cleanup; + } + + ret = pthread_mutex_trylock(m); + if (ret != EBUSY) { + if (ret == 0) { + pthread_mutex_unlock(m); + } + goto cleanup; + } + + if (write(pipe_down[1], &c, 1) != 1) { + goto cleanup; + } + + nread = read(pipe_up[0], &c, 1); + if (nread != 0) { + goto cleanup; + } + + tdb_robust_mutex_wait_for_child(&saved_child_pid); + + ret = pthread_mutex_trylock(m); + if (ret != EOWNERDEAD) { + if (ret == 0) { + pthread_mutex_unlock(m); + } + goto cleanup; + } + + ret = pthread_mutex_consistent(m); + if (ret != 0) { + goto cleanup; + } + + ret = pthread_mutex_trylock(m); + if (ret != EDEADLK && ret != EBUSY) { + pthread_mutex_unlock(m); + goto cleanup; + } + + ret = pthread_mutex_unlock(m); + if (ret != 0) { + goto cleanup; + } + + tdb_mutex_locking_cached = true; + +cleanup: + /* + * Note that we don't reset the signal handler we just reset + * tdb_robust_mutex_pid to -1. This is ok as this code path is only + * called once per process. + * + * Leaving our signal handler avoids races with other threads potentialy + * setting up their SIGCHLD handlers. + * + * The worst thing that can happen is that the other newer signal + * handler will get the SIGCHLD signal for our child and/or reap the + * child with a wait() function. tdb_robust_mutex_wait_for_child() + * handles the case where waitpid returns ECHILD. + */ + tdb_robust_mutex_wait_for_child(&saved_child_pid); + + if (m != NULL) { + pthread_mutex_destroy(m); + } + if (cleanup_ma) { + pthread_mutexattr_destroy(&ma); + } + if (pipe_down[0] != -1) { + close(pipe_down[0]); + } + if (pipe_down[1] != -1) { + close(pipe_down[1]); + } + if (pipe_up[0] != -1) { + close(pipe_up[0]); + } + if (pipe_up[1] != -1) { + close(pipe_up[1]); + } + if (ptr != NULL) { + munmap(ptr, sizeof(pthread_mutex_t)); + } + + return tdb_mutex_locking_cached; +} + +#else + +size_t tdb_mutex_size(struct tdb_context *tdb) +{ + return 0; +} + +bool tdb_have_mutexes(struct tdb_context *tdb) +{ + return false; +} + +int tdb_mutex_allrecord_lock(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags flags) +{ + tdb->ecode = TDB_ERR_LOCK; + return -1; +} + +int tdb_mutex_allrecord_unlock(struct tdb_context *tdb) +{ + return -1; +} + +int tdb_mutex_allrecord_upgrade(struct tdb_context *tdb) +{ + tdb->ecode = TDB_ERR_LOCK; + return -1; +} + +void tdb_mutex_allrecord_downgrade(struct tdb_context *tdb) +{ + return; +} + +int tdb_mutex_mmap(struct tdb_context *tdb) +{ + errno = ENOSYS; + return -1; +} + +int tdb_mutex_munmap(struct tdb_context *tdb) +{ + errno = ENOSYS; + return -1; +} + +int tdb_mutex_init(struct tdb_context *tdb) +{ + errno = ENOSYS; + return -1; +} + +_PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void) +{ + return false; +} + +#endif diff --git a/ldb-2.0.8/lib/tdb/common/open.c b/ldb-2.0.8/lib/tdb/common/open.c new file mode 100644 index 0000000..f7f65b0 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/open.c @@ -0,0 +1,962 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ +static struct tdb_context *tdbs = NULL; + +/* We use two hashes to double-check they're using the right hash function. */ +void tdb_header_hash(struct tdb_context *tdb, + uint32_t *magic1_hash, uint32_t *magic2_hash) +{ + TDB_DATA hash_key; + uint32_t tdb_magic = TDB_MAGIC; + + hash_key.dptr = discard_const_p(unsigned char, TDB_MAGIC_FOOD); + hash_key.dsize = sizeof(TDB_MAGIC_FOOD); + *magic1_hash = tdb->hash_fn(&hash_key); + + hash_key.dptr = (unsigned char *)CONVERT(tdb_magic); + hash_key.dsize = sizeof(tdb_magic); + *magic2_hash = tdb->hash_fn(&hash_key); + + /* Make sure at least one hash is non-zero! */ + if (*magic1_hash == 0 && *magic2_hash == 0) + *magic1_hash = 1; +} + +/* initialise a new database with a specified hash size */ +static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *header, + int hash_size) +{ + struct tdb_header *newdb; + size_t size; + int ret = -1; + + /* We make it up in memory, then write it out if not internal */ + size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t); + if (!(newdb = (struct tdb_header *)calloc(size, 1))) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* Fill in the header */ + newdb->version = TDB_VERSION; + newdb->hash_size = hash_size; + + tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash); + + /* Make sure older tdbs (which don't check the magic hash fields) + * will refuse to open this TDB. */ + if (tdb->flags & TDB_INCOMPATIBLE_HASH) + newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC; + + /* + * We create a tdb with TDB_FEATURE_FLAG_MUTEX support, + * the flag combination and runtime feature checks + * are done by the caller already. + */ + if (tdb->flags & TDB_MUTEX_LOCKING) { + newdb->feature_flags |= TDB_FEATURE_FLAG_MUTEX; + } + + /* + * If we have any features we add the FEATURE_FLAG_MAGIC, overwriting the + * TDB_HASH_RWLOCK_MAGIC above. + */ + if (newdb->feature_flags != 0) { + newdb->rwlocks = TDB_FEATURE_FLAG_MAGIC; + } + + /* + * It's required for some following code pathes + * to have the fields on 'tdb' up-to-date. + * + * E.g. tdb_mutex_size() requires it + */ + tdb->feature_flags = newdb->feature_flags; + tdb->hash_size = newdb->hash_size; + + if (tdb->flags & TDB_INTERNAL) { + tdb->map_size = size; + tdb->map_ptr = (char *)newdb; + memcpy(header, newdb, sizeof(*header)); + /* Convert the `ondisk' version if asked. */ + CONVERT(*newdb); + return 0; + } + if (lseek(tdb->fd, 0, SEEK_SET) == -1) + goto fail; + + if (ftruncate(tdb->fd, 0) == -1) + goto fail; + + if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) { + newdb->mutex_size = tdb_mutex_size(tdb); + tdb->hdr_ofs = newdb->mutex_size; + } + + /* This creates an endian-converted header, as if read from disk */ + CONVERT(*newdb); + memcpy(header, newdb, sizeof(*header)); + /* Don't endian-convert the magic food! */ + memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); + + if (!tdb_write_all(tdb->fd, newdb, size)) + goto fail; + + if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) { + + /* + * Now we init the mutex area + * followed by a second header. + */ + + ret = ftruncate( + tdb->fd, + newdb->mutex_size + sizeof(struct tdb_header)); + if (ret == -1) { + goto fail; + } + ret = tdb_mutex_init(tdb); + if (ret == -1) { + goto fail; + } + + /* + * Write a second header behind the mutexes. That's the area + * that will be mmapp'ed. + */ + ret = lseek(tdb->fd, newdb->mutex_size, SEEK_SET); + if (ret == -1) { + goto fail; + } + if (!tdb_write_all(tdb->fd, newdb, size)) { + goto fail; + } + } + + ret = 0; + fail: + SAFE_FREE(newdb); + return ret; +} + + + +static int tdb_already_open(dev_t device, + ino_t ino) +{ + struct tdb_context *i; + + for (i = tdbs; i; i = i->next) { + if (i->device == device && i->inode == ino) { + return 1; + } + } + + return 0; +} + +/* open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the + database file. A flags value of O_WRONLY is invalid. The hash size + is advisory, use zero for a default value. + + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). + + @param name may be NULL for internal databases. */ +_PUBLIC_ struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); +} + +/* a default logging function */ +static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ +} + +static bool check_header_hash(struct tdb_context *tdb, + struct tdb_header *header, + bool default_hash, uint32_t *m1, uint32_t *m2) +{ + tdb_header_hash(tdb, m1, m2); + if (header->magic1_hash == *m1 && + header->magic2_hash == *m2) { + return true; + } + + /* If they explicitly set a hash, always respect it. */ + if (!default_hash) + return false; + + /* Otherwise, try the other inbuilt hash. */ + if (tdb->hash_fn == tdb_old_hash) + tdb->hash_fn = tdb_jenkins_hash; + else + tdb->hash_fn = tdb_old_hash; + return check_header_hash(tdb, header, false, m1, m2); +} + +static bool tdb_mutex_open_ok(struct tdb_context *tdb, + const struct tdb_header *header) +{ + if (tdb->flags & TDB_NOLOCK) { + /* + * We don't look at locks, so it does not matter to have a + * compatible mutex implementation. Allow the open. + */ + return true; + } + + if (!(tdb->flags & TDB_MUTEX_LOCKING)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_mutex_open_ok[%s]: " + "Can use mutexes only with " + "MUTEX_LOCKING or NOLOCK\n", + tdb->name)); + return false; + } + + if (tdb_mutex_size(tdb) != header->mutex_size) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_mutex_open_ok[%s]: " + "Mutex size changed from %"PRIu32" to %zu\n.", + tdb->name, + header->mutex_size, + tdb_mutex_size(tdb))); + return false; + } + + return true; +} + +_PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn) +{ + int orig_errno = errno; + struct tdb_header header = { + .version = 0, + }; + struct tdb_context *tdb; + struct stat st; + int rev = 0; + bool locked = false; + unsigned char *vp; + uint32_t vertest; + unsigned v; + const char *hash_alg; + uint32_t magic1, magic2; + int ret; + + if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) { + /* Can't log this */ + errno = ENOMEM; + goto fail; + } + tdb_io_init(tdb); + + if (tdb_flags & TDB_INTERNAL) { + tdb_flags |= TDB_INCOMPATIBLE_HASH; + } + if (tdb_flags & TDB_MUTEX_LOCKING) { + tdb_flags |= TDB_INCOMPATIBLE_HASH; + } + + tdb->fd = -1; +#ifdef TDB_TRACE + tdb->tracefd = -1; +#endif + tdb->name = NULL; + tdb->map_ptr = NULL; + tdb->flags = tdb_flags; + tdb->open_flags = open_flags; + if (log_ctx) { + tdb->log = *log_ctx; + } else { + tdb->log.log_fn = null_log_fn; + tdb->log.log_private = NULL; + } + + if (name == NULL && (tdb_flags & TDB_INTERNAL)) { + name = "__TDB_INTERNAL__"; + } + + if (name == NULL) { + tdb->name = discard_const_p(char, "__NULL__"); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: called with name == NULL\n")); + tdb->name = NULL; + errno = EINVAL; + goto fail; + } + + /* now make a copy of the name, as the caller memory might go away */ + if (!(tdb->name = (char *)strdup(name))) { + /* + * set the name as the given string, so that tdb_name() will + * work in case of an error. + */ + tdb->name = discard_const_p(char, name); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't strdup(%s)\n", + name)); + tdb->name = NULL; + errno = ENOMEM; + goto fail; + } + + if (hash_fn) { + tdb->hash_fn = hash_fn; + hash_alg = "the user defined"; + } else { + /* This controls what we use when creating a tdb. */ + if (tdb->flags & TDB_INCOMPATIBLE_HASH) { + tdb->hash_fn = tdb_jenkins_hash; + } else { + tdb->hash_fn = tdb_old_hash; + } + hash_alg = "either default"; + } + + /* cache the page size */ + tdb->page_size = getpagesize(); + if (tdb->page_size <= 0) { + tdb->page_size = 0x2000; + } + + tdb->max_dead_records = (tdb_flags & TDB_VOLATILE) ? 5 : 0; + + if ((open_flags & O_ACCMODE) == O_WRONLY) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", + name)); + errno = EINVAL; + goto fail; + } + + if (hash_size == 0) + hash_size = DEFAULT_HASH_SIZE; + if ((open_flags & O_ACCMODE) == O_RDONLY) { + tdb->read_only = 1; + /* read only databases don't do locking or clear if first */ + tdb->flags |= TDB_NOLOCK; + tdb->flags &= ~(TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING); + } + + if ((tdb->flags & TDB_ALLOW_NESTING) && + (tdb->flags & TDB_DISALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "allow_nesting and disallow_nesting are not allowed together!")); + errno = EINVAL; + goto fail; + } + + if (tdb->flags & TDB_MUTEX_LOCKING) { + /* + * Here we catch bugs in the callers, + * the runtime check for existing tdb's comes later. + */ + + if (tdb->flags & TDB_INTERNAL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "invalid flags for %s - TDB_MUTEX_LOCKING and " + "TDB_INTERNAL are not allowed together\n", name)); + errno = EINVAL; + goto fail; + } + + if (tdb->flags & TDB_NOMMAP) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "invalid flags for %s - TDB_MUTEX_LOCKING and " + "TDB_NOMMAP are not allowed together\n", name)); + errno = EINVAL; + goto fail; + } + + if (tdb->read_only) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "invalid flags for %s - TDB_MUTEX_LOCKING " + "not allowed read only\n", name)); + errno = EINVAL; + goto fail; + } + + /* + * The callers should have called + * tdb_runtime_check_for_robust_mutexes() + * before using TDB_MUTEX_LOCKING! + * + * This makes sure the caller understands + * that the locking may behave a bit differently + * than with pure fcntl locking. E.g. multiple + * read locks are not supported. + */ + if (!tdb_runtime_check_for_robust_mutexes()) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "invalid flags for %s - TDB_MUTEX_LOCKING " + "requires support for robust_mutexes\n", + name)); + errno = ENOSYS; + goto fail; + } + } + + if (getenv("TDB_NO_FSYNC")) { + tdb->flags |= TDB_NOSYNC; + } + + /* + * TDB_ALLOW_NESTING is the default behavior. + * Note: this may change in future versions! + */ + if (!(tdb->flags & TDB_DISALLOW_NESTING)) { + tdb->flags |= TDB_ALLOW_NESTING; + } + + /* internal databases don't mmap or lock, and start off cleared */ + if (tdb->flags & TDB_INTERNAL) { + tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_new_database(tdb, &header, hash_size) != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!")); + goto fail; + } + tdb->hash_size = hash_size; + goto internal; + } + + if ((tdb->fd = open(name, open_flags, mode)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ + } + + /* on exec, don't inherit the fd */ + v = fcntl(tdb->fd, F_GETFD, 0); + fcntl(tdb->fd, F_SETFD, v | FD_CLOEXEC); + + /* ensure there is only one process initialising at once */ + if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get open lock on %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by tdb_brlock */ + } + + /* we need to zero database if we are the only one with it open */ + if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (!tdb->read_only)) { + ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK, + TDB_LOCK_NOWAIT|TDB_LOCK_PROBE); + locked = (ret == 0); + + if (locked) { + ret = tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, + TDB_LOCK_WAIT); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "tdb_brlock failed for %s: %s\n", + name, strerror(errno))); + goto fail; + } + ret = tdb_new_database(tdb, &header, hash_size); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "tdb_new_database failed for " + "%s: %s\n", name, strerror(errno))); + tdb_unlockall(tdb); + goto fail; + } + ret = tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "tdb_unlockall failed for %s: %s\n", + name, strerror(errno))); + goto fail; + } + ret = lseek(tdb->fd, 0, SEEK_SET); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "lseek failed for %s: %s\n", + name, strerror(errno))); + goto fail; + } + } + } + + errno = 0; + if (read(tdb->fd, &header, sizeof(header)) != sizeof(header) + || strcmp(header.magic_food, TDB_MAGIC_FOOD) != 0) { + if (!(open_flags & O_CREAT) || + tdb_new_database(tdb, &header, hash_size) == -1) { + if (errno == 0) { + errno = EIO; /* ie bad format or something */ + } + goto fail; + } + rev = (tdb->flags & TDB_CONVERT); + } else if (header.version != TDB_VERSION + && !(rev = (header.version==TDB_BYTEREV(TDB_VERSION)))) { + /* wrong version */ + errno = EIO; + goto fail; + } + vp = (unsigned char *)&header.version; + vertest = (((uint32_t)vp[0]) << 24) | (((uint32_t)vp[1]) << 16) | + (((uint32_t)vp[2]) << 8) | (uint32_t)vp[3]; + tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; + if (!rev) + tdb->flags &= ~TDB_CONVERT; + else { + tdb->flags |= TDB_CONVERT; + tdb_convert(&header, sizeof(header)); + } + + /* + * We only use st.st_dev and st.st_ino from the raw fstat() + * call, everything else needs to use tdb_fstat() in order + * to skip tdb->hdr_ofs! + */ + if (fstat(tdb->fd, &st) == -1) { + goto fail; + } + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + ZERO_STRUCT(st); + + if (header.rwlocks != 0 && + header.rwlocks != TDB_FEATURE_FLAG_MAGIC && + header.rwlocks != TDB_HASH_RWLOCK_MAGIC) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); + errno = ENOSYS; + goto fail; + } + + if (header.hash_size == 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: invalid database: 0 hash_size\n")); + errno = ENOSYS; + goto fail; + } + + tdb->hash_size = header.hash_size; + + if (header.rwlocks == TDB_FEATURE_FLAG_MAGIC) { + tdb->feature_flags = header.feature_flags; + } + + if (tdb->feature_flags & ~TDB_SUPPORTED_FEATURE_FLAGS) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: unsupported " + "features in tdb %s: 0x%08x (supported: 0x%08x)\n", + name, (unsigned)tdb->feature_flags, + (unsigned)TDB_SUPPORTED_FEATURE_FLAGS)); + errno = ENOSYS; + goto fail; + } + + if (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) { + if (!tdb_mutex_open_ok(tdb, &header)) { + errno = EINVAL; + goto fail; + } + + /* + * We need to remember the hdr_ofs + * also for the TDB_NOLOCK case + * if the current library doesn't support + * mutex locking. + */ + tdb->hdr_ofs = header.mutex_size; + + if ((!(tdb_flags & TDB_CLEAR_IF_FIRST)) && (!tdb->read_only)) { + /* + * Open an existing mutexed tdb, but without + * CLEAR_IF_FIRST. We need to initialize the + * mutex array and keep the CLEAR_IF_FIRST + * lock locked. + */ + ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK, + TDB_LOCK_NOWAIT|TDB_LOCK_PROBE); + locked = (ret == 0); + + if (locked) { + ret = tdb_mutex_init(tdb); + if (ret == -1) { + TDB_LOG((tdb, + TDB_DEBUG_FATAL, + "tdb_open_ex: tdb_mutex_init " + "failed for ""%s: %s\n", + name, strerror(errno))); + goto fail; + } + } + } + } + + if ((header.magic1_hash == 0) && (header.magic2_hash == 0)) { + /* older TDB without magic hash references */ + tdb->hash_fn = tdb_old_hash; + } else if (!check_header_hash(tdb, &header, !hash_fn, + &magic1, &magic2)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "%s was not created with %s hash function we are using\n" + "magic1_hash[0x%08X %s 0x%08X] " + "magic2_hash[0x%08X %s 0x%08X]\n", + name, hash_alg, + header.magic1_hash, + (header.magic1_hash == magic1) ? "==" : "!=", + magic1, + header.magic2_hash, + (header.magic2_hash == magic2) ? "==" : "!=", + magic2)); + errno = EINVAL; + goto fail; + } + + /* Is it already in the open list? If so, fail. */ + if (tdb_already_open(tdb->device, tdb->inode)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "%s (%d,%d) is already open in this process\n", + name, (int)tdb->device, (int)tdb->inode)); + errno = EBUSY; + goto fail; + } + + /* + * We had tdb_mmap(tdb) here before, + * but we need to use tdb_fstat(), + * which is triggered from tdb_oob() before calling tdb_mmap(). + * As this skips tdb->hdr_ofs. + */ + tdb->map_size = 0; + ret = tdb_oob(tdb, 0, 1, 0); + if (ret == -1) { + errno = EIO; + goto fail; + } + + if (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) { + if (!(tdb->flags & TDB_NOLOCK)) { + ret = tdb_mutex_mmap(tdb); + if (ret != 0) { + goto fail; + } + } + } + + if (tdb->hash_size > UINT32_MAX/4) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "hash size %"PRIu32" too large\n", tdb->hash_size)); + errno = EINVAL; + goto fail; + } + + ret = tdb_oob(tdb, FREELIST_TOP, 4*tdb->hash_size, 1); + if (ret == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "hash size %"PRIu32" does not fit\n", tdb->hash_size)); + errno = EINVAL; + goto fail; + } + + if (locked) { + if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "failed to release ACTIVE_LOCK on %s: %s\n", + name, strerror(errno))); + goto fail; + } + + + } + + if (locked || (tdb_flags & TDB_CLEAR_IF_FIRST)) { + /* + * We always need to do this if the CLEAR_IF_FIRST + * flag is set, even if we didn't get the initial + * exclusive lock as we need to let all other users + * know we're using it. + */ + + ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT); + if (ret == -1) { + goto fail; + } + } + + /* if needed, run recovery */ + if (tdb_transaction_recover(tdb) == -1) { + goto fail; + } + +#ifdef TDB_TRACE + { + char tracefile[strlen(name) + 32]; + + snprintf(tracefile, sizeof(tracefile), + "%s.trace.%li", name, (long)getpid()); + tdb->tracefd = open(tracefile, O_WRONLY|O_CREAT|O_EXCL, 0600); + if (tdb->tracefd >= 0) { + tdb_enable_seqnum(tdb); + tdb_trace_open(tdb, "tdb_open", hash_size, tdb_flags, + open_flags); + } else + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to open trace file %s!\n", tracefile)); + } +#endif + + internal: + /* Internal (memory-only) databases skip all the code above to + * do with disk files, and resume here by releasing their + * open lock and hooking into the active list. */ + if (tdb_nest_unlock(tdb, OPEN_LOCK, F_WRLCK, false) == -1) { + goto fail; + } + tdb->next = tdbs; + tdbs = tdb; + errno = orig_errno; + return tdb; + + fail: + { int save_errno = errno; + + if (!tdb) + return NULL; + +#ifdef TDB_TRACE + close(tdb->tracefd); +#endif + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + if (tdb->fd != -1) + if (close(tdb->fd) != 0) + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n")); + SAFE_FREE(tdb->lockrecs); + SAFE_FREE(tdb->name); + SAFE_FREE(tdb); + errno = save_errno; + return NULL; + } +} + +/* + * Set the maximum number of dead records per hash chain + */ + +_PUBLIC_ void tdb_set_max_dead(struct tdb_context *tdb, int max_dead) +{ + tdb->max_dead_records = max_dead; +} + +/** + * Close a database. + * + * @returns -1 for error; 0 for success. + **/ +_PUBLIC_ int tdb_close(struct tdb_context *tdb) +{ + struct tdb_context **i; + int ret = 0; + + if (tdb->transaction) { + tdb_transaction_cancel(tdb); + } + tdb_trace(tdb, "tdb_close"); + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + + tdb_mutex_munmap(tdb); + + SAFE_FREE(tdb->name); + if (tdb->fd != -1) { + ret = close(tdb->fd); + tdb->fd = -1; + } + SAFE_FREE(tdb->lockrecs); + + /* Remove from contexts list */ + for (i = &tdbs; *i; i = &(*i)->next) { + if (*i == tdb) { + *i = tdb->next; + break; + } + } + +#ifdef TDB_TRACE + close(tdb->tracefd); +#endif + memset(tdb, 0, sizeof(*tdb)); + SAFE_FREE(tdb); + + return ret; +} + +/* register a loging function */ +_PUBLIC_ void tdb_set_logging_function(struct tdb_context *tdb, + const struct tdb_logging_context *log_ctx) +{ + tdb->log = *log_ctx; +} + +_PUBLIC_ void *tdb_get_logging_private(struct tdb_context *tdb) +{ + return tdb->log.log_private; +} + +static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock) +{ +#if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \ + !defined(LIBREPLACE_PWRITE_NOT_REPLACED) + struct stat st; +#endif + + if (tdb->flags & TDB_INTERNAL) { + return 0; /* Nothing to do. */ + } + + if (tdb_have_extra_locks(tdb)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n")); + goto fail; + } + + if (tdb->transaction != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n")); + goto fail; + } + +/* If we have real pread & pwrite, we can skip reopen. */ +#if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \ + !defined(LIBREPLACE_PWRITE_NOT_REPLACED) + if (tdb_munmap(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + goto fail; + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + /* + * We only use st.st_dev and st.st_ino from the raw fstat() + * call, everything else needs to use tdb_fstat() in order + * to skip tdb->hdr_ofs! + */ + if (fstat(tdb->fd, &st) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + goto fail; + } + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + ZERO_STRUCT(st); + + /* + * We had tdb_mmap(tdb) here before, + * but we need to use tdb_fstat(), + * which is triggered from tdb_oob() before calling tdb_mmap(). + * As this skips tdb->hdr_ofs. + */ + tdb->map_size = 0; + if (tdb_oob(tdb, 0, 1, 0) != 0) { + goto fail; + } +#endif /* fake pread or pwrite */ + + /* We may still think we hold the active lock. */ + tdb->num_lockrecs = 0; + SAFE_FREE(tdb->lockrecs); + tdb->lockrecs_array_length = 0; + + if (active_lock && tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen a tdb - this can be used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +_PUBLIC_ int tdb_reopen(struct tdb_context *tdb) +{ + bool active_lock; + active_lock = (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING)); + + return tdb_reopen_internal(tdb, active_lock); +} + +/* reopen all tdb's */ +_PUBLIC_ int tdb_reopen_all(int parent_longlived) +{ + struct tdb_context *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + bool active_lock; + + active_lock = + (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING)); + + /* + * If the parent is longlived (ie. a + * parent daemon architecture), we know + * it will keep it's active lock on a + * tdb opened with CLEAR_IF_FIRST. Thus + * for child processes we don't have to + * add an active lock. This is essential + * to improve performance on systems that + * keep POSIX locks as a non-scalable data + * structure in the kernel. + */ + if (parent_longlived) { + /* Ensure no clear-if-first. */ + active_lock = false; + } + + if (tdb_reopen_internal(tdb, active_lock) != 0) + return -1; + } + + return 0; +} diff --git a/ldb-2.0.8/lib/tdb/common/rescue.c b/ldb-2.0.8/lib/tdb/common/rescue.c new file mode 100644 index 0000000..7a85ebc --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/rescue.c @@ -0,0 +1,351 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library, rescue attempt code. + + Copyright (C) Rusty Russell 2012 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ +#include "tdb_private.h" +#include + + +struct found { + tdb_off_t head; /* 0 -> invalid. */ + struct tdb_record rec; + TDB_DATA key; + bool in_hash; + bool in_free; +}; + +struct found_table { + /* As an ordered array (by head offset). */ + struct found *arr; + unsigned int num, max; +}; + +static bool looks_like_valid_record(struct tdb_context *tdb, + tdb_off_t off, + const struct tdb_record *rec, + TDB_DATA *key) +{ + unsigned int hval; + + if (rec->magic != TDB_MAGIC) + return false; + + if (rec->key_len + rec->data_len > rec->rec_len) + return false; + + if (rec->rec_len % TDB_ALIGNMENT) + return false; + + /* Next pointer must make some sense. */ + if (rec->next > 0 && rec->next < TDB_DATA_START(tdb->hash_size)) + return false; + + if (tdb_oob(tdb, rec->next, sizeof(*rec), 1)) + return false; + + key->dsize = rec->key_len; + key->dptr = tdb_alloc_read(tdb, off + sizeof(*rec), key->dsize); + if (!key->dptr) + return false; + + hval = tdb->hash_fn(key); + if (hval != rec->full_hash) { + free(key->dptr); + return false; + } + + /* Caller frees up key->dptr */ + return true; +} + +static bool add_to_table(struct found_table *found, + tdb_off_t off, + struct tdb_record *rec, + TDB_DATA key) +{ + if (found->num + 1 > found->max) { + struct found *new; + found->max = (found->max ? found->max * 2 : 128); + new = realloc(found->arr, found->max * sizeof(found->arr[0])); + if (!new) + return false; + found->arr = new; + } + + found->arr[found->num].head = off; + found->arr[found->num].rec = *rec; + found->arr[found->num].key = key; + found->arr[found->num].in_hash = false; + found->arr[found->num].in_free = false; + + found->num++; + return true; +} + +static bool walk_record(struct tdb_context *tdb, + const struct found *f, + void (*walk)(TDB_DATA, TDB_DATA, void *private_data), + void *private_data) +{ + TDB_DATA data; + + data.dsize = f->rec.data_len; + data.dptr = tdb_alloc_read(tdb, + f->head + sizeof(f->rec) + f->rec.key_len, + data.dsize); + if (!data.dptr) { + if (tdb->ecode == TDB_ERR_OOM) + return false; + /* I/O errors are expected. */ + return true; + } + + walk(f->key, data, private_data); + free(data.dptr); + return true; +} + +/* First entry which has offset >= this one. */ +static unsigned int find_entry(struct found_table *found, tdb_off_t off) +{ + unsigned int start = 0, end = found->num; + + while (start < end) { + /* We can't overflow here. */ + unsigned int mid = (start + end) / 2; + + if (off < found->arr[mid].head) { + end = mid; + } else if (off > found->arr[mid].head) { + start = mid + 1; + } else { + return mid; + } + } + + assert(start == end); + return end; +} + +static void found_in_hashchain(struct found_table *found, tdb_off_t head) +{ + unsigned int match; + + match = find_entry(found, head); + if (match < found->num && found->arr[match].head == head) { + found->arr[match].in_hash = true; + } +} + +static void mark_free_area(struct found_table *found, tdb_off_t head, + tdb_len_t len) +{ + unsigned int match; + + match = find_entry(found, head); + /* Mark everything within this free entry. */ + while (match < found->num) { + if (found->arr[match].head >= head + len) { + break; + } + found->arr[match].in_free = true; + match++; + } +} + +static int cmp_key(const void *a, const void *b) +{ + const struct found *fa = a, *fb = b; + + if (fa->key.dsize < fb->key.dsize) { + return -1; + } else if (fa->key.dsize > fb->key.dsize) { + return 1; + } + return memcmp(fa->key.dptr, fb->key.dptr, fa->key.dsize); +} + +static bool key_eq(TDB_DATA a, TDB_DATA b) +{ + return a.dsize == b.dsize + && memcmp(a.dptr, b.dptr, a.dsize) == 0; +} + +static void free_table(struct found_table *found) +{ + unsigned int i; + + for (i = 0; i < found->num; i++) { + free(found->arr[i].key.dptr); + } + free(found->arr); +} + +static void logging_suppressed(struct tdb_context *tdb, + enum tdb_debug_level level, const char *fmt, ...) +{ +} + +_PUBLIC_ int tdb_rescue(struct tdb_context *tdb, + void (*walk)(TDB_DATA, TDB_DATA, void *private_data), + void *private_data) +{ + struct found_table found = { NULL, 0, 0 }; + tdb_off_t h, off, i; + tdb_log_func oldlog = tdb->log.log_fn; + struct tdb_record rec; + TDB_DATA key; + bool locked; + + /* Read-only databases use no locking at all: it's best-effort. + * We may have a write lock already, so skip that case too. */ + if (tdb->read_only || tdb->allrecord_lock.count != 0) { + locked = false; + } else { + if (tdb_lockall_read(tdb) == -1) + return -1; + locked = true; + } + + /* Make sure we know true size of the underlying file. */ + tdb_oob(tdb, tdb->map_size, 1, 1); + + /* Suppress logging, since we anticipate errors. */ + tdb->log.log_fn = logging_suppressed; + + /* Now walk entire db looking for records. */ + for (off = TDB_DATA_START(tdb->hash_size); + off < tdb->map_size; + off += TDB_ALIGNMENT) { + if (tdb->methods->tdb_read(tdb, off, &rec, sizeof(rec), + DOCONV()) == -1) + continue; + + if (looks_like_valid_record(tdb, off, &rec, &key)) { + if (!add_to_table(&found, off, &rec, key)) { + goto oom; + } + } + } + + /* Walk hash chains to positive vet. */ + for (h = 0; h < 1+tdb->hash_size; h++) { + bool slow_chase = false; + tdb_off_t slow_off = FREELIST_TOP + h*sizeof(tdb_off_t); + + if (tdb_ofs_read(tdb, FREELIST_TOP + h*sizeof(tdb_off_t), + &off) == -1) + continue; + + while (off && off != slow_off) { + if (tdb->methods->tdb_read(tdb, off, &rec, sizeof(rec), + DOCONV()) != 0) { + break; + } + + /* 0 is the free list, rest are hash chains. */ + if (h == 0) { + /* Don't mark garbage as free. */ + if (rec.magic != TDB_FREE_MAGIC) { + break; + } + mark_free_area(&found, off, + sizeof(rec) + rec.rec_len); + } else { + found_in_hashchain(&found, off); + } + + off = rec.next; + + /* Loop detection using second pointer at half-speed */ + if (slow_chase) { + /* First entry happens to be next ptr */ + tdb_ofs_read(tdb, slow_off, &slow_off); + } + slow_chase = !slow_chase; + } + } + + /* Recovery area: must be marked as free, since it often has old + * records in there! */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &off) == 0 && off != 0) { + if (tdb->methods->tdb_read(tdb, off, &rec, sizeof(rec), + DOCONV()) == 0) { + mark_free_area(&found, off, sizeof(rec) + rec.rec_len); + } + } + + /* Now sort by key! */ + if (found.arr != NULL) { + qsort(found.arr, found.num, sizeof(found.arr[0]), cmp_key); + } + + for (i = 0; (found.arr != NULL) && i < found.num; ) { + unsigned int num, num_in_hash = 0; + + /* How many are identical? */ + for (num = 0; num < found.num - i; num++) { + if (!key_eq(found.arr[i].key, found.arr[i+num].key)) { + break; + } + if (found.arr[i+num].in_hash) { + if (!walk_record(tdb, &found.arr[i+num], + walk, private_data)) + goto oom; + num_in_hash++; + } + } + assert(num); + + /* If none were in the hash, we print any not in free list. */ + if (num_in_hash == 0) { + unsigned int j; + + for (j = i; j < i + num; j++) { + if (!found.arr[j].in_free) { + if (!walk_record(tdb, &found.arr[j], + walk, private_data)) + goto oom; + } + } + } + + i += num; + } + + tdb->log.log_fn = oldlog; + if (locked) { + tdb_unlockall_read(tdb); + } + return 0; + +oom: + tdb->log.log_fn = oldlog; + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_rescue: failed allocating\n")); + free_table(&found); + if (locked) { + tdb_unlockall_read(tdb); + } + return -1; +} diff --git a/ldb-2.0.8/lib/tdb/common/summary.c b/ldb-2.0.8/lib/tdb/common/summary.c new file mode 100644 index 0000000..a93eb93 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/summary.c @@ -0,0 +1,219 @@ + /* + Trivial Database: human-readable summary code + Copyright (C) Rusty Russell 2010 + + 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 + Lesser 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 . +*/ +#include "tdb_private.h" + +#define SUMMARY_FORMAT \ + "Size of file/data: %llu/%zu\n" \ + "Header offset/logical size: %zu/%zu\n" \ + "Number of records: %zu\n" \ + "Incompatible hash: %s\n" \ + "Active/supported feature flags: 0x%08x/0x%08x\n" \ + "Robust mutexes locking: %s\n" \ + "Smallest/average/largest keys: %zu/%zu/%zu\n" \ + "Smallest/average/largest data: %zu/%zu/%zu\n" \ + "Smallest/average/largest padding: %zu/%zu/%zu\n" \ + "Number of dead records: %zu\n" \ + "Smallest/average/largest dead records: %zu/%zu/%zu\n" \ + "Number of free records: %zu\n" \ + "Smallest/average/largest free records: %zu/%zu/%zu\n" \ + "Number of hash chains: %zu\n" \ + "Smallest/average/largest hash chains: %zu/%zu/%zu\n" \ + "Number of uncoalesced records: %zu\n" \ + "Smallest/average/largest uncoalesced runs: %zu/%zu/%zu\n" \ + "Percentage keys/data/padding/free/dead/rechdrs&tailers/hashes: %.0f/%.0f/%.0f/%.0f/%.0f/%.0f/%.0f\n" + +/* We don't use tally module, to keep upstream happy. */ +struct tally { + size_t min, max, total; + size_t num; +}; + +static void tally_init(struct tally *tally) +{ + tally->total = 0; + tally->num = 0; + tally->min = tally->max = 0; +} + +static void tally_add(struct tally *tally, size_t len) +{ + if (tally->num == 0) + tally->max = tally->min = len; + else if (len > tally->max) + tally->max = len; + else if (len < tally->min) + tally->min = len; + tally->num++; + tally->total += len; +} + +static size_t tally_mean(const struct tally *tally) +{ + if (!tally->num) + return 0; + return tally->total / tally->num; +} + +static size_t get_hash_length(struct tdb_context *tdb, unsigned int i) +{ + tdb_off_t rec_ptr; + struct tdb_chainwalk_ctx chainwalk; + size_t count = 0; + + if (tdb_ofs_read(tdb, TDB_HASH_TOP(i), &rec_ptr) == -1) + return 0; + + tdb_chainwalk_init(&chainwalk, rec_ptr); + + /* keep looking until we find the right record */ + while (rec_ptr) { + struct tdb_record r; + bool ok; + ++count; + if (tdb_rec_read(tdb, rec_ptr, &r) == -1) + return 0; + rec_ptr = r.next; + ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr); + if (!ok) { + return SIZE_MAX; + } + } + return count; +} + +_PUBLIC_ char *tdb_summary(struct tdb_context *tdb) +{ + off_t file_size; + tdb_off_t off, rec_off; + struct tally freet, keys, data, dead, extra, hashval, uncoal; + struct tdb_record rec; + char *ret = NULL; + bool locked; + size_t unc = 0; + int len; + struct tdb_record recovery; + + /* Read-only databases use no locking at all: it's best-effort. + * We may have a write lock already, so skip that case too. */ + if (tdb->read_only || tdb->allrecord_lock.count != 0) { + locked = false; + } else { + if (tdb_lockall_read(tdb) == -1) + return NULL; + locked = true; + } + + if (tdb_recovery_area(tdb, tdb->methods, &rec_off, &recovery) != 0) { + goto unlock; + } + + tally_init(&freet); + tally_init(&keys); + tally_init(&data); + tally_init(&dead); + tally_init(&extra); + tally_init(&hashval); + tally_init(&uncoal); + + for (off = TDB_DATA_START(tdb->hash_size); + off < tdb->map_size - 1; + off += sizeof(rec) + rec.rec_len) { + if (tdb->methods->tdb_read(tdb, off, &rec, sizeof(rec), + DOCONV()) == -1) + goto unlock; + switch (rec.magic) { + case TDB_MAGIC: + tally_add(&keys, rec.key_len); + tally_add(&data, rec.data_len); + tally_add(&extra, rec.rec_len - (rec.key_len + + rec.data_len)); + if (unc > 1) + tally_add(&uncoal, unc - 1); + unc = 0; + break; + case TDB_FREE_MAGIC: + tally_add(&freet, rec.rec_len); + unc++; + break; + /* If we crash after ftruncate, we can get zeroes or fill. */ + case TDB_RECOVERY_INVALID_MAGIC: + case 0x42424242: + unc++; + /* If it's a valid recovery, we can trust rec_len. */ + if (off != rec_off) { + rec.rec_len = tdb_dead_space(tdb, off) + - sizeof(rec); + } + + FALL_THROUGH; + case TDB_DEAD_MAGIC: + tally_add(&dead, rec.rec_len); + break; + default: + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Unexpected record magic 0x%x at offset %u\n", + rec.magic, off)); + goto unlock; + } + } + if (unc > 1) + tally_add(&uncoal, unc - 1); + + for (off = 0; off < tdb->hash_size; off++) + tally_add(&hashval, get_hash_length(tdb, off)); + + file_size = tdb->hdr_ofs + tdb->map_size; + + len = asprintf(&ret, SUMMARY_FORMAT, + (unsigned long long)file_size, keys.total+data.total, + (size_t)tdb->hdr_ofs, (size_t)tdb->map_size, + keys.num, + (tdb->hash_fn == tdb_jenkins_hash)?"yes":"no", + (unsigned)tdb->feature_flags, TDB_SUPPORTED_FEATURE_FLAGS, + (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX)?"yes":"no", + keys.min, tally_mean(&keys), keys.max, + data.min, tally_mean(&data), data.max, + extra.min, tally_mean(&extra), extra.max, + dead.num, + dead.min, tally_mean(&dead), dead.max, + freet.num, + freet.min, tally_mean(&freet), freet.max, + hashval.num, + hashval.min, tally_mean(&hashval), hashval.max, + uncoal.total, + uncoal.min, tally_mean(&uncoal), uncoal.max, + keys.total * 100.0 / file_size, + data.total * 100.0 / file_size, + extra.total * 100.0 / file_size, + freet.total * 100.0 / file_size, + dead.total * 100.0 / file_size, + (keys.num + freet.num + dead.num) + * (sizeof(struct tdb_record) + sizeof(uint32_t)) + * 100.0 / file_size, + tdb->hash_size * sizeof(tdb_off_t) + * 100.0 / file_size); + if (len == -1) { + goto unlock; + } + +unlock: + if (locked) { + tdb_unlockall_read(tdb); + } + return ret; +} diff --git a/ldb-2.0.8/lib/tdb/common/tdb.c b/ldb-2.0.8/lib/tdb/common/tdb.c new file mode 100644 index 0000000..c56b37b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/tdb.c @@ -0,0 +1,1324 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +_PUBLIC_ TDB_DATA tdb_null; + +/* + non-blocking increment of the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +_PUBLIC_ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + + if (!(tdb->flags & TDB_SEQNUM)) { + return; + } + + /* we ignore errors from this, as we have no sane way of + dealing with them. + */ + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + seqnum++; + tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); +} + +/* + increment the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +static void tdb_increment_seqnum(struct tdb_context *tdb) +{ + if (!(tdb->flags & TDB_SEQNUM)) { + 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; + } + + tdb_increment_seqnum_nonblock(tdb); + + tdb_nest_unlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, false); +} + +static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data) +{ + return memcmp(data.dptr, key.dptr, data.dsize); +} + +void tdb_chainwalk_init(struct tdb_chainwalk_ctx *ctx, tdb_off_t ptr) +{ + *ctx = (struct tdb_chainwalk_ctx) { .slow_ptr = ptr }; +} + +bool tdb_chainwalk_check(struct tdb_context *tdb, + struct tdb_chainwalk_ctx *ctx, + tdb_off_t next_ptr) +{ + int ret; + + if (ctx->slow_chase) { + ret = tdb_ofs_read(tdb, ctx->slow_ptr, &ctx->slow_ptr); + if (ret == -1) { + return false; + } + } + ctx->slow_chase = !ctx->slow_chase; + + if (next_ptr == ctx->slow_ptr) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_chainwalk_check: circular chain\n")); + return false; + } + + return true; +} + +/* Returns 0 on fail. On success, return offset of record, and fills + in rec */ +static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, + struct tdb_record *r) +{ + tdb_off_t rec_ptr; + struct tdb_chainwalk_ctx chainwalk; + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + tdb_chainwalk_init(&chainwalk, rec_ptr); + + /* keep looking until we find the right record */ + while (rec_ptr) { + bool ok; + + if (tdb_rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (!TDB_DEAD(r) && hash==r->full_hash + && key.dsize==r->key_len + && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r), + r->key_len, tdb_key_compare, + NULL) == 0) { + return rec_ptr; + } + rec_ptr = r->next; + + ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr); + if (!ok) { + return 0; + } + } + tdb->ecode = TDB_ERR_NOEXIST; + return 0; +} + +/* As tdb_find, but if you succeed, keep the lock */ +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype, + struct tdb_record *rec) +{ + uint32_t rec_ptr; + + if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) + return 0; + if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) + tdb_unlock(tdb, BUCKET(hash), locktype); + return rec_ptr; +} + +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) +{ + struct tdb_update_hash_state *state = private_data; + unsigned char *dptr = data.dptr; + int i; + + if (state->dbufs_len != data.dsize) { + return -1; + } + + for (i=0; inum_dbufs; i++) { + TDB_DATA dbuf = state->dbufs[i]; + if( dbuf.dsize > 0) { + int ret; + ret = memcmp(dptr, dbuf.dptr, dbuf.dsize); + if (ret != 0) { + return -1; + } + dptr += dbuf.dsize; + } + } + + return 0; +} + +/* update an entry in place - this only works if the new data size + 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, + const TDB_DATA *dbufs, int num_dbufs, + tdb_len_t dbufs_len) +{ + struct tdb_record rec; + tdb_off_t rec_ptr, ofs; + int i; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) + return -1; + + /* it could be an exact duplicate of what is there - this is + * surprisingly common (eg. with a ldb re-index). */ + 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 + dbufs_len + sizeof(tdb_off_t)) { + tdb->ecode = TDB_SUCCESS; /* Not really an error */ + return -1; + } + + ofs = rec_ptr + sizeof(rec) + rec.key_len; + + for (i=0; imethods->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 = dbufs_len; + return tdb_rec_write(tdb, rec_ptr, &rec); + } + + return 0; +} + +/* find an entry in the database given a key */ +/* If an entry doesn't exist tdb_err will be set to + * TDB_ERR_NOEXIST. If a key has no data attached + * then the TDB_DATA will have zero length but + * a non-zero pointer + */ +static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_off_t rec_ptr; + struct tdb_record rec; + TDB_DATA ret; + uint32_t hash; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) + return tdb_null; + + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); + ret.dsize = rec.data_len; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return ret; +} + +_PUBLIC_ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) +{ + TDB_DATA ret = _tdb_fetch(tdb, key); + + tdb_trace_1rec_retrec(tdb, "tdb_fetch", key, ret); + return ret; +} + +/* + * Find an entry in the database and hand the record's data to a parsing + * function. The parsing function is executed under the chain read lock, so it + * should be fast and should not block on other syscalls. + * + * DON'T CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS. + * + * For mmapped tdb's that do not have a transaction open it points the parsing + * function directly at the mmap area, it avoids the malloc/memcpy in this + * case. If a transaction is open or no mmap is available, it has to do + * malloc/read/parse/free. + * + * This is interesting for all readers of potentially large data structures in + * the tdb records, ldb indexes being one example. + * + * Return -1 if the record was not found. + */ + +_PUBLIC_ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + tdb_off_t rec_ptr; + struct tdb_record rec; + int ret; + uint32_t hash; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { + /* record not found */ + tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1); + tdb->ecode = TDB_ERR_NOEXIST; + return -1; + } + tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, 0); + + ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len, parser, private_data); + + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + + return ret; +} + +/* check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm +*/ +static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash) +{ + struct tdb_record rec; + + if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) + return 0; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return 1; +} + +_PUBLIC_ int tdb_exists(struct tdb_context *tdb, TDB_DATA key) +{ + uint32_t hash = tdb->hash_fn(&key); + int ret; + + ret = tdb_exists_hash(tdb, key, hash); + tdb_trace_1rec_ret(tdb, "tdb_exists", key, ret); + return ret; +} + +/* + * Move a dead record to the freelist. The hash chain and freelist + * must be locked. + */ +static int tdb_del_dead(struct tdb_context *tdb, + uint32_t last_ptr, + uint32_t rec_ptr, + struct tdb_record *rec, + bool *deleted) +{ + int ret; + + ret = tdb_write_lock_record(tdb, rec_ptr); + if (ret == -1) { + /* Someone traversing here: Just leave it dead */ + return 0; + } + ret = tdb_write_unlock_record(tdb, rec_ptr); + if (ret == -1) { + return -1; + } + ret = tdb_ofs_write(tdb, last_ptr, &rec->next); + if (ret == -1) { + return -1; + } + + *deleted = true; + + ret = tdb_free(tdb, rec_ptr, rec); + return ret; +} + +/* + * Walk the hash chain and leave tdb->max_dead_records around. Move + * the rest of dead records to the freelist. + */ +int tdb_trim_dead(struct tdb_context *tdb, uint32_t hash) +{ + struct tdb_chainwalk_ctx chainwalk; + struct tdb_record rec; + tdb_off_t last_ptr, rec_ptr; + bool locked_freelist = false; + int num_dead = 0; + int ret; + + last_ptr = TDB_HASH_TOP(hash); + + /* + * Init chainwalk with the pointer to the hash top. It might + * be that the very first record in the chain is a dead one + * that we have to delete. + */ + tdb_chainwalk_init(&chainwalk, last_ptr); + + ret = tdb_ofs_read(tdb, last_ptr, &rec_ptr); + if (ret == -1) { + return -1; + } + + while (rec_ptr != 0) { + bool deleted = false; + uint32_t next; + + ret = tdb_rec_read(tdb, rec_ptr, &rec); + if (ret == -1) { + goto fail; + } + + /* + * Make a copy of rec.next: Further down we might + * delete and put the record on the freelist. Make + * sure that modifications in that code path can't + * break the chainwalk here. + */ + next = rec.next; + + if (rec.magic == TDB_DEAD_MAGIC) { + num_dead += 1; + + if (num_dead > tdb->max_dead_records) { + + if (!locked_freelist) { + /* + * Lock the freelist only if + * it's really required. + */ + ret = tdb_lock(tdb, -1, F_WRLCK); + if (ret == -1) { + goto fail; + }; + locked_freelist = true; + } + + ret = tdb_del_dead( + tdb, + last_ptr, + rec_ptr, + &rec, + &deleted); + + if (ret == -1) { + goto fail; + } + } + } + + /* + * Don't do the chainwalk check if "rec_ptr" was + * deleted. We reduced the chain, and the chainwalk + * check might catch up early. Imagine a valid chain + * with just dead records: We never can bump the + * "slow" pointer in chainwalk_check, as there isn't + * anything left to jump to and compare. + */ + if (!deleted) { + bool ok; + + last_ptr = rec_ptr; + + ok = tdb_chainwalk_check(tdb, &chainwalk, next); + if (!ok) { + ret = -1; + goto fail; + } + } + rec_ptr = next; + } + ret = 0; +fail: + if (locked_freelist) { + tdb_unlock(tdb, -1, F_WRLCK); + } + return ret; +} + +/* delete an entry in the database given a key */ +static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash) +{ + tdb_off_t rec_ptr; + struct tdb_record rec; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec); + if (rec_ptr == 0) { + return -1; + } + + /* + * Mark the record dead + */ + rec.magic = TDB_DEAD_MAGIC; + ret = tdb_rec_write(tdb, rec_ptr, &rec); + if (ret == -1) { + goto done; + } + + tdb_increment_seqnum(tdb); + + ret = tdb_trim_dead(tdb, hash); +done: + if (tdb_unlock(tdb, BUCKET(hash), F_WRLCK) != 0) + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n")); + return ret; +} + +_PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key) +{ + uint32_t hash = tdb->hash_fn(&key); + int ret; + + ret = tdb_delete_hash(tdb, key, hash); + tdb_trace_1rec_ret(tdb, "tdb_delete", key, ret); + return ret; +} + +/* + * See if we have a dead record around with enough space + */ +tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash, + struct tdb_record *r, tdb_len_t length, + tdb_off_t *p_last_ptr) +{ + tdb_off_t rec_ptr, last_ptr; + struct tdb_chainwalk_ctx chainwalk; + tdb_off_t best_rec_ptr = 0; + tdb_off_t best_last_ptr = 0; + struct tdb_record best = { .rec_len = UINT32_MAX }; + + length += sizeof(tdb_off_t); /* tailer */ + + last_ptr = TDB_HASH_TOP(hash); + + /* read in the hash top */ + if (tdb_ofs_read(tdb, last_ptr, &rec_ptr) == -1) + return 0; + + tdb_chainwalk_init(&chainwalk, rec_ptr); + + /* keep looking until we find the right record */ + while (rec_ptr) { + bool ok; + + if (tdb_rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (TDB_DEAD(r) && (r->rec_len >= length) && + (r->rec_len < best.rec_len)) { + best_rec_ptr = rec_ptr; + best_last_ptr = last_ptr; + best = *r; + } + last_ptr = rec_ptr; + rec_ptr = r->next; + + ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr); + if (!ok) { + return 0; + } + } + + if (best.rec_len == UINT32_MAX) { + return 0; + } + + *r = best; + *p_last_ptr = best_last_ptr; + return best_rec_ptr; +} + +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, ofs; + tdb_len_t rec_len, dbufs_len; + int i; + int ret = -1; + + dbufs_len = 0; + + for (i=0; iecode = TDB_ERR_EINVAL; + goto fail; + } + + 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)) { + tdb->ecode = TDB_ERR_EXISTS; + goto fail; + } + } else { + /* first try in-place update, on modify or replace. */ + if (tdb_update_hash(tdb, key, hash, dbufs, num_dbufs, + dbufs_len) == 0) { + goto done; + } + if (tdb->ecode == TDB_ERR_NOEXIST && + flag == TDB_MODIFY) { + /* if the record doesn't exist and we are in TDB_MODIFY mode then + we should fail the store */ + goto fail; + } + } + /* reset the error code potentially set by the tdb_update_hash() */ + tdb->ecode = TDB_SUCCESS; + + /* delete any existing record - if it doesn't exist we don't + care. Doing this first reduces fragmentation, and avoids + coalescing with `allocated' block before it's updated. */ + if (flag != TDB_INSERT) + tdb_delete_hash(tdb, key, hash); + + /* we have to allocate some space */ + rec_ptr = tdb_allocate(tdb, hash, rec_len, &rec); + + if (rec_ptr == 0) { + goto fail; + } + + /* Read hash top into next ptr */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + goto fail; + + rec.key_len = key.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 */ + 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; imethods->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; + } + + done: + ret = 0; + fail: + if (ret == 0) { + tdb_increment_seqnum(tdb); + } + 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 + + return 0 on success, -1 on failure +*/ +_PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +{ + uint32_t hash; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, 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; + + ret = _tdb_store(tdb, key, dbuf, flag, hash); + tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag, ret); + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return ret; +} + +_PUBLIC_ int tdb_storev(struct tdb_context *tdb, TDB_DATA key, + const TDB_DATA *dbufs, int num_dbufs, int flag) +{ + uint32_t hash; + 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; + + 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; +} + +/* 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; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + dbufs[0] = _tdb_fetch(tdb, key); + dbufs[1] = new_dbuf; + + ret = _tdb_storev(tdb, key, dbufs, 2, 0, hash); + tdb_trace_2rec_retrec(tdb, "tdb_append", key, dbufs[0], dbufs[1]); + + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + SAFE_FREE(dbufs[0].dptr); + return ret; +} + + +/* + return the name of the current tdb file + useful for external logging functions +*/ +_PUBLIC_ const char *tdb_name(struct tdb_context *tdb) +{ + return tdb->name; +} + +/* + return the underlying file descriptor being used by tdb, or -1 + useful for external routines that want to check the device/inode + of the fd +*/ +_PUBLIC_ int tdb_fd(struct tdb_context *tdb) +{ + return tdb->fd; +} + +/* + return the current logging function + useful for external tdb routines that wish to log tdb errors +*/ +_PUBLIC_ tdb_log_func tdb_log_fn(struct tdb_context *tdb) +{ + return tdb->log.log_fn; +} + + +/* + get the tdb sequence number. Only makes sense if the writers opened + with TDB_SEQNUM set. Note that this sequence number will wrap quite + quickly, so it should only be used for a 'has something changed' + test, not for code that relies on the count of the number of changes + made. If you want a counter then use a tdb record. + + The aim of this sequence number is to allow for a very lightweight + test of a possible tdb change. +*/ +_PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + return seqnum; +} + +_PUBLIC_ int tdb_hash_size(struct tdb_context *tdb) +{ + return tdb->hash_size; +} + +_PUBLIC_ size_t tdb_map_size(struct tdb_context *tdb) +{ + return tdb->map_size; +} + +_PUBLIC_ int tdb_get_flags(struct tdb_context *tdb) +{ + return tdb->flags; +} + +_PUBLIC_ void tdb_add_flags(struct tdb_context *tdb, unsigned flags) +{ + if ((flags & TDB_ALLOW_NESTING) && + (flags & TDB_DISALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_add_flags: " + "allow_nesting and disallow_nesting are not allowed together!")); + return; + } + + if (flags & TDB_ALLOW_NESTING) { + tdb->flags &= ~TDB_DISALLOW_NESTING; + } + if (flags & TDB_DISALLOW_NESTING) { + tdb->flags &= ~TDB_ALLOW_NESTING; + } + + tdb->flags |= flags; +} + +_PUBLIC_ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags) +{ + if ((flags & TDB_ALLOW_NESTING) && + (flags & TDB_DISALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_remove_flags: " + "allow_nesting and disallow_nesting are not allowed together!")); + return; + } + + if ((flags & TDB_NOLOCK) && + (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) && + (tdb->mutexes == NULL)) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_remove_flags: " + "Can not remove NOLOCK flag on mutexed databases")); + return; + } + + if (flags & TDB_ALLOW_NESTING) { + tdb->flags |= TDB_DISALLOW_NESTING; + } + if (flags & TDB_DISALLOW_NESTING) { + tdb->flags |= TDB_ALLOW_NESTING; + } + + tdb->flags &= ~flags; +} + + +/* + enable sequence number handling on an open tdb +*/ +_PUBLIC_ void tdb_enable_seqnum(struct tdb_context *tdb) +{ + tdb->flags |= TDB_SEQNUM; +} + + +/* + add a region of the file to the freelist. Length is the size of the region in bytes, + which includes the free list header that needs to be added + */ +static int tdb_free_region(struct tdb_context *tdb, tdb_off_t offset, ssize_t length) +{ + struct tdb_record rec; + if (length <= sizeof(rec)) { + /* the region is not worth adding */ + return 0; + } + if (length + offset > tdb->map_size) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: adding region beyond end of file\n")); + return -1; + } + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = length - sizeof(rec); + if (tdb_free(tdb, offset, &rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: failed to add free record\n")); + return -1; + } + return 0; +} + +/* + wipe the entire database, deleting all records. This can be done + very fast by using a allrecord lock. The entire data portion of the + file becomes a single entry in the freelist. + + This code carefully steps around the recovery area, leaving it alone + */ +_PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb) +{ + uint32_t i; + tdb_off_t offset = 0; + ssize_t data_len; + tdb_off_t recovery_head; + tdb_len_t recovery_size = 0; + + if (tdb_lockall(tdb) != 0) { + return -1; + } + + tdb_trace(tdb, "tdb_wipe_all"); + + /* see if the tdb has a recovery area, and remember its size + if so. We don't want to lose this as otherwise each + tdb_wipe_all() in a transaction will increase the size of + the tdb by the size of the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery head\n")); + goto failed; + } + + if (recovery_head != 0) { + struct tdb_record rec; + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery record\n")); + return -1; + } + recovery_size = rec.rec_len + sizeof(rec); + } + + /* wipe the hashes */ + for (i=0;ihash_size;i++) { + if (tdb_ofs_write(tdb, TDB_HASH_TOP(i), &offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to write hash %d\n", i)); + goto failed; + } + } + + /* wipe the freelist */ + if (tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to write freelist\n")); + goto failed; + } + + /* add all the rest of the file to the freelist, possibly leaving a gap + for the recovery area */ + if (recovery_size == 0) { + /* the simple case - the whole file can be used as a freelist */ + data_len = (tdb->map_size - TDB_DATA_START(tdb->hash_size)); + if (tdb_free_region(tdb, TDB_DATA_START(tdb->hash_size), data_len) != 0) { + goto failed; + } + } else { + /* we need to add two freelist entries - one on either + side of the recovery area + + Note that we cannot shift the recovery area during + this operation. Only the transaction.c code may + move the recovery area or we risk subtle data + corruption + */ + data_len = (recovery_head - TDB_DATA_START(tdb->hash_size)); + if (tdb_free_region(tdb, TDB_DATA_START(tdb->hash_size), data_len) != 0) { + goto failed; + } + /* and the 2nd free list entry after the recovery area - if any */ + data_len = tdb->map_size - (recovery_head+recovery_size); + if (tdb_free_region(tdb, recovery_head+recovery_size, data_len) != 0) { + goto failed; + } + } + + tdb_increment_seqnum_nonblock(tdb); + + if (tdb_unlockall(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to unlock\n")); + goto failed; + } + + return 0; + +failed: + tdb_unlockall(tdb); + return -1; +} + +struct traverse_state { + bool error; + struct tdb_context *dest_db; +}; + +/* + traverse function for repacking + */ +static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data) +{ + struct traverse_state *state = (struct traverse_state *)private_data; + if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) { + state->error = true; + return -1; + } + return 0; +} + +/* + repack a tdb + */ +_PUBLIC_ int tdb_repack(struct tdb_context *tdb) +{ + struct tdb_context *tmp_db; + struct traverse_state state; + + tdb_trace(tdb, "tdb_repack"); + + if (tdb_transaction_start(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to start transaction\n")); + return -1; + } + + tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb), TDB_INTERNAL, O_RDWR|O_CREAT, 0); + if (tmp_db == NULL) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to create tmp_db\n")); + tdb_transaction_cancel(tdb); + return -1; + } + + state.error = false; + state.dest_db = tmp_db; + + if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying out\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (state.error) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during traversal\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (tdb_wipe_all(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to wipe database\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + state.error = false; + state.dest_db = tdb; + + if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying back\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (state.error) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during second traversal\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + tdb_close(tmp_db); + + if (tdb_transaction_commit(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to commit\n")); + return -1; + } + + return 0; +} + +/* Even on files, we can get partial writes due to signals. */ +bool tdb_write_all(int fd, const void *buf, size_t count) +{ + while (count) { + ssize_t ret; + ret = write(fd, buf, count); + if (ret < 0) + return false; + buf = (const char *)buf + ret; + count -= ret; + } + return true; +} + +bool tdb_add_off_t(tdb_off_t a, tdb_off_t b, tdb_off_t *pret) +{ + tdb_off_t ret = a + b; + + if ((ret < a) || (ret < b)) { + return false; + } + *pret = ret; + return true; +} + +#ifdef TDB_TRACE +static void tdb_trace_write(struct tdb_context *tdb, const char *str) +{ + if (!tdb_write_all(tdb->tracefd, str, strlen(str))) { + close(tdb->tracefd); + tdb->tracefd = -1; + } +} + +static void tdb_trace_start(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + char msg[sizeof(tdb_off_t) * 4 + 1]; + + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + snprintf(msg, sizeof(msg), "%u ", seqnum); + tdb_trace_write(tdb, msg); +} + +static void tdb_trace_end(struct tdb_context *tdb) +{ + tdb_trace_write(tdb, "\n"); +} + +static void tdb_trace_end_ret(struct tdb_context *tdb, int ret) +{ + char msg[sizeof(ret) * 4 + 4]; + snprintf(msg, sizeof(msg), " = %i\n", ret); + tdb_trace_write(tdb, msg); +} + +static void tdb_trace_record(struct tdb_context *tdb, TDB_DATA rec) +{ + char msg[20 + rec.dsize*2], *p; + unsigned int i; + + /* We differentiate zero-length records from non-existent ones. */ + if (rec.dptr == NULL) { + tdb_trace_write(tdb, " NULL"); + return; + } + + /* snprintf here is purely cargo-cult programming. */ + p = msg; + p += snprintf(p, sizeof(msg), " %zu:", rec.dsize); + for (i = 0; i < rec.dsize; i++) + p += snprintf(p, 2, "%02x", rec.dptr[i]); + + tdb_trace_write(tdb, msg); +} + +void tdb_trace(struct tdb_context *tdb, const char *op) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_end(tdb); +} + +void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op) +{ + char msg[sizeof(tdb_off_t) * 4 + 1]; + + snprintf(msg, sizeof(msg), "%u ", seqnum); + tdb_trace_write(tdb, msg); + tdb_trace_write(tdb, op); + tdb_trace_end(tdb); +} + +void tdb_trace_open(struct tdb_context *tdb, const char *op, + unsigned hash_size, unsigned tdb_flags, unsigned open_flags) +{ + char msg[128]; + + snprintf(msg, sizeof(msg), + "%s %u 0x%x 0x%x", op, hash_size, tdb_flags, open_flags); + tdb_trace_start(tdb); + tdb_trace_write(tdb, msg); + tdb_trace_end(tdb); +} + +void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_end_ret(tdb, ret); +} + +void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_write(tdb, " ="); + tdb_trace_record(tdb, ret); + tdb_trace_end(tdb); +} + +void tdb_trace_1rec(struct tdb_context *tdb, const char *op, + TDB_DATA rec) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec); + tdb_trace_end(tdb); +} + +void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op, + TDB_DATA rec, int ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec); + tdb_trace_end_ret(tdb, ret); +} + +void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op, + TDB_DATA rec, TDB_DATA ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec); + tdb_trace_write(tdb, " ="); + tdb_trace_record(tdb, ret); + tdb_trace_end(tdb); +} + +void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op, + TDB_DATA rec1, TDB_DATA rec2, unsigned flag, + int ret) +{ + char msg[1 + sizeof(ret) * 4]; + + snprintf(msg, sizeof(msg), " %#x", flag); + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec1); + tdb_trace_record(tdb, rec2); + tdb_trace_write(tdb, msg); + 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; if) +#endif + +#define TDB_MAGIC_FOOD "TDB file\n" +#define TDB_VERSION (0x26011967 + 6) +#define TDB_MAGIC (0x26011999U) +#define TDB_FREE_MAGIC (~TDB_MAGIC) +#define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_RECOVERY_MAGIC (0xf53bc0e7U) +#define TDB_RECOVERY_INVALID_MAGIC (0x0) +#define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U) +#define TDB_FEATURE_FLAG_MAGIC (0xbad1a52U) +#define TDB_ALIGNMENT 4 +#define DEFAULT_HASH_SIZE 131 +#define FREELIST_TOP (sizeof(struct tdb_header)) +#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) +#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) +#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) +#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) +#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) +#define TDB_HASHTABLE_SIZE(tdb) ((tdb->hash_size+1)*sizeof(tdb_off_t)) +#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + sizeof(tdb_off_t)) +#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start) +#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number) +#define TDB_PAD_BYTE 0x42 +#define TDB_PAD_U32 0x42424242 + +#define TDB_FEATURE_FLAG_MUTEX 0x00000001 + +#define TDB_SUPPORTED_FEATURE_FLAGS ( \ + TDB_FEATURE_FLAG_MUTEX | \ + 0) + +/* NB assumes there is a local variable called "tdb" that is the + * current context, also takes doubly-parenthesized print-style + * argument. */ +#define TDB_LOG(x) tdb->log.log_fn x + +#ifdef TDB_TRACE +void tdb_trace(struct tdb_context *tdb, const char *op); +void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op); +void tdb_trace_open(struct tdb_context *tdb, const char *op, + unsigned hash_size, unsigned tdb_flags, unsigned open_flags); +void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret); +void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret); +void tdb_trace_1rec(struct tdb_context *tdb, const char *op, + TDB_DATA rec); +void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op, + TDB_DATA rec, int ret); +void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op, + TDB_DATA rec, TDB_DATA ret); +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 +#define tdb_trace(tdb, op) +#define tdb_trace_seqnum(tdb, seqnum, op) +#define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags) +#define tdb_trace_ret(tdb, op, ret) +#define tdb_trace_retrec(tdb, op, ret) +#define tdb_trace_1rec(tdb, op, rec) +#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 */ + +/* lock offsets */ +#define OPEN_LOCK 0 +#define ACTIVE_LOCK 4 +#define TRANSACTION_LOCK 8 + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) +#endif + +/* + * Note: the BUCKET macro is broken as it returns an unexpected result when + * called as BUCKET(-1) for the freelist: + * + * -1 is sign converted to an unsigned int 4294967295 and then the modulo + * tdb->hashtable_size is computed. So with a hashtable_size of 10 the result + * is + * + * 4294967295 % hashtable_size = 5. + * + * where it should be -1 (C uses symmetric modulo). + * + * As all callers will lock the same wrong list consistently locking is still + * consistent. We can not change this without an incompatible on-disk format + * change, otherwise different tdb versions would use incompatible locking. + */ +#define BUCKET(hash) ((hash) % tdb->hash_size) + +#define DOCONV() (tdb->flags & TDB_CONVERT) +#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x) + + +/* the body of the database is made of one tdb_record for the free space + plus a separate data list for each hash value */ +struct tdb_record { + tdb_off_t next; /* offset of the next record in the list */ + tdb_len_t rec_len; /* total byte length of record */ + tdb_len_t key_len; /* byte length of key */ + tdb_len_t data_len; /* byte length of data */ + uint32_t full_hash; /* the full 32 bit hash of the key */ + uint32_t magic; /* try to catch errors */ + /* the following union is implied: + union { + char record[rec_len]; + struct { + char key[key_len]; + char data[data_len]; + } + uint32_t totalsize; (tailer) + } + */ +}; + + +/* this is stored at the front of every database */ +struct tdb_header { + char magic_food[32]; /* for /etc/magic */ + uint32_t version; /* version of the code */ + uint32_t hash_size; /* number of hash entries */ + tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ + tdb_off_t recovery_start; /* offset of transaction recovery region */ + tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ + uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */ + uint32_t magic2_hash; /* hash of TDB_MAGIC. */ + uint32_t feature_flags; + tdb_len_t mutex_size; /* set if TDB_FEATURE_FLAG_MUTEX is set */ + tdb_off_t reserved[25]; +}; + +struct tdb_lock_type { + uint32_t off; + uint32_t count; + uint32_t ltype; +}; + +struct tdb_chainwalk_ctx { + tdb_off_t slow_ptr; + bool slow_chase; +}; + +struct tdb_traverse_lock { + struct tdb_traverse_lock *next; + uint32_t off; + uint32_t list; + int lock_rw; +}; + +void tdb_chainwalk_init(struct tdb_chainwalk_ctx *ctx, tdb_off_t ptr); +bool tdb_chainwalk_check(struct tdb_context *tdb, + struct tdb_chainwalk_ctx *ctx, + tdb_off_t next_ptr); + +enum tdb_lock_flags { + /* WAIT == F_SETLKW, NOWAIT == F_SETLK */ + TDB_LOCK_NOWAIT = 0, + TDB_LOCK_WAIT = 1, + /* If set, don't log an error on failure. */ + TDB_LOCK_PROBE = 2, + /* If set, don't actually lock at all. */ + TDB_LOCK_MARK_ONLY = 4, +}; + +struct tdb_methods { + int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int ); + int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t); + void (*next_hash_chain)(struct tdb_context *, uint32_t *); + int (*tdb_oob)(struct tdb_context *, tdb_off_t , tdb_len_t, int ); + int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); +}; + +struct tdb_mutexes; + +struct tdb_context { + char *name; /* the name of the database */ + void *map_ptr; /* where it is currently mapped */ + int fd; /* open file descriptor for the database */ + tdb_len_t map_size; /* how much space has been mapped */ + int read_only; /* opened read-only */ + int traverse_read; /* read-only traversal */ + int traverse_write; /* read-write traversal */ + struct tdb_lock_type allrecord_lock; /* .offset == upgradable */ + int num_lockrecs; + struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */ + int lockrecs_array_length; + + tdb_off_t hdr_ofs; /* this is 0 or header.mutex_size */ + struct tdb_mutexes *mutexes; /* mmap of the mutex area */ + + enum TDB_ERROR ecode; /* error code for last tdb error */ + uint32_t hash_size; + uint32_t feature_flags; + uint32_t flags; /* the flags passed to tdb_open */ + struct tdb_traverse_lock travlocks; /* current traversal locks */ + struct tdb_context *next; /* all tdbs to avoid multiple opens */ + dev_t device; /* uniquely identifies this tdb */ + ino_t inode; /* uniquely identifies this tdb */ + struct tdb_logging_context log; + unsigned int (*hash_fn)(TDB_DATA *key); + int open_flags; /* flags used in the open - needed by reopen */ + const struct tdb_methods *methods; + struct tdb_transaction *transaction; + int page_size; + int max_dead_records; +#ifdef TDB_TRACE + int tracefd; +#endif + volatile sig_atomic_t *interrupt_sig_ptr; +}; + + +/* + internal prototypes +*/ +int tdb_munmap(struct tdb_context *tdb); +int tdb_mmap(struct tdb_context *tdb); +int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); +int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype, + enum tdb_lock_flags flags); +int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype, + bool mark_lock); +int tdb_unlock(struct tdb_context *tdb, int list, int ltype); +int tdb_brlock(struct tdb_context *tdb, + int rw_type, tdb_off_t offset, size_t len, + enum tdb_lock_flags flags); +int tdb_brunlock(struct tdb_context *tdb, + int rw_type, tdb_off_t offset, size_t len); +bool tdb_have_extra_locks(struct tdb_context *tdb); +void tdb_release_transaction_locks(struct tdb_context *tdb); +int tdb_transaction_lock(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags lockflags); +int tdb_transaction_unlock(struct tdb_context *tdb, int ltype); +int tdb_recovery_area(struct tdb_context *tdb, + const struct tdb_methods *methods, + tdb_off_t *recovery_offset, + struct tdb_record *rec); +int tdb_allrecord_lock(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags flags, bool upgradable); +int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock); +int tdb_allrecord_upgrade(struct tdb_context *tdb); +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +void *tdb_convert(void *buf, uint32_t size); +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); +tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length, + struct tdb_record *rec); + +int _tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe); + +static inline int tdb_oob( + struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) +{ + if (likely((off + len >= off) && (off + len <= tdb->map_size))) { + return 0; + } + return _tdb_oob(tdb, off, len, probe); +} + + +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); +bool tdb_needs_recovery(struct tdb_context *tdb); +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); +unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); +int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, + tdb_off_t offset, tdb_len_t len, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype, + struct tdb_record *rec); +tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash, + struct tdb_record *r, tdb_len_t length, + tdb_off_t *p_last_ptr); +int tdb_trim_dead(struct tdb_context *tdb, uint32_t hash); +void tdb_io_init(struct tdb_context *tdb); +int tdb_expand(struct tdb_context *tdb, tdb_off_t size); +tdb_off_t tdb_expand_adjust(tdb_off_t map_size, tdb_off_t size, int page_size); +int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, + struct tdb_record *rec); +bool tdb_write_all(int fd, const void *buf, size_t count); +int tdb_transaction_recover(struct tdb_context *tdb); +void tdb_header_hash(struct tdb_context *tdb, + uint32_t *magic1_hash, uint32_t *magic2_hash); +unsigned int tdb_old_hash(TDB_DATA *key); +size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off); +bool tdb_add_off_t(tdb_off_t a, tdb_off_t b, tdb_off_t *pret); + +/* tdb_off_t and tdb_len_t right now are both uint32_t */ +#define tdb_add_len_t tdb_add_off_t + +size_t tdb_mutex_size(struct tdb_context *tdb); +bool tdb_have_mutexes(struct tdb_context *tdb); +int tdb_mutex_init(struct tdb_context *tdb); +int tdb_mutex_mmap(struct tdb_context *tdb); +int tdb_mutex_munmap(struct tdb_context *tdb); +bool tdb_mutex_lock(struct tdb_context *tdb, int rw, off_t off, off_t len, + bool waitflag, int *pret); +bool tdb_mutex_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len, + int *pret); +int tdb_mutex_allrecord_lock(struct tdb_context *tdb, int ltype, + enum tdb_lock_flags flags); +int tdb_mutex_allrecord_unlock(struct tdb_context *tdb); +int tdb_mutex_allrecord_upgrade(struct tdb_context *tdb); +void tdb_mutex_allrecord_downgrade(struct tdb_context *tdb); + +#endif /* TDB_PRIVATE_H */ diff --git a/ldb-2.0.8/lib/tdb/common/transaction.c b/ldb-2.0.8/lib/tdb/common/transaction.c new file mode 100644 index 0000000..4f8d1f8 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/transaction.c @@ -0,0 +1,1387 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +/* + transaction design: + + - only allow a single transaction at a time per database. This makes + using the transaction API simpler, as otherwise the caller would + have to cope with temporary failures in transactions that conflict + with other current transactions + + - keep the transaction recovery information in the same file as the + database, using a special 'transaction recovery' record pointed at + by the header. This removes the need for extra journal files as + used by some other databases + + - dynamically allocated the transaction recover record, re-using it + for subsequent transactions. If a larger record is needed then + tdb_free() the old record to place it on the normal tdb freelist + before allocating the new record + + - during transactions, keep a linked list of all writes that have + been performed by intercepting all tdb_write() calls. The hooked + transaction versions of tdb_read() and tdb_write() check this + linked list and try to use the elements of the list in preference + to the real database. + + - don't allow any locks to be held when a transaction starts, + otherwise we can end up with deadlock (plus lack of lock nesting + in posix locks would mean the lock is lost) + + - if the caller gains a lock during the transaction but doesn't + release it then fail the commit + + - allow for nested calls to tdb_transaction_start(), re-using the + existing transaction record. If the inner transaction is cancelled + then a subsequent commit will fail + + - keep a mirrored copy of the tdb hash chain heads to allow for the + fast hash heads scan on traverse, updating the mirrored copy in + the transaction version of tdb_write + + - allow callers to mix transaction and non-transaction use of tdb, + although once a transaction is started then an exclusive lock is + gained until the transaction is committed or cancelled + + - the commit stategy involves first saving away all modified data + into a linearised buffer in the transaction recovery area, then + marking the transaction recovery area with a magic value to + indicate a valid recovery record. In total 4 fsync/msync calls are + needed per commit to prevent race conditions. It might be possible + to reduce this to 3 or even 2 with some more work. + + - check for a valid recovery record on open of the tdb, while the + open lock is held. Automatically recover from the transaction + recovery area if needed, then continue with the open as + usual. This allows for smooth crash recovery with no administrator + intervention. + + - if TDB_NOSYNC is passed to flags in tdb_open then transactions are + still available, but no fsync/msync calls are made. This means we + are still proof against a process dying during transaction commit, + but not against machine reboot. + + - if TDB_ALLOW_NESTING is passed to flags in tdb open, or added using + tdb_add_flags() transaction nesting is enabled. + It resets the TDB_DISALLOW_NESTING flag, as both cannot be used together. + The default is that transaction nesting is allowed. + Note: this default may change in future versions of tdb. + + Beware. when transactions are nested a transaction successfully + completed with tdb_transaction_commit() can be silently unrolled later. + + - if TDB_DISALLOW_NESTING is passed to flags in tdb open, or added using + tdb_add_flags() transaction nesting is disabled. + It resets the TDB_ALLOW_NESTING flag, as both cannot be used together. + An attempt create a nested transaction will fail with TDB_ERR_NESTING. + The default is that transaction nesting is allowed. + Note: this default may change in future versions of tdb. +*/ + + +/* + hold the context of any current transaction +*/ +struct tdb_transaction { + /* we keep a mirrored copy of the tdb hash heads here so + tdb_next_hash_chain() can operate efficiently */ + uint32_t *hash_heads; + + /* the original io methods - used to do IOs to the real db */ + const struct tdb_methods *io_methods; + + /* the list of transaction blocks. When a block is first + written to, it gets created in this list */ + uint8_t **blocks; + uint32_t num_blocks; + uint32_t block_size; /* bytes in each block */ + uint32_t last_block_size; /* number of valid bytes in the last block */ + + /* non-zero when an internal transaction error has + occurred. All write operations will then fail until the + transaction is ended */ + int transaction_error; + + /* when inside a transaction we need to keep track of any + nested tdb_transaction_start() calls, as these are allowed, + but don't create a new transaction */ + int nesting; + + /* set when a prepare has already occurred */ + bool prepared; + tdb_off_t magic_offset; + + /* old file size before transaction */ + tdb_len_t old_map_size; + + /* did we expand in this transaction */ + bool expanded; +}; + + +/* + read while in a transaction. We need to check first if the data is in our list + of transaction elements, then if not do a real read +*/ +static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + uint32_t blk; + + /* break it down into block sized ops */ + while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size); + if (transaction_read(tdb, off, buf, len2, cv) != 0) { + return -1; + } + len -= len2; + off += len2; + buf = (void *)(len2 + (char *)buf); + } + + if (len == 0) { + return 0; + } + + blk = off / tdb->transaction->block_size; + + /* see if we have it in the block list */ + if (tdb->transaction->num_blocks <= blk || + tdb->transaction->blocks[blk] == NULL) { + /* nope, do a real read */ + if (tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv) != 0) { + goto fail; + } + return 0; + } + + /* it is in the block list. Now check for the last block */ + if (blk == tdb->transaction->num_blocks-1) { + if (len > tdb->transaction->last_block_size) { + goto fail; + } + } + + /* now copy it out of this block */ + memcpy(buf, tdb->transaction->blocks[blk] + (off % tdb->transaction->block_size), len); + if (cv) { + tdb_convert(buf, len); + } + return 0; + +fail: + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%u len=%u\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + + +/* + write while in a transaction +*/ +static int transaction_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + uint32_t blk; + + if (buf == NULL) { + return -1; + } + + /* Only a commit is allowed on a prepared transaction */ + if (tdb->transaction->prepared) { + tdb->ecode = TDB_ERR_EINVAL; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: transaction already prepared, write not allowed\n")); + tdb->transaction->transaction_error = 1; + return -1; + } + + /* if the write is to a hash head, then update the transaction + hash heads */ + if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP && + off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) { + uint32_t chain = (off-FREELIST_TOP) / sizeof(tdb_off_t); + memcpy(&tdb->transaction->hash_heads[chain], buf, len); + } + + /* break it up into block sized chunks */ + while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size); + if (transaction_write(tdb, off, buf, len2) != 0) { + return -1; + } + len -= len2; + off += len2; + buf = (const void *)(len2 + (const char *)buf); + } + + if (len == 0) { + return 0; + } + + blk = off / tdb->transaction->block_size; + off = off % tdb->transaction->block_size; + + if (tdb->transaction->num_blocks <= blk) { + uint8_t **new_blocks; + /* expand the blocks array */ + new_blocks = (uint8_t **)realloc(tdb->transaction->blocks, + (blk+1)*sizeof(uint8_t *)); + if (new_blocks == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + memset(&new_blocks[tdb->transaction->num_blocks], 0, + (1+(blk - tdb->transaction->num_blocks))*sizeof(uint8_t *)); + tdb->transaction->blocks = new_blocks; + tdb->transaction->num_blocks = blk+1; + tdb->transaction->last_block_size = 0; + } + + /* allocate and fill a block? */ + if (tdb->transaction->blocks[blk] == NULL) { + tdb->transaction->blocks[blk] = (uint8_t *)calloc(tdb->transaction->block_size, 1); + if (tdb->transaction->blocks[blk] == NULL) { + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + if (tdb->transaction->old_map_size > blk * tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size; + if (len2 + (blk * tdb->transaction->block_size) > tdb->transaction->old_map_size) { + len2 = tdb->transaction->old_map_size - (blk * tdb->transaction->block_size); + } + if (tdb->transaction->io_methods->tdb_read(tdb, blk * tdb->transaction->block_size, + tdb->transaction->blocks[blk], + len2, 0) != 0) { + SAFE_FREE(tdb->transaction->blocks[blk]); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + if (blk == tdb->transaction->num_blocks-1) { + tdb->transaction->last_block_size = len2; + } + } + } + + /* overwrite part of an existing block */ + memcpy(tdb->transaction->blocks[blk] + off, buf, len); + if (blk == tdb->transaction->num_blocks-1) { + if (len + off > tdb->transaction->last_block_size) { + tdb->transaction->last_block_size = len + off; + } + } + + return 0; + +fail: + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%u len=%u\n", + (blk*tdb->transaction->block_size) + off, len)); + tdb->transaction->transaction_error = 1; + return -1; +} + + +/* + write while in a transaction - this variant never expands the transaction blocks, it only + updates existing blocks. This means it cannot change the recovery size +*/ +static int transaction_write_existing(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + uint32_t blk; + + /* break it up into block sized chunks */ + while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size); + if (transaction_write_existing(tdb, off, buf, len2) != 0) { + return -1; + } + len -= len2; + off += len2; + if (buf != NULL) { + buf = (const void *)(len2 + (const char *)buf); + } + } + + if (len == 0 || buf == NULL) { + return 0; + } + + blk = off / tdb->transaction->block_size; + off = off % tdb->transaction->block_size; + + if (tdb->transaction->num_blocks <= blk || + tdb->transaction->blocks[blk] == NULL) { + return 0; + } + + if (blk == tdb->transaction->num_blocks-1 && + off + len > tdb->transaction->last_block_size) { + if (off >= tdb->transaction->last_block_size) { + return 0; + } + len = tdb->transaction->last_block_size - off; + } + + /* overwrite part of an existing block */ + memcpy(tdb->transaction->blocks[blk] + off, buf, len); + + return 0; +} + + +/* + accelerated hash chain head search, using the cached hash heads +*/ +static void transaction_next_hash_chain(struct tdb_context *tdb, uint32_t *chain) +{ + uint32_t h = *chain; + for (;h < tdb->hash_size;h++) { + /* the +1 takes account of the freelist */ + if (0 != tdb->transaction->hash_heads[h+1]) { + break; + } + } + (*chain) = h; +} + +/* + out of bounds check during a transaction +*/ +static int transaction_oob(struct tdb_context *tdb, tdb_off_t off, + tdb_len_t len, int probe) +{ + /* + * This duplicates functionality from tdb_oob(). Don't remove: + * we still have direct callers of tdb->methods->tdb_oob() + * inside transaction.c. + */ + if (off + len >= off && off + len <= tdb->map_size) { + return 0; + } + tdb->ecode = TDB_ERR_IO; + return -1; +} + +/* + transaction version of tdb_expand(). +*/ +static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, + tdb_off_t addition) +{ + const char buf_zero[8192] = {0}; + size_t buf_len = sizeof(buf_zero); + + while (addition > 0) { + size_t n = MIN(addition, buf_len); + int ret; + + ret = transaction_write(tdb, size, buf_zero, n); + if (ret != 0) { + return ret; + } + + addition -= n; + size += n; + } + + tdb->transaction->expanded = true; + + return 0; +} + +static const struct tdb_methods transaction_methods = { + transaction_read, + transaction_write, + transaction_next_hash_chain, + transaction_oob, + transaction_expand_file, +}; + +/* + * Is a transaction currently active on this context? + * + */ +_PUBLIC_ bool tdb_transaction_active(struct tdb_context *tdb) +{ + return (tdb->transaction != NULL); +} + +/* + start a tdb transaction. No token is returned, as only a single + transaction is allowed to be pending per tdb_context +*/ +static int _tdb_transaction_start(struct tdb_context *tdb, + enum tdb_lock_flags lockflags) +{ + /* some sanity checks */ + if (tdb->read_only || (tdb->flags & TDB_INTERNAL) + || tdb->traverse_read) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); + tdb->ecode = TDB_ERR_EINVAL; + return -1; + } + + /* cope with nested tdb_transaction_start() calls */ + if (tdb->transaction != NULL) { + if (!(tdb->flags & TDB_ALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + return -1; + } + tdb->transaction->nesting++; + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", + tdb->transaction->nesting)); + return 0; + } + + if (tdb_have_extra_locks(tdb)) { + /* the caller must not have any locks when starting a + transaction as otherwise we'll be screwed by lack + of nested locks in posix */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->travlocks.next != NULL) { + /* you cannot use transactions inside a traverse (although you can use + traverse inside a transaction) as otherwise you can end up with + deadlock */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + tdb->transaction = (struct tdb_transaction *) + calloc(sizeof(struct tdb_transaction), 1); + if (tdb->transaction == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* a page at a time seems like a reasonable compromise between compactness and efficiency */ + tdb->transaction->block_size = tdb->page_size; + + /* get the transaction write lock. This is a blocking lock. As + discussed with Volker, there are a number of ways we could + make this async, which we will probably do in the future */ + if (tdb_transaction_lock(tdb, F_WRLCK, lockflags) == -1) { + SAFE_FREE(tdb->transaction->blocks); + SAFE_FREE(tdb->transaction); + if ((lockflags & TDB_LOCK_WAIT) == 0) { + tdb->ecode = TDB_ERR_NOLOCK; + } else { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_transaction_start: " + "failed to get transaction lock\n")); + } + return -1; + } + + /* get a read lock from the freelist to the end of file. This + is upgraded to a write lock during the commit */ + if (tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, true) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); + goto fail_allrecord_lock; + } + + /* setup a copy of the hash table heads so the hash scan in + traverse can be fast */ + tdb->transaction->hash_heads = (uint32_t *) + calloc(tdb->hash_size+1, sizeof(uint32_t)); + if (tdb->transaction->hash_heads == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, + TDB_HASHTABLE_SIZE(tdb), 0) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n")); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + + /* make sure we know about any file expansions already done by + anyone else */ + tdb_oob(tdb, tdb->map_size, 1, 1); + tdb->transaction->old_map_size = tdb->map_size; + + /* finally hook the io methods, replacing them with + transaction specific methods */ + tdb->transaction->io_methods = tdb->methods; + tdb->methods = &transaction_methods; + + /* Trace at the end, so we get sequence number correct. */ + tdb_trace(tdb, "tdb_transaction_start"); + return 0; + +fail: + tdb_allrecord_unlock(tdb, F_RDLCK, false); +fail_allrecord_lock: + tdb_transaction_unlock(tdb, F_WRLCK); + SAFE_FREE(tdb->transaction->blocks); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + return -1; +} + +_PUBLIC_ int tdb_transaction_start(struct tdb_context *tdb) +{ + return _tdb_transaction_start(tdb, TDB_LOCK_WAIT); +} + +_PUBLIC_ int tdb_transaction_start_nonblock(struct tdb_context *tdb) +{ + return _tdb_transaction_start(tdb, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE); +} + +/* + sync to disk +*/ +static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length) +{ + if (tdb->flags & TDB_NOSYNC) { + return 0; + } + +#ifdef HAVE_FDATASYNC + if (fdatasync(tdb->fd) != 0) { +#else + if (fsync(tdb->fd) != 0) { +#endif + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n")); + return -1; + } +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + tdb_off_t moffset = offset & ~(tdb->page_size-1); + if (msync(moffset + (char *)tdb->map_ptr, + length + (offset - moffset), MS_SYNC) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n", + strerror(errno))); + return -1; + } + } +#endif + return 0; +} + + +static int _tdb_transaction_cancel(struct tdb_context *tdb) +{ + uint32_t i; + int ret = 0; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->transaction_error = 1; + tdb->transaction->nesting--; + return 0; + } + + tdb->map_size = tdb->transaction->old_map_size; + + /* free all the transaction blocks */ + for (i=0;itransaction->num_blocks;i++) { + if ((tdb->transaction->blocks != NULL) && + tdb->transaction->blocks[i] != NULL) { + free(tdb->transaction->blocks[i]); + } + } + SAFE_FREE(tdb->transaction->blocks); + + if (tdb->transaction->magic_offset) { + const struct tdb_methods *methods = tdb->transaction->io_methods; + const uint32_t invalid = TDB_RECOVERY_INVALID_MAGIC; + + /* remove the recovery marker */ + if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &invalid, 4) == -1 || + transaction_sync(tdb, tdb->transaction->magic_offset, 4) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_cancel: failed to remove recovery magic\n")); + ret = -1; + } + } + + /* This also removes the OPEN_LOCK, if we have it. */ + tdb_release_transaction_locks(tdb); + + /* restore the normal io methods */ + tdb->methods = tdb->transaction->io_methods; + + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + + return ret; +} + +/* + cancel the current transaction +*/ +_PUBLIC_ int tdb_transaction_cancel(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_transaction_cancel"); + return _tdb_transaction_cancel(tdb); +} + +/* + work out how much space the linearised recovery data will consume +*/ +static bool tdb_recovery_size(struct tdb_context *tdb, tdb_len_t *result) +{ + tdb_len_t recovery_size = 0; + uint32_t i; + + recovery_size = sizeof(uint32_t); + for (i=0;itransaction->num_blocks;i++) { + tdb_len_t block_size; + if (i * tdb->transaction->block_size >= tdb->transaction->old_map_size) { + break; + } + if (tdb->transaction->blocks[i] == NULL) { + continue; + } + if (!tdb_add_len_t(recovery_size, 2*sizeof(tdb_off_t), + &recovery_size)) { + return false; + } + if (i == tdb->transaction->num_blocks-1) { + block_size = tdb->transaction->last_block_size; + } else { + block_size = tdb->transaction->block_size; + } + if (!tdb_add_len_t(recovery_size, block_size, + &recovery_size)) { + return false; + } + } + + *result = recovery_size; + return true; +} + +int tdb_recovery_area(struct tdb_context *tdb, + const struct tdb_methods *methods, + tdb_off_t *recovery_offset, + struct tdb_record *rec) +{ + int ret; + + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, recovery_offset) == -1) { + return -1; + } + + if (*recovery_offset == 0) { + rec->rec_len = 0; + return 0; + } + + if (methods->tdb_read(tdb, *recovery_offset, rec, sizeof(*rec), + DOCONV()) == -1) { + return -1; + } + + /* ignore invalid recovery regions: can happen in crash */ + if (rec->magic != TDB_RECOVERY_MAGIC && + rec->magic != TDB_RECOVERY_INVALID_MAGIC) { + *recovery_offset = 0; + rec->rec_len = 0; + } + + ret = methods->tdb_oob(tdb, *recovery_offset, rec->rec_len, 1); + if (ret == -1) { + *recovery_offset = 0; + rec->rec_len = 0; + } + + return 0; +} + +/* + allocate the recovery area, or use an existing recovery area if it is + large enough +*/ +static int tdb_recovery_allocate(struct tdb_context *tdb, + tdb_len_t *recovery_size, + tdb_off_t *recovery_offset, + tdb_len_t *recovery_max_size) +{ + struct tdb_record rec; + const struct tdb_methods *methods = tdb->transaction->io_methods; + tdb_off_t recovery_head, new_end; + + if (tdb_recovery_area(tdb, methods, &recovery_head, &rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n")); + return -1; + } + + if (!tdb_recovery_size(tdb, recovery_size)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: " + "overflow recovery size\n")); + return -1; + } + + /* Existing recovery area? */ + if (recovery_head != 0 && *recovery_size <= rec.rec_len) { + /* it fits in the existing area */ + *recovery_max_size = rec.rec_len; + *recovery_offset = recovery_head; + return 0; + } + + /* If recovery area in middle of file, we need a new one. */ + if (recovery_head == 0 + || recovery_head + sizeof(rec) + rec.rec_len != tdb->map_size) { + /* we need to free up the old recovery area, then allocate a + new one at the end of the file. Note that we cannot use + tdb_allocate() to allocate the new one as that might return + us an area that is being currently used (as of the start of + the transaction) */ + if (recovery_head) { + if (tdb_free(tdb, recovery_head, &rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + "tdb_recovery_allocate: failed to" + " free previous recovery area\n")); + return -1; + } + + /* the tdb_free() call might have increased + * the recovery size */ + if (!tdb_recovery_size(tdb, recovery_size)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + "tdb_recovery_allocate: " + "overflow recovery size\n")); + return -1; + } + } + + /* New head will be at end of file. */ + recovery_head = tdb->map_size; + } + + /* Now we know where it will be. */ + *recovery_offset = recovery_head; + + /* Expand by more than we need, so we don't do it often. */ + *recovery_max_size = tdb_expand_adjust(tdb->map_size, + *recovery_size, + tdb->page_size) + - sizeof(rec); + + if (!tdb_add_off_t(recovery_head, sizeof(rec), &new_end) || + !tdb_add_off_t(new_end, *recovery_max_size, &new_end)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: " + "overflow recovery area\n")); + return -1; + } + + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + new_end - tdb->transaction->old_map_size) + == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n")); + return -1; + } + + /* remap the file (if using mmap) */ + methods->tdb_oob(tdb, tdb->map_size, 1, 1); + + /* we have to reset the old map size so that we don't try to expand the file + again in the transaction commit, which would destroy the recovery area */ + tdb->transaction->old_map_size = tdb->map_size; + + /* write the recovery header offset and sync - we can sync without a race here + as the magic ptr in the recovery record has not been set */ + CONVERT(recovery_head); + if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, + &recovery_head, sizeof(tdb_off_t)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); + return -1; + } + if (transaction_write_existing(tdb, TDB_RECOVERY_HEAD, &recovery_head, sizeof(tdb_off_t)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); + return -1; + } + + return 0; +} + + +/* + setup the recovery data that will be used on a crash during commit +*/ +static int transaction_setup_recovery(struct tdb_context *tdb, + tdb_off_t *magic_offset) +{ + tdb_len_t recovery_size; + unsigned char *data, *p; + const struct tdb_methods *methods = tdb->transaction->io_methods; + struct tdb_record *rec; + tdb_off_t recovery_offset, recovery_max_size; + tdb_off_t old_map_size = tdb->transaction->old_map_size; + uint32_t magic, tailer; + uint32_t i; + + /* + check that the recovery area has enough space + */ + if (tdb_recovery_allocate(tdb, &recovery_size, + &recovery_offset, &recovery_max_size) == -1) { + return -1; + } + + rec = malloc(recovery_size + sizeof(*rec)); + if (rec == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + memset(rec, 0, sizeof(*rec)); + + rec->magic = TDB_RECOVERY_INVALID_MAGIC; + rec->data_len = recovery_size; + rec->rec_len = recovery_max_size; + rec->key_len = old_map_size; + CONVERT(*rec); + + data = (unsigned char *)rec; + + /* build the recovery data into a single blob to allow us to do a single + large write, which should be more efficient */ + p = data + sizeof(*rec); + for (i=0;itransaction->num_blocks;i++) { + tdb_off_t offset; + tdb_len_t length; + + if (tdb->transaction->blocks[i] == NULL) { + continue; + } + + offset = i * tdb->transaction->block_size; + length = tdb->transaction->block_size; + if (i == tdb->transaction->num_blocks-1) { + length = tdb->transaction->last_block_size; + } + + if (offset >= old_map_size) { + continue; + } + if (offset + length > tdb->transaction->old_map_size) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n")); + free(data); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + memcpy(p, &offset, 4); + memcpy(p+4, &length, 4); + if (DOCONV()) { + tdb_convert(p, 8); + } + /* the recovery area contains the old data, not the + new data, so we have to call the original tdb_read + method to get it */ + if (methods->tdb_read(tdb, offset, p + 8, length, 0) != 0) { + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + length; + } + + /* and the tailer */ + tailer = sizeof(*rec) + recovery_max_size; + memcpy(p, &tailer, 4); + if (DOCONV()) { + tdb_convert(p, 4); + } + + /* write the recovery data to the recovery area */ + if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n")); + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + if (transaction_write_existing(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write secondary recovery data\n")); + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* as we don't have ordered writes, we have to sync the recovery + data before we update the magic to indicate that the recovery + data is present */ + if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) { + free(data); + return -1; + } + + free(data); + + magic = TDB_RECOVERY_MAGIC; + CONVERT(magic); + + *magic_offset = recovery_offset + offsetof(struct tdb_record, magic); + + if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + if (transaction_write_existing(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write secondary recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* ensure the recovery magic marker is on disk */ + if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) { + return -1; + } + + return 0; +} + +static int _tdb_transaction_prepare_commit(struct tdb_context *tdb) +{ + const struct tdb_methods *methods; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: no transaction\n")); + return -1; + } + + if (tdb->transaction->prepared) { + tdb->ecode = TDB_ERR_EINVAL; + _tdb_transaction_cancel(tdb); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: transaction already prepared\n")); + return -1; + } + + if (tdb->transaction->transaction_error) { + tdb->ecode = TDB_ERR_IO; + _tdb_transaction_cancel(tdb); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: transaction error pending\n")); + return -1; + } + + + if (tdb->transaction->nesting != 0) { + return 0; + } + + /* check for a null transaction */ + if (tdb->transaction->blocks == NULL) { + return 0; + } + + methods = tdb->transaction->io_methods; + + /* if there are any locks pending then the caller has not + nested their locks properly, so fail the transaction */ + if (tdb_have_extra_locks(tdb)) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: locks pending on commit\n")); + _tdb_transaction_cancel(tdb); + return -1; + } + + /* upgrade the main transaction lock region to a write lock */ + if (tdb_allrecord_upgrade(tdb) == -1) { + if (tdb->ecode == TDB_ERR_RDONLY && tdb->read_only) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_transaction_prepare_commit: " + "failed to upgrade hash locks: " + "database is read only\n")); + } else if (tdb->ecode == TDB_ERR_RDONLY + && tdb->traverse_read) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_transaction_prepare_commit: " + "failed to upgrade hash locks: " + "a database traverse is in progress\n")); + } else { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "tdb_transaction_prepare_commit: " + "failed to upgrade hash locks: %s\n", + tdb_errorstr(tdb))); + } + _tdb_transaction_cancel(tdb); + return -1; + } + + /* get the open lock - this prevents new users attaching to the database + during the commit */ + if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get open lock\n")); + _tdb_transaction_cancel(tdb); + return -1; + } + + /* write the recovery data to the end of the file */ + if (transaction_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: failed to setup recovery data\n")); + _tdb_transaction_cancel(tdb); + return -1; + } + + tdb->transaction->prepared = true; + + /* expand the file to the new size if needed */ + if (tdb->map_size != tdb->transaction->old_map_size) { + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + tdb->map_size - + tdb->transaction->old_map_size) == -1) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: expansion failed\n")); + _tdb_transaction_cancel(tdb); + return -1; + } + tdb->map_size = tdb->transaction->old_map_size; + methods->tdb_oob(tdb, tdb->map_size, 1, 1); + } + + /* Keep the open lock until the actual commit */ + + return 0; +} + +/* + prepare to commit the current transaction +*/ +_PUBLIC_ int tdb_transaction_prepare_commit(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_transaction_prepare_commit"); + return _tdb_transaction_prepare_commit(tdb); +} + +/* A repack is worthwhile if the largest is less than half total free. */ +static bool repack_worthwhile(struct tdb_context *tdb) +{ + tdb_off_t ptr; + struct tdb_record rec; + tdb_len_t total = 0, largest = 0; + + if (tdb_ofs_read(tdb, FREELIST_TOP, &ptr) == -1) { + return false; + } + + while (ptr != 0 && tdb_rec_free_read(tdb, ptr, &rec) == 0) { + total += rec.rec_len; + if (rec.rec_len > largest) { + largest = rec.rec_len; + } + ptr = rec.next; + } + + return total > largest * 2; +} + +/* + commit the current transaction +*/ +_PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb) +{ + const struct tdb_methods *methods; + uint32_t i; + bool need_repack = false; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n")); + return -1; + } + + tdb_trace(tdb, "tdb_transaction_commit"); + + if (tdb->transaction->transaction_error) { + tdb->ecode = TDB_ERR_IO; + _tdb_transaction_cancel(tdb); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n")); + return -1; + } + + + if (tdb->transaction->nesting != 0) { + tdb->transaction->nesting--; + return 0; + } + + /* check for a null transaction */ + if (tdb->transaction->blocks == NULL) { + _tdb_transaction_cancel(tdb); + return 0; + } + + if (!tdb->transaction->prepared) { + int ret = _tdb_transaction_prepare_commit(tdb); + if (ret) + return ret; + } + + methods = tdb->transaction->io_methods; + + /* perform all the writes */ + for (i=0;itransaction->num_blocks;i++) { + tdb_off_t offset; + tdb_len_t length; + + if (tdb->transaction->blocks[i] == NULL) { + continue; + } + + offset = i * tdb->transaction->block_size; + length = tdb->transaction->block_size; + if (i == tdb->transaction->num_blocks-1) { + length = tdb->transaction->last_block_size; + } + + if (methods->tdb_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); + + /* we've overwritten part of the data and + possibly expanded the file, so we need to + run the crash recovery code */ + tdb->methods = methods; + tdb_transaction_recover(tdb); + + _tdb_transaction_cancel(tdb); + + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n")); + return -1; + } + SAFE_FREE(tdb->transaction->blocks[i]); + } + + /* Do this before we drop lock or blocks. */ + if (tdb->transaction->expanded) { + need_repack = repack_worthwhile(tdb); + } + + SAFE_FREE(tdb->transaction->blocks); + tdb->transaction->num_blocks = 0; + + /* ensure the new data is on disk */ + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + return -1; + } + + /* + TODO: maybe write to some dummy hdr field, or write to magic + offset without mmap, before the last sync, instead of the + utime() call + */ + + /* on some systems (like Linux 2.6.x) changes via mmap/msync + don't change the mtime of the file, this means the file may + not be backed up (as tdb rounding to block sizes means that + file size changes are quite rare too). The following forces + mtime changes when a transaction completes */ +#ifdef HAVE_UTIME + utime(tdb->name, NULL); +#endif + + /* use a transaction cancel to free memory and remove the + transaction locks */ + _tdb_transaction_cancel(tdb); + + if (need_repack) { + int ret = tdb_repack(tdb); + if (ret != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + __location__ " Failed to repack database (not fatal)\n")); + } + /* + * Ignore the error. + * + * Why? + * + * We just committed to the DB above, so anything + * written during the transaction is committed, the + * caller needs to know that the long-term state was + * successfully modified. + * + * tdb_repack is an optimization that can fail for + * reasons like lock ordering and we cannot recover + * the transaction lock at this point, having released + * it above. + * + * If we return a failure the caller thinks the + * transaction was rolled back. + */ + } + + return 0; +} + + +/* + recover from an aborted transaction. Must be called with exclusive + database write access already established (including the open + lock to prevent new processes attaching) +*/ +int tdb_transaction_recover(struct tdb_context *tdb) +{ + tdb_off_t recovery_head, recovery_eof; + unsigned char *data, *p; + uint32_t zero = 0; + struct tdb_record rec; + + /* find the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (recovery_head == 0) { + /* we have never allocated a recovery record */ + return 0; + } + + /* read the recovery record */ + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, + sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (rec.magic != TDB_RECOVERY_MAGIC) { + /* there is no valid recovery data */ + return 0; + } + + if (tdb->read_only) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n")); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + + recovery_eof = rec.key_len; + + data = (unsigned char *)malloc(rec.data_len); + if (data == NULL) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n")); + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* read the full recovery data */ + if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, + rec.data_len, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* recover the file data */ + p = data; + while (p+8 < data + rec.data_len) { + uint32_t ofs, len; + if (DOCONV()) { + tdb_convert(p, 8); + } + memcpy(&ofs, p, 4); + memcpy(&len, p+4, 4); + + if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { + free(data); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %u bytes at offset %u\n", len, ofs)); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + len; + } + + free(data); + + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* if the recovery area is after the recovered eof then remove it */ + if (recovery_eof <= recovery_head) { + if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + } + + /* remove the recovery magic */ + if (tdb_ofs_write(tdb, recovery_head + offsetof(struct tdb_record, magic), + &zero) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (transaction_sync(tdb, 0, recovery_eof) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %u byte database\n", + recovery_eof)); + + /* all done */ + return 0; +} + +/* Any I/O failures we say "needs recovery". */ +bool tdb_needs_recovery(struct tdb_context *tdb) +{ + tdb_off_t recovery_head; + struct tdb_record rec; + + /* find the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + return true; + } + + if (recovery_head == 0) { + /* we have never allocated a recovery record */ + return false; + } + + /* read the recovery record */ + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, + sizeof(rec), DOCONV()) == -1) { + return true; + } + + return (rec.magic == TDB_RECOVERY_MAGIC); +} diff --git a/ldb-2.0.8/lib/tdb/common/traverse.c b/ldb-2.0.8/lib/tdb/common/traverse.c new file mode 100644 index 0000000..d69e7df --- /dev/null +++ b/ldb-2.0.8/lib/tdb/common/traverse.c @@ -0,0 +1,510 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include "tdb_private.h" + +#define TDB_NEXT_LOCK_ERR ((tdb_off_t)-1) + +/* Uses traverse lock: 0 = finish, TDB_NEXT_LOCK_ERR = error, + other = record offset */ +static tdb_off_t tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock, + struct tdb_record *rec) +{ + int want_next = (tlock->off != 0); + + /* Lock each chain from the start one. */ + for (; tlock->list < tdb->hash_size; tlock->list++) { + if (!tlock->off && tlock->list != 0) { + /* this is an optimisation for the common case where + the hash chain is empty, which is particularly + common for the use of tdb with ldb, where large + hashes are used. In that case we spend most of our + time in tdb_brlock(), locking empty hash chains. + + To avoid this, we do an unlocked pre-check to see + if the hash chain is empty before starting to look + inside it. If it is empty then we can avoid that + hash chain. If it isn't empty then we can't believe + the value we get back, as we read it without a + lock, so instead we get the lock and re-fetch the + value below. + + Notice that not doing this optimisation on the + first hash chain is critical. We must guarantee + that we have done at least one fcntl lock at the + start of a search to guarantee that memory is + coherent on SMP systems. If records are added by + others during the search then thats OK, and we + could possibly miss those with this trick, but we + could miss them anyway without this trick, so the + semantics don't change. + + With a non-indexed ldb search this trick gains us a + factor of around 80 in speed on a linux 2.6.x + system (testing using ldbtest). + */ + tdb->methods->next_hash_chain(tdb, &tlock->list); + if (tlock->list == tdb->hash_size) { + continue; + } + } + + if (tdb_lock(tdb, tlock->list, tlock->lock_rw) == -1) + return TDB_NEXT_LOCK_ERR; + + /* No previous record? Start at top of chain. */ + if (!tlock->off) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->list), + &tlock->off) == -1) + goto fail; + } else { + /* Otherwise unlock the previous record. */ + if (tdb_unlock_record(tdb, tlock->off) != 0) + goto fail; + } + + if (want_next) { + /* We have offset of old record: grab next */ + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + tlock->off = rec->next; + } + + /* Iterate through chain */ + while( tlock->off) { + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + + /* Detect infinite loops. From "Shlomi Yaakobovich" . */ + if (tlock->off == rec->next) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n")); + goto fail; + } + + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (tdb_lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + + tlock->off = rec->next; + } + tdb_unlock(tdb, tlock->list, tlock->lock_rw); + want_next = 0; + } + /* We finished iteration without finding anything */ + tdb->ecode = TDB_SUCCESS; + return 0; + + fail: + tlock->off = 0; + if (tdb_unlock(tdb, tlock->list, tlock->lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n")); + return TDB_NEXT_LOCK_ERR; +} + +/* traverse the entire database - calling fn(tdb, key, data) on each element. + return -1 on error or the record count traversed + if fn is NULL then it is not called + a non-zero return value from fn() indicates that the traversal should stop + */ +static int tdb_traverse_internal(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data, + struct tdb_traverse_lock *tl) +{ + TDB_DATA key, dbuf; + 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 + */ + tl->next = tdb->travlocks.next; + + /* fcntl locks don't stack: beware traverse inside traverse */ + tdb->travlocks.next = tl; + + /* 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; + int nread; + + if (off == TDB_NEXT_LOCK_ERR) { + ret = -1; + goto out; + } + + full_len = rec.key_len + rec.data_len; + + 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->list, 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; + } + } + + count++; + /* now read the full record */ + 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->list, tl->lock_rw) != 0) + goto out; + if (tdb_unlock_record(tdb, tl->off) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + goto out; + } + key.dsize = rec.key_len; + dbuf.dptr = key.dptr + rec.key_len; + dbuf.dsize = rec.data_len; + + tdb_trace_1rec_retrec(tdb, "traverse", key, dbuf); + + /* Drop chain lock, call out */ + if (tdb_unlock(tdb, tl->list, tl->lock_rw) != 0) { + ret = -1; + goto out; + } + if (fn && fn(tdb, key, dbuf, private_data)) { + /* They want us to terminate traversal */ + tdb_trace_ret(tdb, "tdb_traverse_end", count); + if (tdb_unlock_record(tdb, tl->off) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; + ret = -1; + } + goto out; + } + } + tdb_trace(tdb, "tdb_traverse_end"); +out: + SAFE_FREE(key.dptr); + tdb->travlocks.next = tl->next; + if (ret < 0) + return -1; + else + return count; +} + + +/* + a read style traverse - temporarily marks each record read only +*/ +_PUBLIC_ int tdb_traverse_read(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; + int ret; + + tdb->traverse_read++; + tdb_trace(tdb, "tdb_traverse_read_start"); + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + tdb->traverse_read--; + + return ret; +} + +/* + a write style traverse - needs to get the transaction lock to + prevent deadlocks + + WARNING: The data buffer given to the callback fn does NOT meet the + alignment guarantees malloc gives you. +*/ +_PUBLIC_ int tdb_traverse(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; + enum tdb_lock_flags lock_flags; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + return tdb_traverse_read(tdb, fn, private_data); + } + + lock_flags = TDB_LOCK_WAIT; + + if (tdb->allrecord_lock.count != 0) { + /* + * This avoids a deadlock between tdb_lockall() and + * tdb_traverse(). See + * https://bugzilla.samba.org/show_bug.cgi?id=11381 + */ + lock_flags = TDB_LOCK_NOWAIT; + } + + if (tdb_transaction_lock(tdb, F_WRLCK, lock_flags)) { + return -1; + } + + tdb->traverse_write++; + tdb_trace(tdb, "tdb_traverse_start"); + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + tdb->traverse_write--; + + tdb_transaction_unlock(tdb, F_WRLCK); + + return ret; +} + + +/* find the first entry in the database and return its key */ +_PUBLIC_ TDB_DATA tdb_firstkey(struct tdb_context *tdb) +{ + TDB_DATA key; + struct tdb_record rec; + tdb_off_t off; + + /* release any old lock */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + tdb->travlocks.off = tdb->travlocks.list = 0; + tdb->travlocks.lock_rw = F_RDLCK; + + /* Grab first record: locks chain and returned record. */ + off = tdb_next_lock(tdb, &tdb->travlocks, &rec); + if (off == 0 || off == TDB_NEXT_LOCK_ERR) { + tdb_trace_retrec(tdb, "tdb_firstkey", tdb_null); + return tdb_null; + } + /* now read the key */ + key.dsize = rec.key_len; + key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); + + tdb_trace_retrec(tdb, "tdb_firstkey", key); + + /* Unlock the hash chain of the record we just read. */ + if (tdb_unlock(tdb, tdb->travlocks.list, tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + return key; +} + +/* find the next entry in the database, returning its key */ +_PUBLIC_ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) +{ + uint32_t oldlist; + TDB_DATA key = tdb_null; + struct tdb_record rec; + unsigned char *k = NULL; + tdb_off_t off; + + /* Is locked key the old key? If so, traverse will be reliable. */ + if (tdb->travlocks.off) { + if (tdb_lock(tdb,tdb->travlocks.list,tdb->travlocks.lock_rw)) + return tdb_null; + if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 + || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), + rec.key_len)) + || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { + /* No, it wasn't: unlock it and start from scratch */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) { + tdb_trace_1rec_retrec(tdb, "tdb_nextkey", + oldkey, tdb_null); + SAFE_FREE(k); + return tdb_null; + } + if (tdb_unlock(tdb, tdb->travlocks.list, tdb->travlocks.lock_rw) != 0) { + SAFE_FREE(k); + return tdb_null; + } + tdb->travlocks.off = 0; + } + + SAFE_FREE(k); + } + + if (!tdb->travlocks.off) { + /* No previous element: do normal find, and lock record */ + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec); + if (!tdb->travlocks.off) { + tdb_trace_1rec_retrec(tdb, "tdb_nextkey", oldkey, tdb_null); + return tdb_null; + } + tdb->travlocks.list = BUCKET(rec.full_hash); + if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + return tdb_null; + } + } + oldlist = tdb->travlocks.list; + + /* Grab next record: locks chain and returned record, + unlocks old record */ + off = tdb_next_lock(tdb, &tdb->travlocks, &rec); + if (off != TDB_NEXT_LOCK_ERR && off != 0) { + key.dsize = rec.key_len; + key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), + key.dsize); + /* Unlock the chain of this new record */ + if (tdb_unlock(tdb, tdb->travlocks.list, tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + } + /* Unlock the chain of old record */ + if (tdb_unlock(tdb, oldlist, tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + tdb_trace_1rec_retrec(tdb, "tdb_nextkey", oldkey, key); + return key; +} + +_PUBLIC_ int tdb_traverse_chain(struct tdb_context *tdb, + unsigned chain, + tdb_traverse_func fn, + void *private_data) +{ + tdb_off_t rec_ptr; + struct tdb_chainwalk_ctx chainwalk; + int count = 0; + int ret; + + if (chain >= tdb->hash_size) { + tdb->ecode = TDB_ERR_EINVAL; + return -1; + } + + if (tdb->traverse_read != 0) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + ret = tdb_lock(tdb, chain, F_RDLCK); + if (ret == -1) { + return -1; + } + + tdb->traverse_read += 1; + + ret = tdb_ofs_read(tdb, TDB_HASH_TOP(chain), &rec_ptr); + if (ret == -1) { + goto fail; + } + + tdb_chainwalk_init(&chainwalk, rec_ptr); + + while (rec_ptr != 0) { + struct tdb_record rec; + bool ok; + + ret = tdb_rec_read(tdb, rec_ptr, &rec); + if (ret == -1) { + goto fail; + } + + if (!TDB_DEAD(&rec)) { + /* no overflow checks, tdb_rec_read checked it */ + tdb_off_t key_ofs = rec_ptr + sizeof(rec); + size_t full_len = rec.key_len + rec.data_len; + uint8_t *buf = NULL; + + TDB_DATA key = { .dsize = rec.key_len }; + TDB_DATA data = { .dsize = rec.data_len }; + + if ((tdb->transaction == NULL) && + (tdb->map_ptr != NULL)) { + ret = tdb_oob(tdb, key_ofs, full_len, 0); + if (ret == -1) { + goto fail; + } + key.dptr = (uint8_t *)tdb->map_ptr + key_ofs; + } else { + buf = tdb_alloc_read(tdb, key_ofs, full_len); + if (buf == NULL) { + goto fail; + } + key.dptr = buf; + } + data.dptr = key.dptr + key.dsize; + + ret = fn(tdb, key, data, private_data); + free(buf); + + count += 1; + + if (ret != 0) { + break; + } + } + + rec_ptr = rec.next; + + ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr); + if (!ok) { + goto fail; + } + } + tdb->traverse_read -= 1; + tdb_unlock(tdb, chain, F_RDLCK); + return count; + +fail: + tdb->traverse_read -= 1; + tdb_unlock(tdb, chain, F_RDLCK); + return -1; +} + +_PUBLIC_ int tdb_traverse_key_chain(struct tdb_context *tdb, + TDB_DATA key, + tdb_traverse_func fn, + void *private_data) +{ + uint32_t hash, chain; + int ret; + + hash = tdb->hash_fn(&key); + chain = BUCKET(hash); + ret = tdb_traverse_chain(tdb, chain, fn, private_data); + + return ret; +} diff --git a/ldb-2.0.8/lib/tdb/configure b/ldb-2.0.8/lib/tdb/configure new file mode 100755 index 0000000..d8a8d2a --- /dev/null +++ b/ldb-2.0.8/lib/tdb/configure @@ -0,0 +1,21 @@ +#!/bin/sh + +PREVPATH=`dirname $0` + +if [ -f $PREVPATH/../../buildtools/bin/waf ]; then + WAF=../../buildtools/bin/waf +elif [ -f $PREVPATH/buildtools/bin/waf ]; then + WAF=./buildtools/bin/waf +else + echo "replace: Unable to find waf" + exit 1 +fi + +# using JOBS=1 gives maximum compatibility with +# systems like AIX which have broken threading in python +JOBS=1 +export JOBS + +cd . || exit 1 +$PYTHON $WAF configure "$@" || exit 1 +cd $PREVPATH diff --git a/ldb-2.0.8/lib/tdb/docs/README b/ldb-2.0.8/lib/tdb/docs/README new file mode 100644 index 0000000..86d46a3 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/docs/README @@ -0,0 +1,273 @@ +tdb - a trivial database system +tridge@linuxcare.com December 1999 +================================== + +This is a simple database API. It was inspired by the realisation that +in Samba we have several ad-hoc bits of code that essentially +implement small databases for sharing structures between parts of +Samba. As I was about to add another I realised that a generic +database module was called for to replace all the ad-hoc bits. + +I based the interface on gdbm. I couldn't use gdbm as we need to be +able to have multiple writers to the databases at one time. + +Compilation +----------- + +add HAVE_MMAP=1 to use mmap instead of read/write +add NOLOCK=1 to disable locking code + +Testing +------- + +Compile tdbtest.c and link with gdbm for testing. tdbtest will perform +identical operations via tdb and gdbm then make sure the result is the +same + +Also included is tdbtool, which allows simple database manipulation +on the commandline. + +tdbtest and tdbtool are not built as part of Samba, but are included +for completeness. + +Interface +--------- + +The interface is very similar to gdbm except for the following: + +- different open interface. The tdb_open call is more similar to a + traditional open() +- no tdbm_reorganise() function +- no tdbm_sync() function. No operations are cached in the library anyway +- added a tdb_traverse() function for traversing the whole database +- added transactions support + +A general rule for using tdb is that the caller frees any returned +TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA +return value called p. This is the same as gdbm. + +here is a full list of tdb functions with brief descriptions. + + +---------------------------------------------------------------------- +TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) + + open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the database + file. A flags value of O_WRONLY is invalid + + The hash size is advisory, use zero for a default value. + + return is NULL on error + + possible tdb_flags are: + TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open + TDB_INTERNAL - don't use a file, instead store the data in + memory. The filename is ignored in this case. + TDB_NOLOCK - don't do any locking + TDB_NOMMAP - don't use mmap + TDB_NOSYNC - don't synchronise transactions to disk + TDB_SEQNUM - maintain a sequence number + TDB_VOLATILE - activate the per-hashchain freelist, default 5 + TDB_ALLOW_NESTING - allow transactions to nest + TDB_DISALLOW_NESTING - disallow transactions to nest + +---------------------------------------------------------------------- +TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn) + +This is like tdb_open(), but allows you to pass an initial logging and +hash function. Be careful when passing a hash function - all users of +the database must use the same hash function or you will get data +corruption. + + +---------------------------------------------------------------------- +char *tdb_error(TDB_CONTEXT *tdb); + + return a error string for the last tdb error + +---------------------------------------------------------------------- +int tdb_close(TDB_CONTEXT *tdb); + + close a database + +---------------------------------------------------------------------- +TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); + + fetch an entry in the database given a key + if the return value has a null dptr then a error occurred + + caller must free the resulting data + +---------------------------------------------------------------------- +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); + + Hand a record to a parser function without allocating it. + + This function is meant as a fast tdb_fetch alternative for large records + that are frequently read. The "key" and "data" arguments point directly + into the tdb shared memory, they are not aligned at any boundary. + + WARNING: The parser is called while tdb holds a lock on the record. DO NOT + call other tdb routines from within the parser. Also, for good performance + you should make the parser fast to allow parallel operations. + + tdb_parse_record returns -1 if the record was not found. If the record was + found, the return value of "parser" is passed up to the caller. + +---------------------------------------------------------------------- +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); + + check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm + +---------------------------------------------------------------------- +int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, + TDB_DATA key, TDB_DATA dbuf, void *state), void *state); + + traverse the entire database - calling fn(tdb, key, data, state) on each + element. + + return -1 on error or the record count traversed + + if fn is NULL then it is not called + + a non-zero return value from fn() indicates that the traversal + should stop. Traversal callbacks may not start transactions. + + WARNING: The data buffer given to the callback fn does NOT meet the + alignment restrictions malloc gives you. + +---------------------------------------------------------------------- +int tdb_traverse_read(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, + TDB_DATA key, TDB_DATA dbuf, void *state), void *state); + + traverse the entire database - calling fn(tdb, key, data, state) on + each element, but marking the database read only during the + traversal, so any write operations will fail. This allows tdb to + use read locks, which increases the parallelism possible during the + traversal. + + return -1 on error or the record count traversed + + if fn is NULL then it is not called + + a non-zero return value from fn() indicates that the traversal + should stop. Traversal callbacks may not start transactions. + +---------------------------------------------------------------------- +TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); + + find the first entry in the database and return its key + + the caller must free the returned data + +---------------------------------------------------------------------- +TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); + + find the next entry in the database, returning its key + + the caller must free the returned data + +---------------------------------------------------------------------- +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); + + delete an entry in the database given a key + +---------------------------------------------------------------------- +int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); + + store an element in the database, replacing any existing element + with the same key + + If flag==TDB_INSERT then don't overwrite an existing entry + If flag==TDB_MODIFY then don't create a new entry + + return 0 on success, -1 on failure + +---------------------------------------------------------------------- +int tdb_writelock(TDB_CONTEXT *tdb); + + lock the database. If we already have it locked then don't do anything + +---------------------------------------------------------------------- +int tdb_writeunlock(TDB_CONTEXT *tdb); + unlock the database + +---------------------------------------------------------------------- +int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); + + lock one hash chain. This is meant to be used to reduce locking + contention - it cannot guarantee how many records will be locked + +---------------------------------------------------------------------- +int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); + + unlock one hash chain + +---------------------------------------------------------------------- +int tdb_transaction_start(TDB_CONTEXT *tdb) + + start a transaction. All operations after the transaction start can + either be committed with tdb_transaction_commit() or cancelled with + tdb_transaction_cancel(). + + If you call tdb_transaction_start() again on the same tdb context + while a transaction is in progress, then the same transaction + buffer is re-used. The number of tdb_transaction_{commit,cancel} + operations must match the number of successful + tdb_transaction_start() calls. + + Note that transactions are by default disk synchronous, and use a + recover area in the database to automatically recover the database + on the next open if the system crashes during a transaction. You + can disable the synchronous transaction recovery setup using the + TDB_NOSYNC flag, which will greatly speed up operations at the risk + of corrupting your database if the system crashes. + + Operations made within a transaction are not visible to other users + of the database until a successful commit. + +---------------------------------------------------------------------- +int tdb_transaction_cancel(TDB_CONTEXT *tdb) + + cancel a current transaction, discarding all write and lock + operations that have been made since the transaction started. + + +---------------------------------------------------------------------- +int tdb_transaction_commit(TDB_CONTEXT *tdb) + + commit a current transaction, updating the database and releasing + the transaction locks. + +---------------------------------------------------------------------- +int tdb_transaction_prepare_commit(TDB_CONTEXT *tdb) + + prepare to commit a current transaction, for two-phase commits. + Once prepared for commit, the only allowed calls are + tdb_transaction_commit() or tdb_transaction_cancel(). Preparing + allocates disk space for the pending updates, so a subsequent + commit should succeed (barring any hardware failures). + +---------------------------------------------------------------------- +int tdb_check(TDB_CONTEXT *tdb, + int (*check)(TDB_DATA key, TDB_DATA data, void *private_data), + void *private_data);) + + check the consistency of the database, calling back the check function + (if non-NULL) with each record. If some consistency check fails, or + the supplied check function returns -1, tdb_check returns -1, otherwise + 0. Note that logging function (if set) will be called with additional + information on the corruption found. diff --git a/ldb-2.0.8/lib/tdb/docs/mainpage.dox b/ldb-2.0.8/lib/tdb/docs/mainpage.dox new file mode 100644 index 0000000..d130769 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/docs/mainpage.dox @@ -0,0 +1,61 @@ +/** + +@mainpage + +This is a simple database API. It was inspired by the realisation that in Samba +we have several ad-hoc bits of code that essentially implement small databases +for sharing structures between parts of Samba. + +The interface is based on gdbm. gdbm couldn't be use as we needed to be able to +have multiple writers to the databases at one time. + +@section tdb_download Download + +You can download the latest releases of tdb from the +tdb directory on the samba public source +archive. + +You can download the latest code either via git or rsync. + +To fetch via git see the following guide: + +Using Git for Samba Development +Once you have cloned the tree switch to the master branch and cd into the source/lib/tdb directory. + +To fetch via rsync use these commands: + +
+  rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/tdb .
+  rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/replace .
+
+ +and build in tdb. It will find the replace library in the directory above +automatically. + +@section tdb_bugs Discussion and bug reports + +tdb does not currently have its own mailing list or bug tracking system. For now, +please use the +samba-technical +mailing list, and the Samba bugzilla bug +tracking system. + + +@section tdb_compilation Compilation + +add HAVE_MMAP=1 to use mmap instead of read/write +add NOLOCK=1 to disable locking code + +@section tdb_testing Testing + +Compile tdbtest.c and link with gdbm for testing. tdbtest will perform +identical operations via tdb and gdbm then make sure the result is the +same + +Also included is tdbtool, which allows simple database manipulation +on the commandline. + +tdbtest and tdbtool are not built as part of Samba, but are included +for completeness. + +*/ diff --git a/ldb-2.0.8/lib/tdb/docs/mutex.txt b/ldb-2.0.8/lib/tdb/docs/mutex.txt new file mode 100644 index 0000000..a5a7542 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/docs/mutex.txt @@ -0,0 +1,136 @@ +Tdb is a hashtable database with multiple concurrent writer and external +record lock support. For speed reasons, wherever possible tdb uses a shared +memory mapped area for data access. In its currently released form, it uses +fcntl byte-range locks to coordinate access to the data itself. + +The tdb data is organized as a hashtable. Hash collisions are dealt with by +forming a linked list of records that share a hash value. The individual +linked lists are protected across processes with 1-byte fcntl locks on the +starting pointer of the linked list representing a hash value. + +The external locking API of tdb allows one to lock individual records. Instead of +really locking individual records, the tdb API locks a complete linked list +with a fcntl lock. + +The external locking API of tdb also allows one to lock the complete database, and +ctdb uses this facility to freeze databases during a recovery. While the +so-called allrecord lock is held, all linked lists and all individual records +are frozen alltogether. Tdb achieves this by locking the complete file range +with a single fcntl lock. Individual 1-byte locks for the linked lists +conflict with this. Access to records is prevented by the one large fnctl byte +range lock. + +Fcntl locks have been chosen for tdb for two reasons: First they are portable +across all current unixes. Secondly they provide auto-cleanup. If a process +dies while holding a fcntl lock, the lock is given up as if it was explicitly +unlocked. Thus fcntl locks provide a very robust locking scheme, if a process +dies for any reason the database will not stay blocked until reboot. This +robustness is very important for long-running services, a reboot is not an +option for most users of tdb. + +Unfortunately, during stress testing, fcntl locks have turned out to be a major +problem for performance. The particular problem that was seen happens when +ctdb on a busy server does a recovery. A recovery means that ctdb has to +freeze all tdb databases for some time, usually a few seconds. This is done +with the allrecord lock. During the recovery phase on a busy server many smbd +processes try to access the tdb file with blocking fcntl calls. The specific +test in question easily reproduces 7,000 processes piling up waiting for +1-byte fcntl locks. When ctdb is done with the recovery, it gives up the +allrecord lock, covering the whole file range. All 7,000 processes waiting for +1-byte fcntl locks are woken up, trying to acquire their lock. The special +implementation of fcntl locks in Linux (up to 2013-02-12 at least) protects +all fcntl lock operations with a single system-wide spinlock. If 7,000 process +waiting for the allrecord lock to become released this leads to a thundering +herd condition, all CPUs are spinning on that single spinlock. + +Functionally the kernel is fine, eventually the thundering herd slows down and +every process correctly gets his share and locking range, but the performance +of the system while the herd is active is worse than expected. + +The thundering herd is only the worst case scenario for fcntl lock use. The +single spinlock for fcntl operations is also a performance penalty for normal +operations. In the cluster case, every read and write SMB request has to do +two fcntl calls to provide correct SMB mandatory locks. The single spinlock +is one source of serialization for the SMB read/write requests, limiting the +parallelism that can be achieved in a multi-core system. + +While trying to tune his servers, Ira Cooper, Samba Team member, found fcntl +locks to be a problem on Solaris as well. Ira pointed out that there is a +potential alternative locking mechanism that might be more scalable: Process +shared robust mutexes, as defined by Posix 2008 for example via + +http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setpshared.html +http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html + +Pthread mutexes provide one of the core mechanisms in posix threads to protect +in-process data structures from concurrent access by multiple threads. In the +Linux implementation, a pthread_mutex_t is represented by a data structure in +user space that requires no kernel calls in the uncontended case for locking +and unlocking. Locking and unlocking in the uncontended case is implemented +purely in user space with atomic CPU instructions and thus are very fast. + +The setpshared functions indicate to the kernel that the mutex is about to be +shared between processes in a common shared memory area. + +The process shared posix mutexes have the potential to replace fcntl locking +to coordinate mmap access for tdbs. However, they are missing the criticial +auto-cleanup property that fcntl provides when a process dies. A process that +dies hard while holding a shared mutex has no chance to clean up the protected +data structures and unlock the shared mutex. Thus with a pure process shared +mutex the mutex will remain locked forever until the data structures are +re-initialized from scratch. + +With the robust mutexes defined by Posix the process shared mutexes have been +extended with a limited auto-cleanup property. If a mutex has been declared +robust, when a process exits while holding that mutex, the next process trying +to lock the mutex will get the special error message EOWNERDEAD. This informs +the caller that the data structures the mutex protects are potentially corrupt +and need to be cleaned up. + +The error message EOWNERDEAD when trying to lock a mutex is an extension over +the fcntl functionality. A process that does a blocking fcntl lock call is not +informed about whether the lock was explicitly freed by a process still alive +or due to an unplanned process exit. At the time of this writing (February +2013), at least Linux and OpenSolaris also implement the robustness feature of +process-shared mutexes. + +Converting the tdb locking mechanism from fcntl to mutexes has to take care of +both types of locks that are used on tdb files. + +The easy part is to use mutexes to replace the 1-byte linked list locks +covering the individual hashes. Those can be represented by a mutex each. + +Covering the allrecord lock is more difficult. The allrecord lock uses a fcntl +lock spanning all hash list locks simultaneously. This basic functionality is +not easily possible with mutexes. A mutex carries 1 bit of information, a +fcntl lock can carry an arbitrary amount of information. + +In order to support the allrecord lock, we have an allrecord_lock variable +protected by an allrecord_mutex. The coordination between the allrecord lock +and the chainlocks works like this: + +- Getting a chain lock works like this: + + 1. get chain mutex + 2. return success if allrecord_lock is F_UNLCK (not locked) + 3. return success if allrecord_lock is F_RDLCK (locked readonly) + and we only need a read lock. + 4. release chain mutex + 5. wait for allrecord_mutex + 6. unlock allrecord_mutex + 7. goto 1. + +- Getting the allrecord lock: + + 1. get the allrecord mutex + 2. return error if allrecord_lock is not F_UNLCK (it's locked) + 3. set allrecord_lock to the desired value. + 4. in a loop: lock(blocking) / unlock each chain mutex. + 5. return success. + +- allrecord lock upgrade: + + 1. check we already have the allrecord lock with F_RDLCK. + 3. set allrecord_lock to F_WRLCK + 4. in a loop: lock(blocking) / unlock each chain mutex. + 5. return success. diff --git a/ldb-2.0.8/lib/tdb/docs/tdb.magic b/ldb-2.0.8/lib/tdb/docs/tdb.magic new file mode 100644 index 0000000..f5619e7 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/docs/tdb.magic @@ -0,0 +1,10 @@ +# Magic file(1) information about tdb files. +# +# Install this into /etc/magic or the corresponding location for your +# system, or pass as a -m argument to file(1). + +# You may use and redistribute this file without restriction. + +0 string TDB\ file TDB database +>32 lelong =0x2601196D version 6, little-endian +>>36 lelong x hash size %d bytes diff --git a/ldb-2.0.8/lib/tdb/docs/tracing.txt b/ldb-2.0.8/lib/tdb/docs/tracing.txt new file mode 100644 index 0000000..98c5db9 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/docs/tracing.txt @@ -0,0 +1,46 @@ +How And Why To Use TDB Tracing +============================== + +You can trace all TDB operations, using TDB_TRACE. It is not complete +(error conditions which expect to the logged will not always be traced +correctly, so you should set up a logging function too), but is designed +to collect benchmark-style traces to allow us to optimize TDB. + +Note: tracing is not efficient, and the trace files are huge: a +traverse of the database is particularly large! But they compress very +well with rzip (http://rzip.samba.org) + +How to gather trace files: +-------------------------- +1) Uncomment /* #define TDB_TRACE 1 */ in tdb_private.h. +2) Rebuild TDB, and everything that uses it. +3) Run something. + +Your trace files will be called .trace.. These files +will not be overwritten: if the same process reopens the same TDB, an +error will be logged and tracing will be disabled. + +How to replay trace files: +-------------------------- +1) For benchmarking, remember to rebuild tdb with #define TDB_TRACE commented + out again! +2) Grab the latest "replace_trace.c" from CCAN's tdb module (tools/ dir): + http://ccan.ozlabs.org/tarballs/tdb.tar.bz2 +3) Compile up replay_trace, munging as necessary. +4) Run replay_trace ... + +If given more than one trace file (presumably from the same tdb) +replay_trace will try to figure out the dependencies between the operations +and fire off a child to run each trace. Occasionally it gets stuck, in +which case it will add another dependency and retry. Eventually it will +give a speed value. + +replay_trace can intuit the existence of previous data in the tdb (ie. +activity prior to the trace(s) supplied) and will prepopulate as +neccessary. + +You can run --quiet for straight benchmark results, and -n to run multiple +times (this saves time, since it need only calculate dependencies once). + +Good luck! +Rusty Russell diff --git a/ldb-2.0.8/lib/tdb/doxy.config b/ldb-2.0.8/lib/tdb/doxy.config new file mode 100644 index 0000000..f55e9c3 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/doxy.config @@ -0,0 +1,1697 @@ +# Doxyfile 1.7.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = tdb + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.2.9 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even if there is only one candidate or it is obvious which candidate to choose by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = include \ + docs + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.cpp \ + *.cc \ + *.c \ + *.h \ + *.hh \ + *.hpp \ + *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = */.git/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = NO + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [0,1..20]) +# that doxygen will group on one line in the generated HTML documentation. +# Note that a value of 0 will completely suppress the enum values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NONE + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN \ + PRINTF_ATTRIBUTE(x,y)= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, svg, gif or svg. +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/ldb-2.0.8/lib/tdb/include/tdb.h b/ldb-2.0.8/lib/tdb/include/tdb.h new file mode 100644 index 0000000..825ceed --- /dev/null +++ b/ldb-2.0.8/lib/tdb/include/tdb.h @@ -0,0 +1,1025 @@ +#ifndef __TDB_H__ +#define __TDB_H__ + +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @defgroup tdb The tdb API + * + * tdb is a Trivial database. In concept, it is very much like GDBM, and BSD's + * DB except that it allows multiple simultaneous writers and uses locking + * internally to keep writers from trampling on each other. tdb is also + * extremely small. + * + * @section tdb_interface Interface + * + * The interface is very similar to gdbm except for the following: + * + *
    + *
  • different open interface. The tdb_open call is more similar to a + * traditional open()
  • + *
  • no tdbm_reorganise() function
  • + *
  • no tdbm_sync() function. No operations are cached in the library + * anyway
  • + *
  • added a tdb_traverse() function for traversing the whole database
  • + *
  • added transactions support
  • + *
+ * + * A general rule for using tdb is that the caller frees any returned TDB_DATA + * structures. Just call free(p.dptr) to free a TDB_DATA return value called p. + * This is the same as gdbm. + * + * @{ + */ + +/** Flags to tdb_store() */ +#define TDB_REPLACE 1 /** Unused */ +#define TDB_INSERT 2 /** Don't overwrite an existing entry */ +#define TDB_MODIFY 3 /** Don't create an existing entry */ + +/** Flags for tdb_open() */ +#define TDB_DEFAULT 0 /** just a readability place holder */ +#define TDB_CLEAR_IF_FIRST 1 /** If this is the first open, wipe the db */ +#define TDB_INTERNAL 2 /** Don't store on disk */ +#define TDB_NOLOCK 4 /** Don't do any locking */ +#define TDB_NOMMAP 8 /** Don't use mmap */ +#define TDB_CONVERT 16 /** Convert endian (internal use) */ +#define TDB_BIGENDIAN 32 /** Header is big-endian (internal use) */ +#define TDB_NOSYNC 64 /** Don't use synchronous transactions */ +#define TDB_SEQNUM 128 /** Maintain a sequence number */ +#define TDB_VOLATILE 256 /** Activate the per-hashchain freelist, default 5 */ +#define TDB_ALLOW_NESTING 512 /** Allow transactions to nest */ +#define TDB_DISALLOW_NESTING 1024 /** Disallow transactions to nest */ +#define TDB_INCOMPATIBLE_HASH 2048 /** Better hashing: can't be opened by tdb < 1.2.6. */ +#define TDB_MUTEX_LOCKING 4096 /** optimized locking using robust mutexes if supported, + only with tdb >= 1.3.0 and TDB_CLEAR_IF_FIRST + after checking tdb_runtime_check_for_robust_mutexes() */ + +/** The tdb error codes */ +enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, + TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY, + TDB_ERR_NESTING}; + +/** Debugging uses one of the following levels */ +enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR, + TDB_DEBUG_WARNING, TDB_DEBUG_TRACE}; + +/** The tdb data structure */ +typedef struct TDB_DATA { + unsigned char *dptr; + size_t dsize; +} TDB_DATA; + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** 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 + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/** This is the context structure that is returned from a db open. */ +typedef struct tdb_context TDB_CONTEXT; + +typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(struct tdb_context *, enum tdb_debug_level, const char *, ...) PRINTF_ATTRIBUTE(3, 4); +typedef unsigned int (*tdb_hash_func)(TDB_DATA *key); + +struct tdb_logging_context { + tdb_log_func log_fn; + void *log_private; +}; + +/** + * @brief Open the database and creating it if necessary. + * + * @param[in] name The name of the db to open. + * + * @param[in] hash_size The hash size is advisory, use zero for a default + * value. + * + * @param[in] tdb_flags The flags to use to open the db:\n\n + * TDB_CLEAR_IF_FIRST - Clear database if we are the + * only one with it open\n + * TDB_INTERNAL - Don't use a file, instead store the + * data in memory. The filename is + * ignored in this case.\n + * TDB_NOLOCK - Don't do any locking\n + * TDB_NOMMAP - Don't use mmap\n + * TDB_NOSYNC - Don't synchronise transactions to disk\n + * TDB_SEQNUM - Maintain a sequence number\n + * TDB_VOLATILE - activate the per-hashchain freelist, + * default 5.\n + * TDB_ALLOW_NESTING - Allow transactions to nest.\n + * TDB_DISALLOW_NESTING - Disallow transactions to nest.\n + * TDB_INCOMPATIBLE_HASH - Better hashing: can't be opened by tdb < 1.2.6.\n + * TDB_MUTEX_LOCKING - Optimized locking using robust mutexes if supported, + * can't be opened by tdb < 1.3.0. + * Only valid in combination with TDB_CLEAR_IF_FIRST + * after checking tdb_runtime_check_for_robust_mutexes()\n + * + * @param[in] open_flags Flags for the open(2) function. + * + * @param[in] mode The mode for the open(2) function. + * + * @return A tdb context structure, NULL on error. + */ +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode); + +/** + * @brief Open the database and creating it if necessary. + * + * This is like tdb_open(), but allows you to pass an initial logging and + * hash function. Be careful when passing a hash function - all users of the + * database must use the same hash function or you will get data corruption. + * + * @param[in] name The name of the db to open. + * + * @param[in] hash_size The hash size is advisory, use zero for a default + * value. + * + * @param[in] tdb_flags The flags to use to open the db:\n\n + * TDB_CLEAR_IF_FIRST - Clear database if we are the + * only one with it open\n + * TDB_INTERNAL - Don't use a file, instead store the + * data in memory. The filename is + * ignored in this case.\n + * TDB_NOLOCK - Don't do any locking\n + * TDB_NOMMAP - Don't use mmap\n + * TDB_NOSYNC - Don't synchronise transactions to disk\n + * TDB_SEQNUM - Maintain a sequence number\n + * TDB_VOLATILE - activate the per-hashchain freelist, + * default 5.\n + * TDB_ALLOW_NESTING - Allow transactions to nest.\n + * TDB_DISALLOW_NESTING - Disallow transactions to nest.\n + * TDB_INCOMPATIBLE_HASH - Better hashing: can't be opened by tdb < 1.2.6.\n + * TDB_MUTEX_LOCKING - Optimized locking using robust mutexes if supported, + * can't be opened by tdb < 1.3.0. + * Only valid in combination with TDB_CLEAR_IF_FIRST + * after checking tdb_runtime_check_for_robust_mutexes()\n + * + * @param[in] open_flags Flags for the open(2) function. + * + * @param[in] mode The mode for the open(2) function. + * + * @param[in] log_ctx The logging function to use. + * + * @param[in] hash_fn The hash function you want to use. + * + * @return A tdb context structure, NULL on error. + * + * @see tdb_open() + */ +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn); + +/** + * @brief Set the maximum number of dead records per hash chain. + * + * @param[in] tdb The database handle to set the maximum. + * + * @param[in] max_dead The maximum number of dead records per hash chain. + */ +void tdb_set_max_dead(struct tdb_context *tdb, int max_dead); + +/** + * @brief Reopen a tdb. + * + * This can be used after a fork to ensure that we have an independent seek + * pointer from our parent and to re-establish locks. + * + * @param[in] tdb The database to reopen. It will be free'd on error! + * + * @return 0 on success, -1 on error. + * + * @note Don't call tdb_error() after this function cause the tdb context will + * be freed on error. + */ +int tdb_reopen(struct tdb_context *tdb); + +/** + * @brief Reopen all tdb's + * + * If the parent is longlived (ie. a parent daemon architecture), we know it + * will keep it's active lock on a tdb opened with CLEAR_IF_FIRST. Thus for + * child processes we don't have to add an active lock. This is essential to + * improve performance on systems that keep POSIX locks as a non-scalable data + * structure in the kernel. + * + * @param[in] parent_longlived Whether the parent is longlived or not. + * + * @return 0 on success, -1 on error. + */ +int tdb_reopen_all(int parent_longlived); + +/** + * @brief Set a different tdb logging function. + * + * @param[in] tdb The tdb to set the logging function. + * + * @param[in] log_ctx The logging function to set. + */ +void tdb_set_logging_function(struct tdb_context *tdb, const struct tdb_logging_context *log_ctx); + +/** + * @brief Get the tdb last error code. + * + * @param[in] tdb The tdb to get the error code from. + * + * @return A TDB_ERROR code. + * + * @see TDB_ERROR + */ +enum TDB_ERROR tdb_error(struct tdb_context *tdb); + +/** + * @brief Get a error string for the last tdb error + * + * @param[in] tdb The tdb to get the error code from. + * + * @return An error string. + */ +const char *tdb_errorstr(struct tdb_context *tdb); + +/** + * @brief Fetch an entry in the database given a key. + * + * The caller must free the resulting data. + * + * @param[in] tdb The tdb to fetch the key. + * + * @param[in] key The key to fetch. + * + * @return The key entry found in the database, NULL on error with + * TDB_ERROR set. + * + * @see tdb_error() + * @see tdb_errorstr() + */ +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); + +/** + * @brief Hand a record to a parser function without allocating it. + * + * This function is meant as a fast tdb_fetch alternative for large records + * that are frequently read. The "key" and "data" arguments point directly + * into the tdb shared memory, they are not aligned at any boundary. + * + * @warning The parser is called while tdb holds a lock on the record. DO NOT + * call other tdb routines from within the parser. Also, for good performance + * you should make the parser fast to allow parallel operations. + * + * @param[in] tdb The tdb to parse the record. + * + * @param[in] key The key to parse. + * + * @param[in] parser The parser to use to parse the data. + * + * @param[in] private_data A private data pointer which is passed to the parser + * function. + * + * @return -1 if the record was not found. If the record was found, + * the return value of "parser" is passed up to the caller. + */ +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); + +/** + * @brief Delete an entry in the database given a key. + * + * @param[in] tdb The tdb to delete the key. + * + * @param[in] key The key to delete. + * + * @return 0 on success, -1 if the key doesn't exist. + */ +int tdb_delete(struct tdb_context *tdb, TDB_DATA key); + +/** + * @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] dbuf The data to store under the key. + * + * @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_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. + * + * If the entry doesn't exist, it will create a new one. + * + * @param[in] tdb The database to use. + * + * @param[in] key The key to append the data. + * + * @param[in] new_dbuf The data to append to the key. + * + * @return 0 on success, -1 on error with error code set. + * + * @see tdb_error() + * @see tdb_errorstr() + */ +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf); + +/** + * @brief Close a database. + * + * @param[in] tdb The database to close. The context will be free'd. + * + * @return 0 for success, -1 on error. + * + * @note Don't call tdb_error() after this function cause the tdb context will + * be freed on error. + */ +int tdb_close(struct tdb_context *tdb); + +/** + * @brief Find the first entry in the database and return its key. + * + * The caller must free the returned data. + * + * @param[in] tdb The database to use. + * + * @return The first entry of the database, an empty TDB_DATA entry + * if the database is empty. + */ +TDB_DATA tdb_firstkey(struct tdb_context *tdb); + +/** + * @brief Find the next entry in the database, returning its key. + * + * The caller must free the returned data. + * + * @param[in] tdb The database to use. + * + * @param[in] key The key from which you want the next key. + * + * @return The next entry of the current key, an empty TDB_DATA + * entry if there is no entry. + */ +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); + +/** + * @brief Traverse the entire database. + * + * While traversing the function fn(tdb, key, data, state) is called on each + * element. If fn is NULL then it is not called. A non-zero return value from + * fn() indicates that the traversal should stop. Traversal callbacks may not + * start transactions. + * + * @warning The data buffer given to the callback fn does NOT meet the alignment + * restrictions malloc gives you. + * + * @param[in] tdb The database to traverse. + * + * @param[in] fn The function to call on each entry. + * + * @param[in] private_data The private data which should be passed to the + * traversing function. + * + * @return The record count traversed, -1 on error. + */ +int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data); + +/** + * @brief Traverse the entire database. + * + * While traversing the database the function fn(tdb, key, data, state) is + * called on each element, but marking the database read only during the + * traversal, so any write operations will fail. This allows tdb to use read + * locks, which increases the parallelism possible during the traversal. + * + * @param[in] tdb The database to traverse. + * + * @param[in] fn The function to call on each entry. + * + * @param[in] private_data The private data which should be passed to the + * traversing function. + * + * @return The record count traversed, -1 on error. + */ +int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data); + +/** + * @brief Traverse a single hash chain + * + * Traverse a single hash chain under a single lock operation. No + * database modification is possible in the callback. + * + * This exists for background cleanup of databases. In normal + * operations, traversing a complete database can be much too + * expensive. Databases can have many chains, which will all have to + * be looked at before tdb_traverse finishes. Also tdb_traverse does a + * lot of fcntl activity to protect against concurrent record deletes. + * + * With this you can walk a fraction of the whole tdb, collect the + * entries you want to prune, leave the traverse, and then modify or + * delete the records in a subsequent step. + * + * To walk the entire database, call this function tdb_hash_size() + * times, with 0<=chain + + +2015-04-25 + + + tdbbackup + 8 + Samba + System Administration tools + 3.6 + + + + + tdbbackup + tool for backing up and for validating the integrity of samba .tdb files + + + + + tdbbackup + -s suffix + -v + -h + -n hashsize + -l + + + + + DESCRIPTION + + This tool is part of the samba + 1 suite. + + tdbbackup is a tool that may be used to backup samba .tdb + files. This tool may also be used to verify the integrity of the .tdb files prior + to samba startup or during normal operation. If it finds file damage and it finds + a prior backup the backup file will be restored. + + + + + + OPTIONS + + + + + -h + + Get help information. + + + + + -s suffix + + The -s option allows the administrator to specify a file + backup extension. This way it is possible to keep a history of tdb backup + files by using a new suffix for each backup. + + + + + -v + + The -v will check the database for damages (corrupt data) + which if detected causes the backup to be restored. + + + + + -n hashsize + + The -n option sets the hash size for the new backup tdb. + + + + + -l + + This options disables any locking, by passing TDB_NOLOCK + to tdb_open_ex(). Only use this for database files which + are not used by any other process! And also only if it is otherwise not + possible to open the database, e.g. databases which were created with + mutex locking. + + + + + + + + + COMMANDS + + GENERAL INFORMATION + + + The tdbbackup utility can safely be run at any time. It was designed so + that it can be used at any time to validate the integrity of tdb files, even during Samba + operation. Typical usage for the command will be: + + + tdbbackup [-s suffix] *.tdb + + + Before restarting samba the following command may be run to validate .tdb files: + + + tdbbackup -v [-s suffix] *.tdb + + + Samba .tdb files are stored in various locations, be sure to run backup all + .tdb file on the system. Important files includes: + + + + + secrets.tdb - usual location is in the /usr/local/samba/private + directory, or on some systems in /etc/samba. + + + + passdb.tdb - usual location is in the /usr/local/samba/private + directory, or on some systems in /etc/samba. + + + + *.tdb located in the /usr/local/samba/var directory or on some + systems in the /var/cache or /var/lib/samba directories. + + + + + + + VERSION + + This man page is correct for version 3 of the Samba suite. + + + + AUTHOR + + + The original Samba software and related utilities were created by Andrew Tridgell. + Samba is now developed by the Samba Team as an Open Source project similar to the way + the Linux kernel is developed. + + + The tdbbackup man page was written by John H Terpstra. + + + diff --git a/ldb-2.0.8/lib/tdb/man/tdbdump.8.xml b/ldb-2.0.8/lib/tdb/man/tdbdump.8.xml new file mode 100644 index 0000000..31e6888 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/man/tdbdump.8.xml @@ -0,0 +1,93 @@ + + + +2015-04-25 + + + tdbdump + 8 + Samba + System Administration tools + 3.6 + + + + + tdbdump + tool for printing the contents of a TDB file + + + + + tdbdump + -k keyname + -e + -h + filename + + + + + DESCRIPTION + + This tool is part of the samba + 1 suite. + + tdbdump is a very simple utility that 'dumps' the + contents of a TDB (Trivial DataBase) file to standard output in a + human-readable format. + + + This tool can be used when debugging problems with TDB files. It is + intended for those who are somewhat familiar with Samba internals. + + + + + OPTIONS + + + + + -h + + Get help information. + + + + + -k keyname + + The -k option restricts dumping to a single key, if found. + + + + + -e + + The -e tries to dump out from a corrupt database. Naturally, such a dump is unreliable, at best. + + + + + + + + VERSION + + This man page is correct for version 3 of the Samba suite. + + + + AUTHOR + + + The original Samba software and related utilities were created by Andrew Tridgell. + Samba is now developed by the Samba Team as an Open Source project similar to the way + the Linux kernel is developed. + + + The tdbdump man page was written by Jelmer Vernooij. + + + diff --git a/ldb-2.0.8/lib/tdb/man/tdbrestore.8.xml b/ldb-2.0.8/lib/tdb/man/tdbrestore.8.xml new file mode 100644 index 0000000..034db53 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/man/tdbrestore.8.xml @@ -0,0 +1,67 @@ + + + +2015-04-25 + + + tdbrestore + 8 + Samba + System Administration tools + 3.6 + + + + + tdbrestore + tool for creating a TDB file out of a tdbdump output + + + + + tdbrestore + tdbfilename + + + + + DESCRIPTION + + This tool is part of the samba + 1 suite. + + tdbrestore is a very simple utility that 'restores' the + contents of dump file into TDB (Trivial DataBase) file. The dump file is obtained from the tdbdump + command. + + + This tool wait on the standard input for the content of the dump and will write the tdb in the tdbfilename + parameter. + + This tool can be used for unpacking the content of tdb as backup mean. + + + + + + VERSION + + This man page is correct for version 3 of the Samba suite. + + + + AUTHOR + + + The original Samba software and related utilities were created by Andrew Tridgell. + Samba is now developed by the Samba Team as an Open Source project similar to the way + the Linux kernel is developed. + + This tool was initially written by Volker Lendecke based on an + idea by Simon McVittie. + + + The tdbrestore man page was written by Matthieu Patou. + + + diff --git a/ldb-2.0.8/lib/tdb/man/tdbtool.8.xml b/ldb-2.0.8/lib/tdb/man/tdbtool.8.xml new file mode 100644 index 0000000..045cbde --- /dev/null +++ b/ldb-2.0.8/lib/tdb/man/tdbtool.8.xml @@ -0,0 +1,275 @@ + + + +2015-04-25 + + + tdbtool + 8 + Samba + System Administration tools + 4.0 + + + + + tdbtool + manipulate the contents TDB files + + + + + + tdbtool + + + + tdbtool + -l + + TDBFILE + + + COMMANDS + + + + + + + DESCRIPTION + + This tool is part of the + samba + 1 suite. + + tdbtool a tool for displaying and + altering the contents of Samba TDB (Trivial DataBase) files. Each + of the commands listed below can be entered interactively or + provided on the command line. + + + + + OPTIONS + + + + + -l + + This options disables any locking, by passing TDB_NOLOCK + to tdb_open_ex(). Only use this for database files which + are not used by any other process! And also only if it is otherwise not + possible to open the database, e.g. databases which were created with + mutex locking. + + + + + + + + + + COMMANDS + + + + + + TDBFILE + Create a new database named + TDBFILE. + + + + + + TDBFILE + Open an existing database named + TDBFILE. + + + + + + Erase the current database. + + + + + + Dump the current database as strings. + + + + + + Dump the current database as connection records. + + + + + + Dump the current database keys as strings. + + + + + + Dump the current database keys as hex values. + + + + + + Print summary information about the + current database. + + + + + + KEY + DATA + + Insert a record into the + current database. + + + + + + KEY + TDBFILE + + Move a record from the + current database into TDBFILE. + + + + + + KEY + DATA + + Store (replace) a record in the + current database. + + + + + + KEY + DATA + + Store (replace) a record in the + current database where key and data are in hex format. + + + + + + KEY + + Show a record by key. + + + + + + KEY + + Delete a record by key. + + + + + + + Print the current database hash table and free list. + + + + + + + Print the current database and free list. + + + + + + COMMAND + + Execute the given system command. + + + + + + + + Print the first record in the current database. + + + + + + + + Print the next record in the current database. + + + + + + + + Check the integrity of the current database. + + + + + + + + Repack a database using a temporary file to remove fragmentation. + + + + + + + + Exit tdbtool. + + + + + + + + CAVEATS + The contents of the Samba TDB files are private + to the implementation and should not be altered with + tdbtool. + + + + + VERSION + This man page is correct for version 3.6 of the Samba suite. + + + + AUTHOR + + The original Samba software and related utilities were + created by Andrew Tridgell. Samba is now developed by the + Samba Team as an Open Source project similar to the way the + Linux kernel is developed. + + + diff --git a/ldb-2.0.8/lib/tdb/pytdb.c b/ldb-2.0.8/lib/tdb/pytdb.c new file mode 100644 index 0000000..74e80f9 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/pytdb.c @@ -0,0 +1,830 @@ +/* + Unix SMB/CIFS implementation. + + Python interface to tdb. + + Copyright (C) 2004-2006 Tim Potter + Copyright (C) 2007-2008 Jelmer Vernooij + + ** NOTE! The following LGPL license applies to the tdb + ** 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 + Lesser 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 . +*/ + +#include +#include "replace.h" +#include "system/filesys.h" + +/* Include tdb headers */ +#include + +#if PY_MAJOR_VERSION >= 3 +#define PyInt_FromLong PyLong_FromLong +#define PyInt_Check PyLong_Check +#define PyInt_AsLong PyLong_AsLong +#define Py_TPFLAGS_HAVE_ITER 0 +#endif + +/* discard signature of 'func' in favour of 'target_sig' */ +#define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func + +typedef struct { + PyObject_HEAD + TDB_CONTEXT *ctx; + bool closed; +} PyTdbObject; + +static PyTypeObject PyTdb; + +static void PyErr_SetTDBError(TDB_CONTEXT *tdb) +{ + PyErr_SetObject(PyExc_RuntimeError, + Py_BuildValue("(i,s)", tdb_error(tdb), tdb_errorstr(tdb))); +} + +static TDB_DATA PyBytes_AsTDB_DATA(PyObject *data) +{ + TDB_DATA ret; + ret.dptr = (unsigned char *)PyBytes_AsString(data); + ret.dsize = PyBytes_Size(data); + return ret; +} + +static PyObject *PyBytes_FromTDB_DATA(TDB_DATA data) +{ + if (data.dptr == NULL && data.dsize == 0) { + Py_RETURN_NONE; + } else { + PyObject *ret = PyBytes_FromStringAndSize((const char *)data.dptr, + data.dsize); + free(data.dptr); + return ret; + } +} + +#define PyErr_TDB_ERROR_IS_ERR_RAISE(ret, tdb) \ + if (ret != 0) { \ + PyErr_SetTDBError(tdb); \ + return NULL; \ + } + +#define PyErr_TDB_RAISE_IF_CLOSED(self) \ + if (self->closed) { \ + PyErr_SetObject(PyExc_RuntimeError, \ + Py_BuildValue("(i,s)", TDB_ERR_IO, "Database is already closed")); \ + return NULL; \ + } + +#define PyErr_TDB_RAISE_RETURN_MINUS_1_IF_CLOSED(self) \ + if (self->closed) { \ + PyErr_SetObject(PyExc_RuntimeError, \ + Py_BuildValue("(i,s)", TDB_ERR_IO, "Database is already closed")); \ + return -1; \ + } + +static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + char *name = NULL; + int hash_size = 0, tdb_flags = TDB_DEFAULT, flags = O_RDWR, mode = 0600; + TDB_CONTEXT *ctx; + PyTdbObject *ret; + const char *_kwnames[] = { "name", "hash_size", "tdb_flags", "flags", "mode", NULL }; + char **kwnames = discard_const_p(char *, _kwnames); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siiii", kwnames, &name, &hash_size, &tdb_flags, &flags, &mode)) + return NULL; + + if (name == NULL) { + tdb_flags |= TDB_INTERNAL; + } + + ctx = tdb_open(name, hash_size, tdb_flags, flags, mode); + if (ctx == NULL) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + ret = PyObject_New(PyTdbObject, &PyTdb); + if (!ret) { + tdb_close(ctx); + return NULL; + } + + ret->ctx = ctx; + ret->closed = false; + return (PyObject *)ret; +} + +static PyObject *obj_transaction_cancel(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + ret = tdb_transaction_cancel(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_transaction_commit(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_transaction_commit(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_transaction_prepare_commit(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_transaction_prepare_commit(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_transaction_start(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_transaction_start(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_reopen(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_reopen(self->ctx); + if (ret != 0) { + self->closed = true; + PyErr_SetObject(PyExc_RuntimeError, + Py_BuildValue("(i,s)", + TDB_ERR_IO, + "Failed to reopen database")); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject *obj_lockall(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_lockall(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_unlockall(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_unlockall(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_lockall_read(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_lockall_read(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_unlockall_read(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret = tdb_unlockall_read(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_close(PyTdbObject *self, PyObject *Py_UNUSED(ignored)) +{ + int ret; + if (self->closed) + Py_RETURN_NONE; + ret = tdb_close(self->ctx); + self->closed = true; + if (ret != 0) { + PyErr_SetObject(PyExc_RuntimeError, + Py_BuildValue("(i,s)", + TDB_ERR_IO, + "Failed to close database")); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject *obj_get(PyTdbObject *self, PyObject *args) +{ + TDB_DATA key; + PyObject *py_key; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "O", &py_key)) + return NULL; + + key = PyBytes_AsTDB_DATA(py_key); + if (!key.dptr) + return NULL; + + return PyBytes_FromTDB_DATA(tdb_fetch(self->ctx, key)); +} + +static PyObject *obj_append(PyTdbObject *self, PyObject *args) +{ + TDB_DATA key, data; + PyObject *py_key, *py_data; + int ret; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "OO", &py_key, &py_data)) + return NULL; + + key = PyBytes_AsTDB_DATA(py_key); + if (!key.dptr) + return NULL; + data = PyBytes_AsTDB_DATA(py_data); + if (!data.dptr) + return NULL; + + ret = tdb_append(self->ctx, key, data); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_firstkey(PyTdbObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + + return PyBytes_FromTDB_DATA(tdb_firstkey(self->ctx)); +} + +static PyObject *obj_nextkey(PyTdbObject *self, PyObject *args) +{ + TDB_DATA key; + PyObject *py_key; + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "O", &py_key)) + return NULL; + + key = PyBytes_AsTDB_DATA(py_key); + if (!key.dptr) + return NULL; + + return PyBytes_FromTDB_DATA(tdb_nextkey(self->ctx, key)); +} + +static PyObject *obj_delete(PyTdbObject *self, PyObject *args) +{ + TDB_DATA key; + PyObject *py_key; + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "O", &py_key)) + return NULL; + + key = PyBytes_AsTDB_DATA(py_key); + if (!key.dptr) + return NULL; + ret = tdb_delete(self->ctx, key); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static int obj_contains(PyTdbObject *self, PyObject *py_key) +{ + TDB_DATA key; + int ret; + PyErr_TDB_RAISE_RETURN_MINUS_1_IF_CLOSED(self); + + key = PyBytes_AsTDB_DATA(py_key); + if (!key.dptr) { + PyErr_BadArgument(); + return -1; + } + ret = tdb_exists(self->ctx, key); + if (ret) + return 1; + return 0; +} + +#if PY_MAJOR_VERSION < 3 +static PyObject *obj_has_key(PyTdbObject *self, PyObject *args) +{ + int ret; + PyObject *py_key; + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "O", &py_key)) + return NULL; + + ret = obj_contains(self, py_key); + if (ret == -1) + return NULL; + if (ret) + Py_RETURN_TRUE; + Py_RETURN_FALSE; + +} +#endif + +static PyObject *obj_store(PyTdbObject *self, PyObject *args) +{ + TDB_DATA key, value; + int ret; + int flag = TDB_REPLACE; + PyObject *py_key, *py_value; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "OO|i", &py_key, &py_value, &flag)) + return NULL; + + key = PyBytes_AsTDB_DATA(py_key); + if (!key.dptr) + return NULL; + value = PyBytes_AsTDB_DATA(py_value); + if (!value.dptr) + return NULL; + + ret = tdb_store(self->ctx, key, value, flag); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_add_flags(PyTdbObject *self, PyObject *args) +{ + unsigned flags; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "I", &flags)) + return NULL; + + tdb_add_flags(self->ctx, flags); + Py_RETURN_NONE; +} + +static PyObject *obj_remove_flags(PyTdbObject *self, PyObject *args) +{ + unsigned flags; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + if (!PyArg_ParseTuple(args, "I", &flags)) + return NULL; + + tdb_remove_flags(self->ctx, flags); + Py_RETURN_NONE; +} + +typedef struct { + PyObject_HEAD + TDB_DATA current; + PyTdbObject *iteratee; +} PyTdbIteratorObject; + +static PyObject *tdb_iter_next(PyTdbIteratorObject *self) +{ + TDB_DATA current; + PyObject *ret; + if (self->current.dptr == NULL && self->current.dsize == 0) + return NULL; + current = self->current; + self->current = tdb_nextkey(self->iteratee->ctx, self->current); + ret = PyBytes_FromTDB_DATA(current); + return ret; +} + +static void tdb_iter_dealloc(PyTdbIteratorObject *self) +{ + Py_DECREF(self->iteratee); + PyObject_Del(self); +} + +PyTypeObject PyTdbIterator = { + .tp_name = "Iterator", + .tp_basicsize = sizeof(PyTdbIteratorObject), + .tp_iternext = (iternextfunc)tdb_iter_next, + .tp_dealloc = (destructor)tdb_iter_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_iter = PyObject_SelfIter, +}; + +static PyObject *tdb_object_iter(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + PyTdbIteratorObject *ret; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + ret = PyObject_New(PyTdbIteratorObject, &PyTdbIterator); + if (!ret) + return NULL; + ret->current = tdb_firstkey(self->ctx); + ret->iteratee = self; + Py_INCREF(self); + return (PyObject *)ret; +} + +static PyObject *obj_clear(PyTdbObject *self, PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_wipe_all(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_repack(PyTdbObject *self, PyObject *Py_UNUSED(ignored)) +{ + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_repack(self->ctx); + PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_enable_seqnum(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + tdb_enable_seqnum(self->ctx); + Py_RETURN_NONE; +} + +static PyObject *obj_increment_seqnum_nonblock(PyTdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + tdb_increment_seqnum_nonblock(self->ctx); + Py_RETURN_NONE; +} + +static PyMethodDef tdb_object_methods[] = { + { "transaction_cancel", (PyCFunction)obj_transaction_cancel, METH_NOARGS, + "S.transaction_cancel() -> None\n" + "Cancel the currently active transaction." }, + { "transaction_commit", (PyCFunction)obj_transaction_commit, METH_NOARGS, + "S.transaction_commit() -> None\n" + "Commit the currently active transaction." }, + { "transaction_prepare_commit", (PyCFunction)obj_transaction_prepare_commit, METH_NOARGS, + "S.transaction_prepare_commit() -> None\n" + "Prepare to commit the currently active transaction" }, + { "transaction_start", (PyCFunction)obj_transaction_start, METH_NOARGS, + "S.transaction_start() -> None\n" + "Start a new transaction." }, + { "reopen", (PyCFunction)obj_reopen, METH_NOARGS, "Reopen this file." }, + { "lock_all", (PyCFunction)obj_lockall, METH_NOARGS, NULL }, + { "unlock_all", (PyCFunction)obj_unlockall, METH_NOARGS, NULL }, + { "read_lock_all", (PyCFunction)obj_lockall_read, METH_NOARGS, NULL }, + { "read_unlock_all", (PyCFunction)obj_unlockall_read, METH_NOARGS, NULL }, + { "close", (PyCFunction)obj_close, METH_NOARGS, NULL }, + { "get", (PyCFunction)obj_get, METH_VARARGS, "S.get(key) -> value\n" + "Fetch a value." }, + { "append", (PyCFunction)obj_append, METH_VARARGS, "S.append(key, value) -> None\n" + "Append data to an existing key." }, + { "firstkey", (PyCFunction)obj_firstkey, METH_NOARGS, "S.firstkey() -> data\n" + "Return the first key in this database." }, + { "nextkey", (PyCFunction)obj_nextkey, METH_VARARGS, "S.nextkey(key) -> data\n" + "Return the next key in this database." }, + { "delete", (PyCFunction)obj_delete, METH_VARARGS, "S.delete(key) -> None\n" + "Delete an entry." }, +#if PY_MAJOR_VERSION < 3 + { "has_key", (PyCFunction)obj_has_key, METH_VARARGS, "S.has_key(key) -> None\n" + "Check whether key exists in this database." }, +#endif + { "store", (PyCFunction)obj_store, METH_VARARGS, "S.store(key, data, flag=REPLACE) -> None" + "Store data." }, + { "add_flags", (PyCFunction)obj_add_flags, METH_VARARGS, "S.add_flags(flags) -> None" }, + { "remove_flags", (PyCFunction)obj_remove_flags, METH_VARARGS, "S.remove_flags(flags) -> None" }, +#if PY_MAJOR_VERSION >= 3 + { "keys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" }, +#else + { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" }, +#endif + { "clear", (PyCFunction)obj_clear, METH_NOARGS, "S.clear() -> None\n" + "Wipe the entire database." }, + { "repack", (PyCFunction)obj_repack, METH_NOARGS, "S.repack() -> None\n" + "Repack the entire database." }, + { "enable_seqnum", (PyCFunction)obj_enable_seqnum, METH_NOARGS, + "S.enable_seqnum() -> None" }, + { "increment_seqnum_nonblock", (PyCFunction)obj_increment_seqnum_nonblock, METH_NOARGS, + "S.increment_seqnum_nonblock() -> None" }, + { NULL } +}; + +static PyObject *obj_get_hash_size(PyTdbObject *self, void *closure) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + return PyInt_FromLong(tdb_hash_size(self->ctx)); +} + +static int obj_set_max_dead(PyTdbObject *self, PyObject *max_dead, void *closure) +{ + PyErr_TDB_RAISE_RETURN_MINUS_1_IF_CLOSED(self); + if (!PyInt_Check(max_dead)) + return -1; + tdb_set_max_dead(self->ctx, PyInt_AsLong(max_dead)); + return 0; +} + +static PyObject *obj_get_map_size(PyTdbObject *self, void *closure) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + return PyInt_FromLong(tdb_map_size(self->ctx)); +} + +static PyObject *obj_get_freelist_size(PyTdbObject *self, void *closure) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + return PyInt_FromLong(tdb_freelist_size(self->ctx)); +} + +static PyObject *obj_get_flags(PyTdbObject *self, void *closure) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + return PyInt_FromLong(tdb_get_flags(self->ctx)); +} + +static PyObject *obj_get_filename(PyTdbObject *self, void *closure) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + return PyBytes_FromString(tdb_name(self->ctx)); +} + +static PyObject *obj_get_seqnum(PyTdbObject *self, void *closure) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + return PyInt_FromLong(tdb_get_seqnum(self->ctx)); +} + +static PyObject *obj_get_text(PyTdbObject *self, void *closure) +{ + PyObject *mod, *cls, *inst; + mod = PyImport_ImportModule("_tdb_text"); + if (mod == NULL) + return NULL; + cls = PyObject_GetAttrString(mod, "TdbTextWrapper"); + if (cls == NULL) { + Py_DECREF(mod); + return NULL; + } + inst = PyObject_CallFunction(cls, discard_const_p(char, "O"), self); + Py_DECREF(mod); + Py_DECREF(cls); + return inst; +} + +static PyGetSetDef tdb_object_getsetters[] = { + { + .name = discard_const_p(char, "hash_size"), + .get = (getter)obj_get_hash_size, + }, + { + .name = discard_const_p(char, "map_size"), + .get = (getter)obj_get_map_size, + }, + { + .name = discard_const_p(char, "freelist_size"), + .get = (getter)obj_get_freelist_size, + }, + { + .name = discard_const_p(char, "flags"), + .get = (getter)obj_get_flags, + }, + { + .name = discard_const_p(char, "max_dead"), + .set = (setter)obj_set_max_dead, + }, + { + .name = discard_const_p(char, "filename"), + .get = (getter)obj_get_filename, + .doc = discard_const_p(char, "The filename of this TDB file."), + }, + { + .name = discard_const_p(char, "seqnum"), + .get = (getter)obj_get_seqnum, + }, + { + .name = discard_const_p(char, "text"), + .get = (getter)obj_get_text, + }, + { .name = NULL } +}; + +static PyObject *tdb_object_repr(PyTdbObject *self) +{ + PyErr_TDB_RAISE_IF_CLOSED(self); + if (tdb_get_flags(self->ctx) & TDB_INTERNAL) { + return PyUnicode_FromString("Tdb()"); + } else { + return PyUnicode_FromFormat("Tdb('%s')", tdb_name(self->ctx)); + } +} + +static void tdb_object_dealloc(PyTdbObject *self) +{ + if (!self->closed) + tdb_close(self->ctx); + Py_TYPE(self)->tp_free(self); +} + +static PyObject *obj_getitem(PyTdbObject *self, PyObject *key) +{ + TDB_DATA tkey, val; + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyBytes_Check(key)) { + PyErr_SetString(PyExc_TypeError, "Expected bytestring as key"); + return NULL; + } + + tkey.dptr = (unsigned char *)PyBytes_AsString(key); + tkey.dsize = PyBytes_Size(key); + + val = tdb_fetch(self->ctx, tkey); + if (val.dptr == NULL) { + /* + * if the key doesn't exist raise KeyError(key) to be + * consistent with python dict + */ + PyErr_SetObject(PyExc_KeyError, key); + return NULL; + } else { + return PyBytes_FromTDB_DATA(val); + } +} + +static int obj_setitem(PyTdbObject *self, PyObject *key, PyObject *value) +{ + TDB_DATA tkey, tval; + int ret; + PyErr_TDB_RAISE_RETURN_MINUS_1_IF_CLOSED(self); + if (!PyBytes_Check(key)) { + PyErr_SetString(PyExc_TypeError, "Expected bytestring as key"); + return -1; + } + + tkey = PyBytes_AsTDB_DATA(key); + + if (value == NULL) { + ret = tdb_delete(self->ctx, tkey); + } else { + if (!PyBytes_Check(value)) { + PyErr_SetString(PyExc_TypeError, "Expected string as value"); + return -1; + } + + tval = PyBytes_AsTDB_DATA(value); + + ret = tdb_store(self->ctx, tkey, tval, TDB_REPLACE); + } + + if (ret != 0) { + PyErr_SetTDBError(self->ctx); + return -1; + } + + return ret; +} + +static PyMappingMethods tdb_object_mapping = { + .mp_subscript = (binaryfunc)obj_getitem, + .mp_ass_subscript = (objobjargproc)obj_setitem, +}; +static PySequenceMethods tdb_object_seq = { + .sq_contains = (objobjproc)obj_contains, +}; +static PyTypeObject PyTdb = { + .tp_name = "tdb.Tdb", + .tp_basicsize = sizeof(PyTdbObject), + .tp_methods = tdb_object_methods, + .tp_getset = tdb_object_getsetters, + .tp_new = py_tdb_open, + .tp_doc = "A TDB file", + .tp_repr = (reprfunc)tdb_object_repr, + .tp_dealloc = (destructor)tdb_object_dealloc, + .tp_as_mapping = &tdb_object_mapping, + .tp_as_sequence = &tdb_object_seq, + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, + .tp_iter = PY_DISCARD_FUNC_SIG(getiterfunc,tdb_object_iter), +}; + +static PyMethodDef tdb_methods[] = { + { + .ml_name = "open", + .ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction, py_tdb_open), + .ml_flags = METH_VARARGS|METH_KEYWORDS, + .ml_doc = "open(name, hash_size=0, tdb_flags=TDB_DEFAULT, " + "flags=O_RDWR, mode=0600)\nOpen a TDB file." + }, + { .ml_name = NULL } +}; + +#define MODULE_DOC "simple key-value database that supports multiple writers." + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "tdb", + .m_doc = MODULE_DOC, + .m_size = -1, + .m_methods = tdb_methods, +}; +#endif + +PyObject* module_init(void); +PyObject* module_init(void) +{ + PyObject *m; + + if (PyType_Ready(&PyTdb) < 0) + return NULL; + + if (PyType_Ready(&PyTdbIterator) < 0) + return NULL; + +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("tdb", tdb_methods, MODULE_DOC); +#endif + if (m == NULL) + return NULL; + + PyModule_AddIntConstant(m, "REPLACE", TDB_REPLACE); + PyModule_AddIntConstant(m, "INSERT", TDB_INSERT); + PyModule_AddIntConstant(m, "MODIFY", TDB_MODIFY); + + PyModule_AddIntConstant(m, "DEFAULT", TDB_DEFAULT); + PyModule_AddIntConstant(m, "CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST); + PyModule_AddIntConstant(m, "INTERNAL", TDB_INTERNAL); + PyModule_AddIntConstant(m, "NOLOCK", TDB_NOLOCK); + PyModule_AddIntConstant(m, "NOMMAP", TDB_NOMMAP); + PyModule_AddIntConstant(m, "CONVERT", TDB_CONVERT); + PyModule_AddIntConstant(m, "BIGENDIAN", TDB_BIGENDIAN); + PyModule_AddIntConstant(m, "NOSYNC", TDB_NOSYNC); + PyModule_AddIntConstant(m, "SEQNUM", TDB_SEQNUM); + PyModule_AddIntConstant(m, "VOLATILE", TDB_VOLATILE); + PyModule_AddIntConstant(m, "ALLOW_NESTING", TDB_ALLOW_NESTING); + PyModule_AddIntConstant(m, "DISALLOW_NESTING", TDB_DISALLOW_NESTING); + PyModule_AddIntConstant(m, "INCOMPATIBLE_HASH", TDB_INCOMPATIBLE_HASH); + + PyModule_AddStringConstant(m, "__docformat__", "restructuredText"); + + PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION); + + Py_INCREF(&PyTdb); + PyModule_AddObject(m, "Tdb", (PyObject *)&PyTdb); + + Py_INCREF(&PyTdbIterator); + + return m; +} + + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC PyInit_tdb(void); +PyMODINIT_FUNC PyInit_tdb(void) +{ + return module_init(); +} +#else +void inittdb(void); +void inittdb(void) +{ + module_init(); +} +#endif diff --git a/ldb-2.0.8/lib/tdb/python/tdbdump.py b/ldb-2.0.8/lib/tdb/python/tdbdump.py new file mode 100644 index 0000000..306a950 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/python/tdbdump.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# Trivial reimplementation of tdbdump in Python + +from __future__ import print_function +import tdb, sys + +if len(sys.argv) < 2: + print("Usage: tdbdump.py ") + sys.exit(1) + +db = tdb.Tdb(sys.argv[1]) +for (k, v) in db.items(): + print("{\nkey(%d) = %r\ndata(%d) = %r\n}" % (len(k), k, len(v), v)) diff --git a/ldb-2.0.8/lib/tdb/python/tests/simple.py b/ldb-2.0.8/lib/tdb/python/tests/simple.py new file mode 100644 index 0000000..312d587 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/python/tests/simple.py @@ -0,0 +1,311 @@ +#!/usr/bin/env python3 +# Some simple tests for the Python bindings for TDB +# Note that this tests the interface of the Python bindings +# It does not test tdb itself. +# +# Copyright (C) 2007-2008 Jelmer Vernooij +# Published under the GNU LGPLv3 or later + +import sys +import os +import tempfile +from unittest import TestCase + +import tdb + + +class OpenTdbTests(TestCase): + + def test_nonexistent_read(self): + self.assertRaises(IOError, tdb.Tdb, "/some/nonexistent/file", 0, + tdb.DEFAULT, os.O_RDWR) + +class CloseTdbTests(TestCase): + + def test_double_close(self): + self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, + os.O_CREAT|os.O_RDWR) + self.assertNotEqual(None, self.tdb) + + # ensure that double close does not crash python + self.tdb.close() + self.tdb.close() + + # Check that further operations do not crash python + self.assertRaises(RuntimeError, lambda: self.tdb.transaction_start()) + + self.assertRaises(RuntimeError, lambda: self.tdb["bar"]) + + +class InternalTdbTests(TestCase): + + def test_repr(self): + self.tdb = tdb.Tdb() + + # repr used to crash on internal db + self.assertEqual(repr(self.tdb), "Tdb()") + + +class CommonTdbTests(TestCase): + """Tests common to both the text & bytes interfaces""" + + use_text = False + + def setUp(self): + super(CommonTdbTests, self).setUp() + self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, + os.O_CREAT|os.O_RDWR) + self.assertNotEqual(None, self.tdb) + if self.use_text: + self.tdb = self.tdb.text + + def test_lockall(self): + self.tdb.lock_all() + + def test_max_dead(self): + self.tdb.max_dead = 20 + + def test_unlockall(self): + self.tdb.lock_all() + self.tdb.unlock_all() + + def test_lockall_read(self): + self.tdb.read_lock_all() + self.tdb.read_unlock_all() + + def test_reopen(self): + self.tdb.reopen() + + def test_hash_size(self): + self.tdb.hash_size + + def test_map_size(self): + self.tdb.map_size + + def test_freelist_size(self): + self.tdb.freelist_size + + def test_name(self): + self.tdb.filename + + def test_add_flags(self): + self.tdb.add_flags(tdb.NOMMAP) + self.tdb.remove_flags(tdb.NOMMAP) + + +class TextCommonTdbTests(CommonTdbTests): + + use_text = True + + +class SimpleTdbTests(TestCase): + + def setUp(self): + super(SimpleTdbTests, self).setUp() + self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, + os.O_CREAT|os.O_RDWR) + self.assertNotEqual(None, self.tdb) + + def test_repr(self): + self.assertTrue(repr(self.tdb).startswith("Tdb('")) + + def test_store(self): + self.tdb.store(b"bar", b"bla") + self.assertEqual(b"bla", self.tdb.get(b"bar")) + + def test_getitem(self): + self.tdb[b"bar"] = b"foo" + self.tdb.reopen() + self.assertEqual(b"foo", self.tdb[b"bar"]) + + def test_delete(self): + self.tdb[b"bar"] = b"foo" + del self.tdb[b"bar"] + self.assertRaises(KeyError, lambda: self.tdb[b"bar"]) + + def test_contains(self): + self.tdb[b"bla"] = b"bloe" + self.assertTrue(b"bla" in self.tdb) + self.assertFalse(b"qwertyuiop" in self.tdb) + if sys.version_info < (3, 0): + self.assertTrue(self.tdb.has_key(b"bla")) + self.assertFalse(self.tdb.has_key(b"qwertyuiop")) + + def test_keyerror(self): + self.assertRaises(KeyError, lambda: self.tdb[b"bla"]) + + def test_iterator(self): + self.tdb[b"bla"] = b"1" + self.tdb[b"brainslug"] = b"2" + l = list(self.tdb) + l.sort() + self.assertEqual([b"bla", b"brainslug"], l) + + def test_transaction_cancel(self): + self.tdb[b"bloe"] = b"2" + self.tdb.transaction_start() + self.tdb[b"bloe"] = b"1" + self.tdb.transaction_cancel() + self.assertEqual(b"2", self.tdb[b"bloe"]) + + def test_transaction_commit(self): + self.tdb[b"bloe"] = b"2" + self.tdb.transaction_start() + self.tdb[b"bloe"] = b"1" + self.tdb.transaction_commit() + self.assertEqual(b"1", self.tdb[b"bloe"]) + + def test_transaction_prepare_commit(self): + self.tdb[b"bloe"] = b"2" + self.tdb.transaction_start() + self.tdb[b"bloe"] = b"1" + self.tdb.transaction_prepare_commit() + self.tdb.transaction_commit() + self.assertEqual(b"1", self.tdb[b"bloe"]) + + def test_iterkeys(self): + self.tdb[b"bloe"] = b"2" + self.tdb[b"bla"] = b"25" + if sys.version_info >= (3, 0): + i = self.tdb.keys() + else: + i = self.tdb.iterkeys() + self.assertEqual(set([b"bloe", b"bla"]), set([next(i), next(i)])) + + def test_clear(self): + self.tdb[b"bloe"] = b"2" + self.tdb[b"bla"] = b"25" + self.assertEqual(2, len(list(self.tdb))) + self.tdb.clear() + self.assertEqual(0, len(list(self.tdb))) + + def test_repack(self): + self.tdb[b"foo"] = b"abc" + self.tdb[b"bar"] = b"def" + del self.tdb[b"foo"] + self.tdb.repack() + + def test_seqnum(self): + self.tdb.enable_seqnum() + seq1 = self.tdb.seqnum + self.tdb.increment_seqnum_nonblock() + seq2 = self.tdb.seqnum + self.assertEqual(seq2-seq1, 1) + + def test_len(self): + self.assertEqual(0, len(list(self.tdb))) + self.tdb[b"entry"] = b"value" + self.assertEqual(1, len(list(self.tdb))) + + +class TdbTextTests(TestCase): + + def setUp(self): + super(TdbTextTests, self).setUp() + self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, + os.O_CREAT|os.O_RDWR) + self.assertNotEqual(None, self.tdb) + + def test_repr(self): + self.assertTrue(repr(self.tdb).startswith("Tdb('")) + + def test_store(self): + self.tdb.text.store("bar", "bla") + self.assertEqual("bla", self.tdb.text.get("bar")) + + def test_getitem(self): + self.tdb.text["bar"] = "foo" + self.tdb.reopen() + self.assertEqual("foo", self.tdb.text["bar"]) + + def test_delete(self): + self.tdb.text["bar"] = "foo" + del self.tdb.text["bar"] + self.assertRaises(KeyError, lambda: self.tdb.text["bar"]) + + def test_contains(self): + self.tdb.text["bla"] = "bloe" + self.assertTrue("bla" in self.tdb.text) + self.assertFalse("qwertyuiop" in self.tdb.text) + if sys.version_info < (3, 0): + self.assertTrue(self.tdb.text.has_key("bla")) + self.assertFalse(self.tdb.text.has_key("qwertyuiop")) + + def test_keyerror(self): + self.assertRaises(KeyError, lambda: self.tdb.text["bla"]) + + def test_iterator(self): + self.tdb.text["bla"] = "1" + self.tdb.text["brainslug"] = "2" + l = list(self.tdb.text) + l.sort() + self.assertEqual(["bla", "brainslug"], l) + + def test_transaction_cancel(self): + self.tdb.text["bloe"] = "2" + self.tdb.transaction_start() + self.tdb.text["bloe"] = "1" + self.tdb.transaction_cancel() + self.assertEqual("2", self.tdb.text["bloe"]) + + def test_transaction_commit(self): + self.tdb.text["bloe"] = "2" + self.tdb.transaction_start() + self.tdb.text["bloe"] = "1" + self.tdb.transaction_commit() + self.assertEqual("1", self.tdb.text["bloe"]) + + def test_transaction_prepare_commit(self): + self.tdb.text["bloe"] = "2" + self.tdb.transaction_start() + self.tdb.text["bloe"] = "1" + self.tdb.transaction_prepare_commit() + self.tdb.transaction_commit() + self.assertEqual("1", self.tdb.text["bloe"]) + + def test_iterkeys(self): + self.tdb.text["bloe"] = "2" + self.tdb.text["bla"] = "25" + if sys.version_info >= (3, 0): + i = self.tdb.text.keys() + else: + i = self.tdb.text.iterkeys() + self.assertEqual(set(["bloe", "bla"]), set([next(i), next(i)])) + + def test_clear(self): + self.tdb.text["bloe"] = "2" + self.tdb.text["bla"] = "25" + self.assertEqual(2, len(list(self.tdb))) + self.tdb.clear() + self.assertEqual(0, len(list(self.tdb))) + + def test_repack(self): + self.tdb.text["foo"] = "abc" + self.tdb.text["bar"] = "def" + del self.tdb.text["foo"] + self.tdb.repack() + + def test_len(self): + self.assertEqual(0, len(list(self.tdb.text))) + self.tdb.text["entry"] = "value" + self.assertEqual(1, len(list(self.tdb.text))) + + def test_text_and_binary(self): + text = u'\xfa\u0148\xef\xe7\xf8\xf0\xea' + bytestr = text.encode('utf-8') + self.tdb[b"entry"] = bytestr + self.tdb.text[u"entry2"] = text + self.assertEqual(self.tdb.text["entry"], text) + self.assertEqual(self.tdb[b"entry2"], bytestr) + assert self.tdb.text.raw == self.tdb + + +class VersionTests(TestCase): + + def test_present(self): + self.assertTrue(isinstance(tdb.__version__, str)) + + +if __name__ == '__main__': + import unittest + unittest.TestProgram() diff --git a/ldb-2.0.8/lib/tdb/tdb.pc.in b/ldb-2.0.8/lib/tdb/tdb.pc.in new file mode 100644 index 0000000..b78419e --- /dev/null +++ b/ldb-2.0.8/lib/tdb/tdb.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: tdb +Description: A trivial database +Version: @PACKAGE_VERSION@ +Libs: @LIB_RPATH@ -L${libdir} -ltdb +Cflags: -I${includedir} +URL: http://tdb.samba.org/ diff --git a/ldb-2.0.8/lib/tdb/test/circular_chain.tdb b/ldb-2.0.8/lib/tdb/test/circular_chain.tdb new file mode 100644 index 0000000..1e143d3 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/circular_chain.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/circular_freelist.tdb b/ldb-2.0.8/lib/tdb/test/circular_freelist.tdb new file mode 100644 index 0000000..f1c85e5 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/circular_freelist.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/external-agent.c b/ldb-2.0.8/lib/tdb/test/external-agent.c new file mode 100644 index 0000000..3c59c06 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/external-agent.c @@ -0,0 +1,224 @@ +#include "external-agent.h" +#include "lock-tracking.h" +#include "logging.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "../common/tdb_private.h" +#include "tap-interface.h" +#include +#include + +static struct tdb_context *tdb; + +static enum agent_return do_operation(enum operation op, const char *name) +{ + TDB_DATA k; + enum agent_return ret; + TDB_DATA data; + + if (op != OPEN && op != OPEN_WITH_CLEAR_IF_FIRST && !tdb) { + diag("external: No tdb open!"); + return OTHER_FAILURE; + } + + k.dptr = discard_const_p(uint8_t, name); + k.dsize = strlen(name); + + locking_would_block = 0; + switch (op) { + case OPEN: + if (tdb) { + diag("Already have tdb %s open", tdb_name(tdb)); + return OTHER_FAILURE; + } + tdb = tdb_open_ex(name, 0, TDB_DEFAULT, O_RDWR, 0, + &taplogctx, NULL); + if (!tdb) { + if (!locking_would_block) + diag("Opening tdb gave %s", strerror(errno)); + ret = OTHER_FAILURE; + } else + ret = SUCCESS; + break; + case OPEN_WITH_CLEAR_IF_FIRST: + if (tdb) + return OTHER_FAILURE; + tdb = tdb_open_ex(name, 0, TDB_CLEAR_IF_FIRST, O_RDWR, 0, + &taplogctx, NULL); + ret = tdb ? SUCCESS : OTHER_FAILURE; + break; + case TRANSACTION_START: + ret = tdb_transaction_start(tdb) == 0 ? SUCCESS : OTHER_FAILURE; + break; + case FETCH: + data = tdb_fetch(tdb, k); + if (data.dptr == NULL) { + if (tdb_error(tdb) == TDB_ERR_NOEXIST) + ret = FAILED; + else + ret = OTHER_FAILURE; + } else if (data.dsize != k.dsize + || memcmp(data.dptr, k.dptr, k.dsize) != 0) { + ret = OTHER_FAILURE; + } else { + ret = SUCCESS; + } + free(data.dptr); + break; + case STORE: + ret = tdb_store(tdb, k, k, 0) == 0 ? SUCCESS : OTHER_FAILURE; + break; + case TRANSACTION_COMMIT: + ret = tdb_transaction_commit(tdb)==0 ? SUCCESS : OTHER_FAILURE; + break; + case CHECK: + ret = tdb_check(tdb, NULL, NULL) == 0 ? SUCCESS : OTHER_FAILURE; + break; + case NEEDS_RECOVERY: + ret = tdb_needs_recovery(tdb) ? SUCCESS : FAILED; + break; + case CLOSE: + ret = tdb_close(tdb) == 0 ? SUCCESS : OTHER_FAILURE; + tdb = NULL; + break; + case PING: + ret = SUCCESS; + break; + case UNMAP: + ret = tdb_munmap(tdb) == 0 ? SUCCESS : OTHER_FAILURE; + if (ret == SUCCESS) { + tdb->flags |= TDB_NOMMAP; + } + break; + default: + ret = OTHER_FAILURE; + } + + if (locking_would_block) + ret = WOULD_HAVE_BLOCKED; + + return ret; +} + +struct agent { + int cmdfd, responsefd; + pid_t pid; +}; + +/* Do this before doing any tdb stuff. Return handle, or NULL. */ +struct agent *prepare_external_agent(void) +{ + int ret; + int command[2], response[2]; + char name[1+PATH_MAX]; + struct agent *agent = malloc(sizeof(*agent)); + + if (pipe(command) != 0 || pipe(response) != 0) { + fprintf(stderr, "pipe failed: %s\n", strerror(errno)); + exit(1); + } + + agent->pid = fork(); + if (agent->pid < 0) { + fprintf(stderr, "fork failed: %s\n", strerror(errno)); + exit(1); + } + + if (agent->pid != 0) { + close(command[0]); + close(response[1]); + agent->cmdfd = command[1]; + agent->responsefd = response[0]; + return agent; + } + + close(command[1]); + close(response[0]); + + /* We want to fail, not block. */ + nonblocking_locks = true; + log_prefix = "external: "; + while ((ret = read(command[0], name, sizeof(name))) > 0) { + enum agent_return result; + + result = do_operation(name[0], name+1); + if (write(response[1], &result, sizeof(result)) + != sizeof(result)) + abort(); + } + exit(0); +} + +void shutdown_agent(struct agent *agent) +{ + pid_t p; + + close(agent->cmdfd); + close(agent->responsefd); + p = waitpid(agent->pid, NULL, WNOHANG); + if (p == 0) { + kill(agent->pid, SIGKILL); + } + waitpid(agent->pid, NULL, 0); + free(agent); +} + +/* Ask the external agent to try to do an operation. */ +enum agent_return external_agent_operation(struct agent *agent, + enum operation op, + const char *name) +{ + enum agent_return res; + unsigned int len; + char *string; + + if (!name) + name = ""; + len = 1 + strlen(name) + 1; + string = malloc(len); + + string[0] = op; + 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)) + res = AGENT_DIED; + + free(string); + return res; +} + +const char *agent_return_name(enum agent_return ret) +{ + return ret == SUCCESS ? "SUCCESS" + : ret == WOULD_HAVE_BLOCKED ? "WOULD_HAVE_BLOCKED" + : ret == AGENT_DIED ? "AGENT_DIED" + : ret == FAILED ? "FAILED" + : ret == OTHER_FAILURE ? "OTHER_FAILURE" + : "**INVALID**"; +} + +const char *operation_name(enum operation op) +{ + switch (op) { + case OPEN: return "OPEN"; + case OPEN_WITH_CLEAR_IF_FIRST: return "OPEN_WITH_CLEAR_IF_FIRST"; + case TRANSACTION_START: return "TRANSACTION_START"; + case FETCH: return "FETCH"; + case STORE: return "STORE"; + case TRANSACTION_COMMIT: return "TRANSACTION_COMMIT"; + case CHECK: return "CHECK"; + case NEEDS_RECOVERY: return "NEEDS_RECOVERY"; + case CLOSE: return "CLOSE"; + case PING: return "PING"; + case UNMAP: return "UNMAP"; + } + return "**INVALID**"; +} diff --git a/ldb-2.0.8/lib/tdb/test/external-agent.h b/ldb-2.0.8/lib/tdb/test/external-agent.h new file mode 100644 index 0000000..de9d0ac --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/external-agent.h @@ -0,0 +1,44 @@ +#ifndef TDB_TEST_EXTERNAL_AGENT_H +#define TDB_TEST_EXTERNAL_AGENT_H + +/* For locking tests, we need a different process to try things at + * various times. */ +enum operation { + OPEN, + OPEN_WITH_CLEAR_IF_FIRST, + TRANSACTION_START, + FETCH, + STORE, + TRANSACTION_COMMIT, + CHECK, + NEEDS_RECOVERY, + CLOSE, + PING, + UNMAP, +}; + +/* Do this before doing any tdb stuff. Return handle, or -1. */ +struct agent *prepare_external_agent(void); +void shutdown_agent(struct agent *agent); + +enum agent_return { + SUCCESS, + WOULD_HAVE_BLOCKED, + AGENT_DIED, + FAILED, /* For fetch, or NEEDS_RECOVERY */ + OTHER_FAILURE, +}; + +/* Ask the external agent to try to do an operation. + * name == tdb name for OPEN/OPEN_WITH_CLEAR_IF_FIRST, + * record name for FETCH/STORE (store stores name as data too) + */ +enum agent_return external_agent_operation(struct agent *handle, + enum operation op, + const char *name); + +/* Mapping enum -> string. */ +const char *agent_return_name(enum agent_return ret); +const char *operation_name(enum operation op); + +#endif /* TDB_TEST_EXTERNAL_AGENT_H */ diff --git a/ldb-2.0.8/lib/tdb/test/jenkins-be-hash.tdb b/ldb-2.0.8/lib/tdb/test/jenkins-be-hash.tdb new file mode 100644 index 0000000..b652840 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/jenkins-be-hash.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/jenkins-le-hash.tdb b/ldb-2.0.8/lib/tdb/test/jenkins-le-hash.tdb new file mode 100644 index 0000000..007e0a3 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/jenkins-le-hash.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/lock-tracking.c b/ldb-2.0.8/lib/tdb/test/lock-tracking.c new file mode 100644 index 0000000..b2f092c --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/lock-tracking.c @@ -0,0 +1,157 @@ +/* We save the locks so we can reaquire them. */ +#include "../common/tdb_private.h" +#include +#include +#include +#include +#include "tap-interface.h" +#include "lock-tracking.h" + +struct testlock { + struct testlock *next; + unsigned int off; + unsigned int len; + int type; +}; +static struct testlock *testlocks; +int locking_errors = 0; +bool suppress_lockcheck = false; +bool nonblocking_locks; +int locking_would_block = 0; +void (*unlock_callback)(int fd); + +int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) +{ + va_list ap; + int ret, arg3; + struct flock *fl; + bool may_block = false; + + if (cmd != F_SETLK && cmd != F_SETLKW) { + /* This may be totally bogus, but we don't know in general. */ + va_start(ap, cmd); + arg3 = va_arg(ap, int); + va_end(ap); + + return fcntl(fd, cmd, arg3); + } + + va_start(ap, cmd); + fl = va_arg(ap, struct flock *); + va_end(ap); + + if (cmd == F_SETLKW && nonblocking_locks) { + cmd = F_SETLK; + may_block = true; + } + ret = fcntl(fd, cmd, fl); + + /* Detect when we failed, but might have been OK if we waited. */ + if (may_block && ret == -1 && (errno == EAGAIN || errno == EACCES)) { + locking_would_block++; + } + + if (fl->l_type == F_UNLCK) { + struct testlock **l; + struct testlock *old = NULL; + + for (l = &testlocks; *l; l = &(*l)->next) { + if ((*l)->off == fl->l_start + && (*l)->len == fl->l_len) { + if (ret == 0) { + old = *l; + *l = (*l)->next; + free(old); + } + break; + } + if (((*l)->off == fl->l_start) + && ((*l)->len == 0) + && (ret == 0)) { + /* + * Remove a piece from the start of the + * allrecord_lock + */ + old = *l; + (*l)->off += fl->l_len; + break; + } + } + if (!old && !suppress_lockcheck) { + diag("Unknown unlock %u@%u - %i", + (int)fl->l_len, (int)fl->l_start, ret); + locking_errors++; + } + } else { + struct testlock *new, *i; + unsigned int fl_end = fl->l_start + fl->l_len; + if (fl->l_len == 0) + fl_end = (unsigned int)-1; + + /* Check for overlaps: we shouldn't do this. */ + for (i = testlocks; i; i = i->next) { + unsigned int i_end = i->off + i->len; + if (i->len == 0) + i_end = (unsigned int)-1; + + if (fl->l_start >= i->off && fl->l_start < i_end) + break; + if (fl_end >= i->off && fl_end < i_end) + break; + + /* tdb_allrecord_lock does this, handle adjacent: */ + if (fl->l_start == i_end && fl->l_type == i->type) { + if (ret == 0) { + i->len = fl->l_len + ? i->len + fl->l_len + : 0; + } + goto done; + } + } + if (i) { + /* Special case: upgrade of allrecord lock. */ + if (i->type == F_RDLCK && fl->l_type == F_WRLCK + && i->off == FREELIST_TOP + && fl->l_start == FREELIST_TOP + && i->len == 0 + && fl->l_len == 0) { + if (ret == 0) + i->type = F_WRLCK; + goto done; + } + if (!suppress_lockcheck) { + diag("%s testlock %u@%u overlaps %u@%u", + fl->l_type == F_WRLCK ? "write" : "read", + (int)fl->l_len, (int)fl->l_start, + i->len, (int)i->off); + locking_errors++; + } + } + + if (ret == 0) { + new = malloc(sizeof *new); + new->off = fl->l_start; + new->len = fl->l_len; + new->type = fl->l_type; + new->next = testlocks; + testlocks = new; + } + } +done: + if (ret == 0 && fl->l_type == F_UNLCK && unlock_callback) + unlock_callback(fd); + return ret; +} + +unsigned int forget_locking(void) +{ + unsigned int num = 0; + while (testlocks) { + struct testlock *next = testlocks->next; + free(testlocks); + testlocks = next; + num++; + } + return num; +} diff --git a/ldb-2.0.8/lib/tdb/test/lock-tracking.h b/ldb-2.0.8/lib/tdb/test/lock-tracking.h new file mode 100644 index 0000000..f2c9c44 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/lock-tracking.h @@ -0,0 +1,25 @@ +#ifndef LOCK_TRACKING_H +#define LOCK_TRACKING_H +#include + +/* Set this if you want a callback after fnctl unlock. */ +extern void (*unlock_callback)(int fd); + +/* Replacement fcntl. */ +int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ); + +/* Discard locking info: returns number of locks outstanding. */ +unsigned int forget_locking(void); + +/* Number of errors in locking. */ +extern int locking_errors; + +/* Suppress lock checking. */ +extern bool suppress_lockcheck; + +/* Make all locks non-blocking. */ +extern bool nonblocking_locks; + +/* Number of times we failed a lock because we made it non-blocking. */ +extern int locking_would_block; +#endif /* LOCK_TRACKING_H */ diff --git a/ldb-2.0.8/lib/tdb/test/logging.c b/ldb-2.0.8/lib/tdb/test/logging.c new file mode 100644 index 0000000..dfab486 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/logging.c @@ -0,0 +1,33 @@ +#include "logging.h" +#include "tap-interface.h" +#include +#include +#include +#include + +bool suppress_logging = false; +const char *log_prefix = ""; + +/* Turn log messages into tap diag messages. */ +static void taplog(struct tdb_context *tdb, + enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + char line[200]; + + if (suppress_logging) + return; + + va_start(ap, fmt); + vsprintf(line, fmt, ap); + va_end(ap); + + /* Strip trailing \n: diag adds it. */ + if (line[0] && line[strlen(line)-1] == '\n') + diag("%s%.*s", log_prefix, (unsigned)strlen(line)-1, line); + else + diag("%s%s", log_prefix, line); +} + +struct tdb_logging_context taplogctx = { taplog, NULL }; diff --git a/ldb-2.0.8/lib/tdb/test/logging.h b/ldb-2.0.8/lib/tdb/test/logging.h new file mode 100644 index 0000000..89e77b2 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/logging.h @@ -0,0 +1,11 @@ +#ifndef TDB_TEST_LOGGING_H +#define TDB_TEST_LOGGING_H +#include "replace.h" +#include "../include/tdb.h" +#include + +extern bool suppress_logging; +extern const char *log_prefix; +extern struct tdb_logging_context taplogctx; + +#endif /* TDB_TEST_LOGGING_H */ diff --git a/ldb-2.0.8/lib/tdb/test/old-nohash-be.tdb b/ldb-2.0.8/lib/tdb/test/old-nohash-be.tdb new file mode 100644 index 0000000..1c49116 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/old-nohash-be.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/old-nohash-le.tdb b/ldb-2.0.8/lib/tdb/test/old-nohash-le.tdb new file mode 100644 index 0000000..0655072 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/old-nohash-le.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/run-3G-file.c b/ldb-2.0.8/lib/tdb/test/run-3G-file.c new file mode 100644 index 0000000..79e291b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-3G-file.c @@ -0,0 +1,145 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +static int tdb_expand_file_sparse(struct tdb_context *tdb, + tdb_off_t size, + tdb_off_t addition) +{ + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (tdb_ftruncate(tdb, size+addition) == -1) { + char b = 0; + ssize_t written = tdb_pwrite(tdb, &b, 1, (size+addition) - 1); + if (written == 0) { + /* try once more, potentially revealing errno */ + written = tdb_pwrite(tdb, &b, 1, (size+addition) - 1); + } + if (written == 0) { + /* again - give up, guessing errno */ + errno = ENOSPC; + } + if (written != 1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } + } + + return 0; +} + +static const struct tdb_methods large_io_methods = { + tdb_read, + tdb_write, + tdb_next_hash_chain, + tdb_notrans_oob, + tdb_expand_file_sparse +}; + +static int test_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, + void *_data) +{ + TDB_DATA *expect = _data; + ok1(key.dsize == strlen("hi")); + ok1(memcmp(key.dptr, "hi", strlen("hi")) == 0); + ok1(data.dsize == expect->dsize); + ok1(memcmp(data.dptr, expect->dptr, data.dsize) == 0); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, orig_data, data; + uint32_t hashval; + tdb_off_t rec_ptr; + struct tdb_record rec; + int ret; + + plan_tests(24); + tdb = tdb_open_ex("run-36-file.tdb", 1024, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + ok1(tdb); + tdb->methods = &large_io_methods; + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + orig_data.dsize = strlen("world"); + orig_data.dptr = discard_const_p(uint8_t, "world"); + + /* Enlarge the file (internally multiplies by 2). */ + ret = tdb_expand(tdb, 1500000000); +#ifdef HAVE_INCOHERENT_MMAP + /* This can fail due to mmap failure on 32 bit systems. */ + if (ret == -1) { + /* These should now fail. */ + ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == -1); + data = tdb_fetch(tdb, key); + ok1(data.dptr == NULL); + ok1(tdb_traverse(tdb, test_traverse, &orig_data) == -1); + ok1(tdb_delete(tdb, key) == -1); + ok1(tdb_traverse(tdb, test_traverse, NULL) == -1); + /* Skip the rest... */ + for (ret = 0; ret < 24 - 6; ret++) + ok1(1); + tdb_close(tdb); + return exit_status(); + } +#endif + ok1(ret == 0); + + /* Put an entry in, and check it. */ + ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == 0); + + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + + /* That currently fills at the end, make sure that's true. */ + hashval = tdb->hash_fn(&key); + rec_ptr = tdb_find_lock_hash(tdb, key, hashval, F_RDLCK, &rec); + ok1(rec_ptr); + ok1(rec_ptr > 2U*1024*1024*1024); + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + + /* Traverse must work. */ + ok1(tdb_traverse(tdb, test_traverse, &orig_data) == 1); + + /* Delete should work. */ + ok1(tdb_delete(tdb, key) == 0); + + ok1(tdb_traverse(tdb, test_traverse, NULL) == 0); + + /* Transactions should work. */ + ok1(tdb_transaction_start(tdb) == 0); + ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == 0); + + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + ok1(tdb_transaction_commit(tdb) == 0); + + ok1(tdb_traverse(tdb, test_traverse, &orig_data) == 1); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-allrecord-traverse-deadlock.c b/ldb-2.0.8/lib/tdb/test/run-allrecord-traverse-deadlock.c new file mode 100644 index 0000000..2c58206 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-allrecord-traverse-deadlock.c @@ -0,0 +1,203 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include +#include "logging.h" + +static void do_allrecord_lock(const char *name, int tdb_flags, int up, + int down) +{ + struct tdb_context *tdb; + int ret; + ssize_t nread, nwritten; + char c = 0; + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_lockall(tdb); + ok(ret == 0, "tdb_lockall should succeed"); + + nwritten = write(up, &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(down, &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + ret = tdb_traverse(tdb, NULL, NULL); + ok(ret == -1, "do_allrecord_lock: traverse should fail"); + + nwritten = write(up, &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + exit(0); +} + +static void do_traverse(const char *name, int tdb_flags, int up, int down) +{ + struct tdb_context *tdb; + int ret; + ssize_t nread, nwritten; + char c = 0; + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_traverse(tdb, NULL, NULL); + ok(ret == 1, "do_traverse: tdb_traverse should return 1 record"); + + nwritten = write(up, &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(down, &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + exit(0); +} + +/* + * Process 1: get the allrecord_lock on a tdb. + * Process 2: start a traverse, this will stall waiting for the + * first chainlock: That is taken by the allrecord_lock + * Process 1: start a traverse: This will get EDEADLK in trying to + * get the TRANSACTION_LOCK. It will deadlock for mutexes, + * which don't have built-in deadlock detection. + */ + +static int do_tests(const char *name, int tdb_flags) +{ + struct tdb_context *tdb; + int ret; + pid_t traverse_child, allrecord_child; + int traverse_down[2]; + int traverse_up[2]; + int allrecord_down[2]; + int allrecord_up[2]; + char c; + ssize_t nread, nwritten; + TDB_DATA key, data; + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_store(tdb, key, data, TDB_INSERT); + ok(ret == 0, "tdb_store should succeed"); + + ret = pipe(traverse_down); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(traverse_up); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(allrecord_down); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(allrecord_up); + ok(ret == 0, "pipe should succeed"); + + allrecord_child = fork(); + ok(allrecord_child != -1, "fork should succeed"); + + if (allrecord_child == 0) { + tdb_close(tdb); + close(traverse_up[0]); + close(traverse_up[1]); + close(traverse_down[0]); + close(traverse_down[1]); + close(allrecord_up[0]); + close(allrecord_down[1]); + do_allrecord_lock(name, tdb_flags, + allrecord_up[1], allrecord_down[0]); + exit(0); + } + close(allrecord_up[1]); + close(allrecord_down[0]); + + nread = read(allrecord_up[0], &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + traverse_child = fork(); + ok(traverse_child != -1, "fork should succeed"); + + if (traverse_child == 0) { + tdb_close(tdb); + close(traverse_up[0]); + close(traverse_down[1]); + close(allrecord_up[0]); + close(allrecord_down[1]); + do_traverse(name, tdb_flags, + traverse_up[1], traverse_down[0]); + exit(0); + } + close(traverse_up[1]); + close(traverse_down[0]); + + poll(NULL, 0, 1000); + + nwritten = write(allrecord_down[1], &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(traverse_up[0], &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + nwritten = write(traverse_down[1], &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(allrecord_up[0], &c, sizeof(c)); + ok(nread == sizeof(c), "ret should succeed"); + + close(traverse_up[0]); + close(traverse_down[1]); + close(allrecord_up[0]); + close(allrecord_down[1]); + diag("%s tests done", name); + return exit_status(); +} + +int main(int argc, char *argv[]) +{ + int ret; + bool mutex_support; + + mutex_support = tdb_runtime_check_for_robust_mutexes(); + + ret = do_tests("marklock-deadlock-fcntl.tdb", + TDB_CLEAR_IF_FIRST | + TDB_INCOMPATIBLE_HASH); + ok(ret == 0, "marklock-deadlock-fcntl.tdb tests should succeed"); + + if (!mutex_support) { + skip(1, "No robust mutex support, " + "skipping marklock-deadlock-mutex.tdb tests"); + return exit_status(); + } + + ret = do_tests("marklock-deadlock-mutex.tdb", + TDB_CLEAR_IF_FIRST | + TDB_MUTEX_LOCKING | + TDB_INCOMPATIBLE_HASH); + ok(ret == 0, "marklock-deadlock-mutex.tdb tests should succeed"); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-bad-tdb-header.c b/ldb-2.0.8/lib/tdb/test/run-bad-tdb-header.c new file mode 100644 index 0000000..9d29fdf --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-bad-tdb-header.c @@ -0,0 +1,59 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + struct tdb_header hdr; + int fd; + + plan_tests(11); + /* Can open fine if complete crap, as long as O_CREAT. */ + fd = open("run-bad-tdb-header.tdb", O_RDWR|O_CREAT|O_TRUNC, 0600); + ok1(fd >= 0); + ok1(write(fd, "hello world", 11) == 11); + close(fd); + tdb = tdb_open_ex("run-bad-tdb-header.tdb", 1024, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(!tdb); + tdb = tdb_open_ex("run-bad-tdb-header.tdb", 1024, 0, O_CREAT|O_RDWR, + 0600, &taplogctx, NULL); + ok1(tdb); + tdb_close(tdb); + + /* Now, with wrong version it should *not* overwrite. */ + fd = open("run-bad-tdb-header.tdb", O_RDWR); + ok1(fd >= 0); + ok1(read(fd, &hdr, sizeof(hdr)) == sizeof(hdr)); + ok1(hdr.version == TDB_VERSION); + hdr.version++; + lseek(fd, 0, SEEK_SET); + ok1(write(fd, &hdr, sizeof(hdr)) == sizeof(hdr)); + close(fd); + + tdb = tdb_open_ex("run-bad-tdb-header.tdb", 1024, 0, O_RDWR|O_CREAT, + 0600, &taplogctx, NULL); + ok1(errno == EIO); + ok1(!tdb); + + /* With truncate, will be fine. */ + tdb = tdb_open_ex("run-bad-tdb-header.tdb", 1024, 0, + O_RDWR|O_CREAT|O_TRUNC, 0600, &taplogctx, NULL); + ok1(tdb); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-check.c b/ldb-2.0.8/lib/tdb/test/run-check.c new file mode 100644 index 0000000..ce389a2 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-check.c @@ -0,0 +1,65 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(13); + tdb = tdb_open_ex("run-check.tdb", 1, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + tdb = tdb_open_ex("run-check.tdb", 1024, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + tdb = tdb_open_ex("test/tdb.corrupt", 1024, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == -1); + ok1(tdb_error(tdb) == TDB_ERR_CORRUPT); + tdb_close(tdb); + + /* Big and little endian should work! */ + tdb = tdb_open_ex("test/old-nohash-le.tdb", 1024, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + tdb = tdb_open_ex("test/old-nohash-be.tdb", 1024, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-circular-chain.c b/ldb-2.0.8/lib/tdb/test/run-circular-chain.c new file mode 100644 index 0000000..4fb32a2 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-circular-chain.c @@ -0,0 +1,42 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key; + + plan_tests(3); + tdb = tdb_open_ex( + "test/circular_chain.tdb", + 0, + TDB_DEFAULT, + O_RDONLY, + 0600, + &taplogctx, + NULL); + + ok1(tdb); + key.dsize = strlen("x"); + key.dptr = discard_const_p(uint8_t, "x"); + + ok1(tdb_exists(tdb, key) == 0); + ok1(tdb_error(tdb) == TDB_ERR_CORRUPT); + + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-circular-freelist.c b/ldb-2.0.8/lib/tdb/test/run-circular-freelist.c new file mode 100644 index 0000000..f1bec87 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-circular-freelist.c @@ -0,0 +1,50 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(3); + tdb = tdb_open_ex( + "test/circular_freelist.tdb", + 0, + TDB_DEFAULT, + O_RDWR, + 0600, + &taplogctx, + NULL); + + ok1(tdb); + + /* + * All freelist records are just 1 byte key and value. Insert + * something that will walk the whole freelist and hit the + * circle. + */ + key.dsize = strlen("x"); + key.dptr = discard_const_p(uint8_t, "x"); + data.dsize = strlen("too long"); + data.dptr = discard_const_p(uint8_t, "too long"); + + ok1(tdb_store(tdb, key, data, TDB_INSERT) == -1); + ok1(tdb_error(tdb) == TDB_ERR_CORRUPT); + + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-corrupt.c b/ldb-2.0.8/lib/tdb/test/run-corrupt.c new file mode 100644 index 0000000..e6fc751 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-corrupt.c @@ -0,0 +1,132 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +static int check(TDB_DATA key, TDB_DATA data, void *private) +{ + unsigned int *sizes = private; + + if (key.dsize > strlen("hello")) + return -1; + if (memcmp(key.dptr, "hello", key.dsize) != 0) + return -1; + + if (data.dsize != strlen("world")) + return -1; + if (memcmp(data.dptr, "world", data.dsize) != 0) + return -1; + + sizes[0] += key.dsize; + sizes[1] += data.dsize; + return 0; +} + +static void tdb_flip_bit(struct tdb_context *tdb, unsigned int bit) +{ + unsigned int off = bit / CHAR_BIT; + unsigned char mask = (1 << (bit % CHAR_BIT)); + + if (tdb->map_ptr) + ((unsigned char *)tdb->map_ptr)[off] ^= mask; + else { + unsigned char c; + if (pread(tdb->fd, &c, 1, off) != 1) { + fprintf(stderr, "pread: %s\n", strerror(errno)); + exit(1); + } + c ^= mask; + if (pwrite(tdb->fd, &c, 1, off) != 1) { + fprintf(stderr, "pwrite: %s\n", strerror(errno)); + exit(1); + } + } +} + +static void check_test(struct tdb_context *tdb) +{ + TDB_DATA key, data; + unsigned int i, verifiable, corrupt, sizes[2], dsize, ksize; + + ok1(tdb_check(tdb, NULL, NULL) == 0); + + key.dptr = discard_const_p(uint8_t, "hello"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + /* Key and data size respectively. */ + dsize = ksize = 0; + + /* 5 keys in hash size 2 means we'll have multichains. */ + for (key.dsize = 1; key.dsize <= 5; key.dsize++) { + ksize += key.dsize; + dsize += data.dsize; + if (tdb_store(tdb, key, data, TDB_INSERT) != 0) + abort(); + } + + /* This is how many bytes we expect to be verifiable. */ + /* From the file header. */ + verifiable = strlen(TDB_MAGIC_FOOD) + 1 + + 2 * sizeof(uint32_t) + 2 * sizeof(tdb_off_t) + + 2 * sizeof(uint32_t); + /* From the free list chain and hash chains. */ + verifiable += 3 * sizeof(tdb_off_t); + /* From the record headers & tailer */ + verifiable += 5 * (sizeof(struct tdb_record) + sizeof(uint32_t)); + /* The free block: we ignore datalen, keylen, full_hash. */ + verifiable += sizeof(struct tdb_record) - 3*sizeof(uint32_t) + + sizeof(uint32_t); + /* Our check function verifies the key and data. */ + verifiable += ksize + dsize; + + /* Flip one bit at a time, make sure it detects verifiable bytes. */ + for (i = 0, corrupt = 0; i < tdb->map_size * CHAR_BIT; i++) { + tdb_flip_bit(tdb, i); + memset(sizes, 0, sizeof(sizes)); + if (tdb_check(tdb, check, sizes) != 0) + corrupt++; + else if (sizes[0] != ksize || sizes[1] != dsize) + corrupt++; + tdb_flip_bit(tdb, i); + } + ok(corrupt == verifiable * CHAR_BIT, "corrupt %u should be %u", + corrupt, verifiable * CHAR_BIT); +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + + plan_tests(4); + /* This should use mmap. */ + tdb = tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + if (!tdb) + abort(); + check_test(tdb); + tdb_close(tdb); + + /* This should not. */ + tdb = tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST|TDB_NOMMAP, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + if (!tdb) + abort(); + check_test(tdb); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-die-during-transaction.c b/ldb-2.0.8/lib/tdb/test/run-die-during-transaction.c new file mode 100644 index 0000000..c636d87 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-die-during-transaction.c @@ -0,0 +1,232 @@ +#include "../common/tdb_private.h" +#include "lock-tracking.h" +static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset); +static ssize_t write_check(int fd, const void *buf, size_t count); +static int ftruncate_check(int fd, off_t length); + +#define pwrite pwrite_check +#define write write_check +#define fcntl fcntl_with_lockcheck +#define ftruncate ftruncate_check + +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include +#include "external-agent.h" +#include "logging.h" + +#undef write +#undef pwrite +#undef fcntl +#undef ftruncate + +static bool in_transaction; +static int target, current; +static jmp_buf jmpbuf; +#define TEST_DBNAME "run-die-during-transaction.tdb" +#define KEY_STRING "helloworld" + +static void maybe_die(int fd) +{ + if (in_transaction && current++ == target) { + longjmp(jmpbuf, 1); + } +} + +static ssize_t pwrite_check(int fd, + const void *buf, size_t count, off_t offset) +{ + ssize_t ret; + + maybe_die(fd); + + ret = pwrite(fd, buf, count, offset); + if (ret != count) + return ret; + + maybe_die(fd); + return ret; +} + +static ssize_t write_check(int fd, const void *buf, size_t count) +{ + ssize_t ret; + + maybe_die(fd); + + ret = write(fd, buf, count); + if (ret != count) + return ret; + + maybe_die(fd); + return ret; +} + +static int ftruncate_check(int fd, off_t length) +{ + int ret; + + maybe_die(fd); + + ret = ftruncate(fd, length); + + maybe_die(fd); + return ret; +} + +static bool test_death(enum operation op, struct agent *agent) +{ + struct tdb_context *tdb = NULL; + TDB_DATA key; + enum agent_return ret; + int needed_recovery = 0; + + current = target = 0; +reset: + unlink(TEST_DBNAME); + tdb = tdb_open_ex(TEST_DBNAME, 1024, TDB_NOMMAP, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + if (setjmp(jmpbuf) != 0) { + /* We're partway through. Simulate our death. */ + close(tdb->fd); + forget_locking(); + in_transaction = false; + + ret = external_agent_operation(agent, NEEDS_RECOVERY, ""); + if (ret == SUCCESS) + needed_recovery++; + else if (ret != FAILED) { + diag("Step %u agent NEEDS_RECOVERY = %s", current, + agent_return_name(ret)); + return false; + } + + ret = external_agent_operation(agent, op, KEY_STRING); + if (ret != SUCCESS) { + diag("Step %u op %s failed = %s", current, + operation_name(op), + agent_return_name(ret)); + return false; + } + + ret = external_agent_operation(agent, NEEDS_RECOVERY, ""); + if (ret != FAILED) { + diag("Still needs recovery after step %u = %s", + current, agent_return_name(ret)); + return false; + } + + ret = external_agent_operation(agent, CHECK, ""); + if (ret != SUCCESS) { + diag("Step %u check failed = %s", current, + agent_return_name(ret)); + return false; + } + + ret = external_agent_operation(agent, CLOSE, ""); + if (ret != SUCCESS) { + diag("Step %u close failed = %s", current, + agent_return_name(ret)); + return false; + } + + /* Suppress logging as this tries to use closed fd. */ + suppress_logging = true; + suppress_lockcheck = true; + tdb_close(tdb); + suppress_logging = false; + suppress_lockcheck = false; + target++; + current = 0; + goto reset; + } + + /* Put key for agent to fetch. */ + key.dsize = strlen(KEY_STRING); + key.dptr = discard_const_p(uint8_t, KEY_STRING); + if (tdb_store(tdb, key, key, TDB_INSERT) != 0) + return false; + + /* This is the key we insert in transaction. */ + key.dsize--; + + ret = external_agent_operation(agent, OPEN, TEST_DBNAME); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed to open: %s\n", + agent_return_name(ret)); + exit(1); + } + + ret = external_agent_operation(agent, FETCH, KEY_STRING); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed find key: %s\n", + agent_return_name(ret)); + exit(1); + } + + in_transaction = true; + if (tdb_transaction_start(tdb) != 0) + return false; + + if (tdb_store(tdb, key, key, TDB_INSERT) != 0) + return false; + + if (tdb_transaction_commit(tdb) != 0) + return false; + + in_transaction = false; + + /* We made it! */ + diag("Completed %u runs", current); + tdb_close(tdb); + ret = external_agent_operation(agent, CLOSE, ""); + if (ret != SUCCESS) { + diag("Step %u close failed = %s", current, + agent_return_name(ret)); + return false; + } + +#ifdef HAVE_INCOHERENT_MMAP + /* This means we always mmap, which makes this test a noop. */ + ok1(1); +#else + ok1(needed_recovery); +#endif + ok1(locking_errors == 0); + ok1(forget_locking() == 0); + locking_errors = 0; + return true; +} + +int main(int argc, char *argv[]) +{ + enum operation ops[] = { FETCH, STORE, TRANSACTION_START }; + struct agent *agent; + int i; + + plan_tests(12); + unlock_callback = maybe_die; + + agent = prepare_external_agent(); + + for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { + diag("Testing %s after death", operation_name(ops[i])); + ok1(test_death(ops[i], agent)); + } + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-endian.c b/ldb-2.0.8/lib/tdb/test/run-endian.c new file mode 100644 index 0000000..9d4d5f5 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-endian.c @@ -0,0 +1,64 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(13); + tdb = tdb_open_ex("run-endian.tdb", 1024, + TDB_CLEAR_IF_FIRST|TDB_CONVERT, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + ok1(tdb); + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + ok1(tdb_store(tdb, key, data, TDB_MODIFY) < 0); + ok1(tdb_error(tdb) == TDB_ERR_NOEXIST); + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + ok1(tdb_store(tdb, key, data, TDB_INSERT) < 0); + ok1(tdb_error(tdb) == TDB_ERR_EXISTS); + ok1(tdb_store(tdb, key, data, TDB_MODIFY) == 0); + + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + + key.dsize++; + data = tdb_fetch(tdb, key); + ok1(data.dptr == NULL); + tdb_close(tdb); + + /* Reopen: should read it */ + tdb = tdb_open_ex("run-endian.tdb", 1024, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(tdb); + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-fcntl-deadlock.c b/ldb-2.0.8/lib/tdb/test/run-fcntl-deadlock.c new file mode 100644 index 0000000..0a328af --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-fcntl-deadlock.c @@ -0,0 +1,202 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include +#include "tap-interface.h" + +/* + * This tests the low level locking requirement + * for the allrecord lock/prepare_commit and traverse_read interaction. + * + * The pattern with the traverse_read and prepare_commit interaction is + * the following: + * + * 1. transaction_start got the allrecord lock with F_RDLCK. + * + * 2. the traverse_read code walks the database in a sequence like this + * (per chain): + * 2.1 chainlock(chainX, F_RDLCK) + * 2.2 recordlock(chainX.record1, F_RDLCK) + * 2.3 chainunlock(chainX, F_RDLCK) + * 2.4 callback(chainX.record1) + * 2.5 chainlock(chainX, F_RDLCK) + * 2.6 recordunlock(chainX.record1, F_RDLCK) + * 2.7 recordlock(chainX.record2, F_RDLCK) + * 2.8 chainunlock(chainX, F_RDLCK) + * 2.9 callback(chainX.record2) + * 2.10 chainlock(chainX, F_RDLCK) + * 2.11 recordunlock(chainX.record2, F_RDLCK) + * 2.12 chainunlock(chainX, F_RDLCK) + * 2.13 goto next chain + * + * So it has always one record locked in F_RDLCK mode and tries to + * get the 2nd one before it releases the first one. + * + * 3. prepare_commit tries to upgrade the allrecord lock to F_RWLCK + * If that happens at the time of 2.4, the operation of + * 2.5 may deadlock with the allrecord lock upgrade. + * On Linux step 2.5 works in order to make some progress with the + * locking, but on solaris it might fail because the kernel + * wants to satisfy the 1st lock requester before the 2nd one. + * + * I think the first step is a standalone test that does this: + * + * process1: F_RDLCK for ofs=0 len=2 + * process2: F_RDLCK for ofs=0 len=1 + * process1: upgrade ofs=0 len=2 to F_RWLCK (in blocking mode) + * process2: F_RDLCK for ofs=1 len=1 + * process2: unlock ofs=0 len=2 + * process1: should continue at that point + * + * Such a test follows here... + */ + +static int raw_fcntl_lock(int fd, int rw, off_t off, off_t len, bool waitflag) +{ + struct flock fl; + int cmd; + fl.l_type = rw; + fl.l_whence = SEEK_SET; + fl.l_start = off; + fl.l_len = len; + fl.l_pid = 0; + + cmd = waitflag ? F_SETLKW : F_SETLK; + + return fcntl(fd, cmd, &fl); +} + +static int raw_fcntl_unlock(int fd, off_t off, off_t len) +{ + struct flock fl; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = off; + fl.l_len = len; + fl.l_pid = 0; + + return fcntl(fd, F_SETLKW, &fl); +} + + +int pipe_r; +int pipe_w; +char buf[2]; + +static void expect_char(char c) +{ + read(pipe_r, buf, 1); + if (*buf != c) { + fail("We were expecting %c, but got %c", c, buf[0]); + } +} + +static void send_char(char c) +{ + write(pipe_w, &c, 1); +} + + +int main(int argc, char *argv[]) +{ + int process; + int fd; + const char *filename = "run-fcntl-deadlock.lck"; + int pid; + int pipes_1_2[2]; + int pipes_2_1[2]; + int ret; + + pipe(pipes_1_2); + pipe(pipes_2_1); + fd = open(filename, O_RDWR | O_CREAT, 0755); + + pid = fork(); + if (pid == 0) { + pipe_r = pipes_1_2[0]; + pipe_w = pipes_2_1[1]; + process = 2; + alarm(15); + } else { + pipe_r = pipes_2_1[0]; + pipe_w = pipes_1_2[1]; + process = 1; + alarm(15); + } + + /* a: process1: F_RDLCK for ofs=0 len=2 */ + if (process == 1) { + ret = raw_fcntl_lock(fd, F_RDLCK, 0, 2, true); + ok(ret == 0, + "process 1 lock ofs=0 len=2: %d - %s", + ret, strerror(errno)); + diag("process 1 took read lock on range 0,2"); + send_char('a'); + } + + /* process2: F_RDLCK for ofs=0 len=1 */ + if (process == 2) { + expect_char('a'); + ret = raw_fcntl_lock(fd, F_RDLCK, 0, 1, true); + ok(ret == 0, + "process 2 lock ofs=0 len=1: %d - %s", + ret, strerror(errno));; + diag("process 2 took read lock on range 0,1"); + send_char('b'); + } + + /* process1: upgrade ofs=0 len=2 to F_RWLCK (in blocking mode) */ + if (process == 1) { + expect_char('b'); + send_char('c'); + diag("process 1 starts upgrade on range 0,2"); + ret = raw_fcntl_lock(fd, F_WRLCK, 0, 2, true); + ok(ret == 0, + "process 1 RW lock ofs=0 len=2: %d - %s", + ret, strerror(errno)); + diag("process 1 got read upgrade done"); + /* at this point process 1 is blocked on 2 releasing the + read lock */ + } + + /* + * process2: F_RDLCK for ofs=1 len=1 + * process2: unlock ofs=0 len=2 + */ + if (process == 2) { + expect_char('c'); /* we know process 1 is *about* to lock */ + sleep(1); + ret = raw_fcntl_lock(fd, F_RDLCK, 1, 1, true); + ok(ret == 0, + "process 2 lock ofs=1 len=1: %d - %s", + ret, strerror(errno)); + diag("process 2 got read lock on 1,1\n"); + ret = raw_fcntl_unlock(fd, 0, 2); + ok(ret == 0, + "process 2 unlock ofs=0 len=2: %d - %s", + ret, strerror(errno)); + diag("process 2 released read lock on 0,2\n"); + sleep(1); + send_char('d'); + } + + if (process == 1) { + expect_char('d'); + } + + diag("process %d has got to the end\n", process); + + return 0; +} diff --git a/ldb-2.0.8/lib/tdb/test/run-incompatible.c b/ldb-2.0.8/lib/tdb/test/run-incompatible.c new file mode 100644 index 0000000..5f1b586 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-incompatible.c @@ -0,0 +1,188 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include + +static unsigned int tdb_dumb_hash(TDB_DATA *key) +{ + return key->dsize; +} + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ + unsigned int *count = tdb_get_logging_private(tdb); + if (strstr(fmt, "hash")) + (*count)++; +} + +static unsigned int hdr_rwlocks(const char *fname) +{ + struct tdb_header hdr; + ssize_t nread; + + int fd = open(fname, O_RDONLY); + if (fd == -1) + return -1; + + nread = read(fd, &hdr, sizeof(hdr)); + close(fd); + if (nread != sizeof(hdr)) { + return -1; + } + return hdr.rwlocks; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count, flags; + TDB_DATA d, r; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + + plan_tests(38 * 2); + + for (flags = 0; flags <= TDB_CONVERT; flags += TDB_CONVERT) { + unsigned int rwmagic = TDB_HASH_RWLOCK_MAGIC; + + if (flags & TDB_CONVERT) + tdb_convert(&rwmagic, sizeof(rwmagic)); + + /* Create an old-style hash. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, flags, + O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, + NULL); + ok1(tdb); + ok1(log_count == 0); + d.dptr = discard_const_p(uint8_t, "Hello"); + d.dsize = 5; + ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); + tdb_close(tdb); + + /* Should not have marked rwlocks field. */ + ok1(hdr_rwlocks("run-incompatible.tdb") == 0); + + /* We can still open any old-style with incompat flag. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, + TDB_INCOMPATIBLE_HASH, + O_RDWR, 0600, &log_ctx, NULL); + ok1(tdb); + ok1(log_count == 0); + r = tdb_fetch(tdb, d); + ok1(r.dsize == 5); + free(r.dptr); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + log_count = 0; + tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDONLY, + 0, &log_ctx, tdb_jenkins_hash); + ok1(tdb); + ok1(log_count == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + log_count = 0; + tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDONLY, + 0, &log_ctx, tdb_jenkins_hash); + ok1(tdb); + ok1(log_count == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + /* OK, now create with incompatible flag, default hash. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, + flags|TDB_INCOMPATIBLE_HASH, + O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, + NULL); + ok1(tdb); + ok1(log_count == 0); + d.dptr = discard_const_p(uint8_t, "Hello"); + d.dsize = 5; + ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); + tdb_close(tdb); + + /* Should have marked rwlocks field. */ + ok1(hdr_rwlocks("run-incompatible.tdb") == rwmagic); + + /* Cannot open with old hash. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, + O_RDWR, 0600, &log_ctx, tdb_old_hash); + ok1(!tdb); + ok1(log_count == 1); + + /* Can open with jenkins hash. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, + O_RDWR, 0600, &log_ctx, tdb_jenkins_hash); + ok1(tdb); + ok1(log_count == 0); + r = tdb_fetch(tdb, d); + ok1(r.dsize == 5); + free(r.dptr); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + /* Can open by letting it figure it out itself. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, + O_RDWR, 0600, &log_ctx, NULL); + ok1(tdb); + ok1(log_count == 0); + r = tdb_fetch(tdb, d); + ok1(r.dsize == 5); + free(r.dptr); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + /* We can also use incompatible hash with other hashes. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, + flags|TDB_INCOMPATIBLE_HASH, + O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, + tdb_dumb_hash); + ok1(tdb); + ok1(log_count == 0); + d.dptr = discard_const_p(uint8_t, "Hello"); + d.dsize = 5; + ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); + tdb_close(tdb); + + /* Should have marked rwlocks field. */ + ok1(hdr_rwlocks("run-incompatible.tdb") == rwmagic); + + /* It should not open if we don't specify. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, O_RDWR, 0, + &log_ctx, NULL); + ok1(!tdb); + ok1(log_count == 1); + + /* Should reopen with correct hash. */ + log_count = 0; + tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, O_RDWR, 0, + &log_ctx, tdb_dumb_hash); + ok1(tdb); + ok1(log_count == 0); + r = tdb_fetch(tdb, d); + ok1(r.dsize == 5); + free(r.dptr); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + } + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-marklock-deadlock.c b/ldb-2.0.8/lib/tdb/test/run-marklock-deadlock.c new file mode 100644 index 0000000..37e959f --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-marklock-deadlock.c @@ -0,0 +1,278 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include +#include "logging.h" + +static TDB_DATA key, data; + +static void do_chainlock(const char *name, int tdb_flags, int up, int down) +{ + struct tdb_context *tdb; + int ret; + ssize_t nread, nwritten; + char c = 0; + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_chainlock(tdb, key); + ok(ret == 0, "tdb_chainlock should succeed"); + + nwritten = write(up, &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(down, &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + exit(0); +} + +static void do_allrecord_lock(const char *name, int tdb_flags, int up, int down) +{ + struct tdb_context *tdb; + int ret; + ssize_t nread, nwritten; + char c = 0; + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); + ok(ret == 0, "tdb_allrecord_lock should succeed"); + + nwritten = write(up, &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(down, &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + exit(0); +} + +/* The code should barf on TDBs created with rwlocks. */ +static int do_tests(const char *name, int tdb_flags) +{ + struct tdb_context *tdb; + int ret; + pid_t chainlock_child, allrecord_child; + int chainlock_down[2]; + int chainlock_up[2]; + int allrecord_down[2]; + int allrecord_up[2]; + char c; + ssize_t nread, nwritten; + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + ret = pipe(chainlock_down); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(chainlock_up); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(allrecord_down); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(allrecord_up); + ok(ret == 0, "pipe should succeed"); + + chainlock_child = fork(); + ok(chainlock_child != -1, "fork should succeed"); + + if (chainlock_child == 0) { + close(chainlock_up[0]); + close(chainlock_down[1]); + close(allrecord_up[0]); + close(allrecord_up[1]); + close(allrecord_down[0]); + close(allrecord_down[1]); + do_chainlock(name, tdb_flags, + chainlock_up[1], chainlock_down[0]); + exit(0); + } + close(chainlock_up[1]); + close(chainlock_down[0]); + + nread = read(chainlock_up[0], &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + /* + * Now we have a process holding a chainlock. Start another process + * trying the allrecord lock. This will block. + */ + + allrecord_child = fork(); + ok(allrecord_child != -1, "fork should succeed"); + + if (allrecord_child == 0) { + close(chainlock_up[0]); + close(chainlock_up[1]); + close(chainlock_down[0]); + close(chainlock_down[1]); + close(allrecord_up[0]); + close(allrecord_down[1]); + do_allrecord_lock(name, tdb_flags, + allrecord_up[1], allrecord_down[0]); + exit(0); + } + close(allrecord_up[1]); + close(allrecord_down[0]); + + poll(NULL, 0, 500); + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + /* + * Someone already holds a chainlock, but we're able to get the + * freelist lock. + * + * The freelist lock/mutex is independent from the allrecord lock/mutex. + */ + + ret = tdb_chainlock_nonblock(tdb, key); + ok(ret == -1, "tdb_chainlock_nonblock should not succeed"); + + ret = tdb_lock_nonblock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_lock_nonblock should succeed"); + + ret = tdb_unlock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_unlock should succeed"); + + /* + * We have someone else having done the lock for us. Just mark it. + */ + + ret = tdb_chainlock_mark(tdb, key); + ok(ret == 0, "tdb_chainlock_mark should succeed"); + + /* + * The tdb_store below will block the freelist. In one version of the + * mutex patches, the freelist was already blocked here by the + * allrecord child, which was waiting for the chainlock child to give + * up its chainlock. Make sure that we don't run into this + * deadlock. To exercise the deadlock, just comment out the "ok" + * line. + * + * The freelist lock/mutex is independent from the allrecord lock/mutex. + */ + + ret = tdb_lock_nonblock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_lock_nonblock should succeed"); + + ret = tdb_unlock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_unlock should succeed"); + + ret = tdb_store(tdb, key, data, TDB_INSERT); + ok(ret == 0, "tdb_store should succeed"); + + ret = tdb_chainlock_unmark(tdb, key); + ok(ret == 0, "tdb_chainlock_unmark should succeed"); + + nwritten = write(chainlock_down[1], &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(chainlock_up[0], &c, sizeof(c)); + ok(nread == 0, "read should succeed"); + + nread = read(allrecord_up[0], &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + /* + * Someone already holds the allrecord lock, but we're able to get the + * freelist lock. + * + * The freelist lock/mutex is independent from the allrecord lock/mutex. + */ + + ret = tdb_chainlock_nonblock(tdb, key); + ok(ret == -1, "tdb_chainlock_nonblock should not succeed"); + + ret = tdb_lockall_nonblock(tdb); + ok(ret == -1, "tdb_lockall_nonblock should not succeed"); + + ret = tdb_lock_nonblock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_lock_nonblock should succeed"); + + ret = tdb_unlock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_unlock should succeed"); + + /* + * We have someone else having done the lock for us. Just mark it. + */ + + ret = tdb_lockall_mark(tdb); + ok(ret == 0, "tdb_lockall_mark should succeed"); + + ret = tdb_lock_nonblock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_lock_nonblock should succeed"); + + ret = tdb_unlock(tdb, -1, F_WRLCK); + ok(ret == 0, "tdb_unlock should succeed"); + + ret = tdb_store(tdb, key, data, TDB_REPLACE); + ok(ret == 0, "tdb_store should succeed"); + + ret = tdb_lockall_unmark(tdb); + ok(ret == 0, "tdb_lockall_unmark should succeed"); + + nwritten = write(allrecord_down[1], &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(allrecord_up[0], &c, sizeof(c)); + ok(nread == 0, "read should succeed"); + + close(chainlock_up[0]); + close(chainlock_down[1]); + close(allrecord_up[0]); + close(allrecord_down[1]); + diag("%s tests done", name); + return exit_status(); +} + +int main(int argc, char *argv[]) +{ + int ret; + bool mutex_support; + + mutex_support = tdb_runtime_check_for_robust_mutexes(); + + ret = do_tests("marklock-deadlock-fcntl.tdb", + TDB_CLEAR_IF_FIRST | + TDB_INCOMPATIBLE_HASH); + ok(ret == 0, "marklock-deadlock-fcntl.tdb tests should succeed"); + + if (!mutex_support) { + skip(1, "No robust mutex support, " + "skipping marklock-deadlock-mutex.tdb tests"); + return exit_status(); + } + + ret = do_tests("marklock-deadlock-mutex.tdb", + TDB_CLEAR_IF_FIRST | + TDB_MUTEX_LOCKING | + TDB_INCOMPATIBLE_HASH); + ok(ret == 0, "marklock-deadlock-mutex.tdb tests should succeed"); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-bench.c b/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-bench.c new file mode 100644 index 0000000..b81e597 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-bench.c @@ -0,0 +1,82 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include + +static TDB_DATA key, data; + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2) +{ + return (tv2->tv_sec - tv1->tv_sec) + + (tv2->tv_usec - tv1->tv_usec)*1.0e-6; +} + +static double timeval_elapsed(const struct timeval *tv) +{ + struct timeval tv2; + gettimeofday(&tv2, NULL); + return timeval_elapsed2(tv, &tv2); +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret; + struct timeval start; + double elapsed; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + if (!runtime_support) { + skip(1, "No robust mutex support"); + return exit_status(); + } + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + tdb = tdb_open_ex("mutex-allrecord-bench.tdb", 1000000, + TDB_INCOMPATIBLE_HASH| + TDB_MUTEX_LOCKING| + TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + gettimeofday(&start, NULL); + ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); + elapsed = timeval_elapsed(&start); + + ok(ret == 0, "tdb_allrecord_lock should succeed"); + + diag("allrecord_lock took %f seconds", elapsed); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-block.c b/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-block.c new file mode 100644 index 0000000..fcd3b4f --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-block.c @@ -0,0 +1,120 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include + +static TDB_DATA key, data; + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static int do_child(int tdb_flags, int to, int from) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret; + char c = 0; + + tdb = tdb_open_ex("mutex-allrecord-block.tdb", 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); + ok(ret == 0, "tdb_allrecord_lock should succeed"); + + write(to, &c, sizeof(c)); + + read(from, &c, sizeof(c)); + + ret = tdb_allrecord_unlock(tdb, F_WRLCK, false); + ok(ret == 0, "tdb_allrecord_unlock should succeed"); + + return 0; +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret, status; + pid_t child, wait_ret; + int fromchild[2]; + int tochild[2]; + char c; + int tdb_flags; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + if (!runtime_support) { + skip(1, "No robust mutex support"); + return exit_status(); + } + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + pipe(fromchild); + pipe(tochild); + + tdb_flags = TDB_INCOMPATIBLE_HASH| + TDB_MUTEX_LOCKING| + TDB_CLEAR_IF_FIRST; + + child = fork(); + if (child == 0) { + close(fromchild[0]); + close(tochild[1]); + return do_child(tdb_flags, fromchild[1], tochild[0]); + } + close(fromchild[1]); + close(tochild[0]); + + read(fromchild[0], &c, sizeof(c)); + + tdb = tdb_open_ex("mutex-allrecord-block.tdb", 0, + tdb_flags, O_RDWR|O_CREAT, 0755, + &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_chainlock_nonblock(tdb, key); + ok(ret == -1, "tdb_chainlock_nonblock should not succeed"); + + write(tochild[1], &c, sizeof(c)); + + ret = tdb_chainlock(tdb, key); + ok(ret == 0, "tdb_chainlock should not succeed"); + + ret = tdb_chainunlock(tdb, key); + ok(ret == 0, "tdb_chainunlock should succeed"); + + wait_ret = wait(&status); + ok(wait_ret == child, "child should have exited correctly"); + + diag("done"); + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-trylock.c b/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-trylock.c new file mode 100644 index 0000000..4b683db --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex-allrecord-trylock.c @@ -0,0 +1,113 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include + +static TDB_DATA key, data; + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static int do_child(int tdb_flags, int to, int from) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret; + char c = 0; + + tdb = tdb_open_ex("mutex-allrecord-trylock.tdb", 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_chainlock(tdb, key); + ok(ret == 0, "tdb_chainlock should succeed"); + + write(to, &c, sizeof(c)); + + read(from, &c, sizeof(c)); + + ret = tdb_chainunlock(tdb, key); + ok(ret == 0, "tdb_chainunlock should succeed"); + + return 0; +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret, status; + pid_t child, wait_ret; + int fromchild[2]; + int tochild[2]; + char c; + int tdb_flags; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + if (!runtime_support) { + skip(1, "No robust mutex support"); + return exit_status(); + } + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + pipe(fromchild); + pipe(tochild); + + tdb_flags = TDB_INCOMPATIBLE_HASH| + TDB_MUTEX_LOCKING| + TDB_CLEAR_IF_FIRST; + + child = fork(); + if (child == 0) { + close(fromchild[0]); + close(tochild[1]); + return do_child(tdb_flags, fromchild[1], tochild[0]); + } + close(fromchild[1]); + close(tochild[0]); + + read(fromchild[0], &c, sizeof(c)); + + tdb = tdb_open_ex("mutex-allrecord-trylock.tdb", 0, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_NOWAIT, false); + ok(ret == -1, "tdb_allrecord_lock (nowait) should not succeed"); + + write(tochild[1], &c, sizeof(c)); + + wait_ret = wait(&status); + ok(wait_ret == child, "child should have exited correctly"); + + diag("done"); + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex-die.c b/ldb-2.0.8/lib/tdb/test/run-mutex-die.c new file mode 100644 index 0000000..4b8eac1 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex-die.c @@ -0,0 +1,269 @@ +#include "../common/tdb_private.h" +#include "lock-tracking.h" +static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset); +static ssize_t write_check(int fd, const void *buf, size_t count); +static int ftruncate_check(int fd, off_t length); + +#define pwrite pwrite_check +#define write write_check +#define fcntl fcntl_with_lockcheck +#define ftruncate ftruncate_check + +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include "external-agent.h" +#include "logging.h" + +#undef write +#undef pwrite +#undef fcntl +#undef ftruncate + +static int target, current; +#define TEST_DBNAME "run-mutex-die.tdb" +#define KEY_STRING "helloworld" + +static void maybe_die(int fd) +{ + if (target == 0) { + return; + } + current += 1; + if (current == target) { + _exit(1); + } +} + +static ssize_t pwrite_check(int fd, + const void *buf, size_t count, off_t offset) +{ + ssize_t ret; + + maybe_die(fd); + + ret = pwrite(fd, buf, count, offset); + if (ret != count) + return ret; + + maybe_die(fd); + return ret; +} + +static ssize_t write_check(int fd, const void *buf, size_t count) +{ + ssize_t ret; + + maybe_die(fd); + + ret = write(fd, buf, count); + if (ret != count) + return ret; + + maybe_die(fd); + return ret; +} + +static int ftruncate_check(int fd, off_t length) +{ + int ret; + + maybe_die(fd); + + ret = ftruncate(fd, length); + + maybe_die(fd); + return ret; +} + +static enum agent_return flakey_ops(struct agent *a) +{ + enum agent_return ret; + + /* + * Run in the external agent child + */ + + ret = external_agent_operation(a, OPEN_WITH_CLEAR_IF_FIRST, TEST_DBNAME); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed to open: %s\n", + agent_return_name(ret)); + return ret; + } + ret = external_agent_operation(a, UNMAP, ""); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed to unmap: %s\n", + agent_return_name(ret)); + return ret; + } + ret = external_agent_operation(a, STORE, "xyz"); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed to store: %s\n", + agent_return_name(ret)); + return ret; + } + ret = external_agent_operation(a, STORE, KEY_STRING); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed store: %s\n", + agent_return_name(ret)); + return ret; + } + ret = external_agent_operation(a, FETCH, KEY_STRING); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed find key: %s\n", + agent_return_name(ret)); + return ret; + } + ret = external_agent_operation(a, PING, ""); + if (ret != SUCCESS) { + fprintf(stderr, "Agent failed ping: %s\n", + agent_return_name(ret)); + return ret; + } + return ret; +} + +static bool prep_db(void) { + struct tdb_context *tdb; + TDB_DATA key; + TDB_DATA data; + + key.dptr = discard_const_p(uint8_t, KEY_STRING); + key.dsize = strlen((char *)key.dptr); + data.dptr = discard_const_p(uint8_t, "foo"); + data.dsize = strlen((char *)data.dptr); + + unlink(TEST_DBNAME); + + tdb = tdb_open_ex( + TEST_DBNAME, 2, + TDB_INCOMPATIBLE_HASH|TDB_MUTEX_LOCKING|TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + if (tdb == NULL) { + return false; + } + + if (tdb_store(tdb, key, data, TDB_INSERT) != 0) { + return false; + } + + tdb_close(tdb); + tdb = NULL; + + forget_locking(); + + return true; +} + +static bool test_db(void) { + struct tdb_context *tdb; + int ret; + + tdb = tdb_open_ex( + TEST_DBNAME, 1024, TDB_INCOMPATIBLE_HASH, + O_RDWR, 0600, &taplogctx, NULL); + + if (tdb == NULL) { + perror("tdb_open_ex failed"); + return false; + } + + ret = tdb_traverse(tdb, NULL, NULL); + if (ret == -1) { + perror("traverse failed"); + goto fail; + } + + tdb_close(tdb); + + forget_locking(); + + return true; + +fail: + tdb_close(tdb); + return false; +} + +static bool test_one(void) +{ + enum agent_return ret; + + ret = AGENT_DIED; + target = 19; + + while (ret != SUCCESS) { + struct agent *agent; + + { + int child_target = target; + bool pret; + target = 0; + pret = prep_db(); + ok1(pret); + target = child_target; + } + + agent = prepare_external_agent(); + + ret = flakey_ops(agent); + + diag("Agent (target=%d) returns %s", + target, agent_return_name(ret)); + + if (ret == SUCCESS) { + ok((target > 19), "At least one AGENT_DIED expected"); + } else { + ok(ret == AGENT_DIED, "AGENT_DIED expected"); + } + + shutdown_agent(agent); + + { + int child_target = target; + bool tret; + target = 0; + tret = test_db(); + ok1(tret); + target = child_target; + } + + target += 1; + } + + return true; +} + +int main(int argc, char *argv[]) +{ + bool ret; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + if (!runtime_support) { + skip(1, "No robust mutex support"); + return exit_status(); + } + + plan_tests(12); + unlock_callback = maybe_die; + + ret = test_one(); + ok1(ret); + + diag("done"); + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex-openflags2.c b/ldb-2.0.8/lib/tdb/test/run-mutex-openflags2.c new file mode 100644 index 0000000..89603e6 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex-openflags2.c @@ -0,0 +1,146 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include +#include + +static TDB_DATA key, data; + +static void log_void(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ +} + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static int do_child(int fd) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + struct tdb_logging_context nolog_ctx = { log_void, NULL }; + char c; + + read(fd, &c, 1); + + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_DEFAULT, + O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL); + ok((tdb == NULL) && (errno == EINVAL), "TDB_DEFAULT without " + "TDB_MUTEX_LOCKING should fail with EINVAL - %d", errno); + + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL); + ok((tdb == NULL) && (errno == EINVAL), "TDB_CLEAR_IF_FIRST without " + "TDB_MUTEX_LOCKING should fail with EINVAL - %d", errno); + + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_CLEAR_IF_FIRST | + TDB_MUTEX_LOCKING | + TDB_INTERNAL, + O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL); + ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING with " + "TDB_INTERNAL should fail with EINVAL - %d", errno); + + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_CLEAR_IF_FIRST | + TDB_MUTEX_LOCKING | + TDB_NOMMAP, + O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL); + ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING with " + "TDB_NOMMAP should fail with EINVAL - %d", errno); + + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_CLEAR_IF_FIRST | + TDB_MUTEX_LOCKING, + O_RDONLY, 0755, &nolog_ctx, NULL); + ok((tdb != NULL), "TDB_MUTEX_LOCKING with " + "O_RDONLY should work - %d", errno); + tdb_close(tdb); + + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_CLEAR_IF_FIRST | + TDB_MUTEX_LOCKING, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok((tdb != NULL), "TDB_MUTEX_LOCKING with TDB_CLEAR_IF_FIRST" + "TDB_NOMMAP should work - %d", errno); + + return 0; +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + struct tdb_logging_context nolog_ctx = { log_void, NULL }; + int ret, status; + pid_t child, wait_ret; + int pipefd[2]; + char c = 0; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + ret = pipe(pipefd); + ok1(ret == 0); + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + if (!runtime_support) { + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_CLEAR_IF_FIRST| + TDB_MUTEX_LOCKING, + O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL); + ok((tdb == NULL) && (errno == ENOSYS), "TDB_MUTEX_LOCKING without " + "runtime support should fail with ENOSYS - %d", errno); + + skip(1, "No robust mutex support"); + return exit_status(); + } + + child = fork(); + if (child == 0) { + return do_child(pipefd[0]); + } + + tdb = tdb_open_ex("mutex-openflags2.tdb", 0, + TDB_CLEAR_IF_FIRST| + TDB_MUTEX_LOCKING, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok((tdb != NULL), "tdb_open_ex with mutexes should succeed"); + + write(pipefd[1], &c, 1); + + wait_ret = wait(&status); + ok((wait_ret == child) && (status == 0), + "child should have exited correctly"); + + diag("done"); + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex-transaction1.c b/ldb-2.0.8/lib/tdb/test/run-mutex-transaction1.c new file mode 100644 index 0000000..7b9f7b1 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex-transaction1.c @@ -0,0 +1,236 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include + +static TDB_DATA key, data; + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static int do_child(int tdb_flags, int to, int from) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret; + char c = 0; + + tdb = tdb_open_ex("mutex-transaction1.tdb", 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_transaction_start(tdb); + ok(ret == 0, "tdb_transaction_start should succeed"); + + ret = tdb_store(tdb, key, data, TDB_INSERT); + ok(ret == 0, "tdb_store(tdb, key, data, TDB_INSERT) should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_transaction_cancel(tdb); + ok(ret == 0, "tdb_transaction_cancel should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_transaction_start(tdb); + ok(ret == 0, "tdb_transaction_start should succeed"); + + ret = tdb_store(tdb, key, data, TDB_INSERT); + ok(ret == 0, "tdb_store(tdb, key, data, TDB_INSERT) should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_transaction_commit(tdb); + ok(ret == 0, "tdb_transaction_commit should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_transaction_start(tdb); + ok(ret == 0, "tdb_transaction_start should succeed"); + + ret = tdb_store(tdb, key, key, TDB_REPLACE); + ok(ret == 0, "tdb_store(tdb, key, data, TDB_REPLACE) should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_transaction_commit(tdb); + ok(ret == 0, "tdb_transaction_commit should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + return 0; +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret, status; + pid_t child, wait_ret; + int fromchild[2]; + int tochild[2]; + TDB_DATA val; + char c; + int tdb_flags; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + if (!runtime_support) { + skip(1, "No robust mutex support"); + return exit_status(); + } + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + pipe(fromchild); + pipe(tochild); + + tdb_flags = TDB_INCOMPATIBLE_HASH| + TDB_MUTEX_LOCKING| + TDB_CLEAR_IF_FIRST; + + child = fork(); + if (child == 0) { + close(fromchild[0]); + close(tochild[1]); + return do_child(tdb_flags, fromchild[1], tochild[0]); + } + close(fromchild[1]); + close(tochild[0]); + + read(fromchild[0], &c, sizeof(c)); + + tdb = tdb_open_ex("mutex-transaction1.tdb", 0, + tdb_flags, O_RDWR|O_CREAT, 0755, + &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + /* + * The child has the transaction running + */ + ret = tdb_transaction_start_nonblock(tdb); + ok(ret == -1, "tdb_transaction_start_nonblock not succeed"); + + ret = tdb_chainlock_nonblock(tdb, key); + ok(ret == -1, "tdb_chainlock_nonblock should not succeed"); + + /* + * We can still read + */ + ret = tdb_exists(tdb, key); + ok(ret == 0, "tdb_exists(tdb, key) should return 0"); + + val = tdb_fetch(tdb, key); + ok(val.dsize == 0, "tdb_fetch(tdb, key) should return an empty value"); + + write(tochild[1], &c, sizeof(c)); + + /* + * When the child canceled we can start... + */ + ret = tdb_transaction_start(tdb); + ok(ret == 0, "tdb_transaction_start should succeed"); + + read(fromchild[0], &c, sizeof(c)); + write(tochild[1], &c, sizeof(c)); + + ret = tdb_transaction_cancel(tdb); + ok(ret == 0, "tdb_transaction_cancel should succeed"); + + /* + * When we canceled the child can start and store... + */ + read(fromchild[0], &c, sizeof(c)); + + /* + * We still see the old values before the child commits... + */ + ret = tdb_exists(tdb, key); + ok(ret == 0, "tdb_exists(tdb, key) should return 0"); + + val = tdb_fetch(tdb, key); + ok(val.dsize == 0, "tdb_fetch(tdb, key) should return an empty value"); + + write(tochild[1], &c, sizeof(c)); + read(fromchild[0], &c, sizeof(c)); + + /* + * We see the new values after the commit... + */ + ret = tdb_exists(tdb, key); + ok(ret == 1, "tdb_exists(tdb, key) should return 1"); + + val = tdb_fetch(tdb, key); + ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value"); + ok(val.dsize == data.dsize, "tdb_fetch(tdb, key) should return a value"); + ok(memcmp(val.dptr, data.dptr, data.dsize) == 0, "tdb_fetch(tdb, key) should return a value"); + + write(tochild[1], &c, sizeof(c)); + read(fromchild[0], &c, sizeof(c)); + + /* + * The child started a new transaction and replaces the value, + * but we still see the old values before the child commits... + */ + ret = tdb_exists(tdb, key); + ok(ret == 1, "tdb_exists(tdb, key) should return 1"); + + val = tdb_fetch(tdb, key); + ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value"); + ok(val.dsize == data.dsize, "tdb_fetch(tdb, key) should return a value"); + ok(memcmp(val.dptr, data.dptr, data.dsize) == 0, "tdb_fetch(tdb, key) should return a value"); + + write(tochild[1], &c, sizeof(c)); + read(fromchild[0], &c, sizeof(c)); + + /* + * We see the new values after the commit... + */ + ret = tdb_exists(tdb, key); + ok(ret == 1, "tdb_exists(tdb, key) should return 1"); + + val = tdb_fetch(tdb, key); + ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value"); + ok(val.dsize == key.dsize, "tdb_fetch(tdb, key) should return a value"); + ok(memcmp(val.dptr, key.dptr, key.dsize) == 0, "tdb_fetch(tdb, key) should return a value"); + + write(tochild[1], &c, sizeof(c)); + + wait_ret = wait(&status); + ok(wait_ret == child, "child should have exited correctly"); + + diag("done"); + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex-trylock.c b/ldb-2.0.8/lib/tdb/test/run-mutex-trylock.c new file mode 100644 index 0000000..c96b635 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex-trylock.c @@ -0,0 +1,122 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include + +static TDB_DATA key, data; + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static int do_child(int tdb_flags, int to, int from) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret; + char c = 0; + + tdb = tdb_open_ex("mutex-trylock.tdb", 0, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_chainlock(tdb, key); + ok(ret == 0, "tdb_chainlock should succeed"); + + write(to, &c, sizeof(c)); + + read(from, &c, sizeof(c)); + + ret = tdb_chainunlock(tdb, key); + ok(ret == 0, "tdb_chainunlock should succeed"); + + write(to, &c, sizeof(c)); + + return 0; +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret, status; + pid_t child, wait_ret; + int fromchild[2]; + int tochild[2]; + char c; + int tdb_flags; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + if (!runtime_support) { + skip(1, "No robust mutex support"); + return exit_status(); + } + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + pipe(fromchild); + pipe(tochild); + + tdb_flags = TDB_INCOMPATIBLE_HASH| + TDB_MUTEX_LOCKING| + TDB_CLEAR_IF_FIRST; + + child = fork(); + if (child == 0) { + close(fromchild[0]); + close(tochild[1]); + return do_child(tdb_flags, fromchild[1], tochild[0]); + } + close(fromchild[1]); + close(tochild[0]); + + read(fromchild[0], &c, sizeof(c)); + + tdb = tdb_open_ex("mutex-trylock.tdb", 0, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_chainlock_nonblock(tdb, key); + ok(ret == -1, "tdb_chainlock_nonblock should not succeed"); + + write(tochild[1], &c, sizeof(c)); + + read(fromchild[0], &c, sizeof(c)); + + ret = tdb_chainlock_nonblock(tdb, key); + ok(ret == 0, "tdb_chainlock_nonblock should succeed"); + ret = tdb_chainunlock(tdb, key); + ok(ret == 0, "tdb_chainunlock should succeed"); + + wait_ret = wait(&status); + ok(wait_ret == child, "child should have exited correctly"); + + diag("done"); + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-mutex1.c b/ldb-2.0.8/lib/tdb/test/run-mutex1.c new file mode 100644 index 0000000..eb75946 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-mutex1.c @@ -0,0 +1,138 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include + +static TDB_DATA key, data; + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static int do_child(int tdb_flags, int to, int from) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret; + char c = 0; + + tdb = tdb_open_ex("mutex1.tdb", 0, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_chainlock(tdb, key); + ok(ret == 0, "tdb_chainlock should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_chainunlock(tdb, key); + ok(ret == 0, "tdb_chainunlock should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); + ok(ret == 0, "tdb_allrecord_lock should succeed"); + + write(to, &c, sizeof(c)); + read(from, &c, sizeof(c)); + + ret = tdb_allrecord_unlock(tdb, F_WRLCK, false); + ok(ret == 0, "tdb_allrecord_lock should succeed"); + + return 0; +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + int ret, status; + pid_t child, wait_ret; + int fromchild[2]; + int tochild[2]; + char c; + int tdb_flags; + bool runtime_support; + + runtime_support = tdb_runtime_check_for_robust_mutexes(); + + if (!runtime_support) { + skip(1, "No robust mutex support"); + return exit_status(); + } + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + pipe(fromchild); + pipe(tochild); + + tdb_flags = TDB_INCOMPATIBLE_HASH| + TDB_MUTEX_LOCKING| + TDB_CLEAR_IF_FIRST; + + child = fork(); + if (child == 0) { + close(fromchild[0]); + close(tochild[1]); + return do_child(tdb_flags, fromchild[1], tochild[0]); + } + close(fromchild[1]); + close(tochild[0]); + + read(fromchild[0], &c, sizeof(c)); + + tdb = tdb_open_ex("mutex1.tdb", 0, tdb_flags, + O_RDWR|O_CREAT, 0755, &log_ctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + write(tochild[1], &c, sizeof(c)); + read(fromchild[0], &c, sizeof(c)); + + ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); + ok(ret == 0, "tdb_allrecord_lock should succeed"); + + ret = tdb_store(tdb, key, data, 0); + ok(ret == 0, "tdb_store should succeed"); + + ret = tdb_allrecord_unlock(tdb, F_WRLCK, false); + ok(ret == 0, "tdb_allrecord_unlock should succeed"); + + write(tochild[1], &c, sizeof(c)); + read(fromchild[0], &c, sizeof(c)); + write(tochild[1], &c, sizeof(c)); + + ret = tdb_delete(tdb, key); + ok(ret == 0, "tdb_delete should succeed"); + + wait_ret = wait(&status); + ok(wait_ret == child, "child should have exited correctly"); + + diag("done"); + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-nested-transactions.c b/ldb-2.0.8/lib/tdb/test/run-nested-transactions.c new file mode 100644 index 0000000..864adf2 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-nested-transactions.c @@ -0,0 +1,79 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(27); + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + + tdb = tdb_open_ex("run-nested-transactions.tdb", + 1024, TDB_CLEAR_IF_FIRST|TDB_DISALLOW_NESTING, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + ok1(tdb); + + /* Nesting disallowed. */ + ok1(tdb_transaction_start(tdb) == 0); + data.dptr = discard_const_p(uint8_t, "world"); + data.dsize = strlen("world"); + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + ok1(tdb_transaction_start(tdb) != 0); + ok1(tdb_error(tdb) == TDB_ERR_NESTING); + + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + ok1(tdb_transaction_commit(tdb) == 0); + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + tdb_close(tdb); + + /* Nesting allowed by default */ + tdb = tdb_open_ex("run-nested-transactions.tdb", + 1024, TDB_DEFAULT, O_RDWR, 0, &taplogctx, NULL); + ok1(tdb); + + ok1(tdb_transaction_start(tdb) == 0); + ok1(tdb_transaction_start(tdb) == 0); + ok1(tdb_delete(tdb, key) == 0); + ok1(tdb_transaction_commit(tdb) == 0); + ok1(!tdb_exists(tdb, key)); + ok1(tdb_transaction_cancel(tdb) == 0); + /* Surprise! Kills inner "committed" transaction. */ + ok1(tdb_exists(tdb, key)); + + ok1(tdb_transaction_start(tdb) == 0); + ok1(tdb_transaction_start(tdb) == 0); + ok1(tdb_delete(tdb, key) == 0); + ok1(tdb_transaction_commit(tdb) == 0); + ok1(!tdb_exists(tdb, key)); + ok1(tdb_transaction_commit(tdb) == 0); + ok1(!tdb_exists(tdb, key)); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-nested-traverse.c b/ldb-2.0.8/lib/tdb/test/run-nested-traverse.c new file mode 100644 index 0000000..aeaa085 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-nested-traverse.c @@ -0,0 +1,111 @@ +#include "../common/tdb_private.h" +#include "lock-tracking.h" +#define fcntl fcntl_with_lockcheck +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#undef fcntl +#include +#include +#include "external-agent.h" +#include "logging.h" + +static struct agent *agent; + +static bool correct_key(TDB_DATA key) +{ + return key.dsize == strlen("hi") + && memcmp(key.dptr, "hi", key.dsize) == 0; +} + +static bool correct_data(TDB_DATA data) +{ + return data.dsize == strlen("world") + && memcmp(data.dptr, "world", data.dsize) == 0; +} + +static int traverse2(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, + void *p) +{ + ok1(correct_key(key)); + ok1(correct_data(data)); + return 0; +} + +static int traverse1r(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, + void *p) +{ + ok1(correct_key(key)); + ok1(correct_data(data)); + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == SUCCESS); + ok1(external_agent_operation(agent, STORE, tdb_name(tdb)) + == SUCCESS); + ok1(external_agent_operation(agent, TRANSACTION_COMMIT, tdb_name(tdb)) + == WOULD_HAVE_BLOCKED); + tdb_traverse(tdb, traverse2, NULL); + + /* That should *not* release the all-records lock! */ + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == SUCCESS); + ok1(external_agent_operation(agent, STORE, tdb_name(tdb)) + == SUCCESS); + ok1(external_agent_operation(agent, TRANSACTION_COMMIT, tdb_name(tdb)) + == WOULD_HAVE_BLOCKED); + return 0; +} + +static int traverse1w(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, + void *p) +{ + ok1(correct_key(key)); + ok1(correct_data(data)); + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == WOULD_HAVE_BLOCKED); + tdb_traverse(tdb, traverse2, NULL); + + /* That should *not* release the all-records lock! */ + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == WOULD_HAVE_BLOCKED); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(17); + agent = prepare_external_agent(); + + tdb = tdb_open_ex("run-nested-traverse.tdb", 1024, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + ok1(tdb); + + ok1(external_agent_operation(agent, OPEN, tdb_name(tdb)) == SUCCESS); + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == SUCCESS); + ok1(external_agent_operation(agent, TRANSACTION_COMMIT, tdb_name(tdb)) + == SUCCESS); + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dptr = discard_const_p(uint8_t, "world"); + data.dsize = strlen("world"); + + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + tdb_traverse(tdb, traverse1w, NULL); + tdb_traverse_read(tdb, traverse1r, NULL); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-no-lock-during-traverse.c b/ldb-2.0.8/lib/tdb/test/run-no-lock-during-traverse.c new file mode 100644 index 0000000..737a32f --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-no-lock-during-traverse.c @@ -0,0 +1,114 @@ +#include "../common/tdb_private.h" +#include "lock-tracking.h" + +#define fcntl fcntl_with_lockcheck + +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +#undef fcntl + +#define NUM_ENTRIES 10 + +static bool prepare_entries(struct tdb_context *tdb) +{ + unsigned int i; + TDB_DATA key, data; + + for (i = 0; i < NUM_ENTRIES; i++) { + key.dsize = sizeof(i); + key.dptr = (void *)&i; + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + if (tdb_store(tdb, key, data, 0) != 0) + return false; + } + return true; +} + +static void delete_entries(struct tdb_context *tdb) +{ + unsigned int i; + TDB_DATA key; + + for (i = 0; i < NUM_ENTRIES; i++) { + key.dsize = sizeof(i); + key.dptr = (void *)&i; + + ok1(tdb_delete(tdb, key) == 0); + } +} + +/* We don't know how many times this will run. */ +static int delete_other(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, + void *private_data) +{ + unsigned int i; + memcpy(&i, key.dptr, 4); + i = (i + 1) % NUM_ENTRIES; + key.dptr = (void *)&i; + if (tdb_delete(tdb, key) != 0) + (*(int *)private_data)++; + return 0; +} + +static int delete_self(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, + void *private_data) +{ + ok1(tdb_delete(tdb, key) == 0); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + int errors = 0; + + plan_tests(41); + tdb = tdb_open_ex("run-no-lock-during-traverse.tdb", + 1024, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR, + 0600, &taplogctx, NULL); + + ok1(tdb); + ok1(prepare_entries(tdb)); + ok1(locking_errors == 0); + ok1(tdb_lockall(tdb) == 0); + ok1(locking_errors == 0); + tdb_traverse(tdb, delete_other, &errors); + ok1(errors == 0); + ok1(locking_errors == 0); + ok1(tdb_unlockall(tdb) == 0); + + ok1(prepare_entries(tdb)); + ok1(locking_errors == 0); + ok1(tdb_lockall(tdb) == 0); + ok1(locking_errors == 0); + tdb_traverse(tdb, delete_self, NULL); + ok1(locking_errors == 0); + ok1(tdb_unlockall(tdb) == 0); + + ok1(prepare_entries(tdb)); + ok1(locking_errors == 0); + ok1(tdb_lockall(tdb) == 0); + ok1(locking_errors == 0); + delete_entries(tdb); + ok1(locking_errors == 0); + ok1(tdb_unlockall(tdb) == 0); + + ok1(tdb_close(tdb) == 0); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-oldhash.c b/ldb-2.0.8/lib/tdb/test/run-oldhash.c new file mode 100644 index 0000000..aaee6f6 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-oldhash.c @@ -0,0 +1,50 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + + plan_tests(8); + + /* Old format (with zeroes in the hash magic fields) should + * open with any hash (since we don't know what hash they used). */ + tdb = tdb_open_ex("test/old-nohash-le.tdb", 0, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + tdb = tdb_open_ex("test/old-nohash-be.tdb", 0, 0, O_RDWR, 0, + &taplogctx, NULL); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + tdb = tdb_open_ex("test/old-nohash-le.tdb", 0, 0, O_RDWR, 0, + &taplogctx, tdb_jenkins_hash); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + tdb = tdb_open_ex("test/old-nohash-be.tdb", 0, 0, O_RDWR, 0, + &taplogctx, tdb_jenkins_hash); + ok1(tdb); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-open-during-transaction.c b/ldb-2.0.8/lib/tdb/test/run-open-during-transaction.c new file mode 100644 index 0000000..9a6c6c1 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-open-during-transaction.c @@ -0,0 +1,183 @@ +#include "../common/tdb_private.h" +#include "lock-tracking.h" + +static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset); +static ssize_t write_check(int fd, const void *buf, size_t count); +static int ftruncate_check(int fd, off_t length); + +#define pwrite pwrite_check +#define write write_check +#define fcntl fcntl_with_lockcheck +#define ftruncate ftruncate_check + +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include "external-agent.h" +#include "logging.h" + +static struct agent *agent; +static bool opened; +static int errors = 0; +static bool clear_if_first; +#define TEST_DBNAME "run-open-during-transaction.tdb" + +#undef write +#undef pwrite +#undef fcntl +#undef ftruncate + +static bool is_same(const char *snapshot, const char *latest, off_t len) +{ + unsigned i; + + for (i = 0; i < len; i++) { + if (snapshot[i] != latest[i]) + return false; + } + return true; +} + +static bool compare_file(int fd, const char *snapshot, off_t snapshot_len) +{ + char *contents; + bool same; + + /* over-length read serves as length check. */ + contents = malloc(snapshot_len+1); + same = pread(fd, contents, snapshot_len+1, 0) == snapshot_len + && is_same(snapshot, contents, snapshot_len); + free(contents); + return same; +} + +static void check_file_intact(int fd) +{ + enum agent_return ret; + struct stat st; + char *contents; + + fstat(fd, &st); + contents = malloc(st.st_size); + if (pread(fd, contents, st.st_size, 0) != st.st_size) { + diag("Read fail"); + errors++; + free(contents); + return; + } + + /* Ask agent to open file. */ + ret = external_agent_operation(agent, clear_if_first ? + OPEN_WITH_CLEAR_IF_FIRST : + OPEN, + TEST_DBNAME); + + /* It's OK to open it, but it must not have changed! */ + if (!compare_file(fd, contents, st.st_size)) { + diag("Agent changed file after opening %s", + agent_return_name(ret)); + errors++; + } + + if (ret == SUCCESS) { + ret = external_agent_operation(agent, CLOSE, NULL); + if (ret != SUCCESS) { + diag("Agent failed to close tdb: %s", + agent_return_name(ret)); + errors++; + } + } else if (ret != WOULD_HAVE_BLOCKED) { + diag("Agent opening file gave %s", + agent_return_name(ret)); + errors++; + } + + free(contents); +} + +static void after_unlock(int fd) +{ + if (opened) + check_file_intact(fd); +} + +static ssize_t pwrite_check(int fd, + const void *buf, size_t count, off_t offset) +{ + if (opened) + check_file_intact(fd); + + return pwrite(fd, buf, count, offset); +} + +static ssize_t write_check(int fd, const void *buf, size_t count) +{ + if (opened) + check_file_intact(fd); + + return write(fd, buf, count); +} + +static int ftruncate_check(int fd, off_t length) +{ + if (opened) + check_file_intact(fd); + + return ftruncate(fd, length); + +} + +int main(int argc, char *argv[]) +{ + const int flags[] = { TDB_DEFAULT, + TDB_CLEAR_IF_FIRST, + TDB_NOMMAP, + TDB_CLEAR_IF_FIRST | TDB_NOMMAP }; + int i; + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(20); + agent = prepare_external_agent(); + + unlock_callback = after_unlock; + for (i = 0; i < sizeof(flags)/sizeof(flags[0]); i++) { + clear_if_first = (flags[i] & TDB_CLEAR_IF_FIRST); + diag("Test with %s and %s", + clear_if_first ? "CLEAR" : "DEFAULT", + (flags[i] & TDB_NOMMAP) ? "no mmap" : "mmap"); + unlink(TEST_DBNAME); + tdb = tdb_open_ex(TEST_DBNAME, 1024, flags[i], + O_CREAT|O_TRUNC|O_RDWR, 0600, + &taplogctx, NULL); + ok1(tdb); + + opened = true; + ok1(tdb_transaction_start(tdb) == 0); + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dptr = discard_const_p(uint8_t, "world"); + data.dsize = strlen("world"); + + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + ok1(tdb_transaction_commit(tdb) == 0); + ok(!errors, "We had %u open errors", errors); + + opened = false; + tdb_close(tdb); + } + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-rdlock-upgrade.c b/ldb-2.0.8/lib/tdb/test/run-rdlock-upgrade.c new file mode 100644 index 0000000..042001b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-rdlock-upgrade.c @@ -0,0 +1,166 @@ +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include +#include +#include +#include "logging.h" + +static TDB_DATA key, data; + +static void do_chainlock(const char *name, int tdb_flags, int up, int down) +{ + struct tdb_context *tdb; + int ret; + ssize_t nread, nwritten; + char c = 0; + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + ret = tdb_chainlock_read(tdb, key); + ok(ret == 0, "tdb_chainlock_read should succeed"); + + nwritten = write(up, &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(down, &c, sizeof(c)); + ok(nread == 0, "read should succeed"); + + exit(0); +} + +static void do_trylock(const char *name, int tdb_flags, int up, int down) +{ + struct tdb_context *tdb; + int ret; + ssize_t nread, nwritten; + char c = 0; + + tdb = tdb_open_ex(name, 3, tdb_flags, + O_RDWR|O_CREAT, 0755, &taplogctx, NULL); + ok(tdb, "tdb_open_ex should succeed"); + + /* + * tdb used to have a bug where with fcntl locks an upgrade + * from a readlock to writelock did not check for the + * underlying fcntl lock. Mutexes don't distinguish between + * readlocks and writelocks, so that bug does not apply here. + */ + + ret = tdb_chainlock_read(tdb, key); + ok(ret == 0, "tdb_chainlock_read should succeed"); + + ret = tdb_chainlock_nonblock(tdb, key); + ok(ret == -1, "tdb_chainlock_nonblock should fail"); + + nwritten = write(up, &c, sizeof(c)); + ok(nwritten == sizeof(c), "write should succeed"); + + nread = read(down, &c, sizeof(c)); + ok(nread == 0, "read should succeed"); + + exit(0); +} + +static int do_tests(const char *name, int tdb_flags) +{ + int ret; + pid_t chainlock_child, store_child; + int chainlock_down[2]; + int chainlock_up[2]; + int store_down[2]; + int store_up[2]; + char c; + ssize_t nread; + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + ret = pipe(chainlock_down); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(chainlock_up); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(store_down); + ok(ret == 0, "pipe should succeed"); + + ret = pipe(store_up); + ok(ret == 0, "pipe should succeed"); + + chainlock_child = fork(); + ok(chainlock_child != -1, "fork should succeed"); + + if (chainlock_child == 0) { + close(chainlock_up[0]); + close(chainlock_down[1]); + close(store_up[0]); + close(store_up[1]); + close(store_down[0]); + close(store_down[1]); + do_chainlock(name, tdb_flags, + chainlock_up[1], chainlock_down[0]); + exit(0); + } + close(chainlock_up[1]); + close(chainlock_down[0]); + + nread = read(chainlock_up[0], &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + /* + * Now we have a process holding a chain read lock. Start + * another process trying to write lock. This should fail. + */ + + store_child = fork(); + ok(store_child != -1, "fork should succeed"); + + if (store_child == 0) { + close(chainlock_up[0]); + close(chainlock_down[1]); + close(store_up[0]); + close(store_down[1]); + do_trylock(name, tdb_flags, + store_up[1], store_down[0]); + exit(0); + } + close(store_up[1]); + close(store_down[0]); + + nread = read(store_up[0], &c, sizeof(c)); + ok(nread == sizeof(c), "read should succeed"); + + close(chainlock_up[0]); + close(chainlock_down[1]); + close(store_up[0]); + close(store_down[1]); + diag("%s tests done", name); + return exit_status(); +} + +int main(int argc, char *argv[]) +{ + int ret; + + ret = do_tests("rdlock-upgrade.tdb", + TDB_CLEAR_IF_FIRST | + TDB_INCOMPATIBLE_HASH); + ok(ret == 0, "rdlock-upgrade.tdb tests should succeed"); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-readonly-check.c b/ldb-2.0.8/lib/tdb/test/run-readonly-check.c new file mode 100644 index 0000000..c5e0f7d --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-readonly-check.c @@ -0,0 +1,53 @@ +/* We should be able to tdb_check a O_RDONLY tdb, and we were previously allowed + * to tdb_check() inside a transaction (though that's paranoia!). */ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(11); + tdb = tdb_open_ex("run-readonly-check.tdb", 1024, + TDB_DEFAULT, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + ok1(tdb); + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + + /* We are also allowed to do a check inside a transaction. */ + ok1(tdb_transaction_start(tdb) == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + ok1(tdb_close(tdb) == 0); + + tdb = tdb_open_ex("run-readonly-check.tdb", 1024, + TDB_DEFAULT, O_RDONLY, 0, &taplogctx, NULL); + + ok1(tdb); + ok1(tdb_store(tdb, key, data, TDB_MODIFY) == -1); + ok1(tdb_error(tdb) == TDB_ERR_RDONLY); + ok1(tdb_check(tdb, NULL, NULL) == 0); + ok1(tdb_close(tdb) == 0); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-rescue-find_entry.c b/ldb-2.0.8/lib/tdb/test/run-rescue-find_entry.c new file mode 100644 index 0000000..5d6f8f7 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-rescue-find_entry.c @@ -0,0 +1,51 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/rescue.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +#define NUM 20 + +/* Binary searches are deceptively simple: easy to screw up! */ +int main(int argc, char *argv[]) +{ + unsigned int i, j, n; + struct found f[NUM+1]; + struct found_table table; + + /* Set up array for searching. */ + for (i = 0; i < NUM+1; i++) { + f[i].head = i * 3; + } + table.arr = f; + + for (i = 0; i < NUM; i++) { + table.num = i; + for (j = 0; j < (i + 2) * 3; j++) { + n = find_entry(&table, j); + ok1(n <= i); + + /* If we were searching for something too large... */ + if (j > i*3) + ok1(n == i); + else { + /* It must give us something after j */ + ok1(f[n].head >= j); + ok1(n == 0 || f[n-1].head < j); + } + } + } + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-rescue.c b/ldb-2.0.8/lib/tdb/test/run-rescue.c new file mode 100644 index 0000000..e43f53b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-rescue.c @@ -0,0 +1,127 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/rescue.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +struct walk_data { + TDB_DATA key; + TDB_DATA data; + bool fail; + unsigned count; +}; + +static inline bool tdb_deq(TDB_DATA a, TDB_DATA b) +{ + return a.dsize == b.dsize && memcmp(a.dptr, b.dptr, a.dsize) == 0; +} + +static inline TDB_DATA tdb_mkdata(const void *p, size_t len) +{ + TDB_DATA d; + d.dptr = discard_const_p(uint8_t, p); + d.dsize = len; + return d; +} + +static void walk(TDB_DATA key, TDB_DATA data, void *_wd) +{ + struct walk_data *wd = _wd; + + if (!tdb_deq(key, wd->key)) { + wd->fail = true; + } + + if (!tdb_deq(data, wd->data)) { + wd->fail = true; + } + wd->count++; +} + +static void count_records(TDB_DATA key, TDB_DATA data, void *_wd) +{ + struct walk_data *wd = _wd; + + if (!tdb_deq(key, wd->key) || !tdb_deq(data, wd->data)) + diag("%.*s::%.*s", + (int)key.dsize, key.dptr, (int)data.dsize, data.dptr); + wd->count++; +} + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ + unsigned int *count = tdb_get_logging_private(tdb); + (*count)++; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + struct walk_data wd; + unsigned int i, size, log_count = 0; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + + plan_tests(8); + tdb = tdb_open_ex("run-rescue.tdb", 1, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &log_ctx, NULL); + + wd.key.dsize = strlen("hi"); + wd.key.dptr = discard_const_p(uint8_t, "hi"); + wd.data.dsize = strlen("world"); + wd.data.dptr = discard_const_p(uint8_t, "world"); + wd.count = 0; + wd.fail = false; + + ok1(tdb_store(tdb, wd.key, wd.data, TDB_INSERT) == 0); + + ok1(tdb_rescue(tdb, walk, &wd) == 0); + ok1(!wd.fail); + ok1(wd.count == 1); + + /* Corrupt the database, walk should either get it or not. */ + size = tdb->map_size; + for (i = sizeof(struct tdb_header); i < size; i++) { + char c; + if (tdb->methods->tdb_read(tdb, i, &c, 1, false) != 0) + fail("Reading offset %i", i); + if (tdb->methods->tdb_write(tdb, i, "X", 1) != 0) + fail("Writing X at offset %i", i); + + wd.count = 0; + if (tdb_rescue(tdb, count_records, &wd) != 0) { + wd.fail = true; + break; + } + /* Could be 0 or 1. */ + if (wd.count > 1) { + wd.fail = true; + break; + } + if (tdb->methods->tdb_write(tdb, i, &c, 1) != 0) + fail("Restoring offset %i", i); + } + ok1(log_count == 0); + ok1(!wd.fail); + tdb_close(tdb); + + /* Now try our known-corrupt db. */ + tdb = tdb_open_ex("test/tdb.corrupt", 1024, 0, O_RDWR, 0, + &taplogctx, NULL); + wd.count = 0; + ok1(tdb_rescue(tdb, count_records, &wd) == 0); + ok1(wd.count == 1627); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-rwlock-check.c b/ldb-2.0.8/lib/tdb/test/run-rwlock-check.c new file mode 100644 index 0000000..2ac9dc3 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-rwlock-check.c @@ -0,0 +1,46 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ + unsigned int *count = tdb_get_logging_private(tdb); + if (strstr(fmt, "spinlocks")) + (*count)++; +} + +/* The code should barf on TDBs created with rwlocks. */ +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + + plan_tests(4); + + /* We should fail to open rwlock-using tdbs of either endian. */ + log_count = 0; + tdb = tdb_open_ex("test/rwlock-le.tdb", 0, 0, O_RDWR, 0, + &log_ctx, NULL); + ok1(!tdb); + ok1(log_count == 1); + + log_count = 0; + tdb = tdb_open_ex("test/rwlock-be.tdb", 0, 0, O_RDWR, 0, + &log_ctx, NULL); + ok1(!tdb); + ok1(log_count == 1); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-summary.c b/ldb-2.0.8/lib/tdb/test/run-summary.c new file mode 100644 index 0000000..8b9a1a0 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-summary.c @@ -0,0 +1,65 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/summary.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include + +int main(int argc, char *argv[]) +{ + unsigned int i, j; + struct tdb_context *tdb; + int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP, + TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, + TDB_NOMMAP|TDB_CONVERT }; + TDB_DATA key = { (unsigned char *)&j, sizeof(j) }; + TDB_DATA data = { (unsigned char *)&j, sizeof(j) }; + char *summary; + + plan_tests(sizeof(flags) / sizeof(flags[0]) * 14); + for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { + tdb = tdb_open("run-summary.tdb", 131, flags[i], + O_RDWR|O_CREAT|O_TRUNC, 0600); + ok1(tdb); + if (!tdb) + continue; + + /* Put some stuff in there. */ + for (j = 0; j < 500; j++) { + /* Make sure padding varies to we get some graphs! */ + data.dsize = j % (sizeof(j) + 1); + if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) + fail("Storing in tdb"); + } + + summary = tdb_summary(tdb); + diag("%s", summary); + ok1(strstr(summary, "Size of file/data: ")); + ok1(strstr(summary, "Number of records: 500\n")); + ok1(strstr(summary, "Smallest/average/largest keys: 4/4/4\n")); + ok1(strstr(summary, "Smallest/average/largest data: 0/2/4\n")); + ok1(strstr(summary, "Smallest/average/largest padding: ")); + ok1(strstr(summary, "Number of dead records: 0\n")); + ok1(strstr(summary, "Number of free records: 1\n")); + ok1(strstr(summary, "Smallest/average/largest free records: ")); + ok1(strstr(summary, "Number of hash chains: 131\n")); + ok1(strstr(summary, "Smallest/average/largest hash chains: ")); + ok1(strstr(summary, "Number of uncoalesced records: 0\n")); + ok1(strstr(summary, "Smallest/average/largest uncoalesced runs: 0/0/0\n")); + ok1(strstr(summary, "Percentage keys/data/padding/free/dead/rechdrs&tailers/hashes: ")); + + free(summary); + tdb_close(tdb); + } + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-transaction-expand.c b/ldb-2.0.8/lib/tdb/test/run-transaction-expand.c new file mode 100644 index 0000000..d36b894 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-transaction-expand.c @@ -0,0 +1,125 @@ +#include "../common/tdb_private.h" + +/* Speed up the tests, but do the actual sync tests. */ +static unsigned int sync_counts = 0; +static inline int fake_fsync(int fd) +{ + sync_counts++; + return 0; +} +#define fsync fake_fsync + +#ifdef MS_SYNC +static inline int fake_msync(void *addr, size_t length, int flags) +{ + sync_counts++; + return 0; +} +#define msync fake_msync +#endif + +#ifdef HAVE_FDATASYNC +static inline int fake_fdatasync(int fd) +{ + sync_counts++; + return 0; +} +#define fdatasync fake_fdatasync +#endif + +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +static void write_record(struct tdb_context *tdb, size_t extra_len, + TDB_DATA *data) +{ + TDB_DATA key; + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + + data->dsize += extra_len; + tdb_transaction_start(tdb); + tdb_store(tdb, key, *data, TDB_REPLACE); + tdb_transaction_commit(tdb); +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + size_t i; + TDB_DATA data; + struct tdb_record rec; + tdb_off_t off; + + /* Do *not* suppress sync for this test; we do it ourselves. */ + unsetenv("TDB_NO_FSYNC"); + + plan_tests(5); + tdb = tdb_open_ex("run-transaction-expand.tdb", + 1024, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + ok1(tdb); + + data.dsize = 0; + data.dptr = calloc(1000, getpagesize()); + if (data.dptr == NULL) { + diag("Unable to allocate memory for data.dptr"); + tdb_close(tdb); + exit(1); + } + + /* Simulate a slowly growing record. */ + for (i = 0; i < 1000; i++) + write_record(tdb, getpagesize(), &data); + + tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &off); + tdb_read(tdb, off, &rec, sizeof(rec), DOCONV()); + diag("TDB size = %zu, recovery = %llu-%llu", + (size_t)tdb->map_size, (unsigned long long)off, (unsigned long long)(off + sizeof(rec) + rec.rec_len)); + + /* We should only be about 5 times larger than largest record. */ + ok1(tdb->map_size < 6 * i * getpagesize()); + tdb_close(tdb); + + tdb = tdb_open_ex("run-transaction-expand.tdb", + 1024, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + ok1(tdb); + + data.dsize = 0; + + /* Simulate a slowly growing record, repacking to keep + * recovery area at end. */ + for (i = 0; i < 1000; i++) { + write_record(tdb, getpagesize(), &data); + if (i % 10 == 0) + tdb_repack(tdb); + } + + tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &off); + tdb_read(tdb, off, &rec, sizeof(rec), DOCONV()); + diag("TDB size = %zu, recovery = %llu-%llu", + (size_t)tdb->map_size, (unsigned long long)off, (unsigned long long)(off + sizeof(rec) + rec.rec_len)); + + /* We should only be about 4 times larger than largest record. */ + ok1(tdb->map_size < 5 * i * getpagesize()); + + /* We should have synchronized multiple times. */ + ok1(sync_counts); + tdb_close(tdb); + free(data.dptr); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-traverse-chain.c b/ldb-2.0.8/lib/tdb/test/run-traverse-chain.c new file mode 100644 index 0000000..2a25bec --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-traverse-chain.c @@ -0,0 +1,94 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +static char keystr0[] = "x"; +static TDB_DATA key0 = { .dptr = (uint8_t *)keystr0, + .dsize = sizeof(keystr0) }; +static char valuestr0[] = "y"; +static TDB_DATA value0 = { .dptr = (uint8_t *)valuestr0, + .dsize = sizeof(valuestr0) }; + +static char keystr1[] = "aaa"; +static TDB_DATA key1 = { .dptr = (uint8_t *)keystr1, + .dsize = sizeof(keystr1) }; +static char valuestr1[] = "bbbbb"; +static TDB_DATA value1 = { .dptr = (uint8_t *)valuestr1, + .dsize = sizeof(valuestr1) }; + +static TDB_DATA *keys[] = { &key0, &key1 }; +static TDB_DATA *values[] = { &value0, &value1 }; + +static bool tdb_data_same(TDB_DATA d1, TDB_DATA d2) +{ + if (d1.dsize != d2.dsize) { + return false; + } + return (memcmp(d1.dptr, d2.dptr, d1.dsize) == 0); +} + +struct traverse_chain_state { + size_t idx; + bool ok; +}; + +static int traverse_chain_fn(struct tdb_context *tdb, + TDB_DATA key, + TDB_DATA data, + void *private_data) +{ + struct traverse_chain_state *state = private_data; + + state->ok &= tdb_data_same(key, *keys[state->idx]); + state->ok &= tdb_data_same(data, *values[state->idx]); + state->idx += 1; + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + struct traverse_chain_state state = { .ok = true }; + int ret; + + plan_tests(4); + + tdb = tdb_open_ex( + "traverse_chain.tdb", + 1, + TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, + 0600, + &taplogctx, + NULL); + ok1(tdb); + + /* add in reverse order, tdb_store adds to the front of the list */ + ret = tdb_store(tdb, key1, value1, TDB_INSERT); + ok1(ret == 0); + ret = tdb_store(tdb, key0, value0, TDB_INSERT); + ok1(ret == 0); + + ret = tdb_traverse_key_chain(tdb, key0, traverse_chain_fn, &state); + ok1(ret == 2); + ok1(state.ok); + + unlink(tdb_name(tdb)); + + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-traverse-in-transaction.c b/ldb-2.0.8/lib/tdb/test/run-traverse-in-transaction.c new file mode 100644 index 0000000..d187b9b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-traverse-in-transaction.c @@ -0,0 +1,90 @@ +#include "lock-tracking.h" +#include "../common/tdb_private.h" +#define fcntl fcntl_with_lockcheck +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#undef fcntl_with_lockcheck +#include +#include +#include "external-agent.h" +#include "logging.h" + +static struct agent *agent; + +static bool correct_key(TDB_DATA key) +{ + return key.dsize == strlen("hi") + && memcmp(key.dptr, "hi", key.dsize) == 0; +} + +static bool correct_data(TDB_DATA data) +{ + return data.dsize == strlen("world") + && memcmp(data.dptr, "world", data.dsize) == 0; +} + +static int traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, + void *p) +{ + ok1(correct_key(key)); + ok1(correct_data(data)); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(13); + agent = prepare_external_agent(); + + tdb = tdb_open_ex("run-traverse-in-transaction.tdb", + 1024, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR, + 0600, &taplogctx, NULL); + ok1(tdb); + + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dptr = discard_const_p(uint8_t, "world"); + data.dsize = strlen("world"); + + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + + ok1(external_agent_operation(agent, OPEN, tdb_name(tdb)) == SUCCESS); + + ok1(tdb_transaction_active(tdb) == 0); + ok1(tdb_transaction_start(tdb) == 0); + ok1(tdb_transaction_active(tdb) == 1); + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == WOULD_HAVE_BLOCKED); + tdb_traverse(tdb, traverse, NULL); + + /* That should *not* release the transaction lock! */ + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == WOULD_HAVE_BLOCKED); + tdb_traverse_read(tdb, traverse, NULL); + + /* That should *not* release the transaction lock! */ + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == WOULD_HAVE_BLOCKED); + ok1(tdb_transaction_commit(tdb) == 0); + ok1(tdb_transaction_active(tdb) == 0); + /* Now we should be fine. */ + ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) + == SUCCESS); + + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-wronghash-fail.c b/ldb-2.0.8/lib/tdb/test/run-wronghash-fail.c new file mode 100644 index 0000000..c44b0f5 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-wronghash-fail.c @@ -0,0 +1,121 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include + +static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ + unsigned int *count = tdb_get_logging_private(tdb); + if (strstr(fmt, "hash")) + (*count)++; +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + unsigned int log_count; + TDB_DATA d; + struct tdb_logging_context log_ctx = { log_fn, &log_count }; + + plan_tests(28); + + /* Create with default hash. */ + log_count = 0; + tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, + O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, NULL); + ok1(tdb); + ok1(log_count == 0); + d.dptr = discard_const_p(uint8_t, "Hello"); + d.dsize = 5; + ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); + tdb_close(tdb); + + /* Fail to open with different hash. */ + tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0, + &log_ctx, tdb_jenkins_hash); + ok1(!tdb); + ok1(log_count == 1); + + /* Create with different hash. */ + log_count = 0; + tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, + O_CREAT|O_RDWR|O_TRUNC, + 0600, &log_ctx, tdb_jenkins_hash); + ok1(tdb); + ok1(log_count == 0); + tdb_close(tdb); + + /* Endian should be no problem. */ + log_count = 0; + tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0, + &log_ctx, tdb_old_hash); + ok1(!tdb); + ok1(log_count == 1); + + log_count = 0; + tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0, + &log_ctx, tdb_old_hash); + ok1(!tdb); + ok1(log_count == 1); + + log_count = 0; + /* Fail to open with old default hash. */ + tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0, + &log_ctx, tdb_old_hash); + ok1(!tdb); + ok1(log_count == 1); + + log_count = 0; + tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDONLY, + 0, &log_ctx, tdb_jenkins_hash); + ok1(tdb); + ok1(log_count == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + log_count = 0; + tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDONLY, + 0, &log_ctx, tdb_jenkins_hash); + ok1(tdb); + ok1(log_count == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + /* It should open with jenkins hash if we don't specify. */ + log_count = 0; + tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0, + &log_ctx, NULL); + ok1(tdb); + ok1(log_count == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + log_count = 0; + tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0, + &log_ctx, NULL); + ok1(tdb); + ok1(log_count == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + log_count = 0; + tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDONLY, + 0, &log_ctx, NULL); + ok1(tdb); + ok1(log_count == 0); + ok1(tdb_check(tdb, NULL, NULL) == 0); + tdb_close(tdb); + + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run-zero-append.c b/ldb-2.0.8/lib/tdb/test/run-zero-append.c new file mode 100644 index 0000000..f9eba1b --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run-zero-append.c @@ -0,0 +1,41 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(4); + tdb = tdb_open_ex(NULL, 1024, TDB_INTERNAL, O_CREAT|O_TRUNC|O_RDWR, + 0600, &taplogctx, NULL); + ok1(tdb); + + /* Tickle bug on appending zero length buffer to zero length buffer. */ + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dptr = discard_const_p(uint8_t, "world"); + data.dsize = 0; + + ok1(tdb_append(tdb, key, data) == 0); + ok1(tdb_append(tdb, key, data) == 0); + data = tdb_fetch(tdb, key); + ok1(data.dsize == 0); + tdb_close(tdb); + free(data.dptr); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/run.c b/ldb-2.0.8/lib/tdb/test/run.c new file mode 100644 index 0000000..c744c4d --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/run.c @@ -0,0 +1,50 @@ +#include "../common/tdb_private.h" +#include "../common/io.c" +#include "../common/tdb.c" +#include "../common/lock.c" +#include "../common/freelist.c" +#include "../common/traverse.c" +#include "../common/transaction.c" +#include "../common/error.c" +#include "../common/open.c" +#include "../common/check.c" +#include "../common/hash.c" +#include "../common/mutex.c" +#include "tap-interface.h" +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + TDB_DATA key, data; + + plan_tests(10); + tdb = tdb_open_ex("run.tdb", 1024, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + ok1(tdb); + key.dsize = strlen("hi"); + key.dptr = discard_const_p(uint8_t, "hi"); + data.dsize = strlen("world"); + data.dptr = discard_const_p(uint8_t, "world"); + + ok1(tdb_store(tdb, key, data, TDB_MODIFY) < 0); + ok1(tdb_error(tdb) == TDB_ERR_NOEXIST); + ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); + ok1(tdb_store(tdb, key, data, TDB_INSERT) < 0); + ok1(tdb_error(tdb) == TDB_ERR_EXISTS); + ok1(tdb_store(tdb, key, data, TDB_MODIFY) == 0); + + data = tdb_fetch(tdb, key); + ok1(data.dsize == strlen("world")); + ok1(memcmp(data.dptr, "world", strlen("world")) == 0); + free(data.dptr); + + key.dsize++; + data = tdb_fetch(tdb, key); + ok1(data.dptr == NULL); + tdb_close(tdb); + + return exit_status(); +} diff --git a/ldb-2.0.8/lib/tdb/test/rwlock-be.tdb b/ldb-2.0.8/lib/tdb/test/rwlock-be.tdb new file mode 100644 index 0000000..45b5f09 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/rwlock-be.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/rwlock-le.tdb b/ldb-2.0.8/lib/tdb/test/rwlock-le.tdb new file mode 100644 index 0000000..45b5f09 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/rwlock-le.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/sample_tdb.tdb b/ldb-2.0.8/lib/tdb/test/sample_tdb.tdb new file mode 100644 index 0000000..a40e50c Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/sample_tdb.tdb differ diff --git a/ldb-2.0.8/lib/tdb/test/tap-interface.h b/ldb-2.0.8/lib/tdb/test/tap-interface.h new file mode 100644 index 0000000..8f742d8 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/tap-interface.h @@ -0,0 +1,58 @@ +/* + Unix SMB/CIFS implementation. + Simplistic implementation of tap interface. + + Copyright (C) Rusty Russell 2012 + + ** NOTE! The following LGPL license applies to the talloc + ** 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 + Lesser 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 . +*/ +#include + +#ifndef __location__ +#define __TAP_STRING_LINE1__(s) #s +#define __TAP_STRING_LINE2__(s) __TAP_STRING_LINE1__(s) +#define __TAP_STRING_LINE3__ __TAP_STRING_LINE2__(__LINE__) +#define __location__ __FILE__ ":" __TAP_STRING_LINE3__ +#endif + +#define plan_tests(num) +#define fail(...) do { \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + fflush(stderr); \ + exit(1); \ +} while(0) +#define diag(...) do { \ + fprintf(stdout, __VA_ARGS__); \ + fprintf(stdout, "\n"); \ + fflush(stdout); \ +} while(0) +#define pass(...) do { \ + fprintf(stdout, "."); \ + fflush(stdout); \ +} while(0) +#define ok(e, ...) do { \ + if (e) { \ + pass(); \ + } else { \ + fail(__VA_ARGS__); \ + } \ +} while(0) +#define ok1(e) ok((e), "%s:%s", __location__, #e) +#define skip(n, ...) diag(__VA_ARGS__) +#define exit_status() 0 diff --git a/ldb-2.0.8/lib/tdb/test/tap-to-subunit.h b/ldb-2.0.8/lib/tdb/test/tap-to-subunit.h new file mode 100644 index 0000000..a5cf74f --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/tap-to-subunit.h @@ -0,0 +1,155 @@ +#ifndef TAP_TO_SUBUNIT_H +#define TAP_TO_SUBUNIT_H +/* + * tap-style wrapper for subunit. + * + * Copyright (c) 2011 Rusty Russell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "replace.h" + +/** + * plan_tests - announce the number of tests you plan to run + * @tests: the number of tests + * + * This should be the first call in your test program: it allows tracing + * of failures which mean that not all tests are run. + * + * If you don't know how many tests will actually be run, assume all of them + * and use skip() if you don't actually run some tests. + * + * Example: + * plan_tests(13); + */ +void plan_tests(unsigned int tests); + +/** + * ok1 - Simple conditional test + * @e: the expression which we expect to be true. + * + * This is the simplest kind of test: if the expression is true, the + * test passes. The name of the test which is printed will simply be + * file name, line number, and the expression itself. + * + * Example: + * ok1(somefunc() == 1); + */ +# define ok1(e) ((e) ? \ + _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \ + _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e)) + +/** + * ok - Conditional test with a name + * @e: the expression which we expect to be true. + * @...: the printf-style name of the test. + * + * If the expression is true, the test passes. The name of the test will be + * the filename, line number, and the printf-style string. This can be clearer + * than simply the expression itself. + * + * Example: + * ok1(somefunc() == 1); + * ok(somefunc() == 0, "Second somefunc() should fail"); + */ +# define ok(e, ...) ((e) ? \ + _gen_result(1, __func__, __FILE__, __LINE__, \ + __VA_ARGS__) : \ + _gen_result(0, __func__, __FILE__, __LINE__, \ + __VA_ARGS__)) + +/** + * pass - Note that a test passed + * @...: the printf-style name of the test. + * + * For complicated code paths, it can be easiest to simply call pass() in one + * branch and fail() in another. + * + * Example: + * int x = somefunc(); + * if (x > 0) + * pass("somefunc() returned a valid value"); + * else + * fail("somefunc() returned an invalid value"); + */ +# define pass(...) ok(1, __VA_ARGS__) + +/** + * fail - Note that a test failed + * @...: the printf-style name of the test. + * + * For complicated code paths, it can be easiest to simply call pass() in one + * branch and fail() in another. + */ +# define fail(...) ok(0, __VA_ARGS__) + +unsigned int _gen_result(int, const char *, const char *, unsigned int, + const char *, ...) PRINTF_ATTRIBUTE(5, 6); + +/** + * diag - print a diagnostic message (use instead of printf/fprintf) + * @fmt: the format of the printf-style message + * + * diag ensures that the output will not be considered to be a test + * result by the TAP test harness. It will append '\n' for you. + * + * Example: + * diag("Now running complex tests"); + */ +void diag(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2); + +/** + * skip - print a diagnostic message (use instead of printf/fprintf) + * @n: number of tests you're skipping. + * @fmt: the format of the reason you're skipping the tests. + * + * Sometimes tests cannot be run because the test system lacks some feature: + * you should explicitly document that you're skipping tests using skip(). + * + * From the Test::More documentation: + * If it's something the user might not be able to do, use SKIP. This + * includes optional modules that aren't installed, running under an OS that + * doesn't have some feature (like fork() or symlinks), or maybe you need an + * Internet connection and one isn't available. + * + * Example: + * #ifdef HAVE_SOME_FEATURE + * ok1(somefunc()); + * #else + * skip(1, "Don't have SOME_FEATURE"); + * #endif + */ +void skip(unsigned int n, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3); + +/** + * exit_status - the value that main should return. + * + * For maximum compatibility your test program should return a particular exit + * code (ie. 0 if all tests were run, and every test which was expected to + * succeed succeeded). + * + * Example: + * exit(exit_status()); + */ +int exit_status(void); +#endif /* CCAN_TAP_H */ diff --git a/ldb-2.0.8/lib/tdb/test/tdb.corrupt b/ldb-2.0.8/lib/tdb/test/tdb.corrupt new file mode 100644 index 0000000..83d6677 Binary files /dev/null and b/ldb-2.0.8/lib/tdb/test/tdb.corrupt differ diff --git a/ldb-2.0.8/lib/tdb/test/test_tdbbackup.sh b/ldb-2.0.8/lib/tdb/test/test_tdbbackup.sh new file mode 100755 index 0000000..cf87921 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/test/test_tdbbackup.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# Blackbox test for tdbbackup of given ldb or tdb database +# Copyright (C) 2018 Andrew Bartlett + +if [ $# -lt 1 ]; then + echo "Usage: $0 LDBFILE" + exit 1; +fi + +LDBFILE=$1 + +timestamp() { + date -u +'time: %Y-%m-%d %H:%M:%S.%6NZ' | sed 's/\..*NZ$/.000000Z/' +} + +subunit_fail_test () { + timestamp + printf 'failure: %s [\n' "$1" + cat - + echo "]" +} + +testit () { + name="$1" + shift + cmdline="$@" + timestamp + printf 'test: %s\n' "$1" + output=`$cmdline 2>&1` + status=$? + if [ x$status = x0 ]; then + timestamp + printf 'success: %s\n' "$name" + else + echo "$output" | subunit_fail_test "$name" + fi + return $status +} + +$BINDIR/tdbdump $LDBFILE | sort > orig_dump + +testit "normal tdbbackup on tdb file" $BINDIR/tdbbackup $LDBFILE -s .bak +$BINDIR/tdbdump $LDBFILE.bak | sort > bak_dump +testit "cmp between tdbdumps of original and backup" cmp orig_dump bak_dump +rm $LDBFILE.bak +rm bak_dump + +testit "readonly tdbbackup on tdb file" $BINDIR/tdbbackup $LDBFILE -s .bak -r +$BINDIR/tdbdump $LDBFILE.bak | sort > bak_dump +testit "cmp between tdbdumps of original and back dbs" cmp orig_dump bak_dump +rm $LDBFILE.bak +rm bak_dump + +rm orig_dump diff --git a/ldb-2.0.8/lib/tdb/tools/tdbbackup.c b/ldb-2.0.8/lib/tdb/tools/tdbbackup.c new file mode 100644 index 0000000..1125987 --- /dev/null +++ b/ldb-2.0.8/lib/tdb/tools/tdbbackup.c @@ -0,0 +1,370 @@ +/* + Unix SMB/CIFS implementation. + low level tdb backup and restore utility + Copyright (C) Andrew Tridgell 2002 + + 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 . +*/ + +/* + + This program is meant for backup/restore of tdb databases. Typical usage would be: + tdbbackup *.tdb + when Samba shuts down cleanly, which will make a backup of all the local databases + to *.bak files. Then on Samba startup you would use: + tdbbackup -v *.tdb + and this will check the databases for corruption and if corruption is detected then + the backup will be restored. + + You may also like to do a backup on a regular basis while Samba is + running, perhaps using cron. + + The reason this program is needed is to cope with power failures + while Samba is running. A power failure could lead to database + corruption and Samba will then not start correctly. + + Note that many of the databases in Samba are transient and thus + don't need to be backed up, so you can optimise the above a little + by only running the backup on the critical databases. + + */ + +#include "replace.h" +#include "system/locale.h" +#include "system/time.h" +#include "system/filesys.h" +#include "system/wait.h" +#include "tdb.h" + +#ifdef HAVE_GETOPT_H +#include +#endif + +static int failed; + +static struct tdb_logging_context log_ctx; + +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); +} + +static char *add_suffix(const char *name, const char *suffix) +{ + char *ret; + int len = strlen(name) + strlen(suffix) + 1; + ret = (char *)malloc(len); + if (!ret) { + fprintf(stderr,"Out of memory!\n"); + exit(1); + } + snprintf(ret, len, "%s%s", name, suffix); + return ret; +} + +static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state; + + if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) { + fprintf(stderr,"Failed to insert into %s\n", tdb_name(tdb_new)); + failed = 1; + return 1; + } + return 0; +} + + +static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + return 0; +} + +/* + carefully backup a tdb, validating the contents and + only doing the backup if its OK + this function is also used for restore +*/ +static int backup_tdb(const char *old_name, const char *new_name, + int hash_size, int nolock, bool readonly) +{ + TDB_CONTEXT *tdb; + TDB_CONTEXT *tdb_new; + char *tmp_name; + struct stat st; + int count1, count2; + + tmp_name = add_suffix(new_name, ".tmp"); + + /* stat the old tdb to find its permissions */ + if (stat(old_name, &st) != 0) { + perror(old_name); + free(tmp_name); + return 1; + } + + /* open the old tdb */ + tdb = tdb_open_ex(old_name, 0, + TDB_DEFAULT | (nolock ? TDB_NOLOCK : 0), + O_RDWR, 0, &log_ctx, NULL); + if (!tdb) { + printf("Failed to open %s\n", old_name); + free(tmp_name); + return 1; + } + + /* create the new tdb */ + unlink(tmp_name); + tdb_new = tdb_open_ex(tmp_name, + hash_size ? hash_size : tdb_hash_size(tdb), + TDB_DEFAULT, + O_RDWR|O_CREAT|O_EXCL, st.st_mode & 0777, + &log_ctx, NULL); + if (!tdb_new) { + perror(tmp_name); + free(tmp_name); + return 1; + } + + if (readonly) { + if (tdb_lockall_read(tdb) != 0) { + printf("Failed to obtain read only lock on old tdb\n"); + tdb_close(tdb); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + } else if (tdb_transaction_start(tdb) != 0) { + printf("Failed to start transaction on db\n"); + tdb_close(tdb); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + /* lock the backup tdb so that nobody else can change it */ + if (tdb_lockall(tdb_new) != 0) { + printf("Failed to lock backup tdb\n"); + tdb_close(tdb); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + failed = 0; + + /* traverse and copy */ + if (readonly) { + count1 = tdb_traverse_read(tdb, + copy_fn, + (void *)tdb_new); + } else { + count1 = tdb_traverse(tdb, + copy_fn, + (void *)tdb_new); + } + if (count1 < 0 || failed) { + fprintf(stderr,"failed to copy %s\n", old_name); + tdb_close(tdb); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + /* close the old tdb */ + tdb_close(tdb); + + /* copy done, unlock the backup tdb */ + tdb_unlockall(tdb_new); + +#ifdef HAVE_FDATASYNC + if (fdatasync(tdb_fd(tdb_new)) != 0) { +#else + if (fsync(tdb_fd(tdb_new)) != 0) { +#endif + /* not fatal */ + fprintf(stderr, "failed to fsync backup file\n"); + } + + /* close the new tdb and re-open read-only */ + tdb_close(tdb_new); + tdb_new = tdb_open_ex(tmp_name, + 0, + TDB_DEFAULT, + O_RDONLY, 0, + &log_ctx, NULL); + if (!tdb_new) { + fprintf(stderr,"failed to reopen %s\n", tmp_name); + unlink(tmp_name); + perror(tmp_name); + free(tmp_name); + return 1; + } + + /* traverse the new tdb to confirm */ + count2 = tdb_traverse(tdb_new, test_fn, NULL); + if (count2 != count1) { + fprintf(stderr,"failed to copy %s\n", old_name); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + /* close the new tdb and rename it to .bak */ + tdb_close(tdb_new); + if (rename(tmp_name, new_name) != 0) { + perror(new_name); + free(tmp_name); + return 1; + } + + free(tmp_name); + + return 0; +} + +/* + verify a tdb and if it is corrupt then restore from *.bak +*/ +static int verify_tdb(const char *fname, const char *bak_name) +{ + TDB_CONTEXT *tdb; + int count = -1; + + /* open the tdb */ + tdb = tdb_open_ex(fname, 0, 0, + O_RDONLY, 0, &log_ctx, NULL); + + /* traverse the tdb, then close it */ + if (tdb) { + count = tdb_traverse(tdb, test_fn, NULL); + tdb_close(tdb); + } + + /* count is < 0 means an error */ + if (count < 0) { + printf("restoring %s\n", fname); + return backup_tdb(bak_name, fname, 0, 0, 0); + } + + printf("%s : %d records\n", fname, count); + + return 0; +} + +/* + see if one file is newer than another +*/ +static int file_newer(const char *fname1, const char *fname2) +{ + struct stat st1, st2; + if (stat(fname1, &st1) != 0) { + return 0; + } + if (stat(fname2, &st2) != 0) { + return 1; + } + return (st1.st_mtime > st2.st_mtime); +} + +static void usage(void) +{ + printf("Usage: tdbbackup [options] \n\n"); + printf(" -h this help message\n"); + printf(" -s suffix set the backup suffix\n"); + printf(" -v verify mode (restore if corrupt)\n"); + printf(" -n hashsize set the new hash size for the backup\n"); + printf(" -l open without locking to back up mutex dbs\n"); + printf(" -r open with read only locking\n"); +} + + int main(int argc, char *argv[]) +{ + int i; + int ret = 0; + int c; + int verify = 0; + int hashsize = 0; + int nolock = 0; + bool readonly = false; + const char *suffix = ".bak"; + + log_ctx.log_fn = tdb_log; + + while ((c = getopt(argc, argv, "vhs:n:lr")) != -1) { + switch (c) { + case 'h': + usage(); + exit(0); + case 'v': + verify = 1; + break; + case 's': + suffix = optarg; + break; + case 'n': + hashsize = atoi(optarg); + break; + case 'l': + nolock = 1; + break; + case 'r': + readonly = true; + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + usage(); + exit(1); + } + + for (i=0; i. +*/ + +#include "replace.h" +#include "system/locale.h" +#include "system/time.h" +#include "system/filesys.h" +#include "system/wait.h" +#include "tdb.h" + +static void print_data(TDB_DATA d) +{ + unsigned char *p = (unsigned char *)d.dptr; + int len = d.dsize; + while (len--) { + if (isprint(*p) && !strchr("\"\\", *p)) { + fputc(*p, stdout); + } else { + printf("\\%02X", *p); + } + p++; + } +} + +static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + printf("{\n"); + printf("key(%zu) = \"", key.dsize); + print_data(key); + printf("\"\n"); + printf("data(%zu) = \"", dbuf.dsize); + print_data(dbuf); + printf("\"\n"); + printf("}\n"); + return 0; +} + +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; + const char *name = tdb_name(tdb); + const char *prefix = ""; + + if (!name) + name = "unnamed"; + + switch (level) { + case TDB_DEBUG_ERROR: + prefix = "ERROR: "; + break; + case TDB_DEBUG_WARNING: + prefix = "WARNING: "; + break; + case TDB_DEBUG_TRACE: + return; + + default: + case TDB_DEBUG_FATAL: + prefix = "FATAL: "; + break; + } + + va_start(ap, fmt); + fprintf(stderr, "tdb(%s): %s", name, prefix); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static void emergency_walk(TDB_DATA key, TDB_DATA dbuf, void *keyname) +{ + if (keyname) { + if (key.dsize != strlen(keyname)) + return; + if (memcmp(key.dptr, keyname, key.dsize) != 0) + return; + } + traverse_fn(NULL, key, dbuf, NULL); +} + +static int dump_tdb(const char *fname, const char *keyname, bool emergency) +{ + TDB_CONTEXT *tdb; + TDB_DATA key, value; + struct tdb_logging_context logfn = { + .log_fn = log_stderr, + }; + int tdb_flags = TDB_DEFAULT; + + /* + * Note: that O_RDONLY implies TDB_NOLOCK, but we want to make it + * explicit as it's important when working on databases which were + * created with mutex locking. + */ + tdb_flags |= TDB_NOLOCK; + + tdb = tdb_open_ex(fname, 0, tdb_flags, O_RDONLY, 0, &logfn, NULL); + if (!tdb) { + printf("Failed to open %s\n", fname); + return 1; + } + + if (emergency) { + return tdb_rescue(tdb, emergency_walk, discard_const(keyname)) == 0; + } + if (!keyname) { + return tdb_traverse(tdb, traverse_fn, NULL) == -1 ? 1 : 0; + } else { + key.dptr = discard_const_p(uint8_t, keyname); + key.dsize = strlen(keyname); + value = tdb_fetch(tdb, key); + if (!value.dptr) { + return 1; + } else { + print_data(value); + free(value.dptr); + } + } + + return 0; +} + +static void usage( void) +{ + printf( "Usage: tdbdump [options] \n\n"); + printf( " -h this help message\n"); + printf( " -k keyname dumps value of keyname\n"); + printf( " -e emergency dump, for corrupt databases\n"); +} + + int main(int argc, char *argv[]) +{ + char *fname, *keyname=NULL; + bool emergency = false; + int c; + + if (argc < 2) { + printf("Usage: tdbdump \n"); + exit(1); + } + + while ((c = getopt( argc, argv, "hk:e")) != -1) { + switch (c) { + case 'h': + usage(); + exit( 0); + case 'k': + keyname = optarg; + break; + case 'e': + emergency = true; + break; + default: + usage(); + exit( 1); + } + } + + fname = argv[optind]; + + return dump_tdb(fname, keyname, emergency); +} diff --git a/ldb-2.0.8/lib/tdb/tools/tdbrestore.c b/ldb-2.0.8/lib/tdb/tools/tdbrestore.c new file mode 100644 index 0000000..81c986c --- /dev/null +++ b/ldb-2.0.8/lib/tdb/tools/tdbrestore.c @@ -0,0 +1,222 @@ +/* + tdbrestore -- construct a tdb from tdbdump output. + Copyright (C) Volker Lendecke 2010 + Copyright (C) Simon McVittie 2005 + + 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 . +*/ + +#include "replace.h" +#include +#include "system/locale.h" +#include "system/time.h" +#include "system/filesys.h" +#include "system/wait.h" +#include "tdb.h" + +static int read_linehead(FILE *f) +{ + int i, c; + int num_bytes; + char prefix[128]; + + while (1) { + c = getc(f); + if (c == EOF) { + return -1; + } + if (c == '(') { + break; + } + } + for (i=0; idptr = (unsigned char *)malloc(size); + if (d->dptr == NULL) { + return -1; + } + d->dsize = size; + + for (i=0; idptr[i] = (low|high); + } else { + d->dptr[i] = c; + } + } + return 0; +} + +static int swallow(FILE *f, const char *s, int *eof) +{ + char line[128]; + + if (fgets(line, sizeof(line), f) == NULL) { + if (eof != NULL) { + *eof = 1; + } + return -1; + } + if (strcmp(line, s) != 0) { + return -1; + } + return 0; +} + +static int read_rec(FILE *f, TDB_CONTEXT *tdb, int *eof) +{ + int length; + TDB_DATA key, data; + int ret = -1; + + key.dptr = NULL; + data.dptr = NULL; + + if (swallow(f, "{\n", eof) == -1) { + goto fail; + } + length = read_linehead(f); + if (length == -1) { + goto fail; + } + if (read_data(f, &key, length) == -1) { + goto fail; + } + if (swallow(f, "\"\n", NULL) == -1) { + goto fail; + } + length = read_linehead(f); + if (length == -1) { + goto fail; + } + if (read_data(f, &data, length) == -1) { + goto fail; + } + if ((swallow(f, "\"\n", NULL) == -1) + || (swallow(f, "}\n", NULL) == -1)) { + goto fail; + } + if (tdb_store(tdb, key, data, TDB_INSERT) != 0) { + fprintf(stderr, "TDB error: %s\n", tdb_errorstr(tdb)); + goto fail; + } + + ret = 0; +fail: + free(key.dptr); + free(data.dptr); + return ret; +} + +static int restore_tdb(const char *fname) +{ + TDB_CONTEXT *tdb; + + tdb = tdb_open(fname, 0, 0, O_RDWR|O_CREAT|O_EXCL, 0666); + if (!tdb) { + perror("tdb_open"); + fprintf(stderr, "Failed to open %s\n", fname); + return 1; + } + + while (1) { + int eof = 0; + if (read_rec(stdin, tdb, &eof) == -1) { + if (eof) { + break; + } + return 1; + } + } + if (tdb_close(tdb)) { + fprintf(stderr, "Error closing tdb\n"); + return 1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + char *fname; + + if (argc < 2) { + printf("Usage: %s dbname < tdbdump_output\n", argv[0]); + exit(1); + } + + fname = argv[1]; + + return restore_tdb(fname); +} diff --git a/ldb-2.0.8/lib/tdb/tools/tdbtest.c b/ldb-2.0.8/lib/tdb/tools/tdbtest.c new file mode 100644 index 0000000..0be35dc --- /dev/null +++ b/ldb-2.0.8/lib/tdb/tools/tdbtest.c @@ -0,0 +1,290 @@ +/* a test program for tdb - the trivial database */ + +#include "replace.h" +#include "tdb.h" +#include "system/filesys.h" +#include "system/time.h" + +#include + + +#define DELETE_PROB 7 +#define STORE_PROB 5 + +static struct tdb_context *db; +static GDBM_FILE gdbm; + +struct timeval tp1,tp2; + +static void _start_timer(void) +{ + gettimeofday(&tp1,NULL); +} + +static double _end_timer(void) +{ + gettimeofday(&tp2,NULL); + return((tp2.tv_sec - tp1.tv_sec) + + (tp2.tv_usec - tp1.tv_usec)*1.0e-6); +} + +static void fatal(const char *why) +{ + perror(why); + exit(1); +} + +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif +static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); +} + +static void compare_db(void) +{ + TDB_DATA d, key, nextkey; + datum gd, gkey, gnextkey; + + key = tdb_firstkey(db); + while (key.dptr) { + d = tdb_fetch(db, key); + gkey.dptr = key.dptr; + gkey.dsize = key.dsize; + + gd = gdbm_fetch(gdbm, gkey); + + if (!gd.dptr) fatal("key not in gdbm"); + if (gd.dsize != d.dsize) fatal("data sizes differ"); + if (memcmp(gd.dptr, d.dptr, d.dsize)) { + fatal("data differs"); + } + + nextkey = tdb_nextkey(db, key); + free(key.dptr); + free(d.dptr); + free(gd.dptr); + key = nextkey; + } + + gkey = gdbm_firstkey(gdbm); + while (gkey.dptr) { + gd = gdbm_fetch(gdbm, gkey); + key.dptr = gkey.dptr; + key.dsize = gkey.dsize; + + d = tdb_fetch(db, key); + + if (!d.dptr) fatal("key not in db"); + if (d.dsize != gd.dsize) fatal("data sizes differ"); + if (memcmp(d.dptr, gd.dptr, gd.dsize)) { + fatal("data differs"); + } + + gnextkey = gdbm_nextkey(gdbm, gkey); + free(gkey.dptr); + free(gd.dptr); + free(d.dptr); + gkey = gnextkey; + } +} + +static char *randbuf(int len) +{ + char *buf; + int i; + buf = (char *)malloc(len+1); + + for (i=0;i. +*/ + +#include "replace.h" +#include "system/locale.h" +#include "system/time.h" +#include "system/filesys.h" +#include "system/wait.h" +#include "tdb.h" + +static int do_command(void); +const char *cmdname; +char *arg1, *arg2; +size_t arg1len, arg2len; +int bIterate = 0; +char *line; +TDB_DATA iterate_kbuf; +char cmdline[1024]; +static int disable_mmap; +static int _disable_lock; + +enum commands { + CMD_CREATE_TDB, + CMD_OPEN_TDB, + CMD_TRANSACTION_START, + CMD_TRANSACTION_COMMIT, + CMD_TRANSACTION_CANCEL, + CMD_ERASE, + CMD_DUMP, + CMD_INSERT, + CMD_MOVE, + CMD_STOREHEX, + CMD_STORE, + CMD_SHOW, + CMD_KEYS, + CMD_HEXKEYS, + CMD_DELETE, + CMD_LIST_HASH_FREE, + CMD_LIST_FREE, + CMD_FREELIST_SIZE, + CMD_INFO, + CMD_MMAP, + CMD_SPEED, + CMD_FIRST, + CMD_NEXT, + CMD_SYSTEM, + CMD_CHECK, + CMD_REPACK, + CMD_QUIT, + CMD_HELP +}; + +typedef struct { + const char *name; + enum commands cmd; +} COMMAND_TABLE; + +COMMAND_TABLE cmd_table[] = { + {"create", CMD_CREATE_TDB}, + {"open", CMD_OPEN_TDB}, + {"transaction_start", CMD_TRANSACTION_START}, + {"transaction_commit", CMD_TRANSACTION_COMMIT}, + {"transaction_cancel", CMD_TRANSACTION_CANCEL}, + {"erase", CMD_ERASE}, + {"dump", CMD_DUMP}, + {"insert", CMD_INSERT}, + {"move", CMD_MOVE}, + {"storehex", CMD_STOREHEX}, + {"store", CMD_STORE}, + {"show", CMD_SHOW}, + {"keys", CMD_KEYS}, + {"hexkeys", CMD_HEXKEYS}, + {"delete", CMD_DELETE}, + {"list", CMD_LIST_HASH_FREE}, + {"free", CMD_LIST_FREE}, + {"freelist_size", CMD_FREELIST_SIZE}, + {"info", CMD_INFO}, + {"speed", CMD_SPEED}, + {"mmap", CMD_MMAP}, + {"first", CMD_FIRST}, + {"1", CMD_FIRST}, + {"next", CMD_NEXT}, + {"n", CMD_NEXT}, + {"check", CMD_CHECK}, + {"quit", CMD_QUIT}, + {"q", CMD_QUIT}, + {"!", CMD_SYSTEM}, + {"repack", CMD_REPACK}, + {NULL, CMD_HELP} +}; + +struct timeval tp1,tp2; + +static void _start_timer(void) +{ + gettimeofday(&tp1,NULL); +} + +static double _end_timer(void) +{ + gettimeofday(&tp2,NULL); + return((tp2.tv_sec - tp1.tv_sec) + + (tp2.tv_usec - tp1.tv_usec)*1.0e-6); +} + +#ifdef PRINTF_ATTRIBUTE +static void tdb_log_open(struct tdb_context *tdb, enum tdb_debug_level level, + const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif +static void tdb_log_open(struct tdb_context *tdb, enum tdb_debug_level level, + const char *format, ...) +{ + const char *mutex_msg = + "Can use mutexes only with MUTEX_LOCKING or NOLOCK\n"; + char *p; + va_list ap; + + p = strstr(format, mutex_msg); + if (p != NULL) { + /* + * Yes, this is a hack, but we don't want to see this + * message on first open, but we want to see + * everything else. + */ + return; + } + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +} + +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +} + +/* a tdb tool for manipulating a tdb database */ + +static TDB_CONTEXT *tdb; + +static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); +static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); +static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); + +static void print_asc(const char *buf,int len) +{ + int i; + + /* We're probably printing ASCII strings so don't try to display + the trailing NULL character. */ + + if (buf[len - 1] == 0) + len--; + + for (i=0;i8) printf(" "); + while (n--) printf(" "); + + n = i%16; + if (n > 8) n = 8; + print_asc(&buf[i-(i%16)],n); printf(" "); + n = (i%16) - n; + if (n>0) print_asc(&buf[i-n],n); + printf("\n"); + } +} + +static void help(void) +{ + printf("\n" +"tdbtool: \n" +" create dbname : create a database\n" +" open dbname : open an existing database\n" +" transaction_start : start a transaction\n" +" transaction_commit : commit a transaction\n" +" transaction_cancel : cancel a transaction\n" +" erase : erase the database\n" +" dump : dump the database as strings\n" +" keys : dump the database keys as strings\n" +" hexkeys : dump the database keys as hex values\n" +" info : print summary info about the database\n" +" insert key data : insert a record\n" +" move key file : move a record to a destination tdb\n" +" storehex key data : store a record (replace), key/value in hex format\n" +" store key data : store a record (replace)\n" +" show key : show a record by key\n" +" delete key : delete a record by key\n" +" list : print the database hash table and freelist\n" +" free : print the database freelist\n" +" freelist_size : print the number of records in the freelist\n" +" check : check the integrity of an opened database\n" +" repack : repack the database\n" +" speed : perform speed tests on the database\n" +" ! command : execute system command\n" +" 1 | first : print the first record\n" +" n | next : print the next record\n" +" q | quit : terminate\n" +" \\n : repeat 'next' command\n" +"\n"); +} + +static void terror(const char *why) +{ + printf("%s\n", why); +} + +static void create_tdb(const char *tdbname) +{ + struct tdb_logging_context log_ctx = { NULL, NULL}; + log_ctx.log_fn = tdb_log; + + if (tdb) tdb_close(tdb); + tdb = tdb_open_ex(tdbname, 0, + TDB_CLEAR_IF_FIRST | + (disable_mmap?TDB_NOMMAP:0) | + (_disable_lock?TDB_NOLOCK:0), + O_RDWR | O_CREAT | O_TRUNC, 0600, &log_ctx, NULL); + if (!tdb) { + printf("Could not create %s: %s\n", tdbname, strerror(errno)); + } +} + +static void open_tdb(const char *tdbname) +{ + struct tdb_logging_context log_ctx = { NULL, NULL }; + log_ctx.log_fn = tdb_log_open; + + if (tdb) tdb_close(tdb); + tdb = tdb_open_ex(tdbname, 0, + (disable_mmap?TDB_NOMMAP:0) | + (_disable_lock?TDB_NOLOCK:0), + O_RDWR, 0600, + &log_ctx, NULL); + + log_ctx.log_fn = tdb_log; + if (tdb != NULL) { + tdb_set_logging_function(tdb, &log_ctx); + } + + if ((tdb == NULL) && (errno == EINVAL)) { + /* + * Retry NOLOCK and readonly. There we want to see all + * error messages. + */ + tdb = tdb_open_ex(tdbname, 0, + (disable_mmap?TDB_NOMMAP:0) |TDB_NOLOCK, + O_RDONLY, 0600, + &log_ctx, NULL); + } + + if (!tdb) { + printf("Could not open %s: %s\n", tdbname, strerror(errno)); + } +} + +static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen) +{ + TDB_DATA key, dbuf; + + if ((keyname == NULL) || (keylen == 0)) { + terror("need key"); + return; + } + + key.dptr = (unsigned char *)keyname; + key.dsize = keylen; + dbuf.dptr = (unsigned char *)data; + dbuf.dsize = datalen; + + if (tdb_store(tdb, key, dbuf, TDB_INSERT) != 0) { + terror("insert failed"); + } +} + +static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen) +{ + TDB_DATA key, dbuf; + + if ((keyname == NULL) || (keylen == 0)) { + terror("need key"); + return; + } + + if ((data == NULL) || (datalen == 0)) { + terror("need data"); + return; + } + + key.dptr = (unsigned char *)keyname; + key.dsize = keylen; + dbuf.dptr = (unsigned char *)data; + dbuf.dsize = datalen; + + printf("Storing key:\n"); + print_rec(tdb, key, dbuf, NULL); + + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) != 0) { + terror("store failed"); + } +} + +static bool hexchar(char c, uint8_t *v) +{ + if ((c >= '0') && (c <= '9')) { + *v = (c - '0'); + return true; + } + if ((c >= 'A') && (c <= 'F')) { + *v = (c - 'A' + 10); + return true; + } + if ((c >= 'a') && (c <= 'f')) { + *v = (c - 'a' + 10); + return true; + } + return false; +} + +static bool parse_hex(const char *src, size_t srclen, uint8_t *dst) +{ + size_t i=0; + + if ((srclen % 2) != 0) { + return false; + } + + while (iname) { + cmd_len = strlen(ctp->name); + if (strncmp(ctp->name,cmdname,cmd_len) == 0) { + mycmd = ctp->cmd; + break; + } + ctp++; + } + } + } + + switch (mycmd) { + case CMD_CREATE_TDB: + bIterate = 0; + create_tdb(arg1); + return 0; + case CMD_OPEN_TDB: + bIterate = 0; + open_tdb(arg1); + return 0; + case CMD_SYSTEM: + /* Shell command */ + if (system(arg1) == -1) { + terror("system() call failed\n"); + } + return 0; + case CMD_QUIT: + return 1; + default: + /* all the rest require a open database */ + if (!tdb) { + bIterate = 0; + terror("database not open"); + help(); + return 0; + } + switch (mycmd) { + case CMD_TRANSACTION_START: + bIterate = 0; + tdb_transaction_start(tdb); + return 0; + case CMD_TRANSACTION_COMMIT: + bIterate = 0; + tdb_transaction_commit(tdb); + return 0; + case CMD_REPACK: + bIterate = 0; + tdb_repack(tdb); + return 0; + case CMD_TRANSACTION_CANCEL: + bIterate = 0; + tdb_transaction_cancel(tdb); + return 0; + case CMD_ERASE: + bIterate = 0; + tdb_wipe_all(tdb); + return 0; + case CMD_DUMP: + bIterate = 0; + tdb_traverse(tdb, print_rec, NULL); + return 0; + case CMD_INSERT: + bIterate = 0; + insert_tdb(arg1, arg1len,arg2,arg2len); + return 0; + case CMD_MOVE: + bIterate = 0; + move_rec(arg1,arg1len,arg2); + return 0; + case CMD_STORE: + bIterate = 0; + store_tdb(arg1,arg1len,arg2,arg2len); + return 0; + case CMD_STOREHEX: + bIterate = 0; + store_hex_tdb(arg1,arg1len,arg2,arg2len); + return 0; + case CMD_SHOW: + bIterate = 0; + show_tdb(arg1, arg1len); + return 0; + case CMD_KEYS: + tdb_traverse(tdb, print_key, NULL); + return 0; + case CMD_HEXKEYS: + tdb_traverse(tdb, print_hexkey, NULL); + return 0; + case CMD_DELETE: + bIterate = 0; + delete_tdb(arg1,arg1len); + return 0; + case CMD_LIST_HASH_FREE: + tdb_dump_all(tdb); + return 0; + case CMD_LIST_FREE: + tdb_printfreelist(tdb); + return 0; + case CMD_FREELIST_SIZE: { + int size; + + size = tdb_freelist_size(tdb); + if (size < 0) { + printf("Error getting freelist size.\n"); + } else { + printf("freelist size: %d\n", size); + } + + return 0; + } + case CMD_INFO: + info_tdb(); + return 0; + case CMD_SPEED: + speed_tdb(arg1); + return 0; + case CMD_MMAP: + toggle_mmap(); + return 0; + case CMD_FIRST: + bIterate = 1; + first_record(tdb, &iterate_kbuf); + return 0; + case CMD_NEXT: + if (bIterate) + next_record(tdb, &iterate_kbuf); + return 0; + case CMD_CHECK: + check_db(tdb); + return 0; + case CMD_HELP: + help(); + return 0; + case CMD_CREATE_TDB: + case CMD_OPEN_TDB: + case CMD_SYSTEM: + case CMD_QUIT: + /* + * unhandled commands. cases included here to avoid compiler + * warnings. + */ + return 0; + } + } + + return 0; +} + +static char *tdb_convert_string(char *instring, size_t *sizep) +{ + size_t length = 0; + char *outp, *inp; + char temp[3]; + + outp = inp = instring; + + while (*inp) { + if (*inp == '\\') { + inp++; + if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { + temp[0] = *inp++; + temp[1] = '\0'; + if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { + temp[1] = *inp++; + temp[2] = '\0'; + } + *outp++ = (char)strtol((const char *)temp,NULL,16); + } else { + *outp++ = *inp++; + } + } else { + *outp++ = *inp++; + } + length++; + } + *sizep = length; + return instring; +} + +int main(int argc, char *argv[]) +{ + cmdname = ""; + arg1 = NULL; + arg1len = 0; + arg2 = NULL; + arg2len = 0; + + if (argv[1] && (strcmp(argv[1], "-l") == 0)) { + _disable_lock = 1; + argv[1] = argv[0]; + argv += 1; + argc -= 1; + } + + if (argv[1]) { + cmdname = "open"; + arg1 = argv[1]; + do_command(); + cmdname = ""; + arg1 = NULL; + } + + switch (argc) { + case 1: + case 2: + /* Interactive mode */ + while ((cmdname = tdb_getline("tdb> "))) { + arg2 = arg1 = NULL; + if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) { + arg1++; + arg2 = arg1; + while (*arg2) { + if (*arg2 == ' ') { + *arg2++ = '\0'; + break; + } + if ((*arg2++ == '\\') && (*arg2 == ' ')) { + arg2++; + } + } + } + if (arg1) arg1 = tdb_convert_string(arg1,&arg1len); + if (arg2) arg2 = tdb_convert_string(arg2,&arg2len); + if (do_command()) break; + } + break; + case 5: + arg2 = tdb_convert_string(argv[4],&arg2len); + FALL_THROUGH; + case 4: + arg1 = tdb_convert_string(argv[3],&arg1len); + FALL_THROUGH; + case 3: + cmdname = argv[2]; + FALL_THROUGH; + default: + do_command(); + break; + } + + if (tdb) tdb_close(tdb); + + return 0; +} diff --git a/ldb-2.0.8/lib/tdb/tools/tdbtorture.c b/ldb-2.0.8/lib/tdb/tools/tdbtorture.c new file mode 100644 index 0000000..7d08d4f --- /dev/null +++ b/ldb-2.0.8/lib/tdb/tools/tdbtorture.c @@ -0,0 +1,501 @@ +/* this tests tdb by doing lots of ops from several simultaneous + writers - that stresses the locking code. +*/ + +#include "replace.h" +#include "system/time.h" +#include "system/wait.h" +#include "system/filesys.h" +#include "tdb.h" + +#ifdef HAVE_GETOPT_H +#include +#endif + + +#define REOPEN_PROB 30 +#define DELETE_PROB 8 +#define STORE_PROB 4 +#define APPEND_PROB 6 +#define TRANSACTION_PROB 10 +#define TRANSACTION_PREPARE_PROB 2 +#define LOCKSTORE_PROB 5 +#define TRAVERSE_PROB 20 +#define TRAVERSE_READ_PROB 20 +#define CULL_PROB 100 +#define KEYLEN 3 +#define DATALEN 100 + +static struct tdb_context *db; +static int in_transaction; +static int error_count; +static int always_transaction = 0; +static int hash_size = 2; +static unsigned loopnum; +static int count_pipe; +static bool mutex = false; +static struct tdb_logging_context log_ctx; + +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) +{ + va_list ap; + + /* trace level messages do not indicate an error */ + if (level != TDB_DEBUG_TRACE) { + error_count++; + } + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); +#if 0 + if (level != TDB_DEBUG_TRACE) { + char *ptr; + signal(SIGUSR1, SIG_IGN); + asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid()); + system(ptr); + free(ptr); + } +#endif +} + +static void fatal(const char *why) +{ + perror(why); + error_count++; +} + +static char *randbuf(int len) +{ + char *buf; + int i; + buf = (char *)malloc(len+1); + + for (i=0;i + + +ldb + + + +

tdb

+ +TDB is a Trivial Database. In concept, it is very much like GDBM, and BSD's DB +except that it allows multiple simultaneous writers and uses locking +internally to keep writers from trampling on each other. TDB is also extremely +small. + +

Download

+You can download the latest releases of tdb from the tdb directory on the samba public +source archive. + + +

Discussion and bug reports

+ +tdb does not currently have its own mailing list or bug tracking +system. For now, please use the samba-technical +mailing list, and the Samba +bugzilla bug tracking system. + +

Download

+ +You can download the latest code either via git or rsync.
+
+To fetch via git see the following guide:
+Using Git for Samba Development
+Once you have cloned the tree switch to the master branch and cd into the source/lib/tdb directory.
+
+To fetch via rsync use these commands: + +
+  rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/tdb .
+  rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/replace .
+
+ +and build in tdb. It will find the replace library in the directory +above automatically. + + + diff --git a/ldb-2.0.8/lib/tdb/wscript b/ldb-2.0.8/lib/tdb/wscript new file mode 100644 index 0000000..1ab0e8d --- /dev/null +++ b/ldb-2.0.8/lib/tdb/wscript @@ -0,0 +1,259 @@ +#!/usr/bin/env python + +APPNAME = 'tdb' +VERSION = '1.4.2' + +import sys, os + +# find the buildtools directory +top = '.' +while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5: + top = top + '/..' +sys.path.insert(0, top + '/buildtools/wafsamba') + +out = 'bin' + +import wafsamba +from wafsamba import samba_dist, samba_utils +from waflib import Options, Logs, Context +import shutil + +samba_dist.DIST_DIRS('lib/tdb:. lib/replace:lib/replace buildtools:buildtools third_party/waf:third_party/waf') + +tdb1_unit_tests = [ + 'run-3G-file', + 'run-bad-tdb-header', + 'run', + 'run-check', + 'run-corrupt', + 'run-die-during-transaction', + 'run-endian', + 'run-incompatible', + 'run-nested-transactions', + 'run-nested-traverse', + 'run-no-lock-during-traverse', + 'run-oldhash', + 'run-open-during-transaction', + 'run-readonly-check', + 'run-rescue', + 'run-rescue-find_entry', + 'run-rdlock-upgrade', + 'run-rwlock-check', + 'run-summary', + 'run-transaction-expand', + 'run-traverse-in-transaction', + 'run-wronghash-fail', + 'run-zero-append', + 'run-fcntl-deadlock', + 'run-marklock-deadlock', + 'run-allrecord-traverse-deadlock', + 'run-mutex-openflags2', + 'run-mutex-trylock', + 'run-mutex-allrecord-bench', + 'run-mutex-allrecord-trylock', + 'run-mutex-allrecord-block', + 'run-mutex-transaction1', + 'run-mutex-die', + 'run-mutex1', + 'run-circular-chain', + 'run-circular-freelist', + 'run-traverse-chain', +] + +def options(opt): + opt.BUILTIN_DEFAULT('replace') + opt.PRIVATE_EXTENSION_DEFAULT('tdb', noextension='tdb') + opt.RECURSE('lib/replace') + opt.add_option('--disable-tdb-mutex-locking', + help=("Disable the use of pthread robust mutexes"), + action="store_true", dest='disable_tdb_mutex_locking', + default=False) + + +def configure(conf): + conf.env.disable_tdb_mutex_locking = getattr(Options.options, + 'disable_tdb_mutex_locking', + False) + if not conf.env.disable_tdb_mutex_locking: + conf.env.replace_add_global_pthread = True + conf.RECURSE('lib/replace') + + conf.env.standalone_tdb = conf.IN_LAUNCH_DIR() + conf.env.building_tdb = True + + if not conf.env.standalone_tdb: + if conf.CHECK_BUNDLED_SYSTEM_PKG('tdb', minversion=VERSION, + implied_deps='replace'): + conf.define('USING_SYSTEM_TDB', 1) + conf.env.building_tdb = False + if not conf.env.disable_python and \ + conf.CHECK_BUNDLED_SYSTEM_PYTHON('pytdb', 'tdb', minversion=VERSION): + conf.define('USING_SYSTEM_PYTDB', 1) + + if (conf.CONFIG_SET('HAVE_ROBUST_MUTEXES') and + conf.env.building_tdb and + not conf.env.disable_tdb_mutex_locking): + conf.define('USE_TDB_MUTEX_LOCKING', 1) + + conf.CHECK_XSLTPROC_MANPAGES() + + conf.SAMBA_CHECK_PYTHON() + conf.SAMBA_CHECK_PYTHON_HEADERS() + + conf.SAMBA_CONFIG_H() + + conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS() + +def build(bld): + bld.RECURSE('lib/replace') + + COMMON_FILES='''check.c error.c tdb.c traverse.c + freelistcheck.c lock.c dump.c freelist.c + io.c open.c transaction.c hash.c summary.c rescue.c + mutex.c''' + + COMMON_SRC = bld.SUBDIR('common', COMMON_FILES) + + if bld.env.standalone_tdb: + bld.env.PKGCONFIGDIR = '${LIBDIR}/pkgconfig' + private_library = False + else: + private_library = True + + if not bld.CONFIG_SET('USING_SYSTEM_TDB'): + + tdb_deps = 'replace' + + if bld.CONFIG_SET('USE_TDB_MUTEX_LOCKING'): + tdb_deps += ' pthread' + + bld.SAMBA_LIBRARY('tdb', + COMMON_SRC, + deps=tdb_deps, + includes='include', + abi_directory='ABI', + abi_match='tdb_*', + hide_symbols=True, + vnum=VERSION, + public_headers=('' if private_library else 'include/tdb.h'), + public_headers_install=not private_library, + pc_files='tdb.pc', + private_library=private_library) + + bld.SAMBA_BINARY('tdbtorture', + 'tools/tdbtorture.c', + 'tdb', + install=False) + + bld.SAMBA_BINARY('tdbrestore', + 'tools/tdbrestore.c', + 'tdb', manpages='man/tdbrestore.8') + + bld.SAMBA_BINARY('tdbdump', + 'tools/tdbdump.c', + 'tdb', manpages='man/tdbdump.8') + + bld.SAMBA_BINARY('tdbbackup', + 'tools/tdbbackup.c', + 'tdb', + manpages='man/tdbbackup.8') + + bld.SAMBA_BINARY('tdbtool', + 'tools/tdbtool.c', + 'tdb', manpages='man/tdbtool.8') + + if bld.env.standalone_tdb: + # FIXME: This hardcoded list is stupid, stupid, stupid. + bld.SAMBA_SUBSYSTEM('tdb-test-helpers', + 'test/external-agent.c test/lock-tracking.c test/logging.c', + tdb_deps, + includes='include') + + for t in tdb1_unit_tests: + b = "tdb1-" + t + s = "test/" + t + ".c" + bld.SAMBA_BINARY(b, s, 'replace tdb-test-helpers', + includes='include', install=False) + + if not bld.CONFIG_SET('USING_SYSTEM_PYTDB'): + bld.SAMBA_PYTHON('pytdb', + 'pytdb.c', + deps='tdb', + enabled=not bld.env.disable_python, + realname='tdb.so', + cflags='-DPACKAGE_VERSION=\"%s\"' % VERSION) + + if not bld.env.disable_python: + bld.SAMBA_SCRIPT('_tdb_text.py', + pattern='_tdb_text.py', + installdir='python') + + bld.INSTALL_FILES('${PYTHONARCHDIR}', '_tdb_text.py') + +def testonly(ctx): + '''run tdb testsuite''' + ecode = 0 + + blddir = Context.g_module.out + test_prefix = "%s/st" % (blddir) + shutil.rmtree(test_prefix, ignore_errors=True) + os.makedirs(test_prefix) + os.environ['TEST_DATA_PREFIX'] = test_prefix + + env = samba_utils.LOAD_ENVIRONMENT() + # FIXME: This is horrible :( + if env.building_tdb: + # Create scratch directory for tests. + testdir = os.path.join(test_prefix, 'tdb-tests') + samba_utils.mkdir_p(testdir) + # Symlink back to source dir so it can find tests in test/ + link = os.path.join(testdir, 'test') + if not os.path.exists(link): + os.symlink(ctx.path.make_node('test').abspath(), link) + + sh_tests = ["test/test_tdbbackup.sh test/jenkins-be-hash.tdb"] + + for sh_test in sh_tests: + cmd = "BINDIR=%s %s" % (blddir, sh_test) + print("shell test: " + cmd) + ret = samba_utils.RUN_COMMAND(cmd) + if ret != 0: + print("%s sh test failed" % cmd) + ecode = ret + break + + for t in tdb1_unit_tests: + f = "tdb1-" + t + cmd = "cd " + testdir + " && " + os.path.abspath(os.path.join(blddir, f)) + " > test-output 2>&1" + print("..." + f) + ret = samba_utils.RUN_COMMAND(cmd) + if ret != 0: + print("%s failed:" % f) + samba_utils.RUN_COMMAND("cat " + os.path.join(testdir, 'test-output')) + ecode = ret + break + + if ecode == 0: + cmd = os.path.join(blddir, 'tdbtorture') + ret = samba_utils.RUN_COMMAND(cmd) + print("testsuite returned %d" % ret) + if ret != 0: + ecode = ret + + pyret = samba_utils.RUN_PYTHON_TESTS(['python/tests/simple.py']) + print("python testsuite returned %d" % pyret) + sys.exit(ecode or pyret) + +# WAF doesn't build the unit tests for this, maybe because they don't link with tdb? +# This forces it +def test(ctx): + Options.commands.append('build') + Options.commands.append('testonly') + +def dist(): + '''makes a tarball for distribution''' + samba_dist.dist() + +def reconfigure(ctx): + '''reconfigure if config scripts have changed''' + samba_utils.reconfigure(ctx) diff --git a/ldb-2.0.8/lib/tevent/ABI/tevent-0.10.0.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.10.0.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.10.0.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_entry_untrigger: void (struct tevent_queue_entry *) +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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +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_req_set_profile: bool (struct tevent_req *) +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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.10.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.10.sigs new file mode 100644 index 0000000..9adaba5 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.10.sigs @@ -0,0 +1,73 @@ +_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_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_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_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_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_queue_add: bool (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_start: void (struct tevent_queue *) +tevent_queue_stop: void (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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_signal_support: bool (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_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.11.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.11.sigs new file mode 100644 index 0000000..9adaba5 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.11.sigs @@ -0,0 +1,73 @@ +_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_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_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_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_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_queue_add: bool (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_start: void (struct tevent_queue *) +tevent_queue_stop: void (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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_signal_support: bool (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_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.12.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.12.sigs new file mode 100644 index 0000000..df9b08d --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.12.sigs @@ -0,0 +1,74 @@ +_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_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_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_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_queue_add: bool (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_start: void (struct tevent_queue *) +tevent_queue_stop: void (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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_signal_support: bool (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_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.13.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.13.sigs new file mode 100644 index 0000000..888ca0e --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.13.sigs @@ -0,0 +1,75 @@ +_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_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_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_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_queue_add: bool (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_start: void (struct tevent_queue *) +tevent_queue_stop: void (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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_signal_support: bool (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_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.14.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.14.sigs new file mode 100644 index 0000000..13c461c --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.14.sigs @@ -0,0 +1,78 @@ +_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_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_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_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, 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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_signal_support: bool (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_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.15.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.15.sigs new file mode 100644 index 0000000..13c461c --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.15.sigs @@ -0,0 +1,78 @@ +_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_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_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_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, 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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_signal_support: bool (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_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.16.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.16.sigs new file mode 100644 index 0000000..ea7f944 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.16.sigs @@ -0,0 +1,82 @@ +_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_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_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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.17.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.17.sigs new file mode 100644 index 0000000..ea7f944 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.17.sigs @@ -0,0 +1,82 @@ +_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_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_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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.18.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.18.sigs new file mode 100644 index 0000000..70d20b6 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.18.sigs @@ -0,0 +1,83 @@ +_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_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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.19.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.19.sigs new file mode 100644 index 0000000..70d20b6 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.19.sigs @@ -0,0 +1,83 @@ +_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_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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.20.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.20.sigs new file mode 100644 index 0000000..7b9c77d --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.20.sigs @@ -0,0 +1,87 @@ +_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_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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.21.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.21.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.21.sigs @@ -0,0 +1,88 @@ +_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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.22.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.22.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.22.sigs @@ -0,0 +1,88 @@ +_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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.23.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.23.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.23.sigs @@ -0,0 +1,88 @@ +_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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.24.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.24.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.24.sigs @@ -0,0 +1,88 @@ +_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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.25.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.25.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.25.sigs @@ -0,0 +1,88 @@ +_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_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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.26.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.26.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.26.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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.27.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.27.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.27.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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.28.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.28.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.29.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.29.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.30.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.30.sigs new file mode 100644 index 0000000..9b8bfa1 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.31.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.31.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/ldb-2.0.8/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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.32.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.32.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.32.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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.33.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.33.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.33.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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.34.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.34.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.34.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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.35.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.35.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.35.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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.36.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.36.sigs new file mode 100644 index 0000000..8a579c8 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.36.sigs @@ -0,0 +1,100 @@ +_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_entry_untrigger: void (struct tevent_queue_entry *) +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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.37.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.37.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.37.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_entry_untrigger: void (struct tevent_queue_entry *) +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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +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_req_set_profile: bool (struct tevent_req *) +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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.38.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.38.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.38.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_entry_untrigger: void (struct tevent_queue_entry *) +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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +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_req_set_profile: bool (struct tevent_req *) +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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.39.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.39.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.39.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_entry_untrigger: void (struct tevent_queue_entry *) +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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +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_req_set_profile: bool (struct tevent_req *) +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/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.9.sigs b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.9.sigs new file mode 100644 index 0000000..9adaba5 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/ABI/tevent-0.9.9.sigs @@ -0,0 +1,73 @@ +_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_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_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_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_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_queue_add: bool (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_start: void (struct tevent_queue *) +tevent_queue_stop: void (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_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_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +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_signal_support: bool (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_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/ldb-2.0.8/lib/tevent/Makefile b/ldb-2.0.8/lib/tevent/Makefile new file mode 100644 index 0000000..6a3aab0 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/Makefile @@ -0,0 +1,52 @@ +# simple makefile wrapper to run waf +WAF_BIN=`PATH=buildtools/bin:../../buildtools/bin:$$PATH which waf` +WAF_BINARY=$(PYTHON) $(WAF_BIN) +WAF=PYTHONHASHSEED=1 WAF_MAKE=1 $(WAF_BINARY) + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: + $(WAF) test $(TEST_OPTIONS) + +dist: + touch .tmplock + WAFLOCK=.tmplock $(WAF) dist + +distcheck: + touch .tmplock + WAFLOCK=.tmplock $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags diff --git a/ldb-2.0.8/lib/tevent/bindings.py b/ldb-2.0.8/lib/tevent/bindings.py new file mode 100644 index 0000000..f5e1499 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/bindings.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +# +# Python integration for tevent - tests +# +# Copyright (C) Jelmer Vernooij 2010 +# +# ** NOTE! The following LGPL license applies to the tevent +# ** 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 +# Lesser 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 . + +import signal +from unittest import TestCase, TestProgram +import gc + +import _tevent + + +class BackendListTests(TestCase): + + def test_backend_list(self): + self.assertTrue(isinstance(_tevent.backend_list(), list)) + + +class CreateContextTests(TestCase): + + def test_by_name(self): + ctx = _tevent.Context(_tevent.backend_list()[0]) + self.assertTrue(ctx is not None) + + def test_no_name(self): + ctx = _tevent.Context() + self.assertTrue(ctx is not None) + + +class ContextTests(TestCase): + + def setUp(self): + super(ContextTests, self).setUp() + self.ctx = _tevent.Context() + + def test_signal_support(self): + self.assertTrue(type(self.ctx.signal_support) is bool) + + def test_reinitialise(self): + self.ctx.reinitialise() + + def test_loop_wait(self): + self.ctx.loop_wait() + + def test_add_signal(self): + sig = self.ctx.add_signal(signal.SIGINT, 0, lambda callback: None) + self.assertTrue(isinstance(sig, _tevent.Signal)) + + def test_timer(self): + """Test a timer is can be scheduled""" + collecting_list = [] + # time "0" has already passed, callback will be scheduled immediately + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + self.assertTrue(timer.active) + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertFalse(timer.active) + self.assertEqual(collecting_list, [True]) + + def test_timer_deallocate_timer(self): + """Test timer is scheduled even if reference to it isn't held""" + collecting_list = [] + + def callback(t): + collecting_list.append(True) + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + gc.collect() + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertEqual(collecting_list, [True]) + + def test_timer_deallocate_context(self): + """Test timer is unscheduled when context is freed""" + collecting_list = [] + + def callback(t): + collecting_list.append(True) + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + self.assertTrue(timer.active) + del self.ctx + gc.collect() + self.assertEqual(collecting_list, []) + self.assertFalse(timer.active) + + def test_timer_offset(self): + """Test scheduling timer with an offset""" + collecting_list = [] + self.ctx.add_timer_offset(0.2, lambda t: collecting_list.append(2)) + self.ctx.add_timer_offset(0.1, lambda t: collecting_list.append(1)) + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertEqual(collecting_list, [1]) + self.ctx.loop_once() + self.assertEqual(collecting_list, [1, 2]) + + +if __name__ == '__main__': + TestProgram() diff --git a/ldb-2.0.8/lib/tevent/configure b/ldb-2.0.8/lib/tevent/configure new file mode 100755 index 0000000..c3c4447 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/configure @@ -0,0 +1,21 @@ +#!/bin/sh + +PREVPATH=`dirname $0` + +if [ -f $PREVPATH/../../buildtools/bin/waf ]; then + WAF=../../buildtools/bin/waf +elif [ -f $PREVPATH/buildtools/bin/waf ]; then + WAF=./buildtools/bin/waf +else + echo "tevent: Unable to find waf" + exit 1 +fi + +# using JOBS=1 gives maximum compatibility with +# systems like AIX which have broken threading in python +JOBS=1 +export JOBS + +cd . || exit 1 +$PYTHON $WAF configure "$@" || exit 1 +cd $PREVPATH diff --git a/ldb-2.0.8/lib/tevent/doc/img/tevent_context_stucture.png b/ldb-2.0.8/lib/tevent/doc/img/tevent_context_stucture.png new file mode 100644 index 0000000..fba8161 Binary files /dev/null and b/ldb-2.0.8/lib/tevent/doc/img/tevent_context_stucture.png differ diff --git a/ldb-2.0.8/lib/tevent/doc/img/tevent_subrequest.png b/ldb-2.0.8/lib/tevent/doc/img/tevent_subrequest.png new file mode 100644 index 0000000..ea79223 Binary files /dev/null and b/ldb-2.0.8/lib/tevent/doc/img/tevent_subrequest.png differ diff --git a/ldb-2.0.8/lib/tevent/doc/mainpage.dox b/ldb-2.0.8/lib/tevent/doc/mainpage.dox new file mode 100644 index 0000000..5b76013 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/mainpage.dox @@ -0,0 +1,47 @@ +/** + * @mainpage + * + * Tevent is an event system based on the talloc memory management library. It + * is the core event system used in Samba. + * + * The low level tevent has support for many event types, including timers, + * signals, and the classic file descriptor events. + * + * Tevent also provide helpers to deal with asynchronous code providing the + * tevent_req (tevent request) functions. + * + * @section main_tevent_tutorial Tutorial + * + * You should start by reading @subpage tevent_tutorial, then reading the + * documentation of the interesting functions as you go. + * + * @section main_tevent_download Download + * + * You can download the latest releases of tevent from the + * tevent directory + * on the samba public source archive. + * + * @section main_tevent_bugs Discussion and bug reports + * + * tevent does not currently have its own mailing list or bug tracking system. + * For now, please use the + * samba-technical + * mailing list, and the + * Samba bugzilla + * bug tracking system. + * + * @section main_tevent_devel Development + * You can download the latest code either via git or rsync. + * + * To fetch via git see the following guide: + * + * Using Git for Samba Development + * + * Once you have cloned the tree switch to the master branch and cd into the + * lib/tevent directory. + * + * To fetch via rsync use this command: + * + * rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/tevent . + * + */ diff --git a/ldb-2.0.8/lib/tevent/doc/tevent_context.dox b/ldb-2.0.8/lib/tevent/doc/tevent_context.dox new file mode 100644 index 0000000..39eb85e --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tevent_context.dox @@ -0,0 +1,75 @@ +/** +@page tevent_context Chapter 1: Tevent context + +@section context Tevent context + +Tevent context is an essential logical unit of tevent library. For working with +events at least one such context has to be created - allocated, initialized. +Then, events which are meant to be caught and handled have to be registered +within this specific context. Reason for subordinating events to a tevent +context structure rises from the fact that several context can be created and +each of them is processed at different time. So, there can be 1 context +containing just file descriptor events, another one taking care of signal and +time events and the third one which keeps information about the rest. + +Tevent loops are the part of the library which represents the mechanism where +noticing events and triggering handlers actually happens. They accept just one +argument - tevent context structure. Therefore if theoretically an infinity +loop (tevent_loop_wait) was called, only those arguments which belong to the +passed tevent context structure can be caught and invoked within this call. +Although some more signal events were registered (but within some other +context) they will not be noticed. + +@subsection Example + +First lines which handle mem_ctx belong to talloc library +knowledge but because of the fact that tevent uses the talloc library for its +mechanisms it is necessary to understand a bit talloc as well. For more +information about working with talloc, please visit talloc website where tutorial and +documentation are located. + +Tevent context structure *event_ctx represents the unit which will +further contain information about registered events. It is created via calling +tevent_context_init(). + +@code +TALLOC_CTX *mem_ctx = talloc_new(NULL); +if (mem_ctx == NULL) { + // error handling +} + +struct tevent_context *ev_ctx = tevent_context_init(mem_ctx); +if(ev_ctx == NULL) { + // error handling +} +@endcode + +Tevent context has a structure containing lots of information. It include lists +of all events which are divided according their type and are in order showing +the sequence as they came. + +@image html tevent_context_stucture.png + +In addition to the lists shown in the diagram, the tevent context also contains +many other data (e.g. information about the available system mechanism for +triggering callbacks). + +@section tevent_loops Tevent loops + +Tevent loops are the dispatcher for events. They catch them and trigger the +handlers. In the case of longer processes, the program spends most of its time +at this point waiting for events, invoking handlers and waiting for another +event again. There are 2 types of loop available for use in tevent library: + +
    +
  • int tevent_loop_wait()
  • +
  • int tevent_loop_once()
  • +
+ +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/ldb-2.0.8/lib/tevent/doc/tevent_data.dox b/ldb-2.0.8/lib/tevent/doc/tevent_data.dox new file mode 100644 index 0000000..dbe7a04 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tevent_data.dox @@ -0,0 +1,137 @@ +/** +@page tevent_data Chapter 3: Accessing data +@section data Accessing data with tevent + +A tevent request is (usually) created together with a structure for storing the +data necessary for an asynchronous computation. For these private data, tevent +library uses void (generic) pointers, therefore any data type can be very +simply pointed at. However, this attitude requires clear and guaranteed +knowledge of the data type that will be handled, in advance. Private data can +be of 2 types: connected with a request itself or given as an individual +argument to a callback. It is necessary to differentiate these types, because +there is a slightly different method of data access for each. There are two +possibilities how to access data that is given as an argument directly to a +callback. The difference lies in the pointer that is returned. In one case it +is the data type specified in the function’s argument, in another void* is +returned. + +@code +void tevent_req_callback_data (struct tevent_req *req, #type) +void tevent_req_callback_data_void (struct tevent_req *req) +@endcode + + +To obtain data that are strictly bound to a request, this function is the only +direct procedure. + +@code +void *tevent_req_data (struct tevent_req *req, #type) +@endcode + +Example with both calls which differs between private data within tevent +request and data handed over as an argument. + +@code +#include +#include +#include + +struct foo_state { + int x; +}; + +struct testA { + int y; +}; + + +static void foo_done(struct tevent_req *req) { + // a->x contains 10 since it came from foo_send + struct foo_state *a = tevent_req_data(req, struct foo_state); + + // b->y contains 9 since it came from run + struct testA *b = tevent_req_callback_data(req, struct testA); + + // c->y contains 9 since it came from run we just used a different way + // of getting it. + struct testA *c = (struct testA *)tevent_req_callback_data_void(req); + + printf("a->x: %d\n", a->x); + printf("b->y: %d\n", b->y); + printf("c->y: %d\n", c->y); +} + + +struct tevent_req * foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx) { + +printf("_send\n"); +struct tevent_req *req; +struct foo_state *state; + +req = tevent_req_create(event_ctx, &state, struct foo_state); +state->x = 10; + +return req; +} + +static void run(struct tevent_context *ev, struct tevent_timer *te, + struct timeval current_time, void *private_data) { + struct tevent_req *req; + struct testA *tmp = talloc(ev, struct testA); + + // Note that we did not use the private data passed in + + tmp->y = 9; + req = foo_send(ev, ev); + + tevent_req_set_callback(req, foo_done, tmp); + tevent_req_done(req); + +} + +int main (int argc, char **argv) { + + struct tevent_context *event_ctx; + struct testA *data; + TALLOC_CTX *mem_ctx; + struct tevent_timer *time_event; + + mem_ctx = talloc_new(NULL); //parent + if (mem_ctx == NULL) + return EXIT_FAILURE; + + event_ctx = tevent_context_init(mem_ctx); + if (event_ctx == NULL) + return EXIT_FAILURE; + + data = talloc(mem_ctx, struct testA); + data->y = 11; + + time_event = tevent_add_timer(event_ctx, + mem_ctx, + tevent_timeval_current(), + run, + data); + if (time_event == NULL) { + fprintf(stderr, " FAILED\n"); + return EXIT_FAILURE; + } + + tevent_loop_once(event_ctx); + + talloc_free(mem_ctx); + + printf("Quit\n"); + return EXIT_SUCCESS; +} +@endcode + +Output of this example is: + +@code +a->x: 10 +b->y: 9 +c->y: 9 +@endcode + +*/ diff --git a/ldb-2.0.8/lib/tevent/doc/tevent_events.dox b/ldb-2.0.8/lib/tevent/doc/tevent_events.dox new file mode 100644 index 0000000..d56af25 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tevent_events.dox @@ -0,0 +1,341 @@ +/** +@page tevent_events Chapter 2: Tevent events +@section pools Tevent events + +Ok, after reading previous chapter we can start doing something useful. So, the +way of creating events is similar for all types - signals, file descriptors, +time or immediate events. At the beginning it is good to know about some +typedefs which are set in tevent library and which specify the arguments for +each callback. These callbacks are: + +- tevent_timer_handler_t() + +- tevent_immediate_handler_t() + +- tevent_signal_handler_t() + +- tevent_fd_handler_t() + +According their names it is obvious that for creating callback for e.g. time +event, tevent_timer_handler_t will be used. + +The best way how to introduce registering an event and setting up a callback +would be example, so examples describing all the types of events follow. + +@subsection Time Time event + +This example shows how to set up an event which will be repeated for a minute +with interval of 2 seconds (will be triggered 30 times). After exceeding this +limit, the event loop will finish and all the memory resources will be freed. +This is just example describing repeated activity, nothing usefull is done +within foo function + +@code +#include +#include +#include +#include + +struct state { + struct timeval endtime; + int counter; + TALLOC_CTX *ctx; +}; + +static void callback(struct tevent_context *ev, struct tevent_timer *tim, + struct timeval current_time, void *private_data) +{ + struct state *data = talloc_get_type_abort(private_data, struct state); + struct tevent_timer *time_event; + struct timeval schedule; + + printf("Data value: %d\n", data->counter); + data->counter += 1; // increase counter + + // if time has not reached its limit, set another event + if (tevent_timeval_compare(¤t_time, &(data->endtime)) < 0) { + // do something + // set repeat with delay 2 seconds + schedule = tevent_timeval_current_ofs(2, 0); + time_event = tevent_add_timer(ev, data->ctx, schedule, callback, data); + if (time_event == NULL) { // error ... + fprintf(stderr, "MEMORY PROBLEM\n"); + return; + } + } else { + // time limit exceeded + } +} + +int main(void) { + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_timer *time_event; + struct timeval schedule; + + mem_ctx = talloc_new(NULL); // parent + event_ctx = tevent_context_init(mem_ctx); + + struct state *data = talloc(mem_ctx, struct state); + + schedule = tevent_timeval_current_ofs(2, 0); // +2 second time value + data->endtime = tevent_timeval_add(&schedule, 60, 0); // one minute time limit + data->ctx = mem_ctx; + data->counter = 0; + + // add time event + time_event = tevent_add_timer(event_ctx, mem_ctx, schedule, callback, data); + if (time_event == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + tevent_loop_wait(event_ctx); + talloc_free(mem_ctx); + return EXIT_SUCCESS; +} +@endcode + +Variable counter is only used for counting the number of triggered +functions. List of all available functions which tevent offers for working with +time are listed +here together +with their description. More detailed view at these functions is unnecessary +because their purpose and usage is quite simple and clear. + +@subsection Immediate Immediate event + +These events are, as their name indicates, activated and performed immediately. +It means that this kind of events have priority over others (except signal +events). So if there is a bulk of events registered and after that a +tevent loop is launched, then all the immediate events will be triggered before +the other events. Except other immediate events (and signal events) because +they are also processed sequentially - according the order they were scheduled. +Signals have the highest priority and therefore they are processed +preferentially. Therefore the expression immediate may not correspond exactly +to the dictionary definition of "something without delay" but rather "as soon +as possible" after all preceding immediate events. + +For creating an immediate event there is a small different which lies in the +fact that the creation of such event is done in 2 steps. One represents the +creation (memory allocation), the second one represents registering as the +event within some tevent context. + +@code +struct tevent_immediate *run(TALLOC_CTX* mem_ctx, + struct tevent_context event_ctx, + void * data) +{ + struct tevent_immediate *im; + + im = tevent_create_immediate(mem_ctx); + if (im == NULL) { + return NULL; + } + tevent_schedule_immediate(im, event_ctx, foo, data); + + return im; +} +@endcode + +Example which may be compiled and run representing the creation of immediate event. + +@code + +#include +#include +#include + +struct info_struct { + int counter; +}; + +static void foo(struct tevent_context *ev, struct tevent_immediate *im, + void *private_data) +{ + struct info_struct *data = talloc_get_type_abort(private_data, struct info_struct); + printf("Data value: %d\n", data->counter); +} + +int main (void) { + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_immediate *im; + + printf("INIT\n"); + + mem_ctx = talloc_new(NULL); + event_ctx = tevent_context_init(mem_ctx); + + struct info_struct *data = talloc(mem_ctx, struct info_struct); + + // setting up private data + data->counter = 1; + + // first immediate event + im = tevent_create_immediate(mem_ctx); + if (im == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + tevent_schedule_immediate(im, event_ctx, foo, data); + + tevent_loop_wait(event_ctx); + talloc_free(mem_ctx); + + return 0; +} +@endcode + +@subsection Signal Signal event + +This is an alternative to standard C library functions signal() or sigaction(). +The main difference that distinguishes these ways of treating signals is their +setting up of handlers for different time intervals of the running program. + +While standard C library methods for dealing with signals offer sufficient +tools for most cases, they are inadequate for handling signals within the +tevent loop. It could be necessary to finish certain tevent requests within the +tevent loop without interruption. If a signal was sent to a program at a moment +when the tevent loop is in progress, a standard signal handler would not return +processing to the application at the very same place and it would quit the +tevent loop for ever. In such cases, tevent signal handlers offer the +possibility of dealing with these signals by masking them from the rest of +application and not quitting the loop, so the other events can still be +processed. + +Tevent offers also a control function, which enables us to verify whether it is +possible to handle signals via tevent, is defined within tevent library and it +returns a boolean value revealing the result of the verification. + +@code +bool tevent_signal_support (struct tevent_context *ev) +@endcode + +Checking for signal support is not necessary, but if it is not guaranteed, this +is a good and easy control to prevent unexpected behaviour or failure of the +program occurring. Such a test of course does not have to be run every single +time you wish to create a signal handler, but simply at the beginning - during +the initialization procedures of the program. Afterthat, simply adapt to each +situation that arises. + +@code + +#include +#include +#include + +static void handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + + // Do something usefull + + printf("handling signal...\n"); + exit(EXIT_SUCCESS); +} + +int main (void) +{ + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_signal *sig; + + mem_ctx = talloc_new(NULL); //parent + if (mem_ctx == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + event_ctx = tevent_context_init(mem_ctx); + if (event_ctx == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + if (tevent_signal_support(event_ctx)) { + // create signal event + sig = tevent_add_signal(event_ctx, mem_ctx, SIGINT, 0, handler, NULL); + if (sig == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + tevent_loop_wait(event_ctx); + } + + talloc_free(mem_ctx); + return EXIT_SUCCESS; +} +@endcode + + +@subsection File File descriptor event + +Support of events on file descriptors is mainly useful for socket communication +but it certainly works flawlessly with standard streams (stdin, stdout, stderr) + as well. Working asynchronously with file descriptors enables switching + within processing I/O operations. This ability may rise with a greater + number of I/O operations and such overlapping leads to enhancement of the + throughput. + +There are several other functions included in tevent API related to handling +file descriptors (there are too many functions defined within tevent therefore +just some of them are fully described within this thesis. The +declaration of the rest can be easily found on the library’s website or +directly from the source code): + +
    +
  • tevent_fd_set_close_fn() - can add another function to be called at the + moment when a structure tevent fd is freed.
  • +
  • tevent_fd_set_auto_close() - calling this function can simplify the + maintenance of file descriptors, because it instructs tevent to close the + appropriate file descriptor when the tevent fd structure is about to be + freed.
  • +
  • tevent_fd_get_flags() - returns flags which are set on the file descriptor + connected with this tevent fd structure.
  • +
  • tevent_fd_set_flags() - sets specified flags on the event’s file + descriptor.
  • +
+ +@code + +static void close_fd(struct tevent_context *ev, struct tevent_fd *fd_event, + int fd, void *private_data) +{ + // processing when fd_event is freed +} + +struct static void handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + // handling event; reading from a file descriptor + tevent_fd_set_close_fn (fd_event, close_fd); +} + +int run(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx, + int fd, uint16_t flags, char *buffer) +{ + struct tevent_fd* fd_event = NULL; + + if (flags & TEVENT_FD_READ) { + fd_event = tevent_add_fd(event_ctx, + mem_ctx, + fd, + flags, + handler, + buffer); + } + if (fd_event == NULL) { + // error handling + } + return tevent_loop_once(); +} +@endcode + +*/ diff --git a/ldb-2.0.8/lib/tevent/doc/tevent_queue.dox b/ldb-2.0.8/lib/tevent/doc/tevent_queue.dox new file mode 100644 index 0000000..9c247e5 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tevent_queue.dox @@ -0,0 +1,275 @@ +/** +@page tevent_queue Chapter 5: Tevent queue +@section queue Tevent queue + +There is a possibility that the dispatcher and its handlers may not be able to +handle all the incoming events as quickly as they arrive. One way to deal with +this situation is to buffer the received events by introducing an event queue +into the events stream, between the events generator and the dispatcher. Events +are added to the queue as they arrive, and the dispatcher pops them off the +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 +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 +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. + +@code +struct tevent_queue* tevent_queue_create (TALLOC_CTX *mem_ctx, const char *name) +@endcode + +When the program returns from this function, the allocated memory, set +destructor and labeled queue as running has been done and the structure is +ready to be filled with entries. Stopping and starting queues on the run. If +you need to stop a queue from processing its entries, and then turn it on +again, a couple of functions which serve this purpose are: + +- bool tevent_queue_stop() +- bool tevent_queue_start() + +These functions actually only provide for the simple setting of a variable, +which indicates that the queue has been stopped/started. Returned value +indicates result. + +@subsection add_queue Adding Requests to a Queue + +Tevent in fact offers 3 possible ways of inserting a request into a queue. +There are no vast differences between them, but still there might be situations +where one of them is more suitable and desired than another. + +@code +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +This call is the simplest of all three. It offers only boolean verification of +whether the operation of adding the request into a queue was successful or not. +No additional deletion of an item from the queue is possible, i.e. it is only +possible to deallocate the whole tevent request, which would cause triggering +of destructor handling and also dropping the request from the queue. + +Extended Options + +Both of the following functions have a feature in common - they return tevent +queue entry structure representing the item in a queue. There is no further +possible handling with this structure except the use of the structure’s pointer +for its deallocation (which leads also its removal from the queue). The +difference lies in the possibility that with the following functions it is +possible to remove the tevent request from a queue without its deallocation. +The previous function can only deallocate the tevent request as it was from +memory, and thereby logically cause its removal from the queue as well. There +is no other utilization of this structure via API at this stage of tevent +library. The possibility of easier debugging while developing with tevent could +be considered to be an advantage of this returned pointer. + +@code +struct tevent_queue_entry *tevent_queue_add_entry(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +The feature that allows for the optimized addition of entries to a queue is +that a check for an empty queue with no items is first of all carried out. If +it is found that the queue is empty, then the request for inserting the entry +into a queue will be omitted and directly triggered. + +@code +struct tevent_queue_entry *tevent_queue_add_optimize_empty(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +When calling any of the functions serving for inserting an item into a queue, +it is possible to leave out the fourth argument (trigger) and instead of a +function pass a NULL pointer. This usage sets so-called blocking entries. +These entries, since they do not have any trigger operation to be activated, +just sit in their position until they are labeled as a done by another +function. Their purpose is to block other items in the queue from being +triggered. + +@subsection example_q Example of tevent queue + +@code +#include +#include +#include + +struct foo_state { + int local_var; + int x; +}; + +struct juststruct { + TALLOC_CTX * ctx; + struct tevent_context *ev; + int y; +}; + +int created = 0; + +static void timer_handler(struct tevent_context *ev, struct tevent_timer *te, + struct timeval current_time, void *private_data) +{ + // time event which after all sets request as done. Following item from + // the queue may be invoked. + struct tevent_req *req = private_data; + struct foo_state *stateX = tevent_req_data(req, struct foo_state); + + // processing some stuff + + printf("time_handler\n"); + + tevent_req_done(req); + talloc_free(req); + + printf("Request #%d set as done.\n", stateX->x); +} + +static void trigger(struct tevent_req *req, void *private_data) +{ + struct juststruct *priv = tevent_req_callback_data (req, struct juststruct); + struct foo_state *in = tevent_req_data(req, struct foo_state); + struct timeval schedule; + struct tevent_timer *tim; + schedule = tevent_timeval_current_ofs(1, 0); + printf("Processing request #%d\n", in->x); + + if (in->x % 3 == 0) { // just example; third request does not contain + // any further operation and will be finished right + // away. + tim = NULL; + } else { + tim = tevent_add_timer(priv->ev, req, schedule, timer_handler, req); + } + + if (tim == NULL) { + tevent_req_done(req); + talloc_free(req); + printf("Request #%d set as done.\n", in->x); + } +} + +struct tevent_req *foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *name, int num) +{ + struct tevent_req *req; + struct foo_state *state; + struct foo_state *in; + struct tevent_timer *tim; + + printf("foo_send\n"); + req = tevent_req_create(mem_ctx, &state, struct foo_state); + if (req == NULL) { // check for appropriate allocation + tevent_req_error(req, 1); + return NULL; + } + + // exemplary filling of variables + state->local_var = 1; + state->x = num; + + return req; +} + +static void foo_done(struct tevent_req *req) { + + enum tevent_req_state state; + uint64_t err; + + if (tevent_req_is_error(req, &state, &err)) { + printf("ERROR WAS SET %d\n", state); + return; + } else { + // processing some stuff + printf("Callback is done...\n"); + } +} + +int main (int argc, char **argv) +{ + TALLOC_CTX *mem_ctx; + struct tevent_req* req[6]; + struct tevent_req* tmp; + struct tevent_context *ev; + struct tevent_queue *fronta = NULL; + struct juststruct *data; + int ret; + int i = 0; + + const char * const names[] = { + "first", "second", "third", "fourth", "fifth" + }; + + printf("INIT\n"); + + mem_ctx = talloc_new(NULL); //parent + talloc_parent(mem_ctx); + ev = tevent_context_init(mem_ctx); + if (ev == NULL) { + fprintf(stderr, "MEMORY ERROR\n"); + return EXIT_FAILURE; + } + + // setting up queue + fronta = tevent_queue_create(mem_ctx, "test_queue"); + tevent_queue_stop(fronta); + tevent_queue_start(fronta); + if (tevent_queue_running(fronta)) { + printf ("Queue is runnning (length: %d)\n", tevent_queue_length(fronta)); + } else { + printf ("Queue is not runnning\n"); + } + + data = talloc(ev, struct juststruct); + data->ctx = mem_ctx; + data->ev = ev; + + + // create 4 requests + for (i = 1; i < 5; i++) { + req[i] = foo_send(mem_ctx, ev, names[i], i); + tmp = req[i]; + if (req[i] == NULL) { + fprintf(stderr, "Request error! %d \n", ret); + break; + } + tevent_req_set_callback(req[i], foo_done, data); + created++; + } + + // add item to a queue + tevent_queue_add(fronta, ev, req[1], trigger, data); + tevent_queue_add(fronta, ev, req[2], trigger, data); + tevent_queue_add(fronta, ev, req[3], trigger, data); + tevent_queue_add(fronta, ev, req[4], trigger, data); + + printf("Queue length: %d\n", tevent_queue_length(fronta)); + while(tevent_queue_length(fronta) > 0) { + tevent_loop_once(ev); + printf("Queue: %d items left\n", tevent_queue_length(fronta)); + } + + talloc_free(mem_ctx); + printf("FINISH\n"); + + return EXIT_SUCCESS; +} +@endcode + +*/ diff --git a/ldb-2.0.8/lib/tevent/doc/tevent_request.dox b/ldb-2.0.8/lib/tevent/doc/tevent_request.dox new file mode 100644 index 0000000..e1e45b1 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tevent_request.dox @@ -0,0 +1,189 @@ +/** +@page tevent_request Chapter 4: Tevent request +@section request Tevent request + +A specific feature of the library is the tevent request API that provides for +asynchronous computation and allows much more interconnected working and +cooperation among functions and events. When working with tevent request it +is possible to nest one event under another and handle them bit by bit. This +enables the creation of sequences of steps, and provides an opportunity to +prepare for all problems which may unexpectedly happen within the different +phases. One way or another, subrequests split bigger tasks into smaller ones +which allow a clearer view of each task as a whole. + +@subsection name Naming conventions + +There is a naming convention which is not obligatory but it is followed in this +tutorial: + +- Functions triggered before the event happens. These establish a request. +- \b foo_send(...) - this function is called first and it includes the + creation of tevent request - tevent req structure. It does not block + anything, it simply creates a request, sets a callback (foo done) and lets + the program continue +- Functions as a result of event. +- \b foo_done(...) - this function contains code providing for handling itself + and based upon its results, the request is set either as a done or, if an + error occurs, the request is set as a failure. +- \b foo_recv(...) - this function contains code which should, if demanded, + access the result data and make them further visible. The foo state should + be deallocated from memory when the request’s processing is over and + therefore all computed data up to this point would be lost. + +As was already mentioned, specific naming subsumes not only functions but also +the data themselves: + +- \b foo_state - this is a structure. It contains all the data necessary for + the asynchronous task. + +@subsection cr_req Creating a New Asynchronous Request + +The first step for working asynchronously is the allocation of memory +requirements. As in previous cases, the talloc context is required, upon which +the asynchronous request will be tied. The next step is the creation of the +request itself. + +@code +struct tevent_req* tevent_req_create (TALLOC_CTX *mem_ctx, void **pstate, #type) +@endcode + +The pstate is the pointer to the private data. The necessary amount of memory +(based on data type) is allocated during this call. Within this same memory +area all the data from the asynchronous request that need to be preserved for +some time should be kept. + +Dealing with a lack of memory + +The verification of the returned pointer against NULL is necessary in order to +identify a potential lack of memory. There is a special function which helps +with this check tevent_req_nomem(). + +It handles verification both of the talloc memory allocation and of the +associated tevent request, and is therefore a very useful function for avoiding +unexpected situations. It can easily be used when checking the availability of +further memory resources that are required for a tevent request. Imagine an +example where additional memory needs arise although no memory resources are +currently available. + +@code +bar = talloc(mem_ctx, struct foo); +if(tevent_req_nomem (bar, req)) { + // handling a problem +} +@endcode + +This code ensures that the variable bar, which contains NULL as a result of the +unsuccessful satisfaction of its memory requirements, is noticed, and also that +the tevent request req declares it exceeds memory capacity, which implies the +impossibility of finishing the request as originally programmed. + + +@subsection fini_req Finishing a Request + +Marking each request as finished is an essential principle of the tevent +library. Without marking the request as completed - either successfully or with +an error - the tevent loop could not let the appropriate callback be triggered. +It is important to understand that this would be a significant threat, because +it is not usually a question of one single function which prints some text on a +screen, but rather the request is itself probably just a link in a series of +other requests. Stopping one request would stop the others, memory resources +would not be freed, file descriptors might remain open, communication via +socket could be interrupted, and so on. Therefore it is important to think +about finishing requests, either successfully or not, and also to prepare +functions for all possible scenarios, so that the the callbacks do not process +data that are actually invalid or, even worse, in fact non-existent meaning +that a segmentation fault may arise. + +
    +
  • \b Manually - This is the most common type of finishing request. Calling +this function sets the request as a TEVENT_REQ_DONE. This is the only purpose +of this function and it should be used when everything went well. Typically it +is used within the done functions. + +@code +void tevent_req_done (struct tevent_req *req) +@endcode +Alternatively, the request can end up being unsuccessful. +@code +bool tevent_req_error (struct tevent_req *req, uint64_t error) +@endcode + +The second argument takes the number of an error (declared by the programmer, +for example in an enumerated variable). The function tevent_req_error() sets +the status of the request as a TEVENT_REQ_USER_ERROR and also stores the code +of error within the structure so it can be used, for example for debugging. The +function returns true, if marking the request as an error was processed with no +problem - value error passed to this function is not equal to 1.
  • + +
  • +Setting up a timeout for request - A request can be finished virtually, +or if the process takes too much time, it can be timed out. This is considered +as an error of the request and it leads to calling callback. In the +background, this timeout is set through a time event (described in +@subpage tevent_events ) which eventually triggers an operation marking the +request as a TEVENT_REQ_TIMED_OUT (can not be considered as successfully +finished). In case a time out was already set, this operation will overwrite it +with a new time value (so the timeout may be lengthened) and if everything is +set properly, it returns true. + +@code +bool tevent_req_set_endtime(struct tevent_req *req, + struct tevent_context *ev, + struct timeval endtime); +@endcode +
  • + + +
  • Premature Triggering - Imagine a situation in which some part of a +nested subrequest ended up with a failure and it is still required to trigger a +callback. Such as example might result from lack of memory leading to the +impossibility of allocating enough memory requirements for the event to start +processing another subrequest, or from a clear intention to skip other +procedures and trigger the callback regardless of other progress. In these +cases, the function tevent_req_post() is very handy and offers this option. + +@code +struct tevent_req* tevent_req_post (struct tevent_req *req, + struct tevent_context *ev); +@endcode + +A request finished in this way does not behave as a time event nor as a file +descriptor event but as a immediately scheduled event, and therefore it will be +treated according the description laid down in @subpage tevent_events . +
  • +
+ + +@section nested Subrequests - Nested Requests + +To create more complex and interconnected asynchronous operations, it is +possible to submerge a request into another and thus create a so-called +subrequest. Subrequests are not represented by any other special structure but +they are created from tevent_req_create(). This diagram shows the nesting and +life time of each request. The table below describes the same in words, and +shows the triggering of functions during the application run. + +Wrapper represents the trigger of the whole cascade of (sub)requests. It +may be e.g. a time or file descriptor event, or another request that was +created at a specific time by the function tevent_wakeup_send() which is a +slightly exceptional method of creating + +@code +struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval wakeup_time); +@endcode + +By calling this function, it is possible to create a tevent request which is +actually the return value of this function. In summary, it sets the time value +of the tevent request’s creation. While using this function it is necessary to +use another function in the subrequest’s callback to check for any problems +tevent_wakeup_recv() ) + +@image html tevent_subrequest.png + +A comprehensive example of nested subrequests can be found in the file +echo_server.c. It implements a complete, self-contained echo server with no +dependencies but libevent and libtalloc. + +*/ diff --git a/ldb-2.0.8/lib/tevent/doc/tevent_thread.dox b/ldb-2.0.8/lib/tevent/doc/tevent_thread.dox new file mode 100644 index 0000000..875dae8 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tevent_thread.dox @@ -0,0 +1,322 @@ +/** +@page tevent_thread Chapter 6: 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 +information about working with talloc, please visit talloc website where tutorial and +documentation are located. + +If a tevent context structure is talloced from a NULL, thread-safe talloc +context, then it can be safe to use in a threaded program. The function +talloc_disable_null_tracking() must be called from the initial +program thread before any talloc calls are made to ensure talloc is thread-safe. + +Each thread must create it's own tevent context structure as follows +tevent_context_init(NULL) and no talloc memory contexts +can be shared between threads. + +Separate threads using tevent in this way can communicate +by writing data into file descriptors that are being monitored +by a tevent context on another thread. For example (simplified +with no error handling): + +@code +Main thread: + +main() +{ + talloc_disable_null_tracking(); + + struct tevent_context *master_ev = tevent_context_init(NULL); + void *mem_ctx = talloc_new(master_ev); + + // Create file descriptor to monitor. + int pipefds[2]; + + pipe(pipefds); + + struct tevent_fd *fde = tevent_add_fd(master_ev, + mem_ctx, + pipefds[0], // read side of pipe + TEVENT_FD_READ, + pipe_read_handler, // callback function + private_data_pointer); + + // Create sub thread, pass pipefds[1] write side of pipe to it. + // The above code not shown here.. + + // Process events. + tevent_loop_wait(master_ev); + + // Cleanup if loop exits. + talloc_free(master_ev); +} + +@endcode + +When the subthread writes to pipefds[1], the function +pipe_read_handler() will be called in the main thread. + +@subsection More sophisticated use + +A popular way to use an event library within threaded programs +is to allow a sub-thread to asynchronously schedule a tevent_immediate +function call from the event loop of another thread. This can be built +out of the basic functions and isolation mechanisms of tevent, +but tevent also comes with some utility functions that make +this easier, so long as you understand the limitations that +using threads with talloc and tevent impose. + +To allow a tevent context to receive an asynchronous tevent_immediate +function callback from another thread, create a struct tevent_thread_proxy * +by calling @code + +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx); + +@endcode + +This function allocates the internal data structures to +allow asynchronous callbacks as a talloc child of the +struct tevent_context *, and returns a struct tevent_thread_proxy * +that can be passed to another thread. + +When you have finished receiving asynchronous callbacks, simply +talloc_free the struct tevent_thread_proxy *, or talloc_free +the struct tevent_context *, which will deallocate the resources +used. + +To schedule an asynchronous tevent_immediate function call from one +thread on the tevent loop of another thread, use +@code + +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + tevent_immediate_handler_t handler, + void **pp_private_data); + +@endcode + +This function causes the function handler() +to be invoked as a tevent_immediate callback from the event loop +of the thread that created the struct tevent_thread_proxy * +(so the owning struct tevent_context * should be +long-lived and not in the process of being torn down). + +The struct tevent_thread_proxy object being +used here is a child of the event context of the target +thread. So external synchronization mechanisms must be +used to ensure that the target object is still in use +at the time of the tevent_thread_proxy_schedule() +call. In the example below, the request/response nature +of the communication ensures this. + +The struct tevent_immediate **pp_im passed into this function +should be a struct tevent_immediate * allocated on a talloc context +local to this thread, and will be reparented via talloc_move +to be owned by struct tevent_thread_proxy *tp. +*pp_im will be set to NULL on successful scheduling +of the tevent_immediate call. + +handler() will be called as a normal tevent_immediate +callback from the struct tevent_context * of the destination +event loop that created the struct tevent_thread_proxy * + +Returning from this functions does not mean that the handler +has been invoked, merely that it has been scheduled to be called in the +destination event loop. + +Because the calling thread does not wait for the +callback to be scheduled and run on the destination +thread, this is a fire-and-forget call. If you wish +confirmation of the handler() being +successfully invoked, you must ensure it replies to the +caller in some way. + +Because of asynchronous nature of this call, the nature +of the parameter passed to the destination thread has some +restructions. If you don't need parameters, merely pass +NULL as the value of +void **pp_private_data. + +If you wish to pass a pointer to data between the threads, +it MUST be a pointer to a talloced pointer, which is +not part of a talloc-pool, and it must not have a destructor +attached. The ownership of the memory pointed to will +be passed from the calling thread to the tevent library, +and if the receiving thread does not talloc-reparent +it to its own contexts, it will be freed once the +handler is called. + +On success, *pp_private will be NULL +to signify the talloc memory ownership has been moved. + +In practice for message passing between threads in +event loops these restrictions are not very onerous. + +The easiest way to to a request-reply pair between +tevent loops on different threads is to pass the +parameter block of memory back and forth using +a reply tevent_thread_proxy_schedule() +call. + +Here is an example (without error checking for +simplicity): + +@code +------------------------------------------------ +// Master thread. + +main() +{ + // Make talloc thread-safe. + + talloc_disable_null_tracking(); + + // Create the master event context. + + struct tevent_context *master_ev = tevent_context_init(NULL); + + // Create the master thread proxy to allow it to receive + // async callbacks from other threads. + + struct tevent_thread_proxy *master_tp = + tevent_thread_proxy_create(master_ev); + + // Create sub-threads, passing master_tp in + // some way to them. + // This code not shown.. + + // Process events. + // Function master_callback() below + // will be invoked on this thread on + // master_ev event context. + + tevent_loop_wait(master_ev); + + // Cleanup if loop exits. + + talloc_free(master_ev); +} + +// Data passed between threads. +struct reply_state { + struct tevent_thread_proxy *reply_tp; + pthread_t thread_id; + bool *p_finished; +}; + +// Callback Called in child thread context. + +static void thread_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + // Move the ownership of what private_ptr + // points to from the tevent library back to this thread. + + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + + talloc_steal(ev, rsp); + + *rsp->p_finished = true; + + // im will be talloc_freed on return from this call. + // but rsp will not. +} + +// Callback Called in master thread context. + +static void master_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + // Move the ownership of what private_ptr + // points to from the tevent library to this thread. + + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + + talloc_steal(ev, rsp); + + printf("Callback from thread %s\n", thread_id_to_string(rsp->thread_id)); + + /* Now reply to the thread ! */ + tevent_thread_proxy_schedule(rsp->reply_tp, + &im, + thread_callback, + &rsp); + + // Note - rsp and im are now NULL as the tevent library + // owns the memory. +} + +// Child thread. + +static void *thread_fn(void *private_ptr) +{ + struct tevent_thread_proxy *master_tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + bool finished = false; + int ret; + + // Create our own event context. + + struct tevent_context *ev = tevent_context_init(NULL); + + // Create the local thread proxy to allow us to receive + // async callbacks from other threads. + + struct tevent_thread_proxy *local_tp = + tevent_thread_proxy_create(master_ev); + + // Setup the data to send. + + struct reply_state *rsp = talloc(ev, struct reply_state); + + rsp->reply_tp = local_tp; + rsp->thread_id = pthread_self(); + rsp->p_finished = &finished; + + // Create the immediate event to use. + + struct tevent_immediate *im = tevent_create_immediate(ev); + + // Call the master thread. + + tevent_thread_proxy_schedule(master_tp, + &im, + master_callback, + &rsp); + + // Note - rsp and im are now NULL as the tevent library + // owns the memory. + + // Wait for the reply. + + while (!finished) { + tevent_loop_once(ev); + } + + // Cleanup. + + talloc_free(ev); + return NULL; +} + +@endcode + +Note this doesn't have to be a master-subthread communication. +Any thread that has access to the struct tevent_thread_proxy * +pointer of another thread that has called tevent_thread_proxy_create() + can send an async tevent_immediate request. + +But remember the caveat that external synchronization must be used +to ensure the target struct tevent_thread_proxy * object +exists at the time of the tevent_thread_proxy_schedule() +call or unreproducible crashes will result. +*/ diff --git a/ldb-2.0.8/lib/tevent/doc/tevent_tutorial.dox b/ldb-2.0.8/lib/tevent/doc/tevent_tutorial.dox new file mode 100644 index 0000000..207a244 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tevent_tutorial.dox @@ -0,0 +1,22 @@ +/** +@page tevent_tutorial The Tutorial + +@section tevent_tutorial_introduction Introduction + +Tutorial describing working with tevent library. + +@section tevent_tutorial_toc Table of contents + +@subpage tevent_context + +@subpage tevent_events + +@subpage tevent_data + +@subpage tevent_request + +@subpage tevent_queue + +@subpage tevent_thread + +*/ diff --git a/ldb-2.0.8/lib/tevent/doc/tutorials.dox b/ldb-2.0.8/lib/tevent/doc/tutorials.dox new file mode 100644 index 0000000..e8beed7 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doc/tutorials.dox @@ -0,0 +1,43 @@ +/** + * @page tevent_queue_tutorial The tevent_queue tutorial + * + * @section Introduction + * + * A tevent_queue is used to queue up async requests that must be + * serialized. For example writing buffers into a socket must be + * serialized. Writing a large lump of data into a socket can require + * multiple write(2) or send(2) system calls. If more than one async + * request is outstanding to write large buffers into a socket, every + * request must individually be completed before the next one begins, + * even if multiple syscalls are required. + * + * To do this, every socket gets assigned a tevent_queue struct. + * + * Creating a serialized async request follows the usual convention to + * return a tevent_req structure with an embedded state structure. To + * serialize the work the requests is about to so, instead of directly + * starting or doing that work, tevent_queue_add must be called. When it + * is time for the serialized async request to do its work, the trigger + * callback function tevent_queue_add was given is called. In the example + * of writing to a socket, the trigger is called when the write request + * can begin accessing the socket. + * + * How does this engine work behind the scenes? When the queue is empty, + * tevent_queue_add schedules an immediate call to the trigger + * callback. The trigger callback starts its work, likely by starting + * other async subrequests. While these async subrequests are working, + * more requests can accumulate in the queue by tevent_queue_add. While + * there is no function to explicitly trigger the next waiter in line, it + * still works: When the active request in the queue is done, it will be + * destroyed by talloc_free. Talloc_free of an serialized async request + * that had been added to a queue will trigger the next request in the + * queue via a talloc destructor attached to a child of the serialized + * request. This way the queue will be kept busy when an async request + * finishes. + * + * @section Example + * + * @code + * Metze: Please add a code example here. + * @endcode + */ diff --git a/ldb-2.0.8/lib/tevent/doxy.config b/ldb-2.0.8/lib/tevent/doxy.config new file mode 100644 index 0000000..76d8b4c --- /dev/null +++ b/ldb-2.0.8/lib/tevent/doxy.config @@ -0,0 +1,1908 @@ +# Doxyfile 1.8.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed +# in front of the TAG it is preceding . +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = tevent + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.9.8 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, +# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, +# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields or simple typedef fields will be shown +# inline in the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO (the default), structs, classes, and unions are shown on a separate +# page (for HTML and Man pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can +# be an expensive process and often the same symbol appear multiple times in +# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too +# small doxygen will become slower. If the cache is too large, memory is wasted. +# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid +# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 +# symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . \ + doc + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.cpp \ + *.cc \ + *.c \ + *.h \ + *.hh \ + *.hpp \ + *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = */.git/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = doc/img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be ignored. +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NONE + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript +# pieces of code that will be used on startup of the MathJax code. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search +# engine library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id +# of to a relative location where the documentation can be found. +# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4 will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images +# or other source files which should be copied to the LaTeX output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files +# that can be used to generate PDF. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. If left blank docbook will be used as the default path. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN \ + PRINTF_ATTRIBUTE(x,y)= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed +# in the related pages index. If set to NO, only the current project's +# pages will be listed. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# manageable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/ldb-2.0.8/lib/tevent/echo_server.c b/ldb-2.0.8/lib/tevent/echo_server.c new file mode 100644 index 0000000..f93d8bc --- /dev/null +++ b/ldb-2.0.8/lib/tevent/echo_server.c @@ -0,0 +1,667 @@ +/** + ** NOTE! The following liberal license applies to this sample file only. + ** This does NOT imply that all of Samba is released under this license. + ** + ** This file is meant as a starting point for libtevent users to be used + ** in any program linking against the LGPL licensed libtevent. + **/ + +/* + * This file is being made available by the Samba Team under the following + * license: + * + * Permission to use, copy, modify, and distribute this sample file for any + * purpose is hereby granted without fee. + * + * This work 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tevent.h" +#include "talloc.h" + +/** + * @brief Helper function to get a useful unix error from tevent_req + */ + +static bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno) +{ + enum tevent_req_state state; + uint64_t err; + + if (!tevent_req_is_error(req, &state, &err)) { + return false; + } + switch (state) { + case TEVENT_REQ_TIMED_OUT: + *perrno = ETIMEDOUT; + break; + case TEVENT_REQ_NO_MEMORY: + *perrno = ENOMEM; + break; + case TEVENT_REQ_USER_ERROR: + *perrno = err; + break; + default: + *perrno = EINVAL; + break; + } + return true; +} + +/** + * @brief Wrapper around accept(2) + */ + +struct accept_state { + struct tevent_fd *fde; + int listen_sock; + socklen_t addrlen; + struct sockaddr_storage addr; + int sock; +}; + +static void accept_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data); + +static struct tevent_req *accept_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int listen_sock) +{ + struct tevent_req *req; + struct accept_state *state; + + req = tevent_req_create(mem_ctx, &state, struct accept_state); + if (req == NULL) { + return NULL; + } + + state->listen_sock = listen_sock; + + state->fde = tevent_add_fd(ev, state, listen_sock, TEVENT_FD_READ, + accept_handler, req); + if (tevent_req_nomem(state->fde, req)) { + return tevent_req_post(req, ev); + } + return req; +} + +static void accept_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct accept_state *state = tevent_req_data(req, struct accept_state); + int ret; + + TALLOC_FREE(state->fde); + + if ((flags & TEVENT_FD_READ) == 0) { + tevent_req_error(req, EIO); + return; + } + state->addrlen = sizeof(state->addr); + + ret = accept(state->listen_sock, + (struct sockaddr *)&state->addr, + &state->addrlen); + if (ret == -1) { + tevent_req_error(req, errno); + return; + } + smb_set_close_on_exec(ret); + state->sock = ret; + tevent_req_done(req); +} + +static int accept_recv(struct tevent_req *req, struct sockaddr *paddr, + socklen_t *paddrlen, int *perr) +{ + struct accept_state *state = tevent_req_data(req, struct accept_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + if (paddr != NULL) { + memcpy(paddr, &state->addr, state->addrlen); + } + if (paddrlen != NULL) { + *paddrlen = state->addrlen; + } + return state->sock; +} + +/** + * @brief Wrapper around read(2) + */ + +struct read_state { + struct tevent_fd *fde; + int fd; + void *buf; + size_t count; + + ssize_t nread; +}; + +static void read_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data); + +static struct tevent_req *read_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, void *buf, size_t count) +{ + struct tevent_req *req; + struct read_state *state; + + req = tevent_req_create(mem_ctx, &state, struct read_state); + if (req == NULL) { + return NULL; + } + + state->fd = fd; + state->buf = buf; + state->count = count; + + state->fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, + read_handler, req); + if (tevent_req_nomem(state->fde, req)) { + return tevent_req_post(req, ev); + } + return req; +} + +static void read_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct read_state *state = tevent_req_data(req, struct read_state); + ssize_t ret; + + TALLOC_FREE(state->fde); + + if ((flags & TEVENT_FD_READ) == 0) { + tevent_req_error(req, EIO); + return; + } + + ret = read(state->fd, state->buf, state->count); + if (ret == -1) { + tevent_req_error(req, errno); + return; + } + state->nread = ret; + tevent_req_done(req); +} + +static ssize_t read_recv(struct tevent_req *req, int *perr) +{ + struct read_state *state = tevent_req_data(req, struct read_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + return state->nread; +} + +/** + * @brief Wrapper around write(2) + */ + +struct write_state { + struct tevent_fd *fde; + int fd; + const void *buf; + size_t count; + + ssize_t nwritten; +}; + +static void write_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data); + +static struct tevent_req *write_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const void *buf, size_t count) +{ + struct tevent_req *req; + struct write_state *state; + + req = tevent_req_create(mem_ctx, &state, struct write_state); + if (req == NULL) { + return NULL; + } + + state->fd = fd; + state->buf = buf; + state->count = count; + + state->fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, + write_handler, req); + if (tevent_req_nomem(state->fde, req)) { + return tevent_req_post(req, ev); + } + return req; +} + +static void write_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct write_state *state = tevent_req_data(req, struct write_state); + ssize_t ret; + + TALLOC_FREE(state->fde); + + if ((flags & TEVENT_FD_WRITE) == 0) { + tevent_req_error(req, EIO); + return; + } + + ret = write(state->fd, state->buf, state->count); + if (ret == -1) { + tevent_req_error(req, errno); + return; + } + state->nwritten = ret; + tevent_req_done(req); +} + +static ssize_t write_recv(struct tevent_req *req, int *perr) +{ + struct write_state *state = tevent_req_data(req, struct write_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + return state->nwritten; +} + +/** + * @brief Wrapper function that deals with short writes + */ + +struct writeall_state { + struct tevent_context *ev; + int fd; + const void *buf; + size_t count; + size_t nwritten; +}; + +static void writeall_done(struct tevent_req *subreq); + +static struct tevent_req *writeall_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const void *buf, size_t count) +{ + struct tevent_req *req, *subreq; + struct writeall_state *state; + + req = tevent_req_create(mem_ctx, &state, struct writeall_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->fd = fd; + state->buf = buf; + state->count = count; + state->nwritten = 0; + + subreq = write_send(state, state->ev, state->fd, + ((char *)state->buf)+state->nwritten, + state->count - state->nwritten); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, writeall_done, req); + return req; +} + +static void writeall_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct writeall_state *state = tevent_req_data( + req, struct writeall_state); + ssize_t nwritten; + int err = 0; + + nwritten = write_recv(subreq, &err); + TALLOC_FREE(subreq); + if (nwritten == -1) { + tevent_req_error(req, err); + return; + } + + state->nwritten += nwritten; + + if (state->nwritten < state->count) { + subreq = write_send(state, state->ev, state->fd, + ((char *)state->buf)+state->nwritten, + state->count - state->nwritten); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, writeall_done, req); + return; + } + tevent_req_done(req); +} + +static ssize_t writeall_recv(struct tevent_req *req, int *perr) +{ + struct writeall_state *state = tevent_req_data( + req, struct writeall_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + return state->nwritten; +} + +/** + * @brief Async echo handler code dealing with one client + */ + +struct echo_state { + struct tevent_context *ev; + int fd; + uint8_t *buf; +}; + +static int echo_state_destructor(struct echo_state *s); +static void echo_read_done(struct tevent_req *subreq); +static void echo_writeall_done(struct tevent_req *subreq); + +static struct tevent_req *echo_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, size_t bufsize) +{ + struct tevent_req *req, *subreq; + struct echo_state *state; + + req = tevent_req_create(mem_ctx, &state, struct echo_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->fd = fd; + + talloc_set_destructor(state, echo_state_destructor); + + state->buf = talloc_array(state, uint8_t, bufsize); + if (tevent_req_nomem(state->buf, req)) { + return tevent_req_post(req, ev); + } + + subreq = read_send(state, state->ev, state->fd, + state->buf, talloc_get_size(state->buf)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, echo_read_done, req); + return req; +} + +static int echo_state_destructor(struct echo_state *s) +{ + if (s->fd != -1) { + printf("Closing client fd %d\n", s->fd); + close(s->fd); + s->fd = -1; + } + return 0; +} + +static void echo_read_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct echo_state *state = tevent_req_data( + req, struct echo_state); + ssize_t nread; + int err; + + nread = read_recv(subreq, &err); + TALLOC_FREE(subreq); + if (nread == -1) { + tevent_req_error(req, err); + return; + } + if (nread == 0) { + tevent_req_done(req); + return; + } + + subreq = writeall_send(state, state->ev, state->fd, state->buf, nread); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_writeall_done, req); +} + +static void echo_writeall_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct echo_state *state = tevent_req_data( + req, struct echo_state); + ssize_t nwritten; + int err; + + nwritten = writeall_recv(subreq, &err); + TALLOC_FREE(subreq); + if (nwritten == -1) { + if (err == EPIPE) { + tevent_req_done(req); + return; + } + tevent_req_error(req, err); + return; + } + + subreq = read_send(state, state->ev, state->fd, + state->buf, talloc_get_size(state->buf)); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_read_done, req); +} + +static bool echo_recv(struct tevent_req *req, int *perr) +{ + int err; + + if (tevent_req_is_unix_error(req, &err)) { + *perr = err; + return false; + } + return true; +} + +/** + * @brief Full echo handler code accepting and handling clients + */ + +struct echo_server_state { + struct tevent_context *ev; + int listen_sock; +}; + +static void echo_server_accepted(struct tevent_req *subreq); +static void echo_server_client_done(struct tevent_req *subreq); + +static struct tevent_req *echo_server_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int listen_sock) +{ + struct tevent_req *req, *subreq; + struct echo_server_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct echo_server_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->listen_sock = listen_sock; + + subreq = accept_send(state, state->ev, state->listen_sock); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, echo_server_accepted, req); + return req; +} + +static void echo_server_accepted(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct echo_server_state *state = tevent_req_data( + req, struct echo_server_state); + int sock, err; + + sock = accept_recv(subreq, NULL, NULL, &err); + TALLOC_FREE(subreq); + if (sock == -1) { + tevent_req_error(req, err); + return; + } + + printf("new client fd %d\n", sock); + + subreq = echo_send(state, state->ev, sock, 100); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_server_client_done, req); + + subreq = accept_send(state, state->ev, state->listen_sock); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_server_accepted, req); +} + +static void echo_server_client_done(struct tevent_req *subreq) +{ + bool ret; + int err; + + ret = echo_recv(subreq, &err); + TALLOC_FREE(subreq); + + if (ret) { + printf("Client done\n"); + } else { + printf("Client failed: %s\n", strerror(err)); + } +} + +static bool echo_server_recv(struct tevent_req *req, int *perr) +{ + int err; + + if (tevent_req_is_unix_error(req, &err)) { + *perr = err; + return false; + } + return true; +} + +int main(int argc, const char **argv) +{ + int ret, port, listen_sock, err; + struct tevent_context *ev; + struct sockaddr_in addr; + struct tevent_req *req; + bool result; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + + port = atoi(argv[1]); + + printf("listening on port %d\n", port); + + listen_sock = socket(AF_INET, SOCK_STREAM, 0); + + if (listen_sock == -1) { + perror("socket() failed"); + exit(1); + } + + addr = (struct sockaddr_in) { + .sin_family = AF_INET, + .sin_port = htons(port) + }; + + ret = bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); + if (ret == -1) { + perror("bind() failed"); + exit(1); + } + + ret = listen(listen_sock, 5); + if (ret == -1) { + perror("listen() failed"); + exit(1); + } + + ev = tevent_context_init(NULL); + if (ev == NULL) { + fprintf(stderr, "tevent_context_init failed\n"); + exit(1); + } + + req = echo_server_send(ev, ev, listen_sock); + if (req == NULL) { + fprintf(stderr, "echo_server_send failed\n"); + exit(1); + } + + if (!tevent_req_poll(req, ev)) { + perror("tevent_req_poll() failed"); + exit(1); + } + + result = echo_server_recv(req, &err); + TALLOC_FREE(req); + if (!result) { + fprintf(stderr, "echo_server failed: %s\n", strerror(err)); + exit(1); + } + + return 0; +} diff --git a/ldb-2.0.8/lib/tevent/pytevent.c b/ldb-2.0.8/lib/tevent/pytevent.c new file mode 100644 index 0000000..73a9bd7 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/pytevent.c @@ -0,0 +1,945 @@ +/* + Unix SMB/CIFS implementation. + Python bindings for tevent + + Copyright (C) Jelmer Vernooij 2010 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include +#include "replace.h" +#include + +#if PY_MAJOR_VERSION >= 3 +#define PyInt_FromLong PyLong_FromLong +#endif + +/* discard signature of 'func' in favour of 'target_sig' */ +#define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func + +void init_tevent(void); + +typedef struct { + PyObject_HEAD + struct tevent_context *ev; +} TeventContext_Object; + +typedef struct { + PyObject_HEAD + struct tevent_queue *queue; +} TeventQueue_Object; + +typedef struct { + PyObject_HEAD + struct tevent_req *req; +} TeventReq_Object; + +typedef struct { + PyObject_HEAD + struct tevent_signal *signal; +} TeventSignal_Object; + +typedef struct { + PyObject_HEAD + struct tevent_timer *timer; + PyObject *callback; +} TeventTimer_Object; + +typedef struct { + PyObject_HEAD + struct tevent_fd *fd; +} TeventFd_Object; + +static PyTypeObject TeventContext_Type; +static PyTypeObject TeventReq_Type; +static PyTypeObject TeventQueue_Type; +static PyTypeObject TeventSignal_Type; +static PyTypeObject TeventTimer_Type; +static PyTypeObject TeventFd_Type; + +static int py_context_init(struct tevent_context *ev) +{ + /* FIXME */ + return 0; +} + +static struct tevent_fd *py_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + /* FIXME */ + return NULL; +} + +static void py_set_fd_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + /* FIXME */ +} + +static uint16_t py_get_fd_flags(struct tevent_fd *fde) +{ + /* FIXME */ + return 0; +} + +static void py_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + /* FIXME */ +} + +/* timed_event functions */ +static struct tevent_timer *py_add_timer(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) +{ + /* FIXME */ + return NULL; +} + +/* immediate event functions */ +static void py_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + /* FIXME */ +} + +/* signal functions */ +static struct tevent_signal *py_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + /* FIXME */ + return NULL; +} + +/* loop functions */ +static int py_loop_once(struct tevent_context *ev, const char *location) +{ + /* FIXME */ + return 0; +} + +static int py_loop_wait(struct tevent_context *ev, const char *location) +{ + /* FIXME */ + return 0; +} + +const static struct tevent_ops py_tevent_ops = { + .context_init = py_context_init, + .add_fd = py_add_fd, + .set_fd_close_fn = py_set_fd_close_fn, + .get_fd_flags = py_get_fd_flags, + .set_fd_flags = py_set_fd_flags, + .add_timer = py_add_timer, + .schedule_immediate = py_schedule_immediate, + .add_signal = py_add_signal, + .loop_wait = py_loop_wait, + .loop_once = py_loop_once, +}; + +static PyObject *py_register_backend(PyObject *self, PyObject *args) +{ + PyObject *name, *py_backend; + + if (!PyArg_ParseTuple(args, "O", &py_backend)) + return NULL; + + name = PyObject_GetAttrString(py_backend, "name"); + if (name == NULL) { + PyErr_SetNone(PyExc_AttributeError); + return NULL; + } + + if (!PyUnicode_Check(name)) { + PyErr_SetNone(PyExc_TypeError); + Py_DECREF(name); + return NULL; + } + + if (!tevent_register_backend(PyUnicode_AsUTF8(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ + PyErr_SetNone(PyExc_RuntimeError); + Py_DECREF(name); + return NULL; + } + + Py_DECREF(name); + + Py_RETURN_NONE; +} + +static PyObject *py_tevent_context_reinitialise(TeventContext_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + int ret = tevent_re_initialise(self->ev); + if (ret != 0) { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject *py_tevent_queue_stop(TeventQueue_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + tevent_queue_stop(self->queue); + Py_RETURN_NONE; +} + +static PyObject *py_tevent_queue_start(TeventQueue_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + tevent_queue_start(self->queue); + Py_RETURN_NONE; +} + +static void py_queue_trigger(struct tevent_req *req, void *private_data) +{ + PyObject *callback = private_data, *ret; + + ret = PyObject_CallFunction(callback, discard_const_p(char, "")); + Py_XDECREF(ret); +} + +static PyObject *py_tevent_queue_add(TeventQueue_Object *self, PyObject *args) +{ + TeventContext_Object *py_ev; + TeventReq_Object *py_req; + PyObject *trigger; + bool ret; + + if (!PyArg_ParseTuple(args, "O!O!O", + &TeventContext_Type, &py_ev, + &TeventReq_Type, &py_req, + &trigger)) + return NULL; + + Py_INCREF(trigger); + + ret = tevent_queue_add(self->queue, py_ev->ev, py_req->req, + py_queue_trigger, trigger); + if (!ret) { + PyErr_SetString(PyExc_RuntimeError, "queue add failed"); + Py_DECREF(trigger); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyMethodDef py_tevent_queue_methods[] = { + { "stop", (PyCFunction)py_tevent_queue_stop, + METH_NOARGS, + "S.stop()" }, + { "start", (PyCFunction)py_tevent_queue_start, + METH_NOARGS, + "S.start()" }, + { "add", (PyCFunction)py_tevent_queue_add, METH_VARARGS, + "S.add(ctx, req, trigger, baton)" }, + { NULL }, +}; + +static PyObject *py_tevent_context_wakeup_send(PyObject *self, PyObject *args) +{ + /* FIXME */ + + Py_RETURN_NONE; +} + +static PyObject *py_tevent_context_loop_wait(TeventContext_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + if (tevent_loop_wait(self->ev) != 0) { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject *py_tevent_context_loop_once(TeventContext_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + if (tevent_loop_once(self->ev) != 0) { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } + Py_RETURN_NONE; +} + +static void py_tevent_signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + PyObject *callback = (PyObject *)private_data, *ret; + + ret = PyObject_CallFunction(callback, discard_const_p(char, "ii"), signum, count); + Py_XDECREF(ret); +} + +static void py_tevent_signal_dealloc(TeventSignal_Object *self) +{ + talloc_free(self->signal); + PyObject_Del(self); +} + +static PyTypeObject TeventSignal_Type = { + .tp_name = "tevent.Signal", + .tp_basicsize = sizeof(TeventSignal_Object), + .tp_dealloc = (destructor)py_tevent_signal_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +static PyObject *py_tevent_context_add_signal(TeventContext_Object *self, PyObject *args) +{ + int signum, sa_flags; + PyObject *handler; + struct tevent_signal *sig; + TeventSignal_Object *ret; + + if (!PyArg_ParseTuple(args, "iiO", &signum, &sa_flags, &handler)) + return NULL; + + Py_INCREF(handler); + sig = tevent_add_signal(self->ev, NULL, signum, sa_flags, + py_tevent_signal_handler, handler); + + ret = PyObject_New(TeventSignal_Object, &TeventSignal_Type); + if (ret == NULL) { + PyErr_NoMemory(); + talloc_free(sig); + return NULL; + } + + ret->signal = sig; + + return (PyObject *)ret; +} + +static void py_timer_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + TeventTimer_Object *self = private_data; + PyObject *ret; + + ret = PyObject_CallFunction(self->callback, discard_const_p(char, "l"), te); + if (ret == NULL) { + /* No Python stack to propagate exception to; just print traceback */ + PyErr_PrintEx(0); + } + Py_XDECREF(ret); +} + +static void py_tevent_timer_dealloc(TeventTimer_Object *self) +{ + if (self->timer) { + talloc_free(self->timer); + } + Py_DECREF(self->callback); + PyObject_Del(self); +} + +static int py_tevent_timer_traverse(TeventTimer_Object *self, visitproc visit, void *arg) +{ + Py_VISIT(self->callback); + return 0; +} + +static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyBool_FromLong(self->timer != NULL); +} + +struct PyGetSetDef py_tevent_timer_getset[] = { + { + .name = discard_const_p(char, "active"), + .get = (getter)py_tevent_timer_get_active, + .doc = discard_const_p(char, "true if the timer is scheduled to run"), + }, + {NULL}, +}; + +static PyTypeObject TeventTimer_Type = { + .tp_name = "tevent.Timer", + .tp_basicsize = sizeof(TeventTimer_Object), + .tp_dealloc = (destructor)py_tevent_timer_dealloc, + .tp_traverse = (traverseproc)py_tevent_timer_traverse, + .tp_getset = py_tevent_timer_getset, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +struct TeventTimer_Object_ref { + TeventTimer_Object *obj; +}; + +static int TeventTimer_Object_ref_destructor(struct TeventTimer_Object_ref *ref) +{ + ref->obj->timer = NULL; + Py_DECREF(ref->obj); + return 0; +} + +static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self, + struct timeval next_event, + PyObject *callback) +{ + /* Ownership notes: + * + * There are 5 pieces in play; two tevent contexts and 3 Python objects: + * - The tevent timer + * - The tevent context + * - The Python context -- "self" + * - The Python timer (TeventTimer_Object) -- "ret" + * - The Python callback function -- "callback" + * + * We only use the Python context for getting the tevent context, + * afterwards it can be destroyed. + * + * The tevent context owns the tevent timer. + * + * The tevent timer holds a reference to the Python timer, so the Python + * timer must always outlive the tevent timer. + * The Python timer has a pointer to the tevent timer; a destructor is + * used to set this to NULL when the tevent timer is deallocated. + * + * The tevent timer can be deallocated in these cases: + * 1) when the context is destroyed + * 2) after the event fires + * Posssibly, API might be added to cancel (free the tevent timer). + * + * The Python timer holds a reference to the callback. + */ + TeventTimer_Object *ret; + struct TeventTimer_Object_ref *ref; + + ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + Py_INCREF(callback); + ret->callback = callback; + ret->timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler, + ret); + if (ret->timer == NULL) { + Py_DECREF(ret); + PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); + return NULL; + } + ref = talloc(ret->timer, struct TeventTimer_Object_ref); + if (ref == NULL) { + talloc_free(ret->timer); + Py_DECREF(ret); + PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); + return NULL; + } + Py_INCREF(ret); + ref->obj = ret; + + talloc_set_destructor(ref, TeventTimer_Object_ref_destructor); + + return (PyObject *)ret; +} + +static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) +{ + struct timeval next_event; + PyObject *callback; + double secs, usecs; + if (!PyArg_ParseTuple(args, "dO", &secs, &callback)){ + return NULL; + } + next_event.tv_sec = secs; + usecs = (secs - next_event.tv_sec) * 1000000.0; + next_event.tv_usec = usecs; + return py_tevent_context_add_timer_internal(self, next_event, callback); +} + +static PyObject *py_tevent_context_add_timer_offset(TeventContext_Object *self, PyObject *args) +{ + struct timeval next_event; + double offset; + int seconds; + PyObject *callback; + if (!PyArg_ParseTuple(args, "dO", &offset, &callback)) + return NULL; + + seconds = offset; + offset -= seconds; + next_event = tevent_timeval_current_ofs(seconds, (int)(offset*1000000)); + return py_tevent_context_add_timer_internal(self, next_event, callback); +} + +static void py_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + PyObject *callback = private_data, *ret; + + ret = PyObject_CallFunction(callback, discard_const_p(char, "i"), flags); + Py_XDECREF(ret); +} + +static void py_tevent_fp_dealloc(TeventFd_Object *self) +{ + talloc_free(self->fd); + PyObject_Del(self); +} + +static PyTypeObject TeventFd_Type = { + .tp_name = "tevent.Fd", + .tp_basicsize = sizeof(TeventFd_Object), + .tp_dealloc = (destructor)py_tevent_fp_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args) +{ + int fd, flags; + PyObject *handler; + struct tevent_fd *tfd; + TeventFd_Object *ret; + + if (!PyArg_ParseTuple(args, "iiO", &fd, &flags, &handler)) + return NULL; + + tfd = tevent_add_fd(self->ev, NULL, fd, flags, py_fd_handler, handler); + if (tfd == NULL) { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } + + ret = PyObject_New(TeventFd_Object, &TeventFd_Type); + if (ret == NULL) { + talloc_free(tfd); + return NULL; + } + ret->fd = tfd; + + return (PyObject *)ret; +} + +static PyMethodDef py_tevent_context_methods[] = { + { "reinitialise", (PyCFunction)py_tevent_context_reinitialise, + METH_NOARGS, + "S.reinitialise()" }, + { "wakeup_send", (PyCFunction)py_tevent_context_wakeup_send, + METH_VARARGS, "S.wakeup_send(wakeup_time) -> req" }, + { "loop_wait", (PyCFunction)py_tevent_context_loop_wait, + METH_NOARGS, "S.loop_wait()" }, + { "loop_once", (PyCFunction)py_tevent_context_loop_once, + METH_NOARGS, "S.loop_once()" }, + { "add_signal", (PyCFunction)py_tevent_context_add_signal, + METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" }, + { "add_timer", (PyCFunction)py_tevent_context_add_timer, + METH_VARARGS, "S.add_timer(next_event, handler) -> timer" }, + { "add_timer_offset", (PyCFunction)py_tevent_context_add_timer_offset, + METH_VARARGS, "S.add_timer(offset_seconds, handler) -> timer" }, + { "add_fd", (PyCFunction)py_tevent_context_add_fd, + METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, + { NULL }, +}; + +static PyObject *py_tevent_req_wakeup_recv(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_received(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_is_error(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_poll(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_is_in_progress(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyGetSetDef py_tevent_req_getsetters[] = { + { + .name = discard_const_p(char, "in_progress"), + .get = (getter)py_tevent_req_is_in_progress, + .doc = discard_const_p(char, "Whether the request is in progress"), + }, + { NULL } +}; + +static PyObject *py_tevent_req_post(PyObject *self, PyObject *args) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_set_error(PyObject *self, PyObject *args) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_done(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_notify_callback(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_set_endtime(PyObject *self, PyObject *args) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_cancel(TeventReq_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + if (!tevent_req_cancel(self->req)) { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } + Py_RETURN_NONE; +} + +static PyMethodDef py_tevent_req_methods[] = { + { "wakeup_recv", (PyCFunction)py_tevent_req_wakeup_recv, + METH_NOARGS, + "Wakeup received" }, + { "received", (PyCFunction)py_tevent_req_received, + METH_NOARGS, + "Receive finished" }, + { "is_error", (PyCFunction)py_tevent_req_is_error, METH_NOARGS, + "is_error() -> (error, state)" }, + { "poll", (PyCFunction)py_tevent_req_poll, METH_VARARGS, + "poll(ctx)" }, + { "post", (PyCFunction)py_tevent_req_post, METH_VARARGS, + "post(ctx) -> req" }, + { "set_error", (PyCFunction)py_tevent_req_set_error, METH_VARARGS, + "set_error(error)" }, + { "done", (PyCFunction)py_tevent_req_done, METH_NOARGS, + "done()" }, + { "notify_callback", (PyCFunction)py_tevent_req_notify_callback, + METH_NOARGS, "notify_callback()" }, + { "set_endtime", (PyCFunction)py_tevent_req_set_endtime, + METH_VARARGS, "set_endtime(ctx, endtime)" }, + { "cancel", (PyCFunction)py_tevent_req_cancel, + METH_NOARGS, "cancel()" }, + { NULL } +}; + +static void py_tevent_req_dealloc(TeventReq_Object *self) +{ + talloc_free(self->req); + PyObject_DEL(self); +} + +static PyTypeObject TeventReq_Type = { + .tp_name = "tevent.Request", + .tp_basicsize = sizeof(TeventReq_Object), + .tp_methods = py_tevent_req_methods, + .tp_dealloc = (destructor)py_tevent_req_dealloc, + .tp_getset = py_tevent_req_getsetters, + /* FIXME: .tp_new = py_tevent_req_new, */ +}; + +static PyObject *py_tevent_queue_get_length(TeventQueue_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyInt_FromLong(tevent_queue_length(self->queue)); +} + +static PyGetSetDef py_tevent_queue_getsetters[] = { + { + .name = discard_const_p(char, "length"), + .get = (getter)py_tevent_queue_get_length, + .doc = discard_const_p(char, "The number of elements in the queue."), + }, + { NULL }, +}; + +static void py_tevent_queue_dealloc(TeventQueue_Object *self) +{ + talloc_free(self->queue); + PyObject_Del(self); +} + +static PyTypeObject TeventQueue_Type = { + .tp_name = "tevent.Queue", + .tp_basicsize = sizeof(TeventQueue_Object), + .tp_dealloc = (destructor)py_tevent_queue_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_getset = py_tevent_queue_getsetters, + .tp_methods = py_tevent_queue_methods, +}; + +static PyObject *py_tevent_context_signal_support(PyObject *_self, + PyObject *Py_UNUSED(ignored)) +{ + TeventContext_Object *self = (TeventContext_Object *)_self; + return PyBool_FromLong(tevent_signal_support(self->ev)); +} + +static PyGetSetDef py_tevent_context_getsetters[] = { + { + .name = discard_const_p(char, "signal_support"), + .get = PY_DISCARD_FUNC_SIG(getter, + py_tevent_context_signal_support), + .doc = discard_const_p(char, "if this platform and tevent context support signal handling"), + }, + { NULL } +}; + +static void py_tevent_context_dealloc(TeventContext_Object *self) +{ + talloc_free(self->ev); + PyObject_Del(self); +} + +static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + const char * const kwnames[] = { "name", NULL }; + char *name = NULL; + struct tevent_context *ev; + TeventContext_Object *ret; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &name)) + return NULL; + + if (name == NULL) { + ev = tevent_context_init(NULL); + } else { + ev = tevent_context_init_byname(NULL, name); + } + + if (ev == NULL) { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } + + ret = PyObject_New(TeventContext_Object, type); + if (ret == NULL) { + PyErr_NoMemory(); + talloc_free(ev); + return NULL; + } + + ret->ev = ev; + return (PyObject *)ret; +} + +static PyTypeObject TeventContext_Type = { + .tp_name = "tevent.Context", + .tp_new = py_tevent_context_new, + .tp_basicsize = sizeof(TeventContext_Object), + .tp_dealloc = (destructor)py_tevent_context_dealloc, + .tp_methods = py_tevent_context_methods, + .tp_getset = py_tevent_context_getsetters, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +static PyObject *py_set_default_backend(PyObject *self, PyObject *args) +{ + char *backend_name; + if (!PyArg_ParseTuple(args, "s", &backend_name)) + return NULL; + + tevent_set_default_backend(backend_name); + + Py_RETURN_NONE; +} + +static PyObject *py_backend_list(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + PyObject *ret = NULL; + PyObject *string = NULL; + int i, result; + const char **backends = NULL; + + ret = PyList_New(0); + if (ret == NULL) { + return NULL; + } + + backends = tevent_backend_list(NULL); + if (backends == NULL) { + PyErr_SetNone(PyExc_RuntimeError); + goto err; + } + for (i = 0; backends[i]; i++) { + string = PyUnicode_FromString(backends[i]); + if (!string) { + goto err; + } + result = PyList_Append(ret, string); + if (result) { + goto err; + } + Py_DECREF(string); + string = NULL; + } + + talloc_free(backends); + + return ret; + +err: + Py_XDECREF(ret); + Py_XDECREF(string); + talloc_free(backends); + return NULL; +} + +static PyMethodDef tevent_methods[] = { + { "register_backend", (PyCFunction)py_register_backend, METH_VARARGS, + "register_backend(backend)" }, + { "set_default_backend", (PyCFunction)py_set_default_backend, + METH_VARARGS, "set_default_backend(backend)" }, + { "backend_list", (PyCFunction)py_backend_list, + METH_NOARGS, "backend_list() -> list" }, + { NULL }, +}; + +#define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "_tevent", + .m_doc = MODULE_DOC, + .m_size = -1, + .m_methods = tevent_methods, +}; +#endif + +PyObject * module_init(void); +PyObject * module_init(void) +{ + PyObject *m; + + if (PyType_Ready(&TeventContext_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventQueue_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventReq_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventSignal_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventTimer_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventFd_Type) < 0) + return NULL; + +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC); +#endif + if (m == NULL) + return NULL; + + Py_INCREF(&TeventContext_Type); + PyModule_AddObject(m, "Context", (PyObject *)&TeventContext_Type); + + Py_INCREF(&TeventQueue_Type); + PyModule_AddObject(m, "Queue", (PyObject *)&TeventQueue_Type); + + Py_INCREF(&TeventReq_Type); + PyModule_AddObject(m, "Request", (PyObject *)&TeventReq_Type); + + Py_INCREF(&TeventSignal_Type); + PyModule_AddObject(m, "Signal", (PyObject *)&TeventSignal_Type); + + Py_INCREF(&TeventTimer_Type); + PyModule_AddObject(m, "Timer", (PyObject *)&TeventTimer_Type); + + Py_INCREF(&TeventFd_Type); + PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type); + + PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION); + + return m; +} + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC PyInit__tevent(void); +PyMODINIT_FUNC PyInit__tevent(void) +{ + return module_init(); +} +#else +void init_tevent(void); +void init_tevent(void) +{ + module_init(); +} +#endif diff --git a/ldb-2.0.8/lib/tevent/test_req.c b/ldb-2.0.8/lib/tevent/test_req.c new file mode 100644 index 0000000..2274a8c --- /dev/null +++ b/ldb-2.0.8/lib/tevent/test_req.c @@ -0,0 +1,288 @@ +/* + * Unix SMB/CIFS implementation. + * + * testing of some tevent_req aspects + * + * Copyright (C) Volker Lendecke 2018 + * + * ** NOTE! The following LGPL license applies to the tevent + * ** 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 + * Lesser 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 . + */ + +#include "includes.h" +#include "tevent.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#include "lib/util/tevent_unix.h" +#include "lib/util/tevent_req_profile.h" +#include "lib/util/time_basic.h" + +struct tevent_req_create_state { + uint8_t val; +}; + +static bool test_tevent_req_create(struct torture_context *tctx, + const void *test_data) +{ + struct tevent_req *req; + struct tevent_req_create_state *state; + + req = tevent_req_create(tctx, &state, + struct tevent_req_create_state); + torture_assert_not_null(tctx, req, "tevent_req_create failed\n"); + torture_assert_int_equal(tctx, state->val, 0, "state not initialized\n"); + + TALLOC_FREE(req); + + return true; +} + +struct profile1_state { + uint8_t dummy; +}; + +static bool test_tevent_req_profile1(struct torture_context *tctx, + const void *test_data) +{ + struct tevent_req *req; + struct profile1_state *state; + const struct tevent_req_profile *p1; + struct tevent_req_profile *p2; + struct timeval start, stop; + bool ok; + int cmp; + + req = tevent_req_create(tctx, &state, struct profile1_state); + torture_assert_not_null(tctx, req, "tevent_req_create failed\n"); + + p1 = tevent_req_get_profile(req); + torture_assert(tctx, p1 == NULL, "profile not initialized to NULL\n"); + + ok = tevent_req_set_profile(req); + torture_assert(tctx, ok, "set_profile failed\n"); + + tevent_req_done(req); + + p2 = tevent_req_move_profile(req, tctx); + torture_assert_not_null(tctx, p2, "get_profile failed\n"); + + /* Demonstrate sure "p2" outlives req */ + TALLOC_FREE(req); + + tevent_req_profile_get_start(p2, NULL, &start); + tevent_req_profile_get_stop(p2, NULL, &stop); + + cmp = tevent_timeval_compare(&start, &stop); + torture_assert(tctx, cmp <= 0, "stop before start\n"); + + TALLOC_FREE(p2); + + return true; +} + +struct profile2_state { + uint8_t dummy; +}; + +static void profile2_done(struct tevent_req *subreq); + +static struct tevent_req *profile2_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev) +{ + struct tevent_req *req, *subreq; + struct profile2_state *state; + bool ok; + + req = tevent_req_create(mem_ctx, &state, struct profile2_state); + if (req == NULL) { + return NULL; + } + + ok = tevent_req_set_profile(req); + if (!ok) { + return tevent_req_post(req, ev); + } + + subreq = tevent_wakeup_send( + state, + ev, + tevent_timeval_current_ofs(0, 1)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, profile2_done, req); + + return req; +} + +static void profile2_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + bool ok; + + ok = tevent_wakeup_recv(subreq); + if (!ok) { + tevent_req_oom(req); + return; + } + tevent_req_done(req); +} + +static int profile2_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct tevent_req_profile **profile) +{ + int err; + + if (tevent_req_is_unix_error(req, &err)) { + return err; + } + + *profile = tevent_req_move_profile(req, mem_ctx); + + return 0; +} + +static bool test_tevent_req_profile2(struct torture_context *tctx, + const void *test_data) +{ + struct tevent_context *ev; + struct tevent_req *req; + struct tevent_req_profile *p1 = NULL; + struct tevent_req_profile *p2 = NULL; + const char *str1, *str2; + struct timeval tv1, tv2; + pid_t pid1, pid2; + enum tevent_req_state state1, state2; + uint64_t err1, err2; + char *printstring; + ssize_t pack_len; + int err; + bool ok; + + ev = samba_tevent_context_init(tctx); + torture_assert_not_null(tctx, ev, "samba_tevent_context_init failed\n"); + + req = profile2_send(tctx, ev); + torture_assert_not_null(tctx, req, "profile2_send failed\n"); + + ok = tevent_req_poll_unix(req, ev, &err); + torture_assert(tctx, ok, "tevent_req_poll_unix failed\n"); + + err = profile2_recv(req, tctx, &p1); + torture_assert_int_equal(tctx, err, 0, "profile2_recv failed\n"); + + TALLOC_FREE(req); + TALLOC_FREE(ev); + + printstring = tevent_req_profile_string(tctx, p1, 0, UINT_MAX); + torture_assert_not_null( + tctx, + printstring, + "tevent_req_profile_string failed\n"); + printf("%s\n", printstring); + + pack_len = tevent_req_profile_pack(p1, NULL, 0); + torture_assert(tctx, pack_len>0, "profile_pack failed\n"); + + { + uint8_t buf[pack_len]; + ssize_t unpack_len; + + tevent_req_profile_pack(p1, buf, sizeof(buf)); + dump_data(10, buf, sizeof(buf)); + + unpack_len = tevent_req_profile_unpack( + buf, + pack_len, + tctx, + &p2); + torture_assert_int_equal(tctx, + pack_len, + unpack_len, + "profile_unpack failed\n"); + } + + printstring = tevent_req_profile_string(tctx, p2, 0, UINT_MAX); + torture_assert_not_null( + tctx, + printstring, + "tevent_req_profile_string failed\n"); + printf("%s\n", printstring); + + tevent_req_profile_get_name(p1, &str1); + tevent_req_profile_get_name(p2, &str2); + torture_assert_str_equal(tctx, str1, str2, "names differ\n"); + + tevent_req_profile_get_start(p1, &str1, &tv1); + tevent_req_profile_get_start(p2, &str2, &tv2); + torture_assert_str_equal(tctx, str1, str2, "start strings differ\n"); + torture_assert(tctx, + tevent_timeval_compare(&tv1, &tv2) == 0, + "start times differ\n"); + + tevent_req_profile_get_stop(p1, &str1, &tv1); + tevent_req_profile_get_stop(p2, &str2, &tv2); + torture_assert_str_equal(tctx, str1, str2, "stop strings differ\n"); + torture_assert(tctx, + tevent_timeval_compare(&tv1, &tv2) == 0, + "stop times differ\n"); + + tevent_req_profile_get_status(p1, &pid1, &state1, &err1); + tevent_req_profile_get_status(p2, &pid2, &state2, &err2); + torture_assert_int_equal(tctx, pid1, pid2, "pids differ\n"); + torture_assert_int_equal(tctx, state1, state2, "states differ\n"); + torture_assert_int_equal(tctx, err1, err2, "user errors differ\n"); + + str1 = tevent_req_profile_string(p1, p1, 0, UINT_MAX); + torture_assert_not_null(tctx, str1, "profile_string failed\n"); + str2 = tevent_req_profile_string(p2, p2, 0, UINT_MAX); + torture_assert_not_null(tctx, str2, "profile_string failed\n"); + + torture_assert_str_equal(tctx, str1, str2, "result strings differ\n"); + + TALLOC_FREE(p1); + TALLOC_FREE(p2); + + return true; +} + +struct torture_suite *torture_local_tevent_req(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite; + + suite = torture_suite_create(mem_ctx, "tevent_req"); + + torture_suite_add_simple_tcase_const( + suite, + "create", + test_tevent_req_create, + NULL); + torture_suite_add_simple_tcase_const( + suite, + "profile1", + test_tevent_req_profile1, + NULL); + torture_suite_add_simple_tcase_const( + suite, + "profile2", + test_tevent_req_profile2, + NULL); + + return suite; +} diff --git a/ldb-2.0.8/lib/tevent/testsuite.c b/ldb-2.0.8/lib/tevent/testsuite.c new file mode 100644 index 0000000..ee4c285 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/testsuite.c @@ -0,0 +1,1821 @@ +/* + Unix SMB/CIFS implementation. + + testing of the events subsystem + + Copyright (C) Stefan Metzmacher 2006-2009 + Copyright (C) Jeremy Allison 2013 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "includes.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "system/filesys.h" +#include "system/select.h" +#include "system/network.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#ifdef HAVE_PTHREAD +#include "system/threads.h" +#include +#endif + +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) +{ + int *fd = (int *)private_data; + char c; +#ifdef SA_SIGINFO + kill(getpid(), SIGUSR1); +#endif + kill(getpid(), SIGALRM); + + 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; + + do_write(fd[1], &c, 1); +} + + +/* This will only fire if the fd's returned from pipe() are bi-directional. */ +static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *f, + uint16_t flags, void *private_data) +{ + int *fd = (int *)private_data; + char c; +#ifdef SA_SIGINFO + kill(getpid(), SIGUSR1); +#endif + kill(getpid(), SIGALRM); + + do_read(fd[1], &c, 1); + fde_count++; +} + +/* This will only fire if the fd's returned from pipe() are bi-directional. */ +static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd *f, + uint16_t flags, void *private_data) +{ + int *fd = (int *)private_data; + char c = 0; + do_write(fd[0], &c, 1); +} + +static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te, + struct timeval tval, void *private_data) +{ + int *finished = (int *)private_data; + (*finished) = 1; +} + +static void count_handler(struct tevent_context *ev_ctx, struct tevent_signal *te, + int signum, int count, void *info, void *private_data) +{ + int *countp = (int *)private_data; + (*countp) += count; +} + +static bool test_event_context(struct torture_context *test, + const void *test_data) +{ + struct tevent_context *ev_ctx; + int fd[2] = { -1, -1 }; + const char *backend = (const char *)test_data; + int alarm_count=0, info_count=0; + struct tevent_fd *fde_read; + struct tevent_fd *fde_read_1; + struct tevent_fd *fde_write; + struct tevent_fd *fde_write_1; +#ifdef SA_RESTART + struct tevent_signal *se1 = NULL; +#endif +#ifdef SA_RESETHAND + struct tevent_signal *se2 = NULL; +#endif +#ifdef SA_SIGINFO + struct tevent_signal *se3 = NULL; +#endif + int finished=0; + struct timeval t; + int ret; + + ev_ctx = tevent_context_init_byname(test, backend); + if (ev_ctx == NULL) { + torture_comment(test, "event backend '%s' not supported\n", backend); + return true; + } + + torture_comment(test, "backend '%s' - %s\n", + backend, __FUNCTION__); + + /* reset globals */ + fde_count = 0; + + /* create a pipe */ + ret = pipe(fd); + torture_assert_int_equal(test, ret, 0, "pipe failed"); + + fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ, + fde_handler_read, fd); + fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE, + fde_handler_write_1, fd); + + fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE, + fde_handler_write, fd); + fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ, + fde_handler_read_1, fd); + + tevent_fd_set_auto_close(fde_read); + tevent_fd_set_auto_close(fde_write); + + tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0), + finished_handler, &finished); + +#ifdef SA_RESTART + se1 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count); + torture_assert(test, se1 != NULL, "failed to setup se1"); +#endif +#ifdef SA_RESETHAND + se2 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count); + torture_assert(test, se2 != NULL, "failed to setup se2"); +#endif +#ifdef SA_SIGINFO + se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count); + torture_assert(test, se3 != NULL, "failed to setup se3"); +#endif + + t = timeval_current(); + while (!finished) { + errno = 0; + if (tevent_loop_once(ev_ctx) == -1) { + TALLOC_FREE(ev_ctx); + torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno))); + return false; + } + } + + talloc_free(fde_read_1); + talloc_free(fde_write_1); + talloc_free(fde_read); + talloc_free(fde_write); + + while (alarm_count < fde_count+1) { + if (tevent_loop_once(ev_ctx) == -1) { + break; + } + } + + torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t)); + +#ifdef SA_RESTART + talloc_free(se1); +#endif + + torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch"); + +#ifdef SA_RESETHAND + /* + * we do not call talloc_free(se2) + * because it is already gone, + * after triggering the event handler. + */ +#endif + +#ifdef SA_SIGINFO + talloc_free(se3); + torture_assert_int_equal(test, info_count, fde_count, "info count mismatch"); +#endif + + talloc_free(ev_ctx); + + return true; +} + +struct test_event_fd1_state { + struct torture_context *tctx; + const char *backend; + struct tevent_context *ev; + int sock[2]; + struct tevent_timer *te; + struct tevent_fd *fde0; + struct tevent_fd *fde1; + bool got_write; + bool got_read; + bool drain; + bool drain_done; + unsigned loop_count; + bool finished; + const char *error; +}; + +static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + struct test_event_fd1_state *state = + (struct test_event_fd1_state *)private_data; + + if (state->drain_done) { + state->finished = true; + state->error = __location__; + return; + } + + if (state->drain) { + ssize_t ret; + uint8_t c = 0; + + if (!(flags & TEVENT_FD_READ)) { + state->finished = true; + state->error = __location__; + return; + } + + ret = read(state->sock[0], &c, 1); + if (ret == 1) { + return; + } + + /* + * end of test... + */ + tevent_fd_set_flags(fde, 0); + state->drain_done = true; + return; + } + + if (!state->got_write) { + uint8_t c = 0; + + if (flags != TEVENT_FD_WRITE) { + state->finished = true; + state->error = __location__; + return; + } + state->got_write = true; + + /* + * we write to the other socket... + */ + do_write(state->sock[1], &c, 1); + TEVENT_FD_NOT_WRITEABLE(fde); + TEVENT_FD_READABLE(fde); + return; + } + + if (!state->got_read) { + if (flags != TEVENT_FD_READ) { + state->finished = true; + state->error = __location__; + return; + } + state->got_read = true; + + TEVENT_FD_NOT_READABLE(fde); + return; + } + + state->finished = true; + state->error = __location__; + return; +} + +static void test_event_fd1_finished(struct tevent_context *ev_ctx, + struct tevent_timer *te, + struct timeval tval, + void *private_data) +{ + struct test_event_fd1_state *state = + (struct test_event_fd1_state *)private_data; + + if (state->drain_done) { + state->finished = true; + return; + } + + if (!state->got_write) { + state->finished = true; + state->error = __location__; + return; + } + + if (!state->got_read) { + state->finished = true; + state->error = __location__; + return; + } + + state->loop_count++; + if (state->loop_count > 3) { + state->finished = true; + state->error = __location__; + return; + } + + state->got_write = false; + state->got_read = false; + + tevent_fd_set_flags(state->fde0, TEVENT_FD_WRITE); + + if (state->loop_count > 2) { + state->drain = true; + TALLOC_FREE(state->fde1); + TEVENT_FD_READABLE(state->fde0); + } + + state->te = tevent_add_timer(state->ev, state->ev, + timeval_current_ofs(0,2000), + test_event_fd1_finished, state); +} + +static bool test_event_fd1(struct torture_context *tctx, + const void *test_data) +{ + struct test_event_fd1_state state; + int ret; + + ZERO_STRUCT(state); + state.tctx = tctx; + state.backend = (const char *)test_data; + + state.ev = tevent_context_init_byname(tctx, state.backend); + if (state.ev == NULL) { + torture_skip(tctx, talloc_asprintf(tctx, + "event backend '%s' not supported\n", + state.backend)); + return true; + } + + tevent_set_debug_stderr(state.ev); + torture_comment(tctx, "backend '%s' - %s\n", + state.backend, __FUNCTION__); + + /* + * This tests the following: + * + * It monitors the state of state.sock[0] + * with tevent_fd, but we never read/write on state.sock[0] + * while state.sock[1] * is only used to write a few bytes. + * + * We have a loop: + * - we wait only for TEVENT_FD_WRITE on state.sock[0] + * - we write 1 byte to state.sock[1] + * - we wait only for TEVENT_FD_READ on state.sock[0] + * - we disable events on state.sock[0] + * - the timer event restarts the loop + * Then we close state.sock[1] + * We have a loop: + * - we wait for TEVENT_FD_READ/WRITE on state.sock[0] + * - we try to read 1 byte + * - if the read gets an error of returns 0 + * we disable the event handler + * - the timer finishes the test + */ + state.sock[0] = -1; + state.sock[1] = -1; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock); + torture_assert(tctx, ret == 0, "socketpair() failed"); + + state.te = tevent_add_timer(state.ev, state.ev, + timeval_current_ofs(0,1000), + test_event_fd1_finished, &state); + state.fde0 = tevent_add_fd(state.ev, state.ev, + state.sock[0], TEVENT_FD_WRITE, + test_event_fd1_fde_handler, &state); + /* state.fde1 is only used to auto close */ + state.fde1 = tevent_add_fd(state.ev, state.ev, + state.sock[1], 0, + test_event_fd1_fde_handler, &state); + + tevent_fd_set_auto_close(state.fde0); + tevent_fd_set_auto_close(state.fde1); + + while (!state.finished) { + errno = 0; + if (tevent_loop_once(state.ev) == -1) { + talloc_free(state.ev); + torture_fail(tctx, talloc_asprintf(tctx, + "Failed event loop %s\n", + strerror(errno))); + } + } + + talloc_free(state.ev); + + torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx, + "%s", state.error)); + + return true; +} + +struct test_event_fd2_state { + struct torture_context *tctx; + const char *backend; + struct tevent_context *ev; + struct tevent_timer *te; + struct test_event_fd2_sock { + struct test_event_fd2_state *state; + int fd; + struct tevent_fd *fde; + size_t num_written; + size_t num_read; + bool got_full; + } sock0, sock1; + bool finished; + const char *error; +}; + +static void test_event_fd2_sock_handler(struct tevent_context *ev_ctx, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + struct test_event_fd2_sock *cur_sock = + (struct test_event_fd2_sock *)private_data; + struct test_event_fd2_state *state = cur_sock->state; + struct test_event_fd2_sock *oth_sock = NULL; + uint8_t v = 0, c; + ssize_t ret; + + if (cur_sock == &state->sock0) { + oth_sock = &state->sock1; + } else { + oth_sock = &state->sock0; + } + + if (oth_sock->num_written == 1) { + if (flags != (TEVENT_FD_READ | TEVENT_FD_WRITE)) { + state->finished = true; + state->error = __location__; + return; + } + } + + if (cur_sock->num_read == oth_sock->num_written) { + state->finished = true; + state->error = __location__; + return; + } + + if (!(flags & TEVENT_FD_READ)) { + state->finished = true; + state->error = __location__; + return; + } + + if (oth_sock->num_read >= PIPE_BUF) { + /* + * On Linux we become writable once we've read + * one byte. On Solaris we only become writable + * again once we've read 4096 bytes. PIPE_BUF + * is probably a safe bet to test against. + * + * There should be room to write a byte again + */ + if (!(flags & TEVENT_FD_WRITE)) { + state->finished = true; + state->error = __location__; + return; + } + } + + if ((flags & TEVENT_FD_WRITE) && !cur_sock->got_full) { + v = (uint8_t)cur_sock->num_written; + ret = write(cur_sock->fd, &v, 1); + if (ret != 1) { + state->finished = true; + state->error = __location__; + return; + } + cur_sock->num_written++; + if (cur_sock->num_written > 0x80000000) { + state->finished = true; + state->error = __location__; + return; + } + return; + } + + if (!cur_sock->got_full) { + cur_sock->got_full = true; + + if (!oth_sock->got_full) { + /* + * cur_sock is full, + * lets wait for oth_sock + * to be filled + */ + tevent_fd_set_flags(cur_sock->fde, 0); + return; + } + + /* + * oth_sock waited for cur_sock, + * lets restart it + */ + tevent_fd_set_flags(oth_sock->fde, + TEVENT_FD_READ|TEVENT_FD_WRITE); + } + + ret = read(cur_sock->fd, &v, 1); + if (ret != 1) { + state->finished = true; + state->error = __location__; + return; + } + c = (uint8_t)cur_sock->num_read; + if (c != v) { + state->finished = true; + state->error = __location__; + return; + } + cur_sock->num_read++; + + if (cur_sock->num_read < oth_sock->num_written) { + /* there is more to read */ + return; + } + /* + * we read everything, we need to remove TEVENT_FD_WRITE + * to avoid spinning + */ + TEVENT_FD_NOT_WRITEABLE(cur_sock->fde); + + if (oth_sock->num_read == cur_sock->num_written) { + /* + * both directions are finished + */ + state->finished = true; + } + + return; +} + +static void test_event_fd2_finished(struct tevent_context *ev_ctx, + struct tevent_timer *te, + struct timeval tval, + void *private_data) +{ + struct test_event_fd2_state *state = + (struct test_event_fd2_state *)private_data; + + /* + * this should never be triggered + */ + state->finished = true; + state->error = __location__; +} + +static bool test_event_fd2(struct torture_context *tctx, + const void *test_data) +{ + struct test_event_fd2_state state; + int sock[2]; + uint8_t c = 0; + + ZERO_STRUCT(state); + state.tctx = tctx; + state.backend = (const char *)test_data; + + state.ev = tevent_context_init_byname(tctx, state.backend); + if (state.ev == NULL) { + torture_skip(tctx, talloc_asprintf(tctx, + "event backend '%s' not supported\n", + state.backend)); + return true; + } + + tevent_set_debug_stderr(state.ev); + torture_comment(tctx, "backend '%s' - %s\n", + state.backend, __FUNCTION__); + + /* + * This tests the following + * + * - We write 1 byte to each socket + * - We wait for TEVENT_FD_READ/WRITE on both sockets + * - When we get TEVENT_FD_WRITE we write 1 byte + * until both socket buffers are full, which + * means both sockets only get TEVENT_FD_READ. + * - Then we read 1 byte until we have consumed + * all bytes the other end has written. + */ + sock[0] = -1; + sock[1] = -1; + socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + + /* + * the timer should never expire + */ + state.te = tevent_add_timer(state.ev, state.ev, + timeval_current_ofs(600, 0), + test_event_fd2_finished, &state); + state.sock0.state = &state; + state.sock0.fd = sock[0]; + state.sock0.fde = tevent_add_fd(state.ev, state.ev, + state.sock0.fd, + TEVENT_FD_READ | TEVENT_FD_WRITE, + test_event_fd2_sock_handler, + &state.sock0); + state.sock1.state = &state; + state.sock1.fd = sock[1]; + state.sock1.fde = tevent_add_fd(state.ev, state.ev, + state.sock1.fd, + TEVENT_FD_READ | TEVENT_FD_WRITE, + test_event_fd2_sock_handler, + &state.sock1); + + tevent_fd_set_auto_close(state.sock0.fde); + tevent_fd_set_auto_close(state.sock1.fde); + + do_write(state.sock0.fd, &c, 1); + state.sock0.num_written++; + do_write(state.sock1.fd, &c, 1); + state.sock1.num_written++; + + while (!state.finished) { + errno = 0; + if (tevent_loop_once(state.ev) == -1) { + talloc_free(state.ev); + torture_fail(tctx, talloc_asprintf(tctx, + "Failed event loop %s\n", + strerror(errno))); + } + } + + talloc_free(state.ev); + + torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx, + "%s", state.error)); + + return true; +} + +struct test_wrapper_state { + struct torture_context *tctx; + int num_events; + int num_wrap_handlers; +}; + +static bool test_wrapper_before_use(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; + return true; +} + +static void test_wrapper_after_use(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_fd_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_fd_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_timer_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_timer_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_immediate_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_immediate_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_signal_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_signal_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static const struct tevent_wrapper_ops test_wrapper_ops = { + .name = "test_wrapper", + .before_use = test_wrapper_before_use, + .after_use = test_wrapper_after_use, + .before_fd_handler = test_wrapper_before_fd_handler, + .after_fd_handler = test_wrapper_after_fd_handler, + .before_timer_handler = test_wrapper_before_timer_handler, + .after_timer_handler = test_wrapper_after_timer_handler, + .before_immediate_handler = test_wrapper_before_immediate_handler, + .after_immediate_handler = test_wrapper_after_immediate_handler, + .before_signal_handler = test_wrapper_before_signal_handler, + .after_signal_handler = test_wrapper_after_signal_handler, +}; + +static void test_wrapper_timer_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + + torture_comment(state->tctx, "timer handler\n"); + + state->num_events++; + talloc_free(te); + return; +} + +static void test_wrapper_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + unsigned short fd_flags, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + torture_comment(state->tctx, "fd handler\n"); + + state->num_events++; + talloc_free(fde); + return; +} + +static void test_wrapper_immediate_handler(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + state->num_events++; + talloc_free(im); + + torture_comment(state->tctx, "immediate handler\n"); + return; +} + +static void test_wrapper_signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + torture_comment(state->tctx, "signal handler\n"); + + state->num_events++; + talloc_free(se); + return; +} + +static bool test_wrapper(struct torture_context *tctx, + const void *test_data) +{ + struct test_wrapper_state *state = NULL; + int sock[2] = { -1, -1}; + uint8_t c = 0; + const int num_events = 4; + const char *backend = (const char *)test_data; + struct tevent_context *ev = NULL; + struct tevent_context *wrap_ev = NULL; + struct tevent_fd *fde = NULL; + struct tevent_timer *te = NULL; + struct tevent_signal *se = NULL; + struct tevent_immediate *im = NULL; + int ret; + bool ok = false; + bool ret2; + + ev = tevent_context_init_byname(tctx, backend); + if (ev == NULL) { + torture_skip(tctx, talloc_asprintf(tctx, + "event backend '%s' not supported\n", + backend)); + return true; + } + + tevent_set_debug_stderr(ev); + torture_comment(tctx, "tevent backend '%s'\n", backend); + + wrap_ev = tevent_context_wrapper_create( + ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state); + torture_assert_not_null_goto(tctx, wrap_ev, ok, done, + "tevent_context_wrapper_create failed\n"); + *state = (struct test_wrapper_state) { + .tctx = tctx, + }; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n"); + + te = tevent_add_timer(wrap_ev, wrap_ev, + timeval_current_ofs(0, 0), + test_wrapper_timer_handler, state); + torture_assert_not_null_goto(tctx, te, ok, done, + "tevent_add_timer failed\n"); + + fde = tevent_add_fd(wrap_ev, wrap_ev, + sock[1], + TEVENT_FD_READ, + test_wrapper_fd_handler, + state); + torture_assert_not_null_goto(tctx, fde, ok, done, + "tevent_add_fd failed\n"); + + im = tevent_create_immediate(wrap_ev); + torture_assert_not_null_goto(tctx, im, ok, done, + "tevent_create_immediate failed\n"); + + se = tevent_add_signal(wrap_ev, wrap_ev, + SIGUSR1, + 0, + test_wrapper_signal_handler, + state); + torture_assert_not_null_goto(tctx, se, ok, done, + "tevent_add_signal failed\n"); + + do_write(sock[0], &c, 1); + kill(getpid(), SIGUSR1); + tevent_schedule_immediate(im, + wrap_ev, + test_wrapper_immediate_handler, + state); + + ret2 = tevent_context_push_use(wrap_ev); + torture_assert_goto(tctx, ret2, ok, done, "tevent_context_push_use(wrap_ev) failed\n"); + ret2 = tevent_context_push_use(ev); + torture_assert_goto(tctx, ret2, ok, pop_use, "tevent_context_push_use(ev) failed\n"); + tevent_context_pop_use(ev); + tevent_context_pop_use(wrap_ev); + + ret = tevent_loop_wait(ev); + torture_assert_int_equal_goto(tctx, ret, 0, ok, done, "tevent_loop_wait failed\n"); + + torture_comment(tctx, "Num events: %d\n", state->num_events); + torture_comment(tctx, "Num wrap handlers: %d\n", + state->num_wrap_handlers); + + torture_assert_int_equal_goto(tctx, state->num_events, num_events, ok, done, + "Wrong event count\n"); + torture_assert_int_equal_goto(tctx, state->num_wrap_handlers, + num_events*2+2, + ok, done, "Wrong wrapper count\n"); + + ok = true; + +done: + TALLOC_FREE(wrap_ev); + TALLOC_FREE(ev); + + if (sock[0] != -1) { + close(sock[0]); + } + if (sock[1] != -1) { + close(sock[1]); + } + return ok; +pop_use: + tevent_context_pop_use(wrap_ev); + goto done; +} + +static void test_free_wrapper_signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct torture_context *tctx = + talloc_get_type_abort(private_data, + struct torture_context); + + torture_comment(tctx, "signal handler\n"); + + talloc_free(se); + + /* + * signal handlers have highest priority in tevent, so this signal + * handler will always be started before the other handlers + * below. Freeing the (wrapper) event context here tests that the + * wrapper implementation correclty handles the wrapper ev going away + * with pending events. + */ + talloc_free(ev); + return; +} + +static void test_free_wrapper_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + unsigned short fd_flags, + void *private_data) +{ + /* + * This should never be called as + * test_free_wrapper_signal_handler() + * already destroyed the wrapper tevent_context. + */ + abort(); +} + +static void test_free_wrapper_immediate_handler(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + /* + * This should never be called as + * test_free_wrapper_signal_handler() + * already destroyed the wrapper tevent_context. + */ + abort(); +} + +static void test_free_wrapper_timer_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *private_data) +{ + /* + * This should never be called as + * test_free_wrapper_signal_handler() + * already destroyed the wrapper tevent_context. + */ + abort(); +} + +static bool test_free_wrapper(struct torture_context *tctx, + const void *test_data) +{ + struct test_wrapper_state *state = NULL; + int sock[2] = { -1, -1}; + uint8_t c = 0; + const char *backend = (const char *)test_data; + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev = NULL; + struct tevent_context *wrap_ev = NULL; + struct tevent_fd *fde = NULL; + struct tevent_timer *te = NULL; + struct tevent_signal *se = NULL; + struct tevent_immediate *im = NULL; + int ret; + bool ok = false; + + ev = tevent_context_init_byname(frame, backend); + if (ev == NULL) { + torture_skip(tctx, talloc_asprintf(tctx, + "event backend '%s' not supported\n", + backend)); + return true; + } + + tevent_set_debug_stderr(ev); + torture_comment(tctx, "tevent backend '%s'\n", backend); + + wrap_ev = tevent_context_wrapper_create( + ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state); + torture_assert_not_null_goto(tctx, wrap_ev, ok, done, + "tevent_context_wrapper_create failed\n"); + *state = (struct test_wrapper_state) { + .tctx = tctx, + }; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n"); + + fde = tevent_add_fd(wrap_ev, frame, + sock[1], + TEVENT_FD_READ, + test_free_wrapper_fd_handler, + NULL); + torture_assert_not_null_goto(tctx, fde, ok, done, + "tevent_add_fd failed\n"); + + te = tevent_add_timer(wrap_ev, frame, + timeval_current_ofs(0, 0), + test_free_wrapper_timer_handler, NULL); + torture_assert_not_null_goto(tctx, te, ok, done, + "tevent_add_timer failed\n"); + + im = tevent_create_immediate(frame); + torture_assert_not_null_goto(tctx, im, ok, done, + "tevent_create_immediate failed\n"); + + se = tevent_add_signal(wrap_ev, frame, + SIGUSR1, + 0, + test_free_wrapper_signal_handler, + tctx); + torture_assert_not_null_goto(tctx, se, ok, done, + "tevent_add_signal failed\n"); + + do_write(sock[0], &c, 1); + kill(getpid(), SIGUSR1); + tevent_schedule_immediate(im, + wrap_ev, + test_free_wrapper_immediate_handler, + NULL); + + ret = tevent_loop_wait(ev); + torture_assert_goto(tctx, ret == 0, ok, done, "tevent_loop_wait failed\n"); + + ok = true; + +done: + TALLOC_FREE(frame); + + if (sock[0] != -1) { + close(sock[0]); + } + if (sock[1] != -1) { + close(sock[1]); + } + return ok; +} + +#ifdef HAVE_PTHREAD + +static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER; +static bool do_shutdown = false; + +static void test_event_threaded_lock(void) +{ + int ret; + ret = pthread_mutex_lock(&threaded_mutex); + assert(ret == 0); +} + +static void test_event_threaded_unlock(void) +{ + int ret; + ret = pthread_mutex_unlock(&threaded_mutex); + assert(ret == 0); +} + +static void test_event_threaded_trace(enum tevent_trace_point point, + void *private_data) +{ + switch (point) { + case TEVENT_TRACE_BEFORE_WAIT: + test_event_threaded_unlock(); + break; + case TEVENT_TRACE_AFTER_WAIT: + test_event_threaded_lock(); + break; + case TEVENT_TRACE_BEFORE_LOOP_ONCE: + case TEVENT_TRACE_AFTER_LOOP_ONCE: + break; + } +} + +static void test_event_threaded_timer(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + return; +} + +static void *test_event_poll_thread(void *private_data) +{ + struct tevent_context *ev = (struct tevent_context *)private_data; + + test_event_threaded_lock(); + + while (true) { + int ret; + ret = tevent_loop_once(ev); + assert(ret == 0); + if (do_shutdown) { + test_event_threaded_unlock(); + return NULL; + } + } + +} + +static void test_event_threaded_read_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + int *pfd = (int *)private_data; + char c; + ssize_t nread; + + if ((flags & TEVENT_FD_READ) == 0) { + return; + } + + do { + nread = read(*pfd, &c, 1); + } while ((nread == -1) && (errno == EINTR)); + + assert(nread == 1); +} + +static bool test_event_context_threaded(struct torture_context *test, + const void *test_data) +{ + struct tevent_context *ev; + struct tevent_timer *te; + struct tevent_fd *fde; + pthread_t poll_thread; + int fds[2]; + int ret; + char c = 0; + + ev = tevent_context_init_byname(test, "poll_mt"); + torture_assert(test, ev != NULL, "poll_mt not supported"); + + tevent_set_trace_callback(ev, test_event_threaded_trace, NULL); + + te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0), + test_event_threaded_timer, NULL); + torture_assert(test, te != NULL, "Could not add timer"); + + ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev); + torture_assert(test, ret == 0, "Could not create poll thread"); + + ret = pipe(fds); + torture_assert(test, ret == 0, "Could not create pipe"); + + poll(NULL, 0, 100); + + test_event_threaded_lock(); + + fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ, + test_event_threaded_read_handler, &fds[0]); + torture_assert(test, fde != NULL, "Could not add fd event"); + + test_event_threaded_unlock(); + + poll(NULL, 0, 100); + + do_write(fds[1], &c, 1); + + poll(NULL, 0, 100); + + test_event_threaded_lock(); + do_shutdown = true; + test_event_threaded_unlock(); + + do_write(fds[1], &c, 1); + + ret = pthread_join(poll_thread, NULL); + torture_assert(test, ret == 0, "pthread_join failed"); + + return true; +} + +#define NUM_TEVENT_THREADS 100 + +/* Ugly, but needed for torture_comment... */ +static struct torture_context *thread_test_ctx; +static pthread_t thread_map[NUM_TEVENT_THREADS]; +static unsigned thread_counter; + +/* Called in master thread context */ +static void callback_nowait(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + pthread_t *thread_id_ptr = + talloc_get_type_abort(private_ptr, pthread_t); + unsigned i; + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + if (pthread_equal(*thread_id_ptr, + thread_map[i])) { + break; + } + } + torture_comment(thread_test_ctx, + "Callback %u from thread %u\n", + thread_counter, + i); + thread_counter++; +} + +/* Blast the master tevent_context with a callback, no waiting. */ +static void *thread_fn_nowait(void *private_ptr) +{ + struct tevent_thread_proxy *master_tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + struct tevent_immediate *im; + pthread_t *thread_id_ptr; + + im = tevent_create_immediate(NULL); + if (im == NULL) { + return NULL; + } + thread_id_ptr = talloc(NULL, pthread_t); + if (thread_id_ptr == NULL) { + return NULL; + } + *thread_id_ptr = pthread_self(); + + tevent_thread_proxy_schedule(master_tp, + &im, + callback_nowait, + &thread_id_ptr); + return NULL; +} + +static void timeout_fn(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, void *p) +{ + thread_counter = NUM_TEVENT_THREADS * 10; +} + +static bool test_multi_tevent_threaded(struct torture_context *test, + const void *test_data) +{ + unsigned i; + struct tevent_context *master_ev; + struct tevent_thread_proxy *tp; + + talloc_disable_null_tracking(); + + /* Ugly global stuff. */ + thread_test_ctx = test; + thread_counter = 0; + + master_ev = tevent_context_init(NULL); + if (master_ev == NULL) { + return false; + } + tevent_set_debug_stderr(master_ev); + + tp = tevent_thread_proxy_create(master_ev); + if (tp == NULL) { + torture_fail(test, + talloc_asprintf(test, + "tevent_thread_proxy_create failed\n")); + talloc_free(master_ev); + return false; + } + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + int ret = pthread_create(&thread_map[i], + NULL, + thread_fn_nowait, + tp); + if (ret != 0) { + torture_fail(test, + talloc_asprintf(test, + "Failed to create thread %i, %d\n", + i, ret)); + return false; + } + } + + /* Ensure we don't wait more than 10 seconds. */ + tevent_add_timer(master_ev, + master_ev, + timeval_current_ofs(10,0), + timeout_fn, + NULL); + + while (thread_counter < NUM_TEVENT_THREADS) { + int ret = tevent_loop_once(master_ev); + torture_assert(test, ret == 0, "tevent_loop_once failed"); + } + + torture_assert(test, thread_counter == NUM_TEVENT_THREADS, + "thread_counter fail\n"); + + talloc_free(master_ev); + return true; +} + +struct reply_state { + struct tevent_thread_proxy *reply_tp; + pthread_t thread_id; + int *p_finished; +}; + +static void thread_timeout_fn(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, void *p) +{ + int *p_finished = (int *)p; + + *p_finished = 2; +} + +/* Called in child-thread context */ +static void thread_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + + talloc_steal(ev, rsp); + *rsp->p_finished = 1; +} + +/* Called in master thread context */ +static void master_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + unsigned i; + + talloc_steal(ev, rsp); + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + if (pthread_equal(rsp->thread_id, + thread_map[i])) { + break; + } + } + torture_comment(thread_test_ctx, + "Callback %u from thread %u\n", + thread_counter, + i); + /* Now reply to the thread ! */ + tevent_thread_proxy_schedule(rsp->reply_tp, + &im, + thread_callback, + &rsp); + + thread_counter++; +} + +static void *thread_fn_1(void *private_ptr) +{ + struct tevent_thread_proxy *master_tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + struct tevent_thread_proxy *tp; + struct tevent_immediate *im; + struct tevent_context *ev; + struct reply_state *rsp; + int finished = 0; + int ret; + + ev = tevent_context_init(NULL); + if (ev == NULL) { + return NULL; + } + + tp = tevent_thread_proxy_create(ev); + if (tp == NULL) { + talloc_free(ev); + return NULL; + } + + im = tevent_create_immediate(ev); + if (im == NULL) { + talloc_free(ev); + return NULL; + } + + rsp = talloc(ev, struct reply_state); + if (rsp == NULL) { + talloc_free(ev); + return NULL; + } + + rsp->thread_id = pthread_self(); + rsp->reply_tp = tp; + rsp->p_finished = &finished; + + /* Introduce a little randomness into the mix.. */ + usleep(random() % 7000); + + tevent_thread_proxy_schedule(master_tp, + &im, + master_callback, + &rsp); + + /* Ensure we don't wait more than 10 seconds. */ + tevent_add_timer(ev, + ev, + timeval_current_ofs(10,0), + thread_timeout_fn, + &finished); + + while (finished == 0) { + ret = tevent_loop_once(ev); + assert(ret == 0); + } + + if (finished > 1) { + /* Timeout ! */ + abort(); + } + + /* + * NB. We should talloc_free(ev) here, but if we do + * we currently get hit by helgrind Fix #323432 + * "When calling pthread_cond_destroy or pthread_mutex_destroy + * with initializers as argument Helgrind (incorrectly) reports errors." + * + * http://valgrind.10908.n7.nabble.com/Helgrind-3-9-0-false-positive- + * with-pthread-mutex-destroy-td47757.html + * + * Helgrind doesn't understand that the request/reply + * messages provide synchronization between the lock/unlock + * in tevent_thread_proxy_schedule(), and the pthread_destroy() + * when the struct tevent_thread_proxy object is talloc_free'd. + * + * As a work-around for now return ev for the parent thread to free. + */ + return ev; +} + +static bool test_multi_tevent_threaded_1(struct torture_context *test, + const void *test_data) +{ + unsigned i; + struct tevent_context *master_ev; + struct tevent_thread_proxy *master_tp; + int ret; + + talloc_disable_null_tracking(); + + /* Ugly global stuff. */ + thread_test_ctx = test; + thread_counter = 0; + + master_ev = tevent_context_init(NULL); + if (master_ev == NULL) { + return false; + } + tevent_set_debug_stderr(master_ev); + + master_tp = tevent_thread_proxy_create(master_ev); + if (master_tp == NULL) { + torture_fail(test, + talloc_asprintf(test, + "tevent_thread_proxy_create failed\n")); + talloc_free(master_ev); + return false; + } + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + ret = pthread_create(&thread_map[i], + NULL, + thread_fn_1, + master_tp); + if (ret != 0) { + torture_fail(test, + talloc_asprintf(test, + "Failed to create thread %i, %d\n", + i, ret)); + return false; + } + } + + while (thread_counter < NUM_TEVENT_THREADS) { + ret = tevent_loop_once(master_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(retval); + } + + 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"); + + /* + * tevent_re_initialise used to have a bug where it did not + * re-initialise the thread support after taking it + * down. Exercise that code path. + */ + ret = tevent_re_initialise(ev); + torture_assert(test, ret == 0, "tevent_re_initialise failed"); + + tctx = tevent_threaded_context_create(ev, ev); + torture_assert(test, tctx != NULL, + "tevent_threaded_context_create failed"); + + for (i=0; itctx = 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) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "event"); + const char **list = tevent_backend_list(suite); + int i; + + for (i=0;list && list[i];i++) { + struct torture_suite *backend_suite; + + backend_suite = torture_suite_create(mem_ctx, list[i]); + + torture_suite_add_simple_tcase_const(backend_suite, + "context", + test_event_context, + (const void *)list[i]); + torture_suite_add_simple_tcase_const(backend_suite, + "fd1", + test_event_fd1, + (const void *)list[i]); + torture_suite_add_simple_tcase_const(backend_suite, + "fd2", + test_event_fd2, + (const void *)list[i]); + torture_suite_add_simple_tcase_const(backend_suite, + "wrapper", + test_wrapper, + (const void *)list[i]); + torture_suite_add_simple_tcase_const(backend_suite, + "free_wrapper", + test_free_wrapper, + (const void *)list[i]); + + torture_suite_add_suite(suite, backend_suite); + } + +#ifdef HAVE_PTHREAD + torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt", + test_event_context_threaded, + NULL); + + torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded", + test_multi_tevent_threaded, + NULL); + + torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_1", + 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/ldb-2.0.8/lib/tevent/tevent.c b/ldb-2.0.8/lib/tevent/tevent.c new file mode 100644 index 0000000..dbec182 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent.c @@ -0,0 +1,1037 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003 + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +/* + PLEASE READ THIS BEFORE MODIFYING! + + This module is a general abstraction for the main select loop and + event handling. Do not ever put any localised hacks in here, instead + register one of the possible event types and implement that event + somewhere else. + + There are 2 types of event handling that are handled in this module: + + 1) a file descriptor becoming readable or writeable. This is mostly + used for network sockets, but can be used for any type of file + descriptor. You may only register one handler for each file + descriptor/io combination or you will get unpredictable results + (this means that you can have a handler for read events, and a + separate handler for write events, but not two handlers that are + both handling read events) + + 2) a timed event. You can register an event that happens at a + specific time. You can register as many of these as you + like. They are single shot - add a new timed event in the event + handler to get another event. + + To setup a set of events you first need to create a event_context + structure using the function tevent_context_init(); This returns a + 'struct tevent_context' that you use in all subsequent calls. + + After that you can add/remove events that you are interested in + using tevent_add_*() and talloc_free() + + Finally, you call tevent_loop_wait_once() to block waiting for one of the + events to occor or tevent_loop_wait() which will loop + forever. + +*/ +#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 +#endif + +struct tevent_ops_list { + struct tevent_ops_list *next, *prev; + const char *name; + const struct tevent_ops *ops; +}; + +/* list of registered event backends */ +static struct tevent_ops_list *tevent_backends = NULL; +static char *tevent_default_backend = NULL; + +/* + register an events backend +*/ +bool tevent_register_backend(const char *name, const struct tevent_ops *ops) +{ + struct tevent_ops_list *e; + + for (e = tevent_backends; e != NULL; e = e->next) { + if (0 == strcmp(e->name, name)) { + /* already registered, skip it */ + return true; + } + } + + e = talloc(NULL, struct tevent_ops_list); + if (e == NULL) return false; + + e->name = name; + e->ops = ops; + DLIST_ADD(tevent_backends, e); + + return true; +} + +/* + set the default event backend + */ +void tevent_set_default_backend(const char *backend) +{ + talloc_free(tevent_default_backend); + tevent_default_backend = talloc_strdup(NULL, backend); +} + +/* + initialise backends if not already done +*/ +static void tevent_backend_init(void) +{ + static bool done; + + if (done) { + return; + } + + done = true; + + tevent_poll_init(); + tevent_poll_mt_init(); +#if defined(HAVE_EPOLL) + tevent_epoll_init(); +#elif defined(HAVE_SOLARIS_PORTS) + tevent_port_init(); +#endif + + tevent_standard_init(); +} + +_PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name) +{ + struct tevent_ops_list *e; + + tevent_backend_init(); + + if (name == NULL) { + name = tevent_default_backend; + } + if (name == NULL) { + name = "standard"; + } + + for (e = tevent_backends; e != NULL; e = e->next) { + if (0 == strcmp(e->name, name)) { + return e->ops; + } + } + + return NULL; +} + +/* + list available backends +*/ +const char **tevent_backend_list(TALLOC_CTX *mem_ctx) +{ + const char **list = NULL; + struct tevent_ops_list *e; + + tevent_backend_init(); + + for (e=tevent_backends;e;e=e->next) { + list = ev_str_list_add(list, e->name); + } + + talloc_steal(mem_ctx, list); + + 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; + struct tevent_timer *te, *tn; + struct tevent_immediate *ie, *in; + struct tevent_signal *se, *sn; + struct tevent_wrapper_glue *gl, *gn; +#ifdef HAVE_PTHREAD + int ret; +#endif + + if (ev->wrapper.glue != NULL) { + tevent_abort(ev, + "tevent_common_context_destructor() active on wrapper"); + } + +#ifdef HAVE_PTHREAD + 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); + } + + ret = pthread_mutex_destroy(&ev->scheduled_mutex); + if (ret != 0) { + abort(); + } +#endif + + for (gl = ev->wrapper.list; gl; gl = gn) { + gn = gl->next; + + gl->main_ev = NULL; + DLIST_REMOVE(ev->wrapper.list, gl); + } + + tevent_common_wakeup_fini(ev); + + for (fd = ev->fd_events; fd; fd = fn) { + fn = fd->next; + fd->wrapper = NULL; + fd->event_ctx = NULL; + DLIST_REMOVE(ev->fd_events, fd); + } + + ev->last_zero_timer = NULL; + for (te = ev->timer_events; te; te = tn) { + tn = te->next; + te->wrapper = NULL; + te->event_ctx = NULL; + DLIST_REMOVE(ev->timer_events, te); + } + + for (ie = ev->immediate_events; ie; ie = in) { + in = ie->next; + ie->wrapper = NULL; + ie->event_ctx = NULL; + ie->cancel_fn = NULL; + DLIST_REMOVE(ev->immediate_events, ie); + } + + for (se = ev->signal_events; se; se = sn) { + sn = se->next; + se->wrapper = NULL; + se->event_ctx = NULL; + DLIST_REMOVE(ev->signal_events, se); + /* + * This is important, Otherwise signals + * are handled twice in child. eg, SIGHUP. + * one added in parent, and another one in + * the child. -- BoYang + */ + tevent_cleanup_pending_signal_handlers(se); + } + + /* removing nesting hook or we get an abort when nesting is + * not allowed. -- SSS + * Note that we need to leave the allowed flag at its current + * value, otherwise the use in tevent_re_initialise() will + * leave the event context with allowed forced to false, which + * will break users that expect nesting to be allowed + */ + ev->nesting.level = 0; + ev->nesting.hook_fn = NULL; + ev->nesting.hook_private = NULL; + + return 0; +} + +static int tevent_common_context_constructor(struct tevent_context *ev) +{ + int ret; + +#ifdef HAVE_PTHREAD + + ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork); + if (ret != 0) { + return ret; + } + + ret = pthread_mutex_init(&ev->scheduled_mutex, NULL); + if (ret != 0) { + return ret; + } + + ret = pthread_mutex_lock(&tevent_contexts_mutex); + if (ret != 0) { + pthread_mutex_destroy(&ev->scheduled_mutex); + return ret; + } + + 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); + + return 0; +} + +void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason) +{ + void *parent_ptr = talloc_parent(ptr); + size_t parent_blocks = talloc_total_blocks(parent_ptr); + + if (parent_ptr != NULL && parent_blocks == 0) { + /* + * This is an implicit talloc free, as we still have a parent + * but it's already being destroyed. Note that + * talloc_total_blocks(ptr) also just returns 0 if a + * talloc_free(ptr) is still in progress of freeing all + * children. + */ + return; + } + + tevent_abort(NULL, reason); +} + +/* + create a event_context structure for a specific implemementation. + This must be the first events call, and all subsequent calls pass + this event_context as the first element. Event handlers also + receive this as their first argument. + + This function is for allowing third-party-applications to hook in gluecode + to their own event loop code, so that they can make async usage of our client libs + + NOTE: use tevent_context_init() inside of samba! +*/ +struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, + const struct tevent_ops *ops, + void *additional_data) +{ + struct tevent_context *ev; + int ret; + + ev = talloc_zero(mem_ctx, struct tevent_context); + if (!ev) return NULL; + + ret = tevent_common_context_constructor(ev); + if (ret != 0) { + talloc_free(ev); + return NULL; + } + + ev->ops = ops; + ev->additional_data = additional_data; + + ret = ev->ops->context_init(ev); + if (ret != 0) { + talloc_free(ev); + return NULL; + } + + return ev; +} + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, + const char *name) +{ + const struct tevent_ops *ops; + + ops = tevent_find_ops_byname(name); + if (ops == NULL) { + return NULL; + } + + return tevent_context_init_ops(mem_ctx, ops, NULL); +} + + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx) +{ + return tevent_context_init_byname(mem_ctx, NULL); +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data, + handler_name, location); +} + +/* + set a close function on the fd event +*/ +void tevent_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + if (!fde) return; + if (!fde->event_ctx) return; + fde->event_ctx->ops->set_fd_close_fn(fde, close_fn); +} + +static void tevent_fd_auto_close_fn(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data) +{ + close(fd); +} + +void tevent_fd_set_auto_close(struct tevent_fd *fde) +{ + tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn); +} + +/* + return the fd event flags +*/ +uint16_t tevent_fd_get_flags(struct tevent_fd *fde) +{ + if (!fde) return 0; + if (!fde->event_ctx) return 0; + return fde->event_ctx->ops->get_fd_flags(fde); +} + +/* + set the fd event flags +*/ +void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags) +{ + if (!fde) return; + if (!fde->event_ctx) return; + fde->event_ctx->ops->set_fd_flags(fde, flags); +} + +bool tevent_signal_support(struct tevent_context *ev) +{ + if (ev->ops->add_signal) { + return true; + } + return false; +} + +static void (*tevent_abort_fn)(const char *reason); + +void tevent_set_abort_fn(void (*abort_fn)(const char *reason)) +{ + tevent_abort_fn = abort_fn; +} + +void tevent_abort(struct tevent_context *ev, const char *reason) +{ + if (ev != NULL) { + tevent_debug(ev, TEVENT_DEBUG_FATAL, + "abort: %s\n", reason); + } + + if (!tevent_abort_fn) { + abort(); + } + + tevent_abort_fn(reason); +} + +/* + add a timer event + return NULL on failure +*/ +struct tevent_timer *_tevent_add_timer(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) +{ + return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data, + handler_name, location); +} + +/* + allocate an immediate event + return NULL on failure (memory allocation error) +*/ +struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, + const char *location) +{ + struct tevent_immediate *im; + + im = talloc(mem_ctx, struct tevent_immediate); + if (im == NULL) return NULL; + + *im = (struct tevent_immediate) { .create_location = location }; + + return im; +} + +/* + schedule an immediate event +*/ +void _tevent_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + ev->ops->schedule_immediate(im, ev, handler, private_data, + handler_name, location); +} + +/* + add a signal event + + sa_flags are flags to sigaction(2) + + return NULL on failure +*/ +struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, + handler_name, location); +} + +void tevent_loop_allow_nesting(struct tevent_context *ev) +{ + if (ev->wrapper.glue != NULL) { + tevent_abort(ev, "tevent_loop_allow_nesting() on wrapper"); + return; + } + + if (ev->wrapper.list != NULL) { + tevent_abort(ev, "tevent_loop_allow_nesting() with wrapper"); + return; + } + + ev->nesting.allowed = true; +} + +void tevent_loop_set_nesting_hook(struct tevent_context *ev, + tevent_nesting_hook hook, + void *private_data) +{ + if (ev->nesting.hook_fn && + (ev->nesting.hook_fn != hook || + ev->nesting.hook_private != private_data)) { + /* the way the nesting hook code is currently written + we cannot support two different nesting hooks at the + same time. */ + tevent_abort(ev, "tevent: Violation of nesting hook rules\n"); + } + ev->nesting.hook_fn = hook; + ev->nesting.hook_private = private_data; +} + +static void tevent_abort_nesting(struct tevent_context *ev, const char *location) +{ + const char *reason; + + reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s", + location); + if (!reason) { + reason = "tevent_loop_once() nesting"; + } + + tevent_abort(ev, reason); +} + +/* + do a single event loop using the events defined in ev +*/ +int _tevent_loop_once(struct tevent_context *ev, const char *location) +{ + int ret; + void *nesting_stack_ptr = NULL; + + ev->nesting.level++; + + if (ev->nesting.level > 1) { + if (!ev->nesting.allowed) { + tevent_abort_nesting(ev, location); + errno = ELOOP; + return -1; + } + } + if (ev->nesting.level > 0) { + if (ev->nesting.hook_fn) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + true, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + + tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE); + ret = ev->ops->loop_once(ev, location); + tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE); + + if (ev->nesting.level > 0) { + if (ev->nesting.hook_fn) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + false, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + +done: + ev->nesting.level--; + return ret; +} + +/* + this is a performance optimization for the samba4 nested event loop problems +*/ +int _tevent_loop_until(struct tevent_context *ev, + bool (*finished)(void *private_data), + void *private_data, + const char *location) +{ + int ret = 0; + void *nesting_stack_ptr = NULL; + + ev->nesting.level++; + + if (ev->nesting.level > 1) { + if (!ev->nesting.allowed) { + tevent_abort_nesting(ev, location); + errno = ELOOP; + return -1; + } + } + if (ev->nesting.level > 0) { + if (ev->nesting.hook_fn) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + true, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + + while (!finished(private_data)) { + tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE); + ret = ev->ops->loop_once(ev, location); + tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE); + if (ret != 0) { + break; + } + } + + if (ev->nesting.level > 0) { + if (ev->nesting.hook_fn) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + false, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + +done: + ev->nesting.level--; + 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 +*/ +int tevent_common_loop_wait(struct tevent_context *ev, + const char *location) +{ + /* + * loop as long as we have events pending + */ + while (tevent_common_have_events(ev)) { + int ret; + ret = _tevent_loop_once(ev, location); + if (ret != 0) { + tevent_debug(ev, TEVENT_DEBUG_FATAL, + "_tevent_loop_once() failed: %d - %s\n", + ret, strerror(errno)); + return ret; + } + } + + tevent_debug(ev, TEVENT_DEBUG_WARNING, + "tevent_common_loop_wait() out of events\n"); + return 0; +} + +/* + return on failure or (with 0) if all fd events are removed +*/ +int _tevent_loop_wait(struct tevent_context *ev, const char *location) +{ + return ev->ops->loop_wait(ev, location); +} + + +/* + re-initialise a tevent context. This leaves you with the same + event context, but all events are wiped and the structure is + re-initialised. This is most useful after a fork() + + zero is returned on success, non-zero on failure +*/ +int tevent_re_initialise(struct tevent_context *ev) +{ + tevent_common_context_destructor(ev); + + tevent_common_context_constructor(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/ldb-2.0.8/lib/tevent/tevent.h b/ldb-2.0.8/lib/tevent/tevent.h new file mode 100644 index 0000000..3c3e3cc --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent.h @@ -0,0 +1,2511 @@ +/* + Unix SMB/CIFS implementation. + + generalised event loop handling + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2005-2009 + Copyright (C) Volker Lendecke 2008 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#ifndef __TEVENT_H__ +#define __TEVENT_H__ + +#include +#include +#include +#include + +struct tevent_context; +struct tevent_ops; +struct tevent_fd; +struct tevent_timer; +struct tevent_immediate; +struct tevent_signal; +struct tevent_thread_proxy; +struct tevent_threaded_context; + +/** + * @defgroup tevent The tevent API + * + * The tevent low-level API + * + * This API provides the public interface to manage events in the tevent + * mainloop. Functions are provided for managing low-level events such + * as timer events, fd events and signal handling. + * + * @{ + */ + +/* event handler types */ +/** + * Called when a file descriptor monitored by tevent has + * data to be read or written on it. + */ +typedef void (*tevent_fd_handler_t)(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data); + +/** + * Called when tevent is ceasing the monitoring of a file descriptor. + */ +typedef void (*tevent_fd_close_fn_t)(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data); + +/** + * Called when a tevent timer has fired. + */ +typedef void (*tevent_timer_handler_t)(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data); + +/** + * Called when a tevent immediate event is invoked. + */ +typedef void (*tevent_immediate_handler_t)(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data); + +/** + * Called after tevent detects the specified signal. + */ +typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data); + +/** + * @brief Create a event_context structure. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @return An allocated tevent context, NULL on error. + * + * @see tevent_context_init() + */ +struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); + +/** + * @brief Create a event_context structure and select a specific backend. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @param[in] name The name of the backend to use. + * + * @return An allocated tevent context, NULL on error. + */ +struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); + +/** + * @brief Create a custom event context + * + * @param[in] mem_ctx The memory context to use. + * @param[in] ops The function pointer table of the backend. + * @param[in] additional_data The additional/private data to this instance + * + * @return An allocated tevent context, NULL on error. + * + */ +struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, + const struct tevent_ops *ops, + void *additional_data); + +/** + * @brief List available backends. + * + * @param[in] mem_ctx The memory context to use. + * + * @return A string vector with a terminating NULL element, NULL + * on error. + */ +const char **tevent_backend_list(TALLOC_CTX *mem_ctx); + +/** + * @brief Set the default tevent backend. + * + * @param[in] backend The name of the backend to set. + */ +void tevent_set_default_backend(const char *backend); + +#ifdef DOXYGEN +/** + * @brief Add a file descriptor based event. + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] fd The file descriptor to base the event on. + * + * @param[in] flags #TEVENT_FD_READ or #TEVENT_FD_WRITE + * + * @param[in] handler The callback handler for the event. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @return The file descriptor based event, NULL on error. + * + * @note To cancel the monitoring of a file descriptor, call talloc_free() + * on the object returned by this function. + * + * @note The caller should avoid closing the file descriptor before + * calling talloc_free()! Otherwise the behaviour is undefined which + * might result in crashes. See https://bugzilla.samba.org/show_bug.cgi?id=11141 + * for an example. + */ +struct tevent_fd *tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data); +#else +struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data) \ + _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \ + #handler, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Add a timed event + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] next_event Timeval specifying the absolute time to fire this + * event. This is not an offset. + * + * @param[in] handler The callback handler for the event. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @return The newly-created timer event, or NULL on error. + * + * @note To cancel a timer event before it fires, call talloc_free() on the + * event returned from this function. This event is automatically + * talloc_free()-ed after its event handler files, if it hasn't been freed yet. + * + * @note Unlike some mainloops, tevent timers are one-time events. To set up + * a recurring event, it is necessary to call tevent_add_timer() again during + * the handler processing. + * + * @note Due to the internal mainloop processing, a timer set to run + * immediately will do so after any other pending timers fire, but before + * any further file descriptor or signal handling events fire. Callers should + * not rely on this behavior! + */ +struct tevent_timer *tevent_add_timer(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data); +#else +struct tevent_timer *_tevent_add_timer(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); +#define tevent_add_timer(ev, mem_ctx, next_event, handler, private_data) \ + _tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \ + #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 + * + * This object can be used to trigger an event to occur immediately after + * returning from the current event (before any other event occurs) + * + * @param[in] mem_ctx The talloc memory context to use as the parent + * + * @return An empty tevent_immediate object. Use tevent_schedule_immediate + * to populate and use it. + * + * @note Available as of tevent 0.9.8 + */ +struct tevent_immediate *tevent_create_immediate(TALLOC_CTX *mem_ctx); +#else +struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, + const char *location); +#define tevent_create_immediate(mem_ctx) \ + _tevent_create_immediate(mem_ctx, __location__) +#endif + +#ifdef DOXYGEN + +/** + * Schedule an event for immediate execution. This event will occur + * immediately after returning from the current event (before any other + * event occurs) + * + * @param[in] im The tevent_immediate object to populate and use + * @param[in] ctx The tevent_context to run this event + * @param[in] handler The event handler to run when this event fires + * @param[in] private_data Data to pass to the event handler + */ +void tevent_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ctx, + tevent_immediate_handler_t handler, + void *private_data); +#else +void _tevent_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ctx, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_schedule_immediate(im, ctx, handler, private_data) \ + _tevent_schedule_immediate(im, ctx, handler, private_data, \ + #handler, __location__); +#endif + +#ifdef DOXYGEN +/** + * @brief Add a tevent signal handler + * + * tevent_add_signal() creates a new event for handling a signal the next + * time through the mainloop. It implements a very simple traditional signal + * handler whose only purpose is to add the handler event into the mainloop. + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] signum The signal to trap + * + * @param[in] handler The callback handler for the signal. + * + * @param[in] sa_flags sigaction flags for this signal handler. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @return The newly-created signal handler event, or NULL on error. + * + * @note To cancel a signal handler, call talloc_free() on the event returned + * from this function. + * + * @see tevent_num_signals, tevent_sa_info_queue_count + */ +struct tevent_signal *tevent_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data); +#else +struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) \ + _tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, \ + #handler, __location__) +#endif + +/** + * @brief the number of supported signals + * + * This returns value of the configure time TEVENT_NUM_SIGNALS constant. + * + * The 'signum' argument of tevent_add_signal() must be less than + * TEVENT_NUM_SIGNALS. + * + * @see tevent_add_signal + */ +size_t tevent_num_signals(void); + +/** + * @brief the number of pending realtime signals + * + * This returns value of TEVENT_SA_INFO_QUEUE_COUNT. + * + * The tevent internals remember the last TEVENT_SA_INFO_QUEUE_COUNT + * siginfo_t structures for SA_SIGINFO signals. If the system generates + * more some signals get lost. + * + * @see tevent_add_signal + */ +size_t tevent_sa_info_queue_count(void); + +#ifdef DOXYGEN +/** + * @brief Pass a single time through the mainloop + * + * This will process any appropriate signal, immediate, fd and timer events + * + * @param[in] ev The event context to process + * + * @return Zero on success, nonzero if an internal error occurred + */ +int tevent_loop_once(struct tevent_context *ev); +#else +int _tevent_loop_once(struct tevent_context *ev, const char *location); +#define tevent_loop_once(ev) \ + _tevent_loop_once(ev, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Run the mainloop + * + * The mainloop will run until there are no events remaining to be processed + * + * @param[in] ev The event context to process + * + * @return Zero if all events have been processed. Nonzero if an internal + * error occurred. + */ +int tevent_loop_wait(struct tevent_context *ev); +#else +int _tevent_loop_wait(struct tevent_context *ev, const char *location); +#define tevent_loop_wait(ev) \ + _tevent_loop_wait(ev, __location__) +#endif + + +/** + * Assign a function to run when a tevent_fd is freed + * + * This function is a destructor for the tevent_fd. It does not automatically + * close the file descriptor. If this is the desired behavior, then it must be + * performed by the close_fn. + * + * @param[in] fde File descriptor event on which to set the destructor + * @param[in] close_fn Destructor to execute when fde is freed + * + * @note That the close_fn() on tevent_fd is *NOT* wrapped on contexts + * created by tevent_context_wrapper_create()! + * + * @see tevent_fd_set_close_fn + * @see tevent_context_wrapper_create + */ +void tevent_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); + +/** + * Automatically close the file descriptor when the tevent_fd is freed + * + * This function calls close(fd) internally. + * + * @param[in] fde File descriptor event to auto-close + * + * @see tevent_fd_set_close_fn + */ +void tevent_fd_set_auto_close(struct tevent_fd *fde); + +/** + * Return the flags set on this file descriptor event + * + * @param[in] fde File descriptor event to query + * + * @return The flags set on the event. See #TEVENT_FD_READ and + * #TEVENT_FD_WRITE + */ +uint16_t tevent_fd_get_flags(struct tevent_fd *fde); + +/** + * Set flags on a file descriptor event + * + * @param[in] fde File descriptor event to set + * @param[in] flags Flags to set on the event. See #TEVENT_FD_READ and + * #TEVENT_FD_WRITE + */ +void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); + +/** + * Query whether tevent supports signal handling + * + * @param[in] ev An initialized tevent context + * + * @return True if this platform and tevent context support signal handling + */ +bool tevent_signal_support(struct tevent_context *ev); + +void tevent_set_abort_fn(void (*abort_fn)(const char *reason)); + +/* bits for file descriptor event flags */ + +/** + * Monitor a file descriptor for data to be read + */ +#define TEVENT_FD_READ 1 +/** + * Monitor a file descriptor for writeability + */ +#define TEVENT_FD_WRITE 2 + +/** + * Convenience function for declaring a tevent_fd writable + */ +#define TEVENT_FD_WRITEABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_WRITE) + +/** + * Convenience function for declaring a tevent_fd readable + */ +#define TEVENT_FD_READABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_READ) + +/** + * Convenience function for declaring a tevent_fd non-writable + */ +#define TEVENT_FD_NOT_WRITEABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_WRITE) + +/** + * Convenience function for declaring a tevent_fd non-readable + */ +#define TEVENT_FD_NOT_READABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ) + +/** + * Debug level of tevent + */ +enum tevent_debug_level { + TEVENT_DEBUG_FATAL, + TEVENT_DEBUG_ERROR, + TEVENT_DEBUG_WARNING, + TEVENT_DEBUG_TRACE +}; + +/** + * @brief The tevent debug callbac. + * + * @param[in] context The memory context to use. + * + * @param[in] level The debug level. + * + * @param[in] fmt The format string. + * + * @param[in] ap The arguments for the format string. + */ +typedef void (*tevent_debug_fn)(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0); + +/** + * Set destination for tevent debug messages + * + * @param[in] ev Event context to debug + * @param[in] debug Function to handle output printing + * @param[in] context The context to pass to the debug function. + * + * @return Always returns 0 as of version 0.9.8 + * + * @note Default is to emit no debug messages + */ +int tevent_set_debug(struct tevent_context *ev, + tevent_debug_fn debug, + void *context); + +/** + * Designate stderr for debug message output + * + * @param[in] ev Event context to debug + * + * @note This function will only output TEVENT_DEBUG_FATAL, TEVENT_DEBUG_ERROR + * and TEVENT_DEBUG_WARNING messages. For TEVENT_DEBUG_TRACE, please define a + * function for tevent_set_debug() + */ +int tevent_set_debug_stderr(struct tevent_context *ev); + +enum tevent_trace_point { + /** + * Corresponds to a trace point just before waiting + */ + TEVENT_TRACE_BEFORE_WAIT, + /** + * Corresponds to a trace point just after waiting + */ + TEVENT_TRACE_AFTER_WAIT, +#define TEVENT_HAS_LOOP_ONCE_TRACE_POINTS 1 + /** + * Corresponds to a trace point just before calling + * the loop_once() backend function. + */ + TEVENT_TRACE_BEFORE_LOOP_ONCE, + /** + * Corresponds to a trace point right after the + * loop_once() backend function has returned. + */ + TEVENT_TRACE_AFTER_LOOP_ONCE, +}; + +typedef void (*tevent_trace_callback_t)(enum tevent_trace_point, + void *private_data); + +/** + * Register a callback to be called at certain trace points + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t *cb, + void *private_data); + +/** + * @} + */ + +/** + * @defgroup tevent_request The tevent request functions. + * @ingroup tevent + * + * A tevent_req represents an asynchronous computation. + * + * The tevent_req group of API calls is the recommended way of + * programming async computations within tevent. In particular the + * file descriptor (tevent_add_fd) and timer (tevent_add_timed) events + * are considered too low-level to be used in larger computations. To + * read and write from and to sockets, Samba provides two calls on top + * of tevent_add_fd: tstream_read_packet_send/recv and tstream_writev_send/recv. + * These requests are much easier to compose than the low-level event + * handlers called from tevent_add_fd. + * + * A lot of the simplicity tevent_req has brought to the notoriously + * hairy async programming came via a set of conventions that every + * async computation programmed should follow. One central piece of + * these conventions is the naming of routines and variables. + * + * Every async computation needs a name (sensibly called "computation" + * down from here). From this name quite a few naming conventions are + * derived. + * + * Every computation that requires local state needs a + * @code + * struct computation_state { + * int local_var; + * }; + * @endcode + * Even if no local variables are required, such a state struct should + * be created containing a dummy variable. Quite a few helper + * functions and macros (for example tevent_req_create()) assume such + * a state struct. + * + * An async computation is started by a computation_send + * function. When it is finished, its result can be received by a + * computation_recv function. For an example how to set up an async + * computation, see the code example in the documentation for + * tevent_req_create() and tevent_req_post(). The prototypes for _send + * and _recv functions should follow some conventions: + * + * @code + * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, + * struct tevent_req *ev, + * ... further args); + * int computation_recv(struct tevent_req *req, ... further output args); + * @endcode + * + * The "int" result of computation_recv() depends on the result the + * sync version of the function would have, "int" is just an example + * here. + * + * Another important piece of the conventions is that the program flow + * is interrupted as little as possible. Because a blocking + * sub-computation requires that the flow needs to continue in a + * separate function that is the logical sequel of some computation, + * it should lexically follow sending off the blocking + * sub-computation. Setting the callback function via + * tevent_req_set_callback() requires referencing a function lexically + * below the call to tevent_req_set_callback(), forward declarations + * are required. A lot of the async computations thus begin with a + * sequence of declarations such as + * + * @code + * static void computation_step1_done(struct tevent_req *subreq); + * static void computation_step2_done(struct tevent_req *subreq); + * static void computation_step3_done(struct tevent_req *subreq); + * @endcode + * + * It really helps readability a lot to do these forward declarations, + * because the lexically sequential program flow makes the async + * computations almost as clear to read as a normal, sync program + * flow. + * + * It is up to the user of the async computation to talloc_free it + * after it has finished. If an async computation should be aborted, + * the tevent_req structure can be talloc_free'ed. After it has + * finished, it should talloc_free'ed by the API user. + * + * tevent_req variable naming conventions: + * + * The name of the variable pointing to the tevent_req structure + * returned by a _send() function SHOULD be named differently between + * implementation and caller. + * + * From the point of view of the implementation (of the _send() and + * _recv() functions) the variable returned by tevent_req_create() is + * always called @em req. + * + * While the caller of the _send() function should use @em subreq to + * hold the result. + * + * @see tevent_req_create() + * @see tevent_req_fn() + * + * @{ + */ + +/** + * An async request moves from TEVENT_REQ_INIT to + * TEVENT_REQ_IN_PROGRESS. All other states are valid after a request + * has finished. + */ +enum tevent_req_state { + /** + * We are creating the request + */ + TEVENT_REQ_INIT, + /** + * We are waiting the request to complete + */ + TEVENT_REQ_IN_PROGRESS, + /** + * The request is finished successfully + */ + TEVENT_REQ_DONE, + /** + * A user error has occurred. The user error has been + * indicated by tevent_req_error(), it can be retrieved via + * tevent_req_is_error(). + */ + TEVENT_REQ_USER_ERROR, + /** + * Request timed out after the timeout set by tevent_req_set_endtime. + */ + TEVENT_REQ_TIMED_OUT, + /** + * An internal allocation has failed, or tevent_req_nomem has + * been given a NULL pointer as the first argument. + */ + TEVENT_REQ_NO_MEMORY, + /** + * The request has been received by the caller. No further + * action is valid. + */ + TEVENT_REQ_RECEIVED +}; + +/** + * @brief An async request + */ +struct tevent_req; + +/** + * @brief A tevent request callback function. + * + * @param[in] subreq The tevent async request which executed this callback. + */ +typedef void (*tevent_req_fn)(struct tevent_req *subreq); + +/** + * @brief Set an async request callback. + * + * See the documentation of tevent_req_post() for an example how this + * is supposed to be used. + * + * @param[in] req The async request to set the callback. + * + * @param[in] fn The callback function to set. + * + * @param[in] pvt A pointer to private data to pass to the async request + * callback. + */ +void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); + +#ifdef DOXYGEN +/** + * @brief Get the private data cast to the given type for a callback from + * a tevent request structure. + * + * @code + * static void computation_done(struct tevent_req *subreq) { + * struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + * struct computation_state *state = tevent_req_data(req, struct computation_state); + * .... more things, eventually maybe call tevent_req_done(req); + * } + * @endcode + * + * @param[in] req The structure to get the callback data from. + * + * @param[in] type The type of the private callback data to get. + * + * @return The type casted private data set NULL if not set. + */ +void *tevent_req_callback_data(struct tevent_req *req, #type); +#else +void *_tevent_req_callback_data(struct tevent_req *req); +#define tevent_req_callback_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_callback_data(_req), _type) +#endif + +#ifdef DOXYGEN +/** + * @brief Get the private data for a callback from a tevent request structure. + * + * @param[in] req The structure to get the callback data from. + * + * @return The private data or NULL if not set. + */ +void *tevent_req_callback_data_void(struct tevent_req *req); +#else +#define tevent_req_callback_data_void(_req) \ + _tevent_req_callback_data(_req) +#endif + +#ifdef DOXYGEN +/** + * @brief Get the private data from a tevent request structure. + * + * When the tevent_req has been created by tevent_req_create, the + * result of tevent_req_data() is the state variable created by + * tevent_req_create() as a child of the req. + * + * @param[in] req The structure to get the private data from. + * + * @param[in] type The type of the private data + * + * @return The private data or NULL if not set. + */ +void *tevent_req_data(struct tevent_req *req, #type); +#else +void *_tevent_req_data(struct tevent_req *req); +#define tevent_req_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_data(_req), _type) +#endif + +/** + * @brief The print function which can be set for a tevent async request. + * + * @param[in] req The tevent async request. + * + * @param[in] ctx A talloc memory context which can be uses to allocate + * memory. + * + * @return An allocated string buffer to print. + * + * Example: + * @code + * static char *my_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) + * { + * struct my_data *data = tevent_req_data(req, struct my_data); + * char *result; + * + * result = tevent_req_default_print(mem_ctx, req); + * if (result == NULL) { + * return NULL; + * } + * + * return talloc_asprintf_append_buffer(result, "foo=%d, bar=%d", + * data->foo, data->bar); + * } + * @endcode + */ +typedef char *(*tevent_req_print_fn)(struct tevent_req *req, TALLOC_CTX *ctx); + +/** + * @brief This function sets a print function for the given request. + * + * This function can be used to setup a print function for the given request. + * This will be triggered if the tevent_req_print() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the print function + * + * @note This function should only be used for debugging. + */ +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); + +/** + * @brief The default print function for creating debug messages. + * + * The function should not be used by users of the async API, + * but custom print function can use it and append custom text + * to the string. + * + * @param[in] req The request to be printed. + * + * @param[in] mem_ctx The memory context for the result. + * + * @return Text representation of request. + * + */ +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); + +/** + * @brief Print an tevent_req structure in debug messages. + * + * This function should be used by callers of the async API. + * + * @param[in] mem_ctx The memory context for the result. + * + * @param[in] req The request to be printed. + * + * @return Text representation of request. + */ +char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); + +/** + * @brief A typedef for a cancel function for a tevent request. + * + * @param[in] req The tevent request calling this function. + * + * @return True if the request could be canceled, false if not. + */ +typedef bool (*tevent_req_cancel_fn)(struct tevent_req *req); + +/** + * @brief This function sets a cancel function for the given tevent request. + * + * This function can be used to setup a cancel function for the given request. + * This will be triggered if the tevent_req_cancel() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the cancel function. + */ +void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn); + +#ifdef DOXYGEN +/** + * @brief Try to cancel the given tevent request. + * + * This function can be used to cancel the given request. + * + * It is only possible to cancel a request when the implementation + * has registered a cancel function via the tevent_req_set_cancel_fn(). + * + * @param[in] req The request to use. + * + * @return This function returns true if the request is + * cancelable, otherwise false is returned. + * + * @note Even if the function returns true, the caller need to wait + * for the function to complete normally. + * Only the _recv() function of the given request indicates + * if the request was really canceled. + */ +bool tevent_req_cancel(struct tevent_req *req); +#else +bool _tevent_req_cancel(struct tevent_req *req, const char *location); +#define tevent_req_cancel(req) \ + _tevent_req_cancel(req, __location__) +#endif + +/** + * @brief A typedef for a cleanup function for a tevent request. + * + * @param[in] req The tevent request calling this function. + * + * @param[in] req_state The current tevent_req_state. + * + */ +typedef void (*tevent_req_cleanup_fn)(struct tevent_req *req, + enum tevent_req_state req_state); + +/** + * @brief This function sets a cleanup function for the given tevent request. + * + * This function can be used to setup a cleanup function for the given request. + * This will be triggered when the tevent_req_done() or tevent_req_error() + * function was called, before notifying the callers callback function, + * and also before scheduling the deferred trigger. + * + * This might be useful if more than one tevent_req belong together + * and need to finish both requests at the same time. + * + * The cleanup function is able to call tevent_req_done() or tevent_req_error() + * recursively, the cleanup function is only triggered the first time. + * + * The cleanup function is also called by tevent_req_received() + * (possibly triggered from tevent_req_destructor()) before destroying + * the private data of the tevent_req. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the cancel function. + */ +void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn); + +#ifdef DOXYGEN +/** + * @brief Create an async tevent request. + * + * The new async request will be initialized in state TEVENT_REQ_IN_PROGRESS. + * + * @code + * struct tevent_req *req; + * struct computation_state *state; + * req = tevent_req_create(mem_ctx, &state, struct computation_state); + * @endcode + * + * Tevent_req_create() allocates and zeros the state variable as a talloc + * child of its result. The state variable should be used as the talloc + * parent for all temporary variables that are allocated during the async + * computation. This way, when the user of the async computation frees + * the request, the state as a talloc child will be free'd along with + * all the temporary variables hanging off the state. + * + * @param[in] mem_ctx The memory context for the result. + * @param[in] pstate Pointer to the private request state. + * @param[in] type The name of the request. + * + * @return A new async request. NULL on error. + */ +struct tevent_req *tevent_req_create(TALLOC_CTX *mem_ctx, + void **pstate, #type); +#else +struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, + void *pstate, + size_t state_size, + const char *type, + const char *location); + +#define tevent_req_create(_mem_ctx, _pstate, _type) \ + _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \ + #_type, __location__) +#endif + +/** + * @brief Set a timeout for an async request. On failure, "req" is already + * set to state TEVENT_REQ_NO_MEMORY. + * + * @param[in] req The request to set the timeout for. + * + * @param[in] ev The event context to use for the timer. + * + * @param[in] endtime The endtime of the request. + * + * @return True if succeeded, false if not. + */ +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. + * + * @param[in] req The tevent request to call the notify function from. + * + * @see tevent_req_set_callback() + */ +void tevent_req_notify_callback(struct tevent_req *req); +#else +void _tevent_req_notify_callback(struct tevent_req *req, const char *location); +#define tevent_req_notify_callback(req) \ + _tevent_req_notify_callback(req, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief An async request has successfully finished. + * + * This function is to be used by implementors of async requests. When a + * request is successfully finished, this function calls the user's completion + * function. + * + * @param[in] req The finished request. + */ +void tevent_req_done(struct tevent_req *req); +#else +void _tevent_req_done(struct tevent_req *req, + const char *location); +#define tevent_req_done(req) \ + _tevent_req_done(req, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief An async request has seen an error. + * + * This function is to be used by implementors of async requests. When a + * request can not successfully completed, the implementation should call this + * function with the appropriate status code. + * + * If error is 0 the function returns false and does nothing more. + * + * @param[in] req The request with an error. + * + * @param[in] error The error code. + * + * @return On success true is returned, false if error is 0. + * + * @code + * int error = first_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * error = second_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * tevent_req_done(req); + * return; + * @endcode + */ +bool tevent_req_error(struct tevent_req *req, + uint64_t error); +#else +bool _tevent_req_error(struct tevent_req *req, + uint64_t error, + const char *location); +#define tevent_req_error(req, error) \ + _tevent_req_error(req, error, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Helper function for nomem check. + * + * Convenience helper to easily check alloc failure within a callback + * implementing the next step of an async request. + * + * @param[in] p The pointer to be checked. + * + * @param[in] req The request being processed. + * + * @code + * p = talloc(mem_ctx, bla); + * if (tevent_req_nomem(p, req)) { + * return; + * } + * @endcode + */ +bool tevent_req_nomem(const void *p, + struct tevent_req *req); +#else +bool _tevent_req_nomem(const void *p, + struct tevent_req *req, + const char *location); +#define tevent_req_nomem(p, req) \ + _tevent_req_nomem(p, req, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Indicate out of memory to a request + * + * @param[in] req The request being processed. + */ +void tevent_req_oom(struct tevent_req *req); +#else +void _tevent_req_oom(struct tevent_req *req, + const char *location); +#define tevent_req_oom(req) \ + _tevent_req_oom(req, __location__) +#endif + +/** + * @brief Finish a request before the caller had a chance to set the callback. + * + * An implementation of an async request might find that it can either finish + * the request without waiting for an external event, or it can not even start + * the engine. To present the illusion of a callback to the user of the API, + * the implementation can call this helper function which triggers an + * immediate event. This way the caller can use the same calling + * conventions, independent of whether the request was actually deferred. + * + * @code + * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, + * struct tevent_context *ev) + * { + * struct tevent_req *req, *subreq; + * struct computation_state *state; + * req = tevent_req_create(mem_ctx, &state, struct computation_state); + * if (req == NULL) { + * return NULL; + * } + * subreq = subcomputation_send(state, ev); + * if (tevent_req_nomem(subreq, req)) { + * return tevent_req_post(req, ev); + * } + * tevent_req_set_callback(subreq, computation_done, req); + * return req; + * } + * @endcode + * + * @param[in] req The finished request. + * + * @param[in] ev The tevent_context for the immediate event. + * + * @return The given request will be returned. + */ +struct tevent_req *tevent_req_post(struct tevent_req *req, + struct tevent_context *ev); + +/** + * @brief Finish multiple requests within one function + * + * Normally tevent_req_notify_callback() and all wrappers + * (e.g. tevent_req_done() and tevent_req_error()) + * need to be the last thing an event handler should call. + * This is because the callback is likely to destroy the + * context of the current function. + * + * If a function wants to notify more than one caller, + * it is dangerous if it just triggers multiple callbacks + * in a row. With tevent_req_defer_callback() it is possible + * to set an event context that will be used to defer the callback + * via an immediate event (similar to tevent_req_post()). + * + * @code + * struct complete_state { + * struct tevent_context *ev; + * + * struct tevent_req **reqs; + * }; + * + * void complete(struct complete_state *state) + * { + * size_t i, c = talloc_array_length(state->reqs); + * + * for (i=0; i < c; i++) { + * tevent_req_defer_callback(state->reqs[i], state->ev); + * tevent_req_done(state->reqs[i]); + * } + * } + * @endcode + * + * @param[in] req The finished request. + * + * @param[in] ev The tevent_context for the immediate event. + * + * @return The given request will be returned. + */ +void tevent_req_defer_callback(struct tevent_req *req, + struct tevent_context *ev); + +/** + * @brief Check if the given request is still in progress. + * + * It is typically used by sync wrapper functions. + * + * @param[in] req The request to poll. + * + * @return The boolean form of "is in progress". + */ +bool tevent_req_is_in_progress(struct tevent_req *req); + +/** + * @brief Actively poll for the given request to finish. + * + * This function is typically used by sync wrapper functions. + * + * @param[in] req The request to poll. + * + * @param[in] ev The tevent_context to be used. + * + * @return On success true is returned. If a critical error has + * happened in the tevent loop layer false is returned. + * This is not the return value of the given request! + * + * @note This should only be used if the given tevent context was created by the + * caller, to avoid event loop nesting. + * + * @code + * req = tstream_writev_queue_send(mem_ctx, + * ev_ctx, + * tstream, + * send_queue, + * iov, 2); + * ok = tevent_req_poll(req, tctx->ev); + * rc = tstream_writev_queue_recv(req, &sys_errno); + * TALLOC_FREE(req); + * @endcode + */ +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev); + +/** + * @brief Get the tevent request state and the actual error set by + * tevent_req_error. + * + * @code + * int computation_recv(struct tevent_req *req, uint64_t *perr) + * { + * enum tevent_req_state state; + * uint64_t err; + * if (tevent_req_is_error(req, &state, &err)) { + * *perr = err; + * return -1; + * } + * return 0; + * } + * @endcode + * + * @param[in] req The tevent request to get the error from. + * + * @param[out] state A pointer to store the tevent request error state. + * + * @param[out] error A pointer to store the error set by tevent_req_error(). + * + * @return True if the function could set error and state, false + * otherwise. + * + * @see tevent_req_error() + */ +bool tevent_req_is_error(struct tevent_req *req, + enum tevent_req_state *state, + uint64_t *error); + +/** + * @brief Use as the last action of a _recv() function. + * + * This function destroys the attached private data. + * + * @param[in] req The finished request. + */ +void tevent_req_received(struct tevent_req *req); + +/** + * @brief Mark a tevent_req for profiling + * + * This will turn on profiling for this tevent_req an all subreqs that + * are directly started as helper requests off this + * tevent_req. subreqs are chained by walking up the talloc_parent + * hierarchy at a subreq's tevent_req_create. This means to get the + * profiling chain right the subreq that needs to be profiled as part + * of this tevent_req's profile must be a talloc child of the requests + * state variable. + * + * @param[in] req The request to do tracing for + * + * @return False if the profile could not be activated + */ +bool tevent_req_set_profile(struct tevent_req *req); + +struct tevent_req_profile; + +/** + * @brief Get the a request's profile for inspection + * + * @param[in] req The request to get the profile from + * + * @return The request's profile + */ +const struct tevent_req_profile *tevent_req_get_profile( + struct tevent_req *req); + +/** + * @brief Move the profile out of a request + * + * This function detaches the request's profile from the request, so + * that the profile can outlive the request in a _recv function. + * + * @param[in] req The request to move the profile out of + * @param[in] mem_ctx The new talloc context for the profile + * + * @return The moved profile + */ + +struct tevent_req_profile *tevent_req_move_profile(struct tevent_req *req, + TALLOC_CTX *mem_ctx); + +/** + * @brief Get a profile description + * + * @param[in] profile The profile to be queried + * @param[in] req_name The name of the request (state's name) + * + * "req_name" after this call is still in talloc-posession of "profile" + */ +void tevent_req_profile_get_name(const struct tevent_req_profile *profile, + const char **req_name); + +/** + * @brief Get a profile's start event data + * + * @param[in] profile The profile to be queried + * @param[in] start_location The location where this event started + * @param[in] start_time The time this event started + * + * "start_location" after this call is still in talloc-posession of "profile" + */ +void tevent_req_profile_get_start(const struct tevent_req_profile *profile, + const char **start_location, + struct timeval *start_time); + +/** + * @brief Get a profile's stop event data + * + * @param[in] profile The profile to be queried + * @param[in] stop_location The location where this event stopped + * @param[in] stop_time The time this event stopped + * + * "stop_location" after this call is still in talloc-posession of "profile" + */ +void tevent_req_profile_get_stop(const struct tevent_req_profile *profile, + const char **stop_location, + struct timeval *stop_time); + +/** + * @brief Get a profile's result data + * + * @param[in] pid The process where this profile was taken + * @param[in] state The status the profile's tevent_req finished with + * @param[in] user_error The user error of the profile's tevent_req + */ +void tevent_req_profile_get_status(const struct tevent_req_profile *profile, + pid_t *pid, + enum tevent_req_state *state, + uint64_t *user_error); + +/** + * @brief Retrieve the first subreq's profile from a profile + * + * @param[in] profile The profile to query + * + * @return The first tevent subreq's profile + */ +const struct tevent_req_profile *tevent_req_profile_get_subprofiles( + const struct tevent_req_profile *profile); + +/** + * @brief Walk the chain of subreqs + * + * @param[in] profile The subreq's profile to walk + * + * @return The next subprofile in the list + */ +const struct tevent_req_profile *tevent_req_profile_next( + const struct tevent_req_profile *profile); + +/** + * @brief Create a fresh tevent_req_profile + * + * @param[in] mem_ctx The talloc context to hang the fresh struct off + * + * @return The fresh struct + */ +struct tevent_req_profile *tevent_req_profile_create(TALLOC_CTX *mem_ctx); + +/** + * @brief Set a profile's name + * + * @param[in] profile The profile to set the name for + * @param[in] name The new name for the profile + * + * @return True if the internal talloc_strdup succeeded + */ +bool tevent_req_profile_set_name(struct tevent_req_profile *profile, + const char *name); + +/** + * @brief Set a profile's start event + * + * @param[in] profile The profile to set the start data for + * @param[in] start_location The new start location + * @param[in] start_time The new start time + * + * @return True if the internal talloc_strdup succeeded + */ +bool tevent_req_profile_set_start(struct tevent_req_profile *profile, + const char *start_location, + struct timeval start_time); + +/** + * @brief Set a profile's stop event + * + * @param[in] profile The profile to set the stop data for + * @param[in] stop_location The new stop location + * @param[in] stop_time The new stop time + * + * @return True if the internal talloc_strdup succeeded + */ +bool tevent_req_profile_set_stop(struct tevent_req_profile *profile, + const char *stop_location, + struct timeval stop_time); + +/** + * @brief Set a profile's exit status + * + * @param[in] profile The profile to set the exit status for + * @param[in] pid The process where this profile was taken + * @param[in] state The status the profile's tevent_req finished with + * @param[in] user_error The user error of the profile's tevent_req + */ +void tevent_req_profile_set_status(struct tevent_req_profile *profile, + pid_t pid, + enum tevent_req_state state, + uint64_t user_error); + +/** + * @brief Add a subprofile to a profile + * + * @param[in] parent_profile The profile to be modified + * @param[in] sub_profile The subreqs profile profile to be added + * + * "subreq" is talloc_move'ed into "parent_profile", so the talloc + * ownership of "sub_profile" changes + */ + +void tevent_req_profile_append_sub(struct tevent_req_profile *parent_profile, + struct tevent_req_profile **sub_profile); + +/** + * @brief Create a tevent subrequest at a given time. + * + * The idea is that always the same syntax for tevent requests. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] ev The event handle to setup the request. + * + * @param[in] wakeup_time The time to wakeup and execute the request. + * + * @return The new subrequest, NULL on error. + * + * Example: + * @code + * static void my_callback_wakeup_done(tevent_req *subreq) + * { + * struct tevent_req *req = tevent_req_callback_data(subreq, + * struct tevent_req); + * bool ok; + * + * ok = tevent_wakeup_recv(subreq); + * TALLOC_FREE(subreq); + * if (!ok) { + * tevent_req_error(req, -1); + * return; + * } + * ... + * } + * @endcode + * + * @code + * subreq = tevent_wakeup_send(mem_ctx, ev, wakeup_time); + * if (tevent_req_nomem(subreq, req)) { + * return false; + * } + * tevent_set_callback(subreq, my_callback_wakeup_done, req); + * @endcode + * + * @see tevent_wakeup_recv() + */ +struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval wakeup_time); + +/** + * @brief Check if the wakeup has been correctly executed. + * + * This function needs to be called in the callback function set after calling + * tevent_wakeup_send(). + * + * @param[in] req The tevent request to check. + * + * @return True on success, false otherwise. + * + * @see tevent_wakeup_recv() + */ +bool tevent_wakeup_recv(struct tevent_req *req); + +/* @} */ + +/** + * @defgroup tevent_helpers The tevent helper functions + * @ingroup tevent + * + * @todo description + * + * @{ + */ + +/** + * @brief Compare two timeval values. + * + * @param[in] tv1 The first timeval value to compare. + * + * @param[in] tv2 The second timeval value to compare. + * + * @return 0 if they are equal. + * 1 if the first time is greater than the second. + * -1 if the first time is smaller than the second. + */ +int tevent_timeval_compare(const struct timeval *tv1, + const struct timeval *tv2); + +/** + * @brief Get a zero timeval value. + * + * @return A zero timeval value. + */ +struct timeval tevent_timeval_zero(void); + +/** + * @brief Get a timeval value for the current time. + * + * @return A timeval value with the current time. + */ +struct timeval tevent_timeval_current(void); + +/** + * @brief Get a timeval structure with the given values. + * + * @param[in] secs The seconds to set. + * + * @param[in] usecs The microseconds to set. + * + * @return A timeval structure with the given values. + */ +struct timeval tevent_timeval_set(uint32_t secs, uint32_t usecs); + +/** + * @brief Get the difference between two timeval values. + * + * @param[in] tv1 The first timeval. + * + * @param[in] tv2 The second timeval. + * + * @return A timeval structure with the difference between the + * first and the second value. + */ +struct timeval tevent_timeval_until(const struct timeval *tv1, + const struct timeval *tv2); + +/** + * @brief Check if a given timeval structure is zero. + * + * @param[in] tv The timeval to check if it is zero. + * + * @return True if it is zero, false otherwise. + */ +bool tevent_timeval_is_zero(const struct timeval *tv); + +/** + * @brief Add the given amount of time to a timeval structure. + * + * @param[in] tv The timeval structure to add the time. + * + * @param[in] secs The seconds to add to the timeval. + * + * @param[in] usecs The microseconds to add to the timeval. + * + * @return The timeval structure with the new time. + */ +struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, + uint32_t usecs); + +/** + * @brief Get a timeval in the future with a specified offset from now. + * + * @param[in] secs The seconds of the offset from now. + * + * @param[in] usecs The microseconds of the offset from now. + * + * @return A timeval with the given offset in the future. + */ +struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); + +/* @} */ + + +/** + * @defgroup tevent_queue The tevent queue functions + * @ingroup tevent + * + * A tevent_queue is used to queue up async requests that must be + * serialized. For example writing buffers into a socket must be + * serialized. Writing a large lump of data into a socket can require + * multiple write(2) or send(2) system calls. If more than one async + * request is outstanding to write large buffers into a socket, every + * request must individually be completed before the next one begins, + * even if multiple syscalls are required. + * + * Take a look at @ref tevent_queue_tutorial for more details. + * @{ + */ + +struct tevent_queue; +struct tevent_queue_entry; + +#ifdef DOXYGEN +/** + * @brief Create and start a tevent queue. + * + * @param[in] mem_ctx The talloc memory context to allocate the queue. + * + * @param[in] name The name to use to identify the queue. + * + * @return An allocated tevent queue on success, NULL on error. + * + * @see tevent_queue_start() + * @see tevent_queue_stop() + */ +struct tevent_queue *tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name); +#else +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location); + +#define tevent_queue_create(_mem_ctx, _name) \ + _tevent_queue_create((_mem_ctx), (_name), __location__) +#endif + +/** + * @brief A callback trigger function run by the queue. + * + * @param[in] req The tevent request the trigger function is executed on. + * + * @param[in] private_data The private data pointer specified by + * tevent_queue_add(). + * + * @see tevent_queue_add() + * @see tevent_queue_add_entry() + * @see tevent_queue_add_optimize_empty() + */ +typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req, + void *private_data); + +/** + * @brief Add a tevent request to the queue. + * + * @param[in] queue The queue to add the request. + * + * @param[in] ev The event handle to use for the request. + * + * @param[in] req The tevent request to add to the queue. + * + * @param[in] trigger The function triggered by the queue when the request + * is called. Since tevent 0.9.14 it's possible to + * pass NULL, in order to just add a "blocker" to the + * queue. + * + * @param[in] private_data The private data passed to the trigger function. + * + * @return True if the request has been successfully added, false + * otherwise. + */ +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); + +/** + * @brief Add a tevent request to the queue. + * + * The request can be removed from the queue by calling talloc_free() + * (or a similar function) on the returned queue entry. This + * is the only difference to tevent_queue_add(). + * + * @param[in] queue The queue to add the request. + * + * @param[in] ev The event handle to use for the request. + * + * @param[in] req The tevent request to add to the queue. + * + * @param[in] trigger The function triggered by the queue when the request + * is called. Since tevent 0.9.14 it's possible to + * pass NULL, in order to just add a "blocker" to the + * queue. + * + * @param[in] private_data The private data passed to the trigger function. + * + * @return a pointer to the tevent_queue_entry if the request + * has been successfully added, NULL otherwise. + * + * @see tevent_queue_add() + * @see tevent_queue_add_optimize_empty() + */ +struct tevent_queue_entry *tevent_queue_add_entry( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); + +/** + * @brief Add a tevent request to the queue using a possible optimization. + * + * This tries to optimize for the empty queue case and may calls + * the trigger function directly. This is the only difference compared + * to tevent_queue_add_entry(). + * + * The caller needs to be prepared that the trigger function has + * already called tevent_req_notify_callback(), tevent_req_error(), + * tevent_req_done() or a similar function. + * + * The trigger function has no chance to see the returned + * queue_entry in the optimized case. + * + * The request can be removed from the queue by calling talloc_free() + * (or a similar function) on the returned queue entry. + * + * @param[in] queue The queue to add the request. + * + * @param[in] ev The event handle to use for the request. + * + * @param[in] req The tevent request to add to the queue. + * + * @param[in] trigger The function triggered by the queue when the request + * is called. Since tevent 0.9.14 it's possible to + * pass NULL, in order to just add a "blocker" to the + * queue. + * + * @param[in] private_data The private data passed to the trigger function. + * + * @return a pointer to the tevent_queue_entry if the request + * has been successfully added, NULL otherwise. + * + * @see tevent_queue_add() + * @see tevent_queue_add_entry() + */ +struct tevent_queue_entry *tevent_queue_add_optimize_empty( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); + +/** + * @brief Untrigger an already triggered queue entry. + * + * If a trigger function detects that it needs to remain + * in the queue, it needs to call tevent_queue_stop() + * followed by tevent_queue_entry_untrigger(). + * + * @note In order to call tevent_queue_entry_untrigger() + * the queue must be already stopped and the given queue_entry + * must be the first one in the queue! Otherwise it calls abort(). + * + * @note You can't use this together with tevent_queue_add_optimize_empty() + * because the trigger function don't have access to the quene entry + * in the case of an empty queue. + * + * @param[in] queue_entry The queue entry to rearm. + * + * @see tevent_queue_add_entry() + * @see tevent_queue_stop() + */ +void tevent_queue_entry_untrigger(struct tevent_queue_entry *entry); + +/** + * @brief Start a tevent queue. + * + * The queue is started by default. + * + * @param[in] queue The queue to start. + */ +void tevent_queue_start(struct tevent_queue *queue); + +/** + * @brief Stop a tevent queue. + * + * The queue is started by default. + * + * @param[in] queue The queue to stop. + */ +void tevent_queue_stop(struct tevent_queue *queue); + +/** + * @brief Get the length of the queue. + * + * @param[in] queue The queue to get the length from. + * + * @return The number of elements. + */ +size_t tevent_queue_length(struct tevent_queue *queue); + +/** + * @brief Is the tevent queue running. + * + * The queue is started by default. + * + * @param[in] queue The queue. + * + * @return Whether the queue is running or not.. + */ +bool tevent_queue_running(struct tevent_queue *queue); + +/** + * @brief Create a tevent subrequest that waits in a tevent_queue + * + * The idea is that always the same syntax for tevent requests. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] ev The event handle to setup the request. + * + * @param[in] queue The queue to wait in. + * + * @return The new subrequest, NULL on error. + * + * @see tevent_queue_wait_recv() + */ +struct tevent_req *tevent_queue_wait_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue); + +/** + * @brief Check if we no longer need to wait in the queue. + * + * This function needs to be called in the callback function set after calling + * tevent_queue_wait_send(). + * + * @param[in] req The tevent request to check. + * + * @return True on success, false otherwise. + * + * @see tevent_queue_wait_send() + */ +bool tevent_queue_wait_recv(struct tevent_req *req); + +typedef int (*tevent_nesting_hook)(struct tevent_context *ev, + void *private_data, + uint32_t level, + bool begin, + void *stack_ptr, + const char *location); + +/** + * @brief Create a tevent_thread_proxy for message passing between threads. + * + * The tevent_context must have been allocated on the NULL + * talloc context, and talloc_disable_null_tracking() must + * have been called. + * + * @param[in] dest_ev_ctx The tevent_context to receive events. + * + * @return An allocated tevent_thread_proxy, NULL on error. + * If tevent was compiled without PTHREAD support + * NULL is always returned and errno set to ENOSYS. + * + * @see tevent_thread_proxy_schedule() + */ +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx); + +/** + * @brief Schedule an immediate event on an event context from another thread. + * + * Causes dest_ev_ctx, being run by another thread, to receive an + * immediate event calling the handler with the *pp_private parameter. + * + * *pp_im must be a pointer to an immediate event talloced on a context owned + * by the calling thread, or the NULL context. Ownership will + * be transferred to the tevent_thread_proxy and *pp_im will be returned as NULL. + * + * *pp_private_data must be a talloced area of memory with no destructors. + * Ownership of this memory will be transferred to the tevent library and + * *pp_private_data will be set to NULL on successful completion of + * the call. Set pp_private to NULL if no parameter transfer + * needed (a pure callback). This is an asynchronous request, caller + * does not wait for callback to be completed before returning. + * + * @param[in] tp The tevent_thread_proxy to use. + * + * @param[in] pp_im Pointer to immediate event pointer. + * + * @param[in] handler The function that will be called. + * + * @param[in] pp_private_data The talloced memory to transfer. + * + * @see tevent_thread_proxy_create() + */ +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + 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 talloc_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_ +#ifdef HAVE___ATTRIBUTE__ +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif +void tevent_loop_allow_nesting(struct tevent_context *ev) _DEPRECATED_; +void tevent_loop_set_nesting_hook(struct tevent_context *ev, + tevent_nesting_hook hook, + void *private_data) _DEPRECATED_; +int _tevent_loop_until(struct tevent_context *ev, + bool (*finished)(void *private_data), + void *private_data, + const char *location) _DEPRECATED_; +#define tevent_loop_until(ev, finished, private_data) \ + _tevent_loop_until(ev, finished, private_data, __location__) +#endif + +int tevent_re_initialise(struct tevent_context *ev); + +/* @} */ + +/** + * @defgroup tevent_ops The tevent operation functions + * @ingroup tevent + * + * The following structure and registration functions are exclusively + * needed for people writing and pluggin a different event engine. + * There is nothing useful for normal tevent user in here. + * @{ + */ + +struct tevent_ops { + /* context init */ + int (*context_init)(struct tevent_context *ev); + + /* fd_event functions */ + struct tevent_fd *(*add_fd)(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); + void (*set_fd_close_fn)(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); + uint16_t (*get_fd_flags)(struct tevent_fd *fde); + void (*set_fd_flags)(struct tevent_fd *fde, uint16_t flags); + + /* timed_event functions */ + struct tevent_timer *(*add_timer)(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); + + /* immediate event functions */ + void (*schedule_immediate)(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); + + /* signal functions */ + struct tevent_signal *(*add_signal)(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); + + /* loop functions */ + int (*loop_once)(struct tevent_context *ev, const char *location); + int (*loop_wait)(struct tevent_context *ev, const char *location); +}; + +bool tevent_register_backend(const char *name, const struct tevent_ops *ops); + +/* @} */ + +#ifdef TEVENT_DEPRECATED +/** + * @defgroup tevent_wrapper_ops The tevent wrapper operation functions + * @ingroup tevent + * + * The following structure and registration functions are exclusively + * needed for people writing wrapper functions for event handlers + * e.g. wrappers can be used for debugging/profiling or impersonation. + * + * There is nothing useful for normal tevent user in here. + * + * @note That the close_fn() on tevent_fd is *NOT* wrapped! + * + * @see tevent_context_wrapper_create + * @see tevent_fd_set_auto_close + * @{ + */ + +struct tevent_wrapper_ops { + const char *name; + + bool (*before_use)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + const char *location); + void (*after_use)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + const char *location); + + void (*before_fd_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location); + void (*after_fd_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location); + + void (*before_timer_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location); + void (*after_timer_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location); + + void (*before_immediate_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location); + void (*after_immediate_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location); + + void (*before_signal_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location); + void (*after_signal_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location); +}; + +#ifdef DOXYGEN +/** + * @brief Create a wrapper tevent_context. + * + * @param[in] main_ev The main event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] ops The tevent_wrapper_ops function table. + * + * @param[out] private_state The private state use by the wrapper functions. + * + * @param[in] private_type The talloc type of the private_state. + * + * @return The wrapper event context, NULL on error. + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +struct tevent_context *tevent_context_wrapper_create(struct tevent_context *main_ev, + TALLOC_CTX *mem_ctx, + const struct tevent_wrapper_ops *ops, + void **private_state, + const char *private_type); +#else +struct tevent_context *_tevent_context_wrapper_create(struct tevent_context *main_ev, + TALLOC_CTX *mem_ctx, + const struct tevent_wrapper_ops *ops, + void *pstate, + size_t psize, + const char *type, + const char *location) _DEPRECATED_; +#define tevent_context_wrapper_create(main_ev, mem_ctx, ops, state, type) \ + _tevent_context_wrapper_create(main_ev, mem_ctx, ops, \ + state, sizeof(type), #type, __location__) +#endif + +/** + * @brief Check if the event context is a wrapper event context. + * + * @param[in] ev The event context to work on. + * + * @return Is a wrapper (true), otherwise (false). + * + * @see tevent_context_wrapper_create() + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +bool tevent_context_is_wrapper(struct tevent_context *ev) _DEPRECATED_; + +#ifdef DOXYGEN +/** + * @brief Prepare the environment of a (wrapper) event context. + * + * A caller might call this before passing a wrapper event context + * to a tevent_req based *_send() function. + * + * The wrapper event context might do something like impersonation. + * + * tevent_context_push_use() must always be used in combination + * with tevent_context_pop_use(). + * + * There is a global stack of currently active/busy wrapper event contexts. + * Each wrapper can only appear once on that global stack! + * The stack size is limited to 32 elements, which should be enough + * for all useful scenarios. + * + * In addition to an explicit tevent_context_push_use() also + * the invocation of an immediate, timer or fd handler implicitly + * pushes the wrapper on the stack. + * + * Therefore there are some strict constraints for the usage of + * tevent_context_push_use(): + * - It must not be called from within an event handler + * that already acts on the wrapper. + * - tevent_context_pop_use() must be called before + * leaving the code block that called tevent_context_push_use(). + * - The caller is responsible ensure the correct stack ordering + * - Any violation of these constraints results in calling + * the abort handler of the given tevent context. + * + * Calling tevent_context_push_use() on a raw event context + * still consumes an element on the stack, but it's otherwise + * a no-op. + * + * If tevent_context_push_use() returns false, it means + * that the wrapper's before_use() hook returned this failure, + * in that case you must not call tevent_context_pop_use() as + * the wrapper is not pushed onto the stack. + * + * @param[in] ev The event context to work on. + * + * @return Success (true) or failure (false). + * + * @note This is only needed if wrapper event contexts are in use. + * + * @see tevent_context_pop_use + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +bool tevent_context_push_use(struct tevent_context *ev); +#else +bool _tevent_context_push_use(struct tevent_context *ev, + const char *location) _DEPRECATED_; +#define tevent_context_push_use(ev) \ + _tevent_context_push_use(ev, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Release the environment of a (wrapper) event context. + * + * The wrapper event context might undo something like impersonation. + * + * This must be called after a succesful tevent_context_push_use(). + * Any ordering violation results in calling + * the abort handler of the given tevent context. + * + * This basically calls the wrapper's after_use() hook. + * + * @param[in] ev The event context to work on. + * + * @note This is only needed if wrapper event contexts are in use. + * + * @see tevent_context_push_use + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +void tevent_context_pop_use(struct tevent_context *ev); +#else +void _tevent_context_pop_use(struct tevent_context *ev, + const char *location) _DEPRECATED_; +#define tevent_context_pop_use(ev) \ + _tevent_context_pop_use(ev, __location__) +#endif + +/** + * @brief Check is the two context pointers belong to the same low level loop + * + * With the introduction of wrapper contexts it's not trivial + * to check if two context pointers belong to the same low level + * event loop. Some code may need to know this in order + * to make some caching decisions. + * + * @param[in] ev1 The first event context. + * @param[in] ev2 The second event context. + * + * @return true if both contexts belong to the same (still existing) context + * loop, false otherwise. + * + * @see tevent_context_wrapper_create + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +bool tevent_context_same_loop(struct tevent_context *ev1, + struct tevent_context *ev2) _DEPRECATED_; + +/* @} */ +#endif /* TEVENT_DEPRECATED */ + +/** + * @defgroup tevent_compat The tevent compatibility functions + * @ingroup tevent + * + * The following definitions are usueful only for compatibility with the + * implementation originally developed within the samba4 code and will be + * soon removed. Please NEVER use in new code. + * + * @todo Ignore it? + * + * @{ + */ + +#ifdef TEVENT_COMPAT_DEFINES + +#define event_context tevent_context +#define event_ops tevent_ops +#define fd_event tevent_fd +#define timed_event tevent_timer +#define signal_event tevent_signal + +#define event_fd_handler_t tevent_fd_handler_t +#define event_timed_handler_t tevent_timer_handler_t +#define event_signal_handler_t tevent_signal_handler_t + +#define event_context_init(mem_ctx) \ + tevent_context_init(mem_ctx) + +#define event_context_init_byname(mem_ctx, name) \ + tevent_context_init_byname(mem_ctx, name) + +#define event_backend_list(mem_ctx) \ + tevent_backend_list(mem_ctx) + +#define event_set_default_backend(backend) \ + tevent_set_default_backend(backend) + +#define event_add_fd(ev, mem_ctx, fd, flags, handler, private_data) \ + tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data) + +#define event_add_timed(ev, mem_ctx, next_event, handler, private_data) \ + tevent_add_timer(ev, mem_ctx, next_event, handler, private_data) + +#define event_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) \ + tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) + +#define event_loop_once(ev) \ + tevent_loop_once(ev) + +#define event_loop_wait(ev) \ + tevent_loop_wait(ev) + +#define event_get_fd_flags(fde) \ + tevent_fd_get_flags(fde) + +#define event_set_fd_flags(fde, flags) \ + tevent_fd_set_flags(fde, flags) + +#define EVENT_FD_READ TEVENT_FD_READ +#define EVENT_FD_WRITE TEVENT_FD_WRITE + +#define EVENT_FD_WRITEABLE(fde) \ + TEVENT_FD_WRITEABLE(fde) + +#define EVENT_FD_READABLE(fde) \ + TEVENT_FD_READABLE(fde) + +#define EVENT_FD_NOT_WRITEABLE(fde) \ + TEVENT_FD_NOT_WRITEABLE(fde) + +#define EVENT_FD_NOT_READABLE(fde) \ + TEVENT_FD_NOT_READABLE(fde) + +#define ev_debug_level tevent_debug_level + +#define EV_DEBUG_FATAL TEVENT_DEBUG_FATAL +#define EV_DEBUG_ERROR TEVENT_DEBUG_ERROR +#define EV_DEBUG_WARNING TEVENT_DEBUG_WARNING +#define EV_DEBUG_TRACE TEVENT_DEBUG_TRACE + +#define ev_set_debug(ev, debug, context) \ + tevent_set_debug(ev, debug, context) + +#define ev_set_debug_stderr(_ev) tevent_set_debug_stderr(ev) + +#endif /* TEVENT_COMPAT_DEFINES */ + +/* @} */ + +#endif /* __TEVENT_H__ */ diff --git a/ldb-2.0.8/lib/tevent/tevent.pc.in b/ldb-2.0.8/lib/tevent/tevent.pc.in new file mode 100644 index 0000000..eb0e564 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: tevent +Description: An event system library +Version: @PACKAGE_VERSION@ +Requires: talloc +Libs: @LIB_RPATH@ -L${libdir} -ltevent +Cflags: -I${includedir} +URL: http://samba.org/ diff --git a/ldb-2.0.8/lib/tevent/tevent.py b/ldb-2.0.8/lib/tevent/tevent.py new file mode 100644 index 0000000..14aa27d --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent.py @@ -0,0 +1,28 @@ +# +# Python integration for tevent +# +# Copyright (C) Jelmer Vernooij 2011 +# +# ** NOTE! The following LGPL license applies to the tevent +# ** 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 +# Lesser 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 . + +from _tevent import ( + __version__, + backend_list, + Context, + Signal, +) diff --git a/ldb-2.0.8/lib/tevent/tevent_debug.c b/ldb-2.0.8/lib/tevent/tevent_debug.c new file mode 100644 index 0000000..0a57639 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_debug.c @@ -0,0 +1,135 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_internal.h" + +/******************************************************************** + * Debug wrapper functions, modeled (with lot's of code copied as is) + * after the ev debug wrapper functions + ********************************************************************/ + +/* + this allows the user to choose their own debug function +*/ +int tevent_set_debug(struct tevent_context *ev, + void (*debug)(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0), + void *context) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_debug() on wrapper"); + errno = EINVAL; + return -1; + } + + ev->debug_ops.debug = debug; + ev->debug_ops.context = context; + return 0; +} + +/* + debug function for ev_set_debug_stderr +*/ +static void tevent_debug_stderr(void *private_data, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0); +static void tevent_debug_stderr(void *private_data, + enum tevent_debug_level level, + const char *fmt, va_list ap) +{ + if (level <= TEVENT_DEBUG_WARNING) { + vfprintf(stderr, fmt, ap); + } +} + +/* + convenience function to setup debug messages on stderr + messages of level TEVENT_DEBUG_WARNING and higher are printed +*/ +int tevent_set_debug_stderr(struct tevent_context *ev) +{ + return tevent_set_debug(ev, tevent_debug_stderr, ev); +} + +/* + * log a message + * + * The default debug action is to ignore debugging messages. + * This is the most appropriate action for a library. + * Applications using the library must decide where to + * redirect debugging messages +*/ +void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, + const char *fmt, ...) +{ + va_list ap; + if (!ev) { + return; + } + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + } + if (ev->debug_ops.debug == NULL) { + return; + } + va_start(ap, fmt); + ev->debug_ops.debug(ev->debug_ops.context, level, fmt, ap); + va_end(ap); +} + +void tevent_set_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_callback() on wrapper"); + return; + } + + ev->tracing.callback = cb; + ev->tracing.private_data = private_data; +} + +void tevent_get_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t *cb, + void *private_data) +{ + *cb = ev->tracing.callback; + *(void**)private_data = ev->tracing.private_data; +} + +void tevent_trace_point_callback(struct tevent_context *ev, + enum tevent_trace_point tp) +{ + if (ev->tracing.callback != NULL) { + ev->tracing.callback(tp, ev->tracing.private_data); + } +} diff --git a/ldb-2.0.8/lib/tevent/tevent_epoll.c b/ldb-2.0.8/lib/tevent/tevent_epoll.c new file mode 100644 index 0000000..9cbe505 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_epoll.c @@ -0,0 +1,956 @@ +/* + Unix SMB/CIFS implementation. + + main select loop and event handling - epoll implementation + + Copyright (C) Andrew Tridgell 2003-2005 + Copyright (C) Stefan Metzmacher 2005-2013 + Copyright (C) Jeremy Allison 2013 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/select.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct epoll_event_context { + /* a pointer back to the generic event_context */ + struct tevent_context *ev; + + /* when using epoll this is the handle from epoll_create */ + int epoll_fd; + + pid_t pid; + + bool panic_force_replay; + bool *panic_state; + bool (*panic_fallback)(struct tevent_context *ev, bool replay); +}; + +#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0) +#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) +#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) +#define EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX (1<<3) + +#ifdef TEST_PANIC_FALLBACK + +static int epoll_create_panic_fallback(struct epoll_event_context *epoll_ev, + int size) +{ + if (epoll_ev->panic_fallback == NULL) { + return epoll_create(size); + } + + /* 50% of the time, fail... */ + if ((random() % 2) == 0) { + errno = EINVAL; + return -1; + } + + return epoll_create(size); +} + +static int epoll_ctl_panic_fallback(struct epoll_event_context *epoll_ev, + int epfd, int op, int fd, + struct epoll_event *event) +{ + if (epoll_ev->panic_fallback == NULL) { + return epoll_ctl(epfd, op, fd, event); + } + + /* 50% of the time, fail... */ + if ((random() % 2) == 0) { + errno = EINVAL; + return -1; + } + + return epoll_ctl(epfd, op, fd, event); +} + +static int epoll_wait_panic_fallback(struct epoll_event_context *epoll_ev, + int epfd, + struct epoll_event *events, + int maxevents, + int timeout) +{ + if (epoll_ev->panic_fallback == NULL) { + return epoll_wait(epfd, events, maxevents, timeout); + } + + /* 50% of the time, fail... */ + if ((random() % 2) == 0) { + errno = EINVAL; + return -1; + } + + return epoll_wait(epfd, events, maxevents, timeout); +} + +#define epoll_create(_size) \ + epoll_create_panic_fallback(epoll_ev, _size) +#define epoll_ctl(_epfd, _op, _fd, _event) \ + epoll_ctl_panic_fallback(epoll_ev,_epfd, _op, _fd, _event) +#define epoll_wait(_epfd, _events, _maxevents, _timeout) \ + epoll_wait_panic_fallback(epoll_ev, _epfd, _events, _maxevents, _timeout) +#endif + +/* + called to set the panic fallback function. +*/ +_PRIVATE_ void tevent_epoll_set_panic_fallback(struct tevent_context *ev, + bool (*panic_fallback)(struct tevent_context *ev, + bool replay)) +{ + struct epoll_event_context *epoll_ev = + talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + + epoll_ev->panic_fallback = panic_fallback; +} + +/* + called when a epoll call fails +*/ +static void epoll_panic(struct epoll_event_context *epoll_ev, + const char *reason, bool replay) +{ + struct tevent_context *ev = epoll_ev->ev; + bool (*panic_fallback)(struct tevent_context *ev, bool replay); + + panic_fallback = epoll_ev->panic_fallback; + + if (epoll_ev->panic_state != NULL) { + *epoll_ev->panic_state = true; + } + + if (epoll_ev->panic_force_replay) { + replay = true; + } + + TALLOC_FREE(ev->additional_data); + + if (panic_fallback == NULL) { + tevent_debug(ev, TEVENT_DEBUG_FATAL, + "%s (%s) replay[%u] - calling abort()\n", + reason, strerror(errno), (unsigned)replay); + abort(); + } + + tevent_debug(ev, TEVENT_DEBUG_ERROR, + "%s (%s) replay[%u] - calling panic_fallback\n", + reason, strerror(errno), (unsigned)replay); + + if (!panic_fallback(ev, replay)) { + /* Fallback failed. */ + tevent_debug(ev, TEVENT_DEBUG_FATAL, + "%s (%s) replay[%u] - calling abort()\n", + reason, strerror(errno), (unsigned)replay); + abort(); + } +} + +/* + map from TEVENT_FD_* to EPOLLIN/EPOLLOUT +*/ +static uint32_t epoll_map_flags(uint16_t flags) +{ + uint32_t ret = 0; + if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); + if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); + return ret; +} + +/* + free the epoll fd +*/ +static int epoll_ctx_destructor(struct epoll_event_context *epoll_ev) +{ + close(epoll_ev->epoll_fd); + epoll_ev->epoll_fd = -1; + return 0; +} + +/* + init the epoll fd +*/ +static int epoll_init_ctx(struct epoll_event_context *epoll_ev) +{ + epoll_ev->epoll_fd = epoll_create(64); + if (epoll_ev->epoll_fd == -1) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "Failed to create epoll handle.\n"); + return -1; + } + + if (!ev_set_close_on_exec(epoll_ev->epoll_fd)) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + epoll_ev->pid = getpid(); + talloc_set_destructor(epoll_ev, epoll_ctx_destructor); + + return 0; +} + +static void epoll_update_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde); + +/* + reopen the epoll handle when our pid changes + see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an + demonstration of why this is needed + */ +static void epoll_check_reopen(struct epoll_event_context *epoll_ev) +{ + struct tevent_fd *fde; + bool *caller_panic_state = epoll_ev->panic_state; + bool panic_triggered = false; + + if (epoll_ev->pid == getpid()) { + return; + } + + close(epoll_ev->epoll_fd); + epoll_ev->epoll_fd = epoll_create(64); + if (epoll_ev->epoll_fd == -1) { + epoll_panic(epoll_ev, "epoll_create() failed", false); + return; + } + + if (!ev_set_close_on_exec(epoll_ev->epoll_fd)) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + epoll_ev->pid = getpid(); + epoll_ev->panic_state = &panic_triggered; + for (fde=epoll_ev->ev->fd_events;fde;fde=fde->next) { + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + epoll_update_event(epoll_ev, fde); + + if (panic_triggered) { + if (caller_panic_state != NULL) { + *caller_panic_state = true; + } + return; + } + } + epoll_ev->panic_state = NULL; +} + +/* + epoll cannot add the same file descriptor twice, once + with read, once with write which is allowed by the + tevent backend. Multiplex the existing fde, flag it + as such so we can search for the correct fde on + event triggering. +*/ + +static int epoll_add_multiplex_fd(struct epoll_event_context *epoll_ev, + struct tevent_fd *add_fde) +{ + struct epoll_event event; + struct tevent_fd *mpx_fde; + int ret; + + /* Find the existing fde that caused the EEXIST error. */ + for (mpx_fde = epoll_ev->ev->fd_events; mpx_fde; mpx_fde = mpx_fde->next) { + if (mpx_fde->fd != add_fde->fd) { + continue; + } + + if (mpx_fde == add_fde) { + continue; + } + + break; + } + if (mpx_fde == NULL) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "can't find multiplex fde for fd[%d]", + add_fde->fd); + return -1; + } + + if (mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* Logic error. Can't have more than 2 multiplexed fde's. */ + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "multiplex fde for fd[%d] is already multiplexed\n", + mpx_fde->fd); + return -1; + } + + /* + * The multiplex fde must have the same fd, and also + * already have an epoll event attached. + */ + if (!(mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) { + /* Logic error. Can't have more than 2 multiplexed fde's. */ + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "multiplex fde for fd[%d] has no event\n", + mpx_fde->fd); + return -1; + } + + /* Modify the mpx_fde to add in the new flags. */ + ZERO_STRUCT(event); + event.events = epoll_map_flags(mpx_fde->flags); + event.events |= epoll_map_flags(add_fde->flags); + event.data.ptr = mpx_fde; + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, mpx_fde->fd, &event); + if (ret != 0 && errno == EBADF) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_ERROR, + "EPOLL_CTL_MOD EBADF for " + "add_fde[%p] mpx_fde[%p] fd[%d] - disabling\n", + add_fde, mpx_fde, add_fde->fd); + DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); + mpx_fde->wrapper = NULL; + mpx_fde->event_ctx = NULL; + DLIST_REMOVE(epoll_ev->ev->fd_events, add_fde); + add_fde->wrapper = NULL; + add_fde->event_ctx = NULL; + return 0; + } else if (ret != 0) { + return ret; + } + + /* + * Make each fde->additional_data pointers point at each other + * so we can look them up from each other. They are now paired. + */ + mpx_fde->additional_data = (struct tevent_fd *)add_fde; + add_fde->additional_data = (struct tevent_fd *)mpx_fde; + + /* Now flag both fde's as being multiplexed. */ + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + + /* we need to keep the GOT_ERROR flag */ + if (mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR) { + add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; + } + + return 0; +} + +/* + add the epoll event to the given fd_event +*/ +static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) +{ + struct epoll_event event; + int ret; + struct tevent_fd *mpx_fde = NULL; + + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is a multiplexed fde, we need to include both + * flags in the modified event. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + + ZERO_STRUCT(event); + event.events = epoll_map_flags(fde->flags); + if (mpx_fde != NULL) { + event.events |= epoll_map_flags(mpx_fde->flags); + } + event.data.ptr = fde; + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event); + if (ret != 0 && errno == EBADF) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_ERROR, + "EPOLL_CTL_ADD EBADF for " + "fde[%p] mpx_fde[%p] fd[%d] - disabling\n", + fde, mpx_fde, fde->fd); + DLIST_REMOVE(epoll_ev->ev->fd_events, fde); + fde->wrapper = NULL; + fde->event_ctx = NULL; + if (mpx_fde != NULL) { + DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); + mpx_fde->wrapper = NULL; + mpx_fde->event_ctx = NULL; + } + return; + } else if (ret != 0 && errno == EEXIST && mpx_fde == NULL) { + ret = epoll_add_multiplex_fd(epoll_ev, fde); + if (ret != 0) { + epoll_panic(epoll_ev, "epoll_add_multiplex_fd failed", + false); + return; + } + } else if (ret != 0) { + epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false); + return; + } + + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + /* only if we want to read we want to tell the event handler about errors */ + if (fde->flags & TEVENT_FD_READ) { + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + + if (mpx_fde == NULL) { + return; + } + + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + /* only if we want to read we want to tell the event handler about errors */ + if (mpx_fde->flags & TEVENT_FD_READ) { + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } +} + +/* + delete the epoll event for given fd_event +*/ +static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) +{ + struct epoll_event event; + int ret; + struct tevent_fd *mpx_fde = NULL; + + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is a multiplexed fde, we need to modify both events. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + + ZERO_STRUCT(event); + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); + if (ret != 0 && errno == ENOENT) { + /* + * This can happen after a epoll_check_reopen + * within epoll_event_fd_destructor. + */ + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_TRACE, + "EPOLL_CTL_DEL ignoring ENOENT for fd[%d]\n", + fde->fd); + return; + } else if (ret != 0 && errno == EBADF) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "EPOLL_CTL_DEL EBADF for " + "fde[%p] mpx_fde[%p] fd[%d] - disabling\n", + fde, mpx_fde, fde->fd); + DLIST_REMOVE(epoll_ev->ev->fd_events, fde); + fde->wrapper = NULL; + fde->event_ctx = NULL; + if (mpx_fde != NULL) { + DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); + mpx_fde->wrapper = NULL; + mpx_fde->event_ctx = NULL; + } + return; + } else if (ret != 0) { + epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false); + return; + } +} + +/* + change the epoll event to the given fd_event +*/ +static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) +{ + struct tevent_fd *mpx_fde = NULL; + struct epoll_event event; + int ret; + + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is a multiplexed fde, we need to include both + * flags in the modified event. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + + ZERO_STRUCT(event); + event.events = epoll_map_flags(fde->flags); + if (mpx_fde != NULL) { + event.events |= epoll_map_flags(mpx_fde->flags); + } + event.data.ptr = fde; + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event); + if (ret != 0 && errno == EBADF) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_ERROR, + "EPOLL_CTL_MOD EBADF for " + "fde[%p] mpx_fde[%p] fd[%d] - disabling\n", + fde, mpx_fde, fde->fd); + DLIST_REMOVE(epoll_ev->ev->fd_events, fde); + fde->wrapper = NULL; + fde->event_ctx = NULL; + if (mpx_fde != NULL) { + DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); + mpx_fde->wrapper = NULL; + mpx_fde->event_ctx = NULL; + } + return; + } else if (ret != 0) { + epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed", false); + return; + } + + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + /* only if we want to read we want to tell the event handler about errors */ + if (fde->flags & TEVENT_FD_READ) { + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + + if (mpx_fde == NULL) { + return; + } + + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + /* only if we want to read we want to tell the event handler about errors */ + if (mpx_fde->flags & TEVENT_FD_READ) { + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } +} + +static void epoll_update_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) +{ + bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR); + bool want_read = (fde->flags & TEVENT_FD_READ); + bool want_write= (fde->flags & TEVENT_FD_WRITE); + struct tevent_fd *mpx_fde = NULL; + + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * work out what the multiplexed fde wants. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + if (mpx_fde->flags & TEVENT_FD_READ) { + want_read = true; + } + + if (mpx_fde->flags & TEVENT_FD_WRITE) { + want_write = true; + } + } + + /* there's already an event */ + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) { + if (want_read || (want_write && !got_error)) { + epoll_mod_event(epoll_ev, fde); + return; + } + /* + * if we want to match the select behavior, we need to remove the epoll_event + * when the caller isn't interested in events. + * + * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them + */ + epoll_del_event(epoll_ev, fde); + return; + } + + /* there's no epoll_event attached to the fde */ + if (want_read || (want_write && !got_error)) { + epoll_add_event(epoll_ev, fde); + return; + } +} + +/* + Cope with epoll returning EPOLLHUP|EPOLLERR on an event. + Return true if there's nothing else to do, false if + this event needs further handling. +*/ +static bool epoll_handle_hup_or_err(struct epoll_event_context *epoll_ev, + struct tevent_fd *fde) +{ + if (fde == NULL) { + /* Nothing to do if no event. */ + return true; + } + + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; + /* + * if we only wait for TEVENT_FD_WRITE, we should not tell the + * event handler about it, and remove the epoll_event, + * as we only report errors when waiting for read events, + * to match the select() behavior + */ + if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) { + /* + * Do the same as the poll backend and + * remove the writeable flag. + */ + fde->flags &= ~TEVENT_FD_WRITE; + return true; + } + /* This has TEVENT_FD_READ set, we're not finished. */ + return false; +} + +/* + event loop handling using epoll +*/ +static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval *tvalp) +{ + int ret, i; +#define MAXEVENTS 1 + struct epoll_event events[MAXEVENTS]; + int timeout = -1; + int wait_errno; + + if (tvalp) { + /* it's better to trigger timed events a bit later than too early */ + timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000); + } + + if (epoll_ev->ev->signal_events && + tevent_common_check_signal(epoll_ev->ev)) { + return 0; + } + + tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_BEFORE_WAIT); + ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout); + wait_errno = errno; + tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_AFTER_WAIT); + + if (ret == -1 && wait_errno == EINTR && epoll_ev->ev->signal_events) { + if (tevent_common_check_signal(epoll_ev->ev)) { + return 0; + } + } + + if (ret == -1 && wait_errno != EINTR) { + epoll_panic(epoll_ev, "epoll_wait() failed", true); + return -1; + } + + if (ret == 0 && tvalp) { + /* we don't care about a possible delay here */ + tevent_common_loop_timer_delay(epoll_ev->ev); + return 0; + } + + for (i=0;iadditional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * Save off the multiplexed event in case we need + * to use it to call the handler function. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + } + if (events[i].events & (EPOLLHUP|EPOLLERR)) { + bool handled_fde = epoll_handle_hup_or_err(epoll_ev, fde); + bool handled_mpx = epoll_handle_hup_or_err(epoll_ev, mpx_fde); + + if (handled_fde && handled_mpx) { + epoll_update_event(epoll_ev, fde); + continue; + } + + if (!handled_mpx) { + /* + * If the mpx event was the one that needs + * further handling, it's the TEVENT_FD_READ + * event so switch over and call that handler. + */ + fde = mpx_fde; + mpx_fde = NULL; + } + flags |= TEVENT_FD_READ; + } + if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ; + if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE; + + if (flags & TEVENT_FD_WRITE) { + if (fde->flags & TEVENT_FD_WRITE) { + mpx_fde = NULL; + } + if (mpx_fde && mpx_fde->flags & TEVENT_FD_WRITE) { + fde = mpx_fde; + mpx_fde = NULL; + } + } + + if (mpx_fde) { + /* Ensure we got the right fde. */ + if ((flags & fde->flags) == 0) { + fde = mpx_fde; + mpx_fde = NULL; + } + } + + /* + * make sure we only pass the flags + * the handler is expecting. + */ + flags &= fde->flags; + if (flags) { + return tevent_common_invoke_fd_handler(fde, flags, NULL); + } + } + + return 0; +} + +/* + create a epoll_event_context structure. +*/ +static int epoll_event_context_init(struct tevent_context *ev) +{ + int ret; + struct epoll_event_context *epoll_ev; + + /* + * We might be called during tevent_re_initialise() + * which means we need to free our old additional_data. + */ + TALLOC_FREE(ev->additional_data); + + epoll_ev = talloc_zero(ev, struct epoll_event_context); + if (!epoll_ev) return -1; + epoll_ev->ev = ev; + epoll_ev->epoll_fd = -1; + + ret = epoll_init_ctx(epoll_ev); + if (ret != 0) { + talloc_free(epoll_ev); + return ret; + } + + ev->additional_data = epoll_ev; + return 0; +} + +/* + destroy an fd_event +*/ +static int epoll_event_fd_destructor(struct tevent_fd *fde) +{ + struct tevent_context *ev = fde->event_ctx; + struct epoll_event_context *epoll_ev = NULL; + bool panic_triggered = false; + struct tevent_fd *mpx_fde = NULL; + int flags = fde->flags; + + if (ev == NULL) { + return tevent_common_fd_destructor(fde); + } + + epoll_ev = talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + + /* + * we must remove the event from the list + * otherwise a panic fallback handler may + * reuse invalid memory + */ + DLIST_REMOVE(ev->fd_events, fde); + + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + + fde->additional_data = NULL; + mpx_fde->additional_data = NULL; + + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + } + + epoll_ev->panic_state = &panic_triggered; + epoll_check_reopen(epoll_ev); + if (panic_triggered) { + return tevent_common_fd_destructor(fde); + } + + if (mpx_fde != NULL) { + epoll_update_event(epoll_ev, mpx_fde); + if (panic_triggered) { + return tevent_common_fd_destructor(fde); + } + } + + fde->flags = 0; + epoll_update_event(epoll_ev, fde); + fde->flags = flags; + if (panic_triggered) { + return tevent_common_fd_destructor(fde); + } + epoll_ev->panic_state = NULL; + + return tevent_common_fd_destructor(fde); +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct epoll_event_context *epoll_ev = + talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + struct tevent_fd *fde; + bool panic_triggered = false; + + fde = tevent_common_add_fd(ev, mem_ctx, fd, flags, + handler, private_data, + handler_name, location); + if (!fde) return NULL; + + talloc_set_destructor(fde, epoll_event_fd_destructor); + + epoll_ev->panic_state = &panic_triggered; + epoll_check_reopen(epoll_ev); + if (panic_triggered) { + return fde; + } + epoll_ev->panic_state = NULL; + + epoll_update_event(epoll_ev, fde); + + return fde; +} + +/* + set the fd event flags +*/ +static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + struct tevent_context *ev; + struct epoll_event_context *epoll_ev; + bool panic_triggered = false; + + if (fde->flags == flags) return; + + ev = fde->event_ctx; + epoll_ev = talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + + fde->flags = flags; + + epoll_ev->panic_state = &panic_triggered; + epoll_check_reopen(epoll_ev); + if (panic_triggered) { + return; + } + epoll_ev->panic_state = NULL; + + epoll_update_event(epoll_ev, fde); +} + +/* + do a single event loop using the events defined in ev +*/ +static int epoll_event_loop_once(struct tevent_context *ev, const char *location) +{ + struct epoll_event_context *epoll_ev = + talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + struct timeval tval; + bool panic_triggered = false; + + if (ev->signal_events && + tevent_common_check_signal(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; + } + + tval = tevent_common_loop_timer_delay(ev); + if (tevent_timeval_is_zero(&tval)) { + return 0; + } + + epoll_ev->panic_state = &panic_triggered; + epoll_ev->panic_force_replay = true; + epoll_check_reopen(epoll_ev); + if (panic_triggered) { + errno = EINVAL; + return -1; + } + epoll_ev->panic_force_replay = false; + epoll_ev->panic_state = NULL; + + return epoll_event_loop(epoll_ev, &tval); +} + +static const struct tevent_ops epoll_event_ops = { + .context_init = epoll_event_context_init, + .add_fd = epoll_event_add_fd, + .set_fd_close_fn = tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, + .set_fd_flags = epoll_event_set_fd_flags, + .add_timer = tevent_common_add_timer_v2, + .schedule_immediate = tevent_common_schedule_immediate, + .add_signal = tevent_common_add_signal, + .loop_once = epoll_event_loop_once, + .loop_wait = tevent_common_loop_wait, +}; + +_PRIVATE_ bool tevent_epoll_init(void) +{ + return tevent_register_backend("epoll", &epoll_event_ops); +} diff --git a/ldb-2.0.8/lib/tevent/tevent_fd.c b/ldb-2.0.8/lib/tevent/tevent_fd.c new file mode 100644 index 0000000..a0557fe --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_fd.c @@ -0,0 +1,161 @@ +/* + Unix SMB/CIFS implementation. + + common events code for fd events + + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +int tevent_common_fd_destructor(struct tevent_fd *fde) +{ + if (fde->destroyed) { + tevent_common_check_double_free(fde, "tevent_fd double free"); + goto done; + } + fde->destroyed = true; + + if (fde->event_ctx) { + DLIST_REMOVE(fde->event_ctx->fd_events, fde); + } + + if (fde->close_fn) { + fde->close_fn(fde->event_ctx, fde, fde->fd, fde->private_data); + fde->fd = -1; + fde->close_fn = NULL; + } + + fde->event_ctx = NULL; +done: + if (fde->busy) { + return -1; + } + fde->wrapper = NULL; + + return 0; +} + +struct tevent_fd *tevent_common_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_fd *fde; + + /* tevent will crash later on select() if we save + * a negative file descriptor. Better to fail here + * so that consumers will be able to debug it + */ + if (fd < 0) return NULL; + + fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd); + if (!fde) return NULL; + + *fde = (struct tevent_fd) { + .event_ctx = ev, + .fd = fd, + .flags = flags, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .location = location, + }; + + DLIST_ADD(ev->fd_events, fde); + + talloc_set_destructor(fde, tevent_common_fd_destructor); + + return fde; +} +uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde) +{ + return fde->flags; +} + +void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags) +{ + if (fde->flags == flags) return; + fde->flags = flags; +} + +void tevent_common_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + fde->close_fn = close_fn; +} + +int tevent_common_invoke_fd_handler(struct tevent_fd *fde, uint16_t flags, + bool *removed) +{ + struct tevent_context *handler_ev = fde->event_ctx; + + if (removed != NULL) { + *removed = false; + } + + if (fde->event_ctx == NULL) { + return 0; + } + + fde->busy = true; + if (fde->wrapper != NULL) { + handler_ev = fde->wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, fde->wrapper); + fde->wrapper->ops->before_fd_handler( + fde->wrapper->wrap_ev, + fde->wrapper->private_state, + fde->wrapper->main_ev, + fde, + flags, + fde->handler_name, + fde->location); + } + fde->handler(handler_ev, fde, flags, fde->private_data); + if (fde->wrapper != NULL) { + fde->wrapper->ops->after_fd_handler( + fde->wrapper->wrap_ev, + fde->wrapper->private_state, + fde->wrapper->main_ev, + fde, + flags, + fde->handler_name, + fde->location); + tevent_wrapper_pop_use_internal(handler_ev, fde->wrapper); + } + fde->busy = false; + + if (fde->destroyed) { + talloc_set_destructor(fde, NULL); + TALLOC_FREE(fde); + if (removed != NULL) { + *removed = true; + } + } + + return 0; +} diff --git a/ldb-2.0.8/lib/tevent/tevent_immediate.c b/ldb-2.0.8/lib/tevent/tevent_immediate.c new file mode 100644 index 0000000..d7f8dcc --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_immediate.c @@ -0,0 +1,210 @@ +/* + Unix SMB/CIFS implementation. + + common events code for immediate events + + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +static void tevent_common_immediate_cancel(struct tevent_immediate *im) +{ + const char *create_location = im->create_location; + bool busy = im->busy; + + if (im->destroyed) { + tevent_abort(im->event_ctx, "tevent_immediate use after free"); + return; + } + + if (!im->event_ctx) { + return; + } + + if (im->handler_name != NULL) { + tevent_debug(im->event_ctx, TEVENT_DEBUG_TRACE, + "Cancel immediate event %p \"%s\"\n", + im, im->handler_name); + } + + /* let the backend free im->additional_data */ + if (im->cancel_fn) { + im->cancel_fn(im); + } + + DLIST_REMOVE(im->event_ctx->immediate_events, im); + + *im = (struct tevent_immediate) { + .create_location = create_location, + .busy = busy, + }; + + if (!busy) { + talloc_set_destructor(im, NULL); + } +} + +/* + destroy an immediate event +*/ +static int tevent_common_immediate_destructor(struct tevent_immediate *im) +{ + if (im->destroyed) { + tevent_common_check_double_free(im, + "tevent_immediate double free"); + goto done; + } + + tevent_common_immediate_cancel(im); + + im->destroyed = true; + +done: + if (im->busy) { + return -1; + } + + return 0; +} + +/* + * schedule an immediate event on + */ +void tevent_common_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + const char *create_location = im->create_location; + bool busy = im->busy; + struct tevent_wrapper_glue *glue = im->wrapper; + + tevent_common_immediate_cancel(im); + + if (!handler) { + return; + } + + *im = (struct tevent_immediate) { + .event_ctx = ev, + .wrapper = glue, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .create_location = create_location, + .schedule_location = location, + .busy = busy, + }; + + DLIST_ADD_END(ev->immediate_events, im); + talloc_set_destructor(im, tevent_common_immediate_destructor); + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Schedule immediate event \"%s\": %p\n", + handler_name, im); +} + +int tevent_common_invoke_immediate_handler(struct tevent_immediate *im, + bool *removed) +{ + struct tevent_context *handler_ev = im->event_ctx; + struct tevent_context *ev = im->event_ctx; + struct tevent_immediate cur = *im; + + if (removed != NULL) { + *removed = false; + } + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Run immediate event \"%s\": %p\n", + im->handler_name, im); + + /* + * remember the handler and then clear the event + * the handler might reschedule the event + */ + + im->busy = true; + im->handler_name = NULL; + tevent_common_immediate_cancel(im); + if (cur.wrapper != NULL) { + handler_ev = cur.wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, cur.wrapper); + cur.wrapper->ops->before_immediate_handler( + cur.wrapper->wrap_ev, + cur.wrapper->private_state, + cur.wrapper->main_ev, + im, + cur.handler_name, + cur.schedule_location); + } + cur.handler(handler_ev, im, cur.private_data); + if (cur.wrapper != NULL) { + cur.wrapper->ops->after_immediate_handler( + cur.wrapper->wrap_ev, + cur.wrapper->private_state, + cur.wrapper->main_ev, + im, + cur.handler_name, + cur.schedule_location); + tevent_wrapper_pop_use_internal(handler_ev, cur.wrapper); + } + im->busy = false; + + if (im->destroyed) { + talloc_set_destructor(im, NULL); + TALLOC_FREE(im); + if (removed != NULL) { + *removed = true; + } + } + + return 0; +} + +/* + trigger the first immediate event and return true + if no event was triggered return false +*/ +bool tevent_common_loop_immediate(struct tevent_context *ev) +{ + struct tevent_immediate *im = ev->immediate_events; + int ret; + + if (!im) { + return false; + } + + ret = tevent_common_invoke_immediate_handler(im, NULL); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_immediate_handler() failed"); + } + + return true; +} + diff --git a/ldb-2.0.8/lib/tevent/tevent_internal.h b/ldb-2.0.8/lib/tevent/tevent_internal.h new file mode 100644 index 0000000..5365fce --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_internal.h @@ -0,0 +1,471 @@ +/* + Unix SMB/CIFS implementation. + + generalised event loop handling + + INTERNAL STRUCTS. THERE ARE NO API GUARANTEES. + External users should only ever have to include this header when + implementing new tevent backends. + + Copyright (C) Stefan Metzmacher 2005-2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +struct tevent_req { + /** + * @brief What to do on completion + * + * This is used for the user of an async request, fn is called when + * the request completes, either successfully or with an error. + */ + struct { + /** + * @brief Completion function + * Completion function, to be filled by the API user + */ + tevent_req_fn fn; + /** + * @brief Private data for the completion function + */ + void *private_data; + } async; + + /** + * @brief Private state pointer for the actual implementation + * + * The implementation doing the work for the async request needs to + * keep around current data like for example a fd event. The user of + * an async request should not touch this. + */ + void *data; + + /** + * @brief A function to overwrite the default print function + * + * The implementation doing the work may want to implement a + * custom function to print the text representation of the async + * request. + */ + tevent_req_print_fn private_print; + + /** + * @brief A function to cancel the request + * + * The implementation might want to set a function + * that is called when the tevent_req_cancel() function + * was called. + */ + tevent_req_cancel_fn private_cancel; + + /** + * @brief A function to cleanup the request + * + * The implementation might want to set a function + * that is called before the tevent_req_done() and tevent_req_error() + * trigger the callers callback function. + */ + struct { + tevent_req_cleanup_fn fn; + enum tevent_req_state state; + } private_cleanup; + + /** + * @brief Internal state of the request + * + * Callers should only access this via functions and never directly. + */ + struct { + /** + * @brief The talloc type of the data pointer + * + * This is filled by the tevent_req_create() macro. + * + * This for debugging only. + */ + const char *private_type; + + /** + * @brief The location where the request was created + * + * This uses the __location__ macro via the tevent_req_create() + * macro. + * + * This for debugging only. + */ + const char *create_location; + + /** + * @brief The location where the request was finished + * + * This uses the __location__ macro via the tevent_req_done(), + * tevent_req_error() or tevent_req_nomem() macro. + * + * This for debugging only. + */ + const char *finish_location; + + /** + * @brief The location where the request was canceled + * + * This uses the __location__ macro via the + * tevent_req_cancel() macro. + * + * This for debugging only. + */ + const char *cancel_location; + + /** + * @brief The external state - will be queried by the caller + * + * While the async request is being processed, state will remain in + * TEVENT_REQ_IN_PROGRESS. A request is finished if + * req->state>=TEVENT_REQ_DONE. + */ + enum tevent_req_state state; + + /** + * @brief status code when finished + * + * This status can be queried in the async completion function. It + * will be set to 0 when everything went fine. + */ + uint64_t error; + + /** + * @brief the immediate event used by tevent_req_post + * + */ + struct tevent_immediate *trigger; + + /** + * @brief An event context which will be used to + * defer the _tevent_req_notify_callback(). + */ + struct tevent_context *defer_callback_ev; + + /** + * @brief the timer event if tevent_req_set_endtime was used + * + */ + struct tevent_timer *timer; + + /** + * @brief The place where profiling data is kept + */ + struct tevent_req_profile *profile; + } internal; +}; + +struct tevent_req_profile { + struct tevent_req_profile *prev, *next; + struct tevent_req_profile *parent; + const char *req_name; + pid_t pid; + const char *start_location; + struct timeval start_time; + const char *stop_location; + struct timeval stop_time; + enum tevent_req_state state; + uint64_t user_error; + struct tevent_req_profile *subprofiles; +}; + +struct tevent_fd { + struct tevent_fd *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + int fd; + uint16_t flags; /* see TEVENT_FD_* flags */ + tevent_fd_handler_t handler; + tevent_fd_close_fn_t close_fn; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; + /* this is private for the events_ops implementation */ + uint64_t additional_flags; + void *additional_data; +}; + +struct tevent_timer { + struct tevent_timer *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + struct timeval next_event; + tevent_timer_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; + /* this is private for the events_ops implementation */ + void *additional_data; +}; + +struct tevent_immediate { + struct tevent_immediate *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + tevent_immediate_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *create_location; + const char *schedule_location; + /* this is private for the events_ops implementation */ + void (*cancel_fn)(struct tevent_immediate *im); + void *additional_data; +}; + +struct tevent_signal { + struct tevent_signal *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + int signum; + int sa_flags; + tevent_signal_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; + /* this is private for the events_ops implementation */ + 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; +}; + +struct tevent_debug_ops { + void (*debug)(void *context, enum tevent_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + void *context; +}; + +void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); + +void tevent_abort(struct tevent_context *ev, const char *reason); + +void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason); + +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 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 *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; + + /* info about the nesting status */ + struct { + bool allowed; + uint32_t level; + tevent_nesting_hook hook_fn; + void *hook_private; + } nesting; + + struct { + tevent_trace_callback_t callback; + void *private_data; + } tracing; + + struct { + /* + * This is used on the main event context + */ + struct tevent_wrapper_glue *list; + + /* + * This is used on the wrapper event context + */ + struct tevent_wrapper_glue *glue; + } wrapper; + + /* + * an optimization pointer into timer_events + * used by used by common code via + * 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); + +int tevent_common_context_destructor(struct tevent_context *ev); +int tevent_common_loop_wait(struct tevent_context *ev, + const char *location); + +int tevent_common_fd_destructor(struct tevent_fd *fde); +struct tevent_fd *tevent_common_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +void tevent_common_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); +uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde); +void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags); +int tevent_common_invoke_fd_handler(struct tevent_fd *fde, uint16_t flags, + bool *removed); + +struct tevent_timer *tevent_common_add_timer(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); +struct tevent_timer *tevent_common_add_timer_v2(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); +struct timeval tevent_common_loop_timer_delay(struct tevent_context *); +int tevent_common_invoke_timer_handler(struct tevent_timer *te, + struct timeval current_time, + bool *removed); + +void tevent_common_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +int tevent_common_invoke_immediate_handler(struct tevent_immediate *im, + bool *removed); +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, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +int tevent_common_check_signal(struct tevent_context *ev); +void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se); +int tevent_common_invoke_signal_handler(struct tevent_signal *se, + int signum, int count, void *siginfo, + bool *removed); + +struct tevent_context *tevent_wrapper_main_ev(struct tevent_context *ev); + +struct tevent_wrapper_ops; + +struct tevent_wrapper_glue { + struct tevent_wrapper_glue *prev, *next; + struct tevent_context *wrap_ev; + struct tevent_context *main_ev; + bool busy; + bool destroyed; + const struct tevent_wrapper_ops *ops; + void *private_state; +}; + +void tevent_wrapper_push_use_internal(struct tevent_context *ev, + struct tevent_wrapper_glue *wrapper); +void tevent_wrapper_pop_use_internal(const struct tevent_context *__ev_ptr, + struct tevent_wrapper_glue *wrapper); + +bool tevent_standard_init(void); +bool tevent_poll_init(void); +bool tevent_poll_event_add_fd_internal(struct tevent_context *ev, + struct tevent_fd *fde); +bool tevent_poll_mt_init(void); +#ifdef HAVE_EPOLL +bool tevent_epoll_init(void); +void tevent_epoll_set_panic_fallback(struct tevent_context *ev, + bool (*panic_fallback)(struct tevent_context *ev, + bool replay)); +#endif +#ifdef HAVE_SOLARIS_PORTS +bool tevent_port_init(void); +#endif + + +void tevent_trace_point_callback(struct tevent_context *ev, + enum tevent_trace_point); diff --git a/ldb-2.0.8/lib/tevent/tevent_liboop.c b/ldb-2.0.8/lib/tevent/tevent_liboop.c new file mode 100644 index 0000000..68be76b --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_liboop.c @@ -0,0 +1,292 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + wrapper for http://git.lysator.liu.se/liboop/ + + Copyright (C) Stefan Metzmacher 2005 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "events.h" +#include "events_internal.h" + +#include + +/* + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + NOTE: this code compiles fine, but is completely *UNTESTED* + and is only committed as an example + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +*/ + +static int oop_event_context_destructor(struct tevent_context *ev) +{ + oop_source_sys *oop_sys = ev->additional_data; + + oop_sys_delete(oop_sys); + + return 0; +} + +/* + create a oop_event_context structure. +*/ +static int oop_event_context_init(struct tevent_context *ev, void *private_data) +{ + oop_source_sys *oop_sys = private_data; + + if (!oop_sys) { + oop_sys = oop_sys_new(); + if (!oop_sys) { + return -1; + } + + talloc_set_destructor(ev, oop_event_context_destructor); + } + + ev->additional_data = oop_sys; + + return 0; +} + +static void *oop_event_fd_handler(oop_source *oop, int fd, oop_event oop_type, void *ptr) +{ + struct tevent_fd *fde = ptr; + + if (fd != fde->fd) return OOP_ERROR; + + switch(oop_type) { + case OOP_READ: + fde->handler(fde->event_ctx, fde, EVENT_FD_READ, fde->private_data); + return OOP_CONTINUE; + case OOP_WRITE: + fde->handler(fde->event_ctx, fde, EVENT_FD_WRITE, fde->private_data); + return OOP_CONTINUE; + case OOP_EXCEPTION: + return OOP_ERROR; + case OOP_NUM_EVENTS: + return OOP_ERROR; + } + + return OOP_ERROR; +} + +/* + destroy an fd_event +*/ +static int oop_event_fd_destructor(struct tevent_fd *fde) +{ + struct tevent_context *ev = fde->event_ctx; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + if (fde->flags & EVENT_FD_READ) + oop->cancel_fd(oop, fde->fd, OOP_READ); + if (fde->flags & EVENT_FD_WRITE) + oop->cancel_fd(oop, fde->fd, OOP_WRITE); + + if (fde->flags & EVENT_FD_AUTOCLOSE) { + close(fde->fd); + fde->fd = -1; + } + + return 0; +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *oop_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + event_fd_handler_t handler, + void *private_data) +{ + struct tevent_fd *fde; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd); + if (!fde) return NULL; + + fde->event_ctx = ev; + fde->fd = fd; + fde->flags = flags; + fde->handler = handler; + fde->private_data = private_data; + fde->additional_flags = 0; + fde->additional_data = NULL; + + if (fde->flags & EVENT_FD_READ) + oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); + if (fde->flags & EVENT_FD_WRITE) + oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); + + talloc_set_destructor(fde, oop_event_fd_destructor); + + return fde; +} + +/* + return the fd event flags +*/ +static uint16_t oop_event_get_fd_flags(struct tevent_fd *fde) +{ + return fde->flags; +} + +/* + set the fd event flags +*/ +static void oop_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + oop_source_sys *oop_sys; + oop_source *oop; + + oop_sys = fde->event_ctx->additional_data; + oop = oop_sys_source(oop_sys); + + if ((fde->flags & EVENT_FD_READ)&&(!(flags & EVENT_FD_READ))) + oop->cancel_fd(oop, fde->fd, OOP_READ); + + if ((!(fde->flags & EVENT_FD_READ))&&(flags & EVENT_FD_READ)) + oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); + + if ((fde->flags & EVENT_FD_WRITE)&&(!(flags & EVENT_FD_WRITE))) + oop->cancel_fd(oop, fde->fd, OOP_WRITE); + + if ((!(fde->flags & EVENT_FD_WRITE))&&(flags & EVENT_FD_WRITE)) + oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); + + fde->flags = flags; +} + +static int oop_event_timed_destructor(struct tevent_timer *te); + +static int oop_event_timed_deny_destructor(struct tevent_timer *te) +{ + return -1; +} + +static void *oop_event_timed_handler(oop_source *oop, struct timeval t, void *ptr) +{ + struct tevent_timer *te = ptr; + + /* deny the handler to free the event */ + talloc_set_destructor(te, oop_event_timed_deny_destructor); + te->handler(te->event_ctx, te, t, te->private_data); + + talloc_set_destructor(te, oop_event_timed_destructor); + talloc_free(te); + + return OOP_CONTINUE; +} + +/* + destroy a timed event +*/ +static int oop_event_timed_destructor(struct tevent_timer *te) +{ + struct tevent_context *ev = te->event_ctx; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te); + + return 0; +} + +/* + add a timed event + return NULL on failure (memory allocation error) +*/ +static struct tevent_timer *oop_event_add_timed(struct tevent_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private_data) +{ + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + 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->additional_data = NULL; + + oop->on_time(oop, te->next_event, oop_event_timed_handler, te); + + talloc_set_destructor(te, oop_event_timed_destructor); + + return te; +} + +/* + do a single event loop using the events defined in ev +*/ +static int oop_event_loop_once(struct tevent_context *ev) +{ + void *oop_ret; + oop_source_sys *oop_sys = ev->additional_data; + + oop_ret = oop_sys_run_once(oop_sys); + if (oop_ret == OOP_CONTINUE) { + return 0; + } + + return -1; +} + +/* + return on failure or (with 0) if all fd events are removed +*/ +static int oop_event_loop_wait(struct tevent_context *ev) +{ + void *oop_ret; + oop_source_sys *oop_sys = ev->additional_data; + + oop_ret = oop_sys_run(oop_sys); + if (oop_ret == OOP_CONTINUE) { + return 0; + } + + return -1; +} + +static const struct event_ops event_oop_ops = { + .context_init = oop_event_context_init, + .add_fd = oop_event_add_fd, + .get_fd_flags = oop_event_get_fd_flags, + .set_fd_flags = oop_event_set_fd_flags, + .add_timer = oop_event_add_timed, + .add_signal = common_event_add_signal, + .loop_once = oop_event_loop_once, + .loop_wait = oop_event_loop_wait, +}; + +const struct event_ops *event_liboop_get_ops(void) +{ + return &event_oop_ops; +} diff --git a/ldb-2.0.8/lib/tevent/tevent_poll.c b/ldb-2.0.8/lib/tevent/tevent_poll.c new file mode 100644 index 0000000..f4c6c2d --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_poll.c @@ -0,0 +1,663 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003-2005 + Copyright (C) Stefan Metzmacher 2005-2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/select.h" +#include "tevent.h" +#include "tevent_util.h" +#include "tevent_internal.h" + +struct poll_event_context { + /* a pointer back to the generic event_context */ + struct tevent_context *ev; + + /* + * one or more events were deleted or disabled + */ + bool deleted; + + /* + * These two arrays are maintained together. + * + * The following is always true: + * num_fds <= num_fdes + * + * new 'fresh' elements are added at the end + * of the 'fdes' array and picked up later + * to the 'fds' array in poll_event_sync_arrays() + * before the poll() syscall. + */ + struct pollfd *fds; + size_t num_fds; + struct tevent_fd **fdes; + size_t num_fdes; + + /* + * use tevent_common_wakeup(ev) to wake the poll() thread + */ + bool use_mt_mode; +}; + +/* + create a poll_event_context structure. +*/ +static int poll_event_context_init(struct tevent_context *ev) +{ + struct poll_event_context *poll_ev; + + /* + * we might be called during tevent_re_initialise() + * which means we need to free our old additional_data + * in order to detach old fd events from the + * poll_ev->fresh list + */ + TALLOC_FREE(ev->additional_data); + + poll_ev = talloc_zero(ev, struct poll_event_context); + if (poll_ev == NULL) { + return -1; + } + poll_ev->ev = ev; + ev->additional_data = poll_ev; + return 0; +} + +static int poll_event_context_init_mt(struct tevent_context *ev) +{ + struct poll_event_context *poll_ev; + int ret; + + ret = poll_event_context_init(ev); + if (ret == -1) { + return ret; + } + + poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + + ret = tevent_common_wakeup_init(ev); + if (ret != 0) { + return ret; + } + + poll_ev->use_mt_mode = true; + + return 0; +} + +static void poll_event_wake_pollthread(struct poll_event_context *poll_ev) +{ + if (!poll_ev->use_mt_mode) { + return; + } + tevent_common_wakeup(poll_ev->ev); +} + +/* + destroy an fd_event +*/ +static int poll_event_fd_destructor(struct tevent_fd *fde) +{ + struct tevent_context *ev = fde->event_ctx; + struct poll_event_context *poll_ev; + uint64_t del_idx = fde->additional_flags; + + if (ev == NULL) { + goto done; + } + + poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + + if (del_idx == UINT64_MAX) { + goto done; + } + + poll_ev->fdes[del_idx] = NULL; + poll_ev->deleted = true; + poll_event_wake_pollthread(poll_ev); +done: + return tevent_common_fd_destructor(fde); +} + +static void poll_event_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct poll_event_context *poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + + tevent_common_schedule_immediate(im, ev, handler, private_data, + handler_name, location); + poll_event_wake_pollthread(poll_ev); +} + +/* + Private function called by "standard" backend fallback. + Note this only allows fallback to "poll" backend, not "poll-mt". +*/ +_PRIVATE_ bool tevent_poll_event_add_fd_internal(struct tevent_context *ev, + struct tevent_fd *fde) +{ + struct poll_event_context *poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + uint64_t fde_idx = UINT64_MAX; + size_t num_fdes; + + fde->additional_flags = UINT64_MAX; + talloc_set_destructor(fde, poll_event_fd_destructor); + + if (fde->flags == 0) { + /* + * Nothing more to do... + */ + return true; + } + + /* + * We need to add it to the end of the 'fdes' array. + */ + num_fdes = poll_ev->num_fdes + 1; + if (num_fdes > talloc_array_length(poll_ev->fdes)) { + struct tevent_fd **tmp_fdes = NULL; + size_t array_length; + + array_length = (num_fdes + 15) & ~15; /* round up to 16 */ + + tmp_fdes = talloc_realloc(poll_ev, + poll_ev->fdes, + struct tevent_fd *, + array_length); + if (tmp_fdes == NULL) { + return false; + } + poll_ev->fdes = tmp_fdes; + } + + fde_idx = poll_ev->num_fdes; + fde->additional_flags = fde_idx; + poll_ev->fdes[fde_idx] = fde; + poll_ev->num_fdes++; + + return true; +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *poll_event_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct poll_event_context *poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + struct tevent_fd *fde; + bool ok; + + if (fd < 0) { + return NULL; + } + + fde = tevent_common_add_fd(ev, + mem_ctx, + fd, + flags, + handler, + private_data, + handler_name, + location); + if (fde == NULL) { + return NULL; + } + + ok = tevent_poll_event_add_fd_internal(ev, fde); + if (!ok) { + TALLOC_FREE(fde); + return NULL; + } + poll_event_wake_pollthread(poll_ev); + + /* + * poll_event_loop_poll will take care of the rest in + * poll_event_setup_fresh + */ + return fde; +} + +/* + set the fd event flags +*/ +static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + struct tevent_context *ev = fde->event_ctx; + struct poll_event_context *poll_ev; + uint64_t idx = fde->additional_flags; + uint16_t pollflags; + + if (ev == NULL) { + return; + } + + if (fde->flags == flags) { + return; + } + + poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + + fde->flags = flags; + + if (idx == UINT64_MAX) { + /* + * We move it between the fresh and disabled lists. + */ + tevent_poll_event_add_fd_internal(ev, fde); + poll_event_wake_pollthread(poll_ev); + return; + } + + if (fde->flags == 0) { + /* + * We need to remove it from the array + * and move it to the disabled list. + */ + poll_ev->fdes[idx] = NULL; + poll_ev->deleted = true; + fde->additional_flags = UINT64_MAX; + poll_event_wake_pollthread(poll_ev); + return; + } + + if (idx >= poll_ev->num_fds) { + /* + * Not yet added to the + * poll_ev->fds array. + */ + poll_event_wake_pollthread(poll_ev); + return; + } + + pollflags = 0; + + if (flags & TEVENT_FD_READ) { + pollflags |= (POLLIN|POLLHUP); + } + if (flags & TEVENT_FD_WRITE) { + pollflags |= (POLLOUT); + } + poll_ev->fds[idx].events = pollflags; + + poll_event_wake_pollthread(poll_ev); +} + +static bool poll_event_sync_arrays(struct tevent_context *ev, + struct poll_event_context *poll_ev) +{ + size_t i; + size_t array_length; + + if (poll_ev->deleted) { + + for (i=0; i < poll_ev->num_fds;) { + struct tevent_fd *fde = poll_ev->fdes[i]; + size_t ci; + + if (fde != NULL) { + i++; + continue; + } + + /* + * This fde was talloc_free()'ed. Delete it + * from the arrays + */ + poll_ev->num_fds -= 1; + ci = poll_ev->num_fds; + if (ci > i) { + poll_ev->fds[i] = poll_ev->fds[ci]; + poll_ev->fdes[i] = poll_ev->fdes[ci]; + if (poll_ev->fdes[i] != NULL) { + poll_ev->fdes[i]->additional_flags = i; + } + } + poll_ev->fds[ci] = (struct pollfd) { .fd = -1 }; + poll_ev->fdes[ci] = NULL; + } + poll_ev->deleted = false; + } + + if (poll_ev->num_fds == poll_ev->num_fdes) { + return true; + } + + /* + * Recheck the size of both arrays and make sure + * poll_fd->fds array has at least the size of the + * in use poll_ev->fdes array. + */ + if (poll_ev->num_fdes > talloc_array_length(poll_ev->fds)) { + struct pollfd *tmp_fds = NULL; + + /* + * Make sure both allocated the same length. + */ + array_length = talloc_array_length(poll_ev->fdes); + + tmp_fds = talloc_realloc(poll_ev, + poll_ev->fds, + struct pollfd, + array_length); + if (tmp_fds == NULL) { + return false; + } + poll_ev->fds = tmp_fds; + } + + /* + * Now setup the new elements. + */ + for (i = poll_ev->num_fds; i < poll_ev->num_fdes; i++) { + struct tevent_fd *fde = poll_ev->fdes[i]; + struct pollfd *pfd = &poll_ev->fds[poll_ev->num_fds]; + + if (fde == NULL) { + continue; + } + + if (i > poll_ev->num_fds) { + poll_ev->fdes[poll_ev->num_fds] = fde; + fde->additional_flags = poll_ev->num_fds; + poll_ev->fdes[i] = NULL; + } + + pfd->fd = fde->fd; + pfd->events = 0; + pfd->revents = 0; + + if (fde->flags & TEVENT_FD_READ) { + pfd->events |= (POLLIN|POLLHUP); + } + if (fde->flags & TEVENT_FD_WRITE) { + pfd->events |= (POLLOUT); + } + + poll_ev->num_fds += 1; + } + /* Both are in sync again */ + poll_ev->num_fdes = poll_ev->num_fds; + + /* + * Check if we should shrink the arrays + * But keep at least 16 elements. + */ + + array_length = (poll_ev->num_fds + 15) & ~15; /* round up to 16 */ + array_length = MAX(array_length, 16); + if (array_length < talloc_array_length(poll_ev->fdes)) { + struct tevent_fd **tmp_fdes = NULL; + struct pollfd *tmp_fds = NULL; + + tmp_fdes = talloc_realloc(poll_ev, + poll_ev->fdes, + struct tevent_fd *, + array_length); + if (tmp_fdes == NULL) { + return false; + } + poll_ev->fdes = tmp_fdes; + + tmp_fds = talloc_realloc(poll_ev, + poll_ev->fds, + struct pollfd, + array_length); + if (tmp_fds == NULL) { + return false; + } + poll_ev->fds = tmp_fds; + } + + return true; +} + +/* + event loop handling using poll() +*/ +static int poll_event_loop_poll(struct tevent_context *ev, + struct timeval *tvalp) +{ + struct poll_event_context *poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + int pollrtn; + int timeout = -1; + int poll_errno; + struct tevent_fd *fde = NULL; + struct tevent_fd *next = NULL; + unsigned i; + bool ok; + + if (ev->signal_events && tevent_common_check_signal(ev)) { + return 0; + } + + if (tvalp != NULL) { + timeout = tvalp->tv_sec * 1000; + timeout += (tvalp->tv_usec + 999) / 1000; + } + + ok = poll_event_sync_arrays(ev, poll_ev); + if (!ok) { + return -1; + } + + tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT); + pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout); + poll_errno = errno; + tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT); + + if (pollrtn == -1 && poll_errno == EINTR && ev->signal_events) { + tevent_common_check_signal(ev); + return 0; + } + + if (pollrtn == 0 && tvalp) { + /* we don't care about a possible delay here */ + tevent_common_loop_timer_delay(ev); + return 0; + } + + if (pollrtn <= 0) { + /* + * No fd's ready + */ + return 0; + } + + /* at least one file descriptor is ready - check + which ones and call the handler, being careful to allow + the handler to remove itself when called */ + + for (fde = ev->fd_events; fde; fde = next) { + uint64_t idx = fde->additional_flags; + struct pollfd *pfd; + uint16_t flags = 0; + + next = fde->next; + + if (idx == UINT64_MAX) { + continue; + } + + pfd = &poll_ev->fds[idx]; + + if (pfd->revents & POLLNVAL) { + /* + * the socket is dead! this should never + * happen as the socket should have first been + * made readable and that should have removed + * the event, so this must be a bug. + * + * We ignore it here to match the epoll + * behavior. + */ + tevent_debug(ev, TEVENT_DEBUG_ERROR, + "POLLNVAL on fde[%p] fd[%d] - disabling\n", + fde, pfd->fd); + poll_ev->fdes[idx] = NULL; + poll_ev->deleted = true; + DLIST_REMOVE(ev->fd_events, fde); + fde->wrapper = NULL; + fde->event_ctx = NULL; + continue; + } + + if (pfd->revents & (POLLHUP|POLLERR)) { + /* If we only wait for TEVENT_FD_WRITE, we + should not tell the event handler about it, + and remove the writable flag, as we only + report errors when waiting for read events + to match the select behavior. */ + if (!(fde->flags & TEVENT_FD_READ)) { + TEVENT_FD_NOT_WRITEABLE(fde); + continue; + } + flags |= TEVENT_FD_READ; + } + if (pfd->revents & POLLIN) { + flags |= TEVENT_FD_READ; + } + if (pfd->revents & POLLOUT) { + flags |= TEVENT_FD_WRITE; + } + /* + * Note that fde->flags could be changed when using + * the poll_mt backend together with threads, + * that why we need to check pfd->revents and fde->flags + */ + flags &= fde->flags; + if (flags != 0) { + DLIST_DEMOTE(ev->fd_events, fde); + return tevent_common_invoke_fd_handler(fde, flags, NULL); + } + } + + for (i = 0; i < poll_ev->num_fds; i++) { + if (poll_ev->fds[i].revents & POLLNVAL) { + /* + * the socket is dead! this should never + * happen as the socket should have first been + * made readable and that should have removed + * the event, so this must be a bug or + * a race in the poll_mt usage. + */ + fde = poll_ev->fdes[i]; + tevent_debug(ev, TEVENT_DEBUG_WARNING, + "POLLNVAL on dangling fd[%d] fde[%p] - disabling\n", + poll_ev->fds[i].fd, fde); + poll_ev->fdes[i] = NULL; + poll_ev->deleted = true; + if (fde != NULL) { + DLIST_REMOVE(ev->fd_events, fde); + fde->wrapper = NULL; + fde->event_ctx = NULL; + } + } + } + + return 0; +} + +/* + do a single event loop using the events defined in ev +*/ +static int poll_event_loop_once(struct tevent_context *ev, + const char *location) +{ + struct timeval tval; + + if (ev->signal_events && + tevent_common_check_signal(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; + } + + tval = tevent_common_loop_timer_delay(ev); + if (tevent_timeval_is_zero(&tval)) { + return 0; + } + + return poll_event_loop_poll(ev, &tval); +} + +static const struct tevent_ops poll_event_ops = { + .context_init = poll_event_context_init, + .add_fd = poll_event_add_fd, + .set_fd_close_fn = tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, + .set_fd_flags = poll_event_set_fd_flags, + .add_timer = tevent_common_add_timer_v2, + .schedule_immediate = tevent_common_schedule_immediate, + .add_signal = tevent_common_add_signal, + .loop_once = poll_event_loop_once, + .loop_wait = tevent_common_loop_wait, +}; + +_PRIVATE_ bool tevent_poll_init(void) +{ + return tevent_register_backend("poll", &poll_event_ops); +} + +static const struct tevent_ops poll_event_mt_ops = { + .context_init = poll_event_context_init_mt, + .add_fd = poll_event_add_fd, + .set_fd_close_fn = tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, + .set_fd_flags = poll_event_set_fd_flags, + .add_timer = tevent_common_add_timer_v2, + .schedule_immediate = poll_event_schedule_immediate, + .add_signal = tevent_common_add_signal, + .loop_once = poll_event_loop_once, + .loop_wait = tevent_common_loop_wait, +}; + +_PRIVATE_ bool tevent_poll_mt_init(void) +{ + return tevent_register_backend("poll_mt", &poll_event_mt_ops); +} diff --git a/ldb-2.0.8/lib/tevent/tevent_port.c b/ldb-2.0.8/lib/tevent/tevent_port.c new file mode 100644 index 0000000..e91d442 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_port.c @@ -0,0 +1,803 @@ +/* + Unix SMB/CIFS implementation. + + Main select loop and event handling - Solaris port implementation. + Losely based on the Linux epoll backend. + + Copyright (C) Jeremy Allison 2013 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/select.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct port_associate_vals { + struct port_associate_vals *prev, *next; + struct port_event_context *port_ev; + int events; + struct tevent_fd *fde; + bool associated_event; +}; + +struct port_event_context { + /* a pointer back to the generic event_context */ + struct tevent_context *ev; + + /* This is the handle from port_create */ + int port_fd; + + pid_t pid; + + /* List of associations. */ + struct port_associate_vals *po_vals; +}; + +#define PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION (1<<0) +#define PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) +#define PORT_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) +#define PORT_ADDITIONAL_FD_FLAG_HAS_MPX (1<<3) + +/* + Map from TEVENT_FD_* to POLLIN/POLLOUT +*/ +static int port_map_flags(uint16_t flags) +{ + int ret = 0; + if (flags & TEVENT_FD_READ) ret |= (POLLIN | POLLERR | POLLHUP); + if (flags & TEVENT_FD_WRITE) ret |= (POLLOUT | POLLERR | POLLHUP); + return ret; +} + +/* + Free the port fd +*/ +static int port_ctx_destructor(struct port_event_context *port_ev) +{ + close(port_ev->port_fd); + port_ev->port_fd = -1; + return 0; +} + +/* + Init the port fd +*/ +static int port_init_ctx(struct port_event_context *port_ev) +{ + port_ev->port_fd = port_create(); + if (port_ev->port_fd == -1) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "Failed to create port handle.\n"); + return -1; + } + + if (!ev_set_close_on_exec(port_ev->port_fd)) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + port_ev->pid = getpid(); + talloc_set_destructor(port_ev, port_ctx_destructor); + + return 0; +} + +/* + Functions to manage the lower level cache of associated events on the port_fd. +*/ + +static int port_associate_vals_destructor(struct port_associate_vals *val) +{ + DLIST_REMOVE(val->port_ev->po_vals, val); + memset(val, '\0', sizeof(struct port_associate_vals)); + return 0; +} + +/* + * TODO: As the port_association is per-fde, it should be possible to store it + * directly in fde->additional_data, alongside any multiplexed-fde. That way the + * lookup on store and delete would be avoided, and associate_all_events() could + * walk the ev->fd_events list. + */ +static bool store_port_association(struct port_event_context *port_ev, + struct tevent_fd *fde, + int events) +{ + struct port_associate_vals *val; + + for (val = port_ev->po_vals; val; val = val->next) { + if (val->fde->fd == fde->fd) { + /* Association already attached to fd. */ + if (val->events != events) { + val->events = events; + val->associated_event = false; + } + return true; + } + } + + val = talloc_zero(port_ev, struct port_associate_vals); + if (val == NULL) { + return false; + } + + val->port_ev = port_ev; + val->fde = fde; + val->events = events; + val->associated_event = false; + + DLIST_ADD(port_ev->po_vals, val); + talloc_set_destructor(val, port_associate_vals_destructor); + + return true; +} + +static void delete_port_association(struct port_event_context *port_ev, + struct tevent_fd *fde) +{ + struct port_associate_vals *val; + + for (val = port_ev->po_vals; val; val = val->next) { + if (val->fde == fde) { + if (val->associated_event) { + (void)port_dissociate(port_ev->port_fd, + PORT_SOURCE_FD, + fde->fd); + } + talloc_free(val); + return; + } + } +} + +static int associate_all_events(struct port_event_context *port_ev) +{ + struct port_associate_vals *val; + + for (val = port_ev->po_vals; val; val = val->next) { + int ret; + if (val->associated_event) { + continue; + } + ret = port_associate(port_ev->port_fd, + PORT_SOURCE_FD, + (uintptr_t)val->fde->fd, + val->events, + (void *)val); + if (ret != 0) { + return -1; + } + val->associated_event = true; + } + return 0; +} + +static int port_update_event(struct port_event_context *port_ev, struct tevent_fd *fde); + +/* + Reopen the port handle when our pid changes. + */ +static int port_check_reopen(struct port_event_context *port_ev) +{ + struct tevent_fd *fde; + + if (port_ev->pid == getpid()) { + return 0; + } + + close(port_ev->port_fd); + port_ev->port_fd = port_create(); + if (port_ev->port_fd == -1) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "port_create() failed"); + return -1; + } + + if (!ev_set_close_on_exec(port_ev->port_fd)) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + port_ev->pid = getpid(); + for (fde=port_ev->ev->fd_events;fde;fde=fde->next) { + fde->additional_flags &= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + if (port_update_event(port_ev, fde) != 0) { + return -1; + } + } + return 0; +} + +/* + * Solaris ports cannot add the same file descriptor twice, once + * with read, once with write which is allowed by the tevent backend. + * Multiplex the existing fde, flag it as such so we can search for the + * correct fde on event triggering. + */ + +static void port_setup_multiplex_fd(struct port_event_context *port_ev, + struct tevent_fd *add_fde, + struct tevent_fd *mpx_fde) +{ + /* + * Make each fde->additional_data pointers point at each other + * so we can look them up from each other. They are now paired. + */ + mpx_fde->additional_data = add_fde; + add_fde->additional_data = mpx_fde; + + /* Now flag both fde's as being multiplexed. */ + mpx_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + add_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + + /* We need to keep the GOT_ERROR flag. */ + if (mpx_fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_GOT_ERROR) { + add_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_GOT_ERROR; + } +} + +/* + Add the port event to the given fd_event, + Or modify an existing event. +*/ + +static int port_add_event(struct port_event_context *port_ev, struct tevent_fd *fde) +{ + int flags = port_map_flags(fde->flags); + struct tevent_fd *mpx_fde = NULL; + + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is already a multiplexed fde, we need to include both + * flags in the modified event. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + flags |= port_map_flags(mpx_fde->flags); + } else { + /* + * Not (yet) a multiplexed event. See if there + * is already an event with the same fd. + */ + for (mpx_fde = port_ev->ev->fd_events; mpx_fde; mpx_fde = mpx_fde->next) { + if (mpx_fde->fd != fde->fd) { + continue; + } + if (mpx_fde == fde) { + continue; + } + /* Same fd. */ + break; + } + if (mpx_fde) { + if (mpx_fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* Logic error. Can't have more then 2 multiplexed fde's. */ + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "multiplex fde for fd[%d] is already multiplexed\n", + mpx_fde->fd); + return -1; + } + flags |= port_map_flags(mpx_fde->flags); + } + } + + if (!store_port_association(port_ev, + fde, + flags)) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "store_port_association failed for fd[%d]\n", + fde->fd); + return -1; + } + + /* Note we have an association now. */ + fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + /* Only if we want to read do we tell the event handler about errors. */ + if (fde->flags & TEVENT_FD_READ) { + fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + if (mpx_fde == NULL) { + return 0; + } + /* Set up the multiplex pointer. Does no harm if already multiplexed. */ + port_setup_multiplex_fd(port_ev, + fde, + mpx_fde); + + mpx_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + /* Only if we want to read do we tell the event handler about errors. */ + if (mpx_fde->flags & TEVENT_FD_READ) { + mpx_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + + return 0; +} + +/* + Delete the port association for the given fd_event. +*/ + +static void port_del_event(struct port_event_context *port_ev, struct tevent_fd *fde) +{ + struct tevent_fd *mpx_fde = NULL; + + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is a multiplexed fde, we need to remove + * both associations. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + mpx_fde->additional_data = NULL; + + fde->additional_data = NULL; + } + delete_port_association(port_ev, fde); +} + +/* + Add or remove the port event from the given fd_event +*/ +static int port_update_event(struct port_event_context *port_ev, struct tevent_fd *fde) +{ + bool got_error = (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_GOT_ERROR); + bool want_read = (fde->flags & TEVENT_FD_READ); + bool want_write = (fde->flags & TEVENT_FD_WRITE); + struct tevent_fd *mpx_fde = NULL; + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * work out what the multiplexed fde wants. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + if (mpx_fde->flags & TEVENT_FD_READ) { + want_read = true; + } + if (mpx_fde->flags & TEVENT_FD_WRITE) { + want_write = true; + } + } + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION) { + /* There's already an association. */ + if (want_read || (want_write && !got_error)) { + return port_add_event(port_ev, fde); + } + /* + * If we want to match the select behavior, we need to remove the port event + * when the caller isn't interested in events. + */ + port_del_event(port_ev, fde); + return 0; + } + + /* There's no port event attached to the fde. */ + if (want_read || (want_write && !got_error)) { + return port_add_event(port_ev, fde); + } + return 0; +} + +/* + Cope with port_get returning EPOLLHP|EPOLLERR on an association. + Return true if there's nothing else to do, false if this event + needs further handling. +*/ + +static bool port_handle_hup_or_err(struct port_event_context *port_ev, + struct tevent_fd *fde) +{ + if (fde == NULL) { + return true; + } + + fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_GOT_ERROR; + /* + * If we only wait for TEVENT_FD_WRITE, we should not tell the + * event handler about it, and remove the port association, + * as we only report error when waiting for read events, + * to match the select() behavior. + */ + if (!(fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR)) { + /* + * Do the same as the poll backend and + * remove the writable flag. + */ + fde->flags &= ~TEVENT_FD_WRITE; + return true; + } + /* This has TEVENT_FD_READ set, we're not finished. */ + return false; +} + +/* + Event loop handling using Solaris ports. +*/ +static int port_event_loop(struct port_event_context *port_ev, struct timeval *tvalp) +{ + int ret; +#define MAXEVENTS 1 + port_event_t events[MAXEVENTS]; + uint_t nget = 1; + uint_t max_events = MAXEVENTS; + uint_t i; + int port_errno; + struct timespec ts; + struct tevent_context *ev = port_ev->ev; + + if (tvalp) { + ts.tv_sec = tvalp->tv_sec; + ts.tv_nsec = tvalp->tv_usec * 1000; + } + + if (port_ev->ev->signal_events && + tevent_common_check_signal(ev)) { + return 0; + } + + /* + * Solaris triggers sending the event to the port + * at the time the port association is done. Postpone + * associating fd's until just before we get the events, + * otherwise we can deadlock. + */ + + if (associate_all_events(port_ev) != 0) { + return -1; + } + + tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_WAIT); + ret = port_getn(port_ev->port_fd, events, max_events, &nget, &ts); + port_errno = errno; + tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_WAIT); + + if (ret == -1 && port_errno == EINTR) { + if (ev->signal_events) { + tevent_common_check_signal(ev); + } + /* + * If no signal handlers we got an unsolicited + * signal wakeup. This can happen with epoll + * too. Just return and ignore. + */ + return 0; + } + + if (ret == -1 && port_errno == ETIME) { + /* + * If errno is set to ETIME it is possible that we still got an event. + * In that case we need to go through the processing loop so that we + * reassociate the received event with the port or the association will + * be lost so check the value of nget is 0 before returning. + */ + if (nget == 0) { + /* we don't care about a possible delay here */ + tevent_common_loop_timer_delay(ev); + return 0; + } + /* + * Set the return value to 0 since we do not actually have an error and we + * do have events that need to be processed. This keeps us from getting + * caught in the generic error test. + */ + ret = 0; + } + + if (ret == -1) { + tevent_debug(ev, TEVENT_DEBUG_ERROR, + "port_get failed (%s)\n", + strerror(errno)); + return -1; + } + + for (i = 0; i < nget; i++) { + struct tevent_fd *mpx_fde = NULL; + struct tevent_fd *fde = NULL; + uint16_t flags = 0; + struct port_associate_vals *val = talloc_get_type(events[i].portev_user, + struct port_associate_vals); + if (val == NULL) { + tevent_debug(ev, TEVENT_DEBUG_ERROR, + "port_getn() gave bad data"); + return -1; + } + + /* Mark this event as needing to be re-associated. */ + val->associated_event = false; + + fde = val->fde; + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * Save off the multiplexed event in case we need + * to use it to call the handler function. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + } + + if (events[i].portev_events & (POLLHUP|POLLERR)) { + bool handled_fde = port_handle_hup_or_err(port_ev, fde); + bool handled_mpx = port_handle_hup_or_err(port_ev, mpx_fde); + + if (handled_fde && handled_mpx) { + return port_update_event(port_ev, fde); + } + + if (!handled_mpx) { + /* + * If the mpx event was the one that needs + * further handling, it's the TEVENT_FD_READ + * event so switch over and call that handler. + */ + fde = mpx_fde; + mpx_fde = NULL; + } + flags |= TEVENT_FD_READ; + } + + if (events[i].portev_events & POLLIN) { + flags |= TEVENT_FD_READ; + } + if (events[i].portev_events & POLLOUT) { + flags |= TEVENT_FD_WRITE; + } + + if (flags & TEVENT_FD_WRITE) { + if (fde->flags & TEVENT_FD_WRITE) { + mpx_fde = NULL; + } + if (mpx_fde && (mpx_fde->flags & TEVENT_FD_WRITE)) { + fde = mpx_fde; + mpx_fde = NULL; + } + + if (mpx_fde) { + /* Ensure we got the right fde. */ + if ((flags & fde->flags) == 0) { + fde = mpx_fde; + mpx_fde = NULL; + } + } + } + + /* + * Make sure we only pass the flags + * the handler is expecting. + */ + flags &= fde->flags; + if (flags) { + return tevent_common_invoke_fd_handler(fde, flags, NULL); + } + } + + return 0; +} + + +/* + create a port_event_context structure. +*/ +static int port_event_context_init(struct tevent_context *ev) +{ + int ret; + struct port_event_context *port_ev; + + /* + * We might be called during tevent_re_initialise() + * which means we need to free our old additional_data. + */ + TALLOC_FREE(ev->additional_data); + + port_ev = talloc_zero(ev, struct port_event_context); + if (!port_ev) { + return -1; + } + port_ev->ev = ev; + port_ev->port_fd = -1; + port_ev->pid = (pid_t)-1; + + ret = port_init_ctx(port_ev); + if (ret != 0) { + talloc_free(port_ev); + return ret; + } + + ev->additional_data = port_ev; + return 0; +} + +/* + destroy an fd_event +*/ +static int port_event_fd_destructor(struct tevent_fd *fde) +{ + struct tevent_context *ev = fde->event_ctx; + struct port_event_context *port_ev = NULL; + struct tevent_fd *mpx_fde = NULL; + int flags = (int)fde->flags; + + if (ev == NULL) { + return tevent_common_fd_destructor(fde); + } + + port_ev = talloc_get_type_abort(ev->additional_data, + struct port_event_context); + + DLIST_REMOVE(ev->fd_events, fde); + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + + fde->additional_data = NULL; + mpx_fde->additional_data = NULL; + + fde->additional_flags &= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + } + + (void)port_check_reopen(port_ev); + + if (mpx_fde != NULL) { + (void)port_update_event(port_ev, mpx_fde); + } + + fde->flags = 0; + (void)port_update_event(port_ev, fde); + fde->flags = flags; + + return tevent_common_fd_destructor(fde); +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *port_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct port_event_context *port_ev = + talloc_get_type_abort(ev->additional_data, + struct port_event_context); + struct tevent_fd *fde; + + fde = tevent_common_add_fd(ev, mem_ctx, fd, flags, + handler, private_data, + handler_name, location); + if (!fde) { + return NULL; + } + + talloc_set_destructor(fde, port_event_fd_destructor); + + if (port_check_reopen(port_ev) != 0) { + TALLOC_FREE(fde); + return NULL; + } + + if (port_update_event(port_ev, fde) != 0) { + TALLOC_FREE(fde); + return NULL; + } + + return fde; +} + +/* + set the fd event flags +*/ +static void port_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + struct tevent_context *ev; + struct port_event_context *port_ev; + + if (fde->flags == flags) { + return; + } + + ev = fde->event_ctx; + port_ev = talloc_get_type_abort(ev->additional_data, + struct port_event_context); + + fde->flags = flags; + + (void)port_check_reopen(port_ev); + (void)port_update_event(port_ev, fde); +} + +/* + do a single event loop using the events defined in ev +*/ +static int port_event_loop_once(struct tevent_context *ev, const char *location) +{ + struct port_event_context *port_ev = talloc_get_type(ev->additional_data, + struct port_event_context); + struct timeval tval; + + if (ev->signal_events && + tevent_common_check_signal(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; + } + + tval = tevent_common_loop_timer_delay(ev); + if (tevent_timeval_is_zero(&tval)) { + return 0; + } + + if (port_check_reopen(port_ev) != 0) { + errno = EINVAL; + return -1; + } + return port_event_loop(port_ev, &tval); +} + +static const struct tevent_ops port_event_ops = { + .context_init = port_event_context_init, + .add_fd = port_event_add_fd, + .set_fd_close_fn = tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, + .set_fd_flags = port_event_set_fd_flags, + .add_timer = tevent_common_add_timer_v2, + .schedule_immediate = tevent_common_schedule_immediate, + .add_signal = tevent_common_add_signal, + .loop_once = port_event_loop_once, + .loop_wait = tevent_common_loop_wait, +}; + +_PRIVATE_ bool tevent_port_init(void) +{ + if (!tevent_register_backend("port", &port_event_ops)) { + return false; + } + tevent_set_default_backend("port"); + return true; +} diff --git a/ldb-2.0.8/lib/tevent/tevent_queue.c b/ldb-2.0.8/lib/tevent/tevent_queue.c new file mode 100644 index 0000000..9c3973b --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_queue.c @@ -0,0 +1,370 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct tevent_queue_entry { + struct tevent_queue_entry *prev, *next; + struct tevent_queue *queue; + + bool triggered; + + struct tevent_req *req; + struct tevent_context *ev; + + tevent_queue_trigger_fn_t trigger; + void *private_data; +}; + +struct tevent_queue { + const char *name; + const char *location; + + bool running; + struct tevent_immediate *immediate; + + size_t length; + struct tevent_queue_entry *list; +}; + +static void tevent_queue_immediate_trigger(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data); + +static int tevent_queue_entry_destructor(struct tevent_queue_entry *e) +{ + struct tevent_queue *q = e->queue; + + if (!q) { + return 0; + } + + DLIST_REMOVE(q->list, e); + q->length--; + + if (!q->running) { + return 0; + } + + if (!q->list) { + return 0; + } + + if (q->list->triggered) { + return 0; + } + + tevent_schedule_immediate(q->immediate, + q->list->ev, + tevent_queue_immediate_trigger, + q); + + return 0; +} + +static int tevent_queue_destructor(struct tevent_queue *q) +{ + q->running = false; + + while (q->list) { + struct tevent_queue_entry *e = q->list; + talloc_free(e); + } + + return 0; +} + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location) +{ + struct tevent_queue *queue; + + queue = talloc_zero(mem_ctx, struct tevent_queue); + if (!queue) { + return NULL; + } + + queue->name = talloc_strdup(queue, name); + if (!queue->name) { + talloc_free(queue); + return NULL; + } + queue->immediate = tevent_create_immediate(queue); + if (!queue->immediate) { + talloc_free(queue); + return NULL; + } + + queue->location = location; + + /* queue is running by default */ + queue->running = true; + + talloc_set_destructor(queue, tevent_queue_destructor); + return queue; +} + +static void tevent_queue_immediate_trigger(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + struct tevent_queue *q = + talloc_get_type_abort(private_data, + struct tevent_queue); + + if (!q->running) { + return; + } + + if (!q->list) { + return; + } + + q->list->triggered = true; + q->list->trigger(q->list->req, q->list->private_data); +} + +static struct tevent_queue_entry *tevent_queue_add_internal( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data, + bool allow_direct) +{ + struct tevent_queue_entry *e; + + e = talloc_zero(req, struct tevent_queue_entry); + if (e == NULL) { + return NULL; + } + + e->queue = queue; + e->req = req; + e->ev = ev; + e->trigger = trigger; + e->private_data = private_data; + + /* + * if there is no trigger, it is just a blocker + */ + if (trigger == NULL) { + e->triggered = true; + } + + if (queue->length > 0) { + /* + * if there are already entries in the + * queue do not optimize. + */ + allow_direct = false; + } + + if (req->async.fn != NULL) { + /* + * 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. + */ + allow_direct = false; + } + + DLIST_ADD_END(queue->list, e); + queue->length++; + talloc_set_destructor(e, tevent_queue_entry_destructor); + + if (!queue->running) { + return e; + } + + if (queue->list->triggered) { + return e; + } + + /* + * If allowed we directly call the trigger + * avoiding possible delays caused by + * an immediate event. + */ + if (allow_direct) { + queue->list->triggered = true; + queue->list->trigger(queue->list->req, + queue->list->private_data); + return e; + } + + tevent_schedule_immediate(queue->immediate, + queue->list->ev, + tevent_queue_immediate_trigger, + queue); + + return e; +} + +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + struct tevent_queue_entry *e; + + e = tevent_queue_add_internal(queue, ev, req, + trigger, private_data, false); + if (e == NULL) { + return false; + } + + return true; +} + +struct tevent_queue_entry *tevent_queue_add_entry( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + return tevent_queue_add_internal(queue, ev, req, + trigger, private_data, false); +} + +struct tevent_queue_entry *tevent_queue_add_optimize_empty( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + return tevent_queue_add_internal(queue, ev, req, + trigger, private_data, true); +} + +void tevent_queue_entry_untrigger(struct tevent_queue_entry *entry) +{ + if (entry->queue->running) { + abort(); + } + + if (entry->queue->list != entry) { + abort(); + } + + entry->triggered = false; +} + +void tevent_queue_start(struct tevent_queue *queue) +{ + if (queue->running) { + /* already started */ + return; + } + + queue->running = true; + + if (!queue->list) { + return; + } + + if (queue->list->triggered) { + return; + } + + tevent_schedule_immediate(queue->immediate, + queue->list->ev, + tevent_queue_immediate_trigger, + queue); +} + +void tevent_queue_stop(struct tevent_queue *queue) +{ + queue->running = false; +} + +size_t tevent_queue_length(struct tevent_queue *queue) +{ + return queue->length; +} + +bool tevent_queue_running(struct tevent_queue *queue) +{ + return queue->running; +} + +struct tevent_queue_wait_state { + uint8_t dummy; +}; + +static void tevent_queue_wait_trigger(struct tevent_req *req, + void *private_data); + +struct tevent_req *tevent_queue_wait_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue) +{ + struct tevent_req *req; + struct tevent_queue_wait_state *state; + bool ok; + + req = tevent_req_create(mem_ctx, &state, + struct tevent_queue_wait_state); + if (req == NULL) { + return NULL; + } + + ok = tevent_queue_add(queue, ev, req, + tevent_queue_wait_trigger, + NULL); + if (!ok) { + tevent_req_oom(req); + return tevent_req_post(req, ev); + } + + return req; +} + +static void tevent_queue_wait_trigger(struct tevent_req *req, + void *private_data) +{ + tevent_req_done(req); +} + +bool tevent_queue_wait_recv(struct tevent_req *req) +{ + enum tevent_req_state state; + uint64_t err; + + if (tevent_req_is_error(req, &state, &err)) { + tevent_req_received(req); + return false; + } + + tevent_req_received(req); + return true; +} diff --git a/ldb-2.0.8/lib/tevent/tevent_req.c b/ldb-2.0.8/lib/tevent/tevent_req.c new file mode 100644 index 0000000..7821d9a --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_req.c @@ -0,0 +1,570 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) +{ + return talloc_asprintf(mem_ctx, + "tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] " + " state[%s (%p)] timer[%p] finish[%s]", + req, req->internal.create_location, + req->internal.state, + (unsigned long long)req->internal.error, + (unsigned long long)req->internal.error, + req->internal.private_type, + req->data, + req->internal.timer, + req->internal.finish_location + ); +} + +char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) +{ + if (req == NULL) { + return talloc_strdup(mem_ctx, "tevent_req[NULL]"); + } + + if (!req->private_print) { + return tevent_req_default_print(req, mem_ctx); + } + + return req->private_print(req, mem_ctx); +} + +static int tevent_req_destructor(struct tevent_req *req); + +struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, + void *pdata, + size_t data_size, + const char *type, + const char *location) +{ + struct tevent_req *req; + struct tevent_req *parent; + 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, + sizeof(struct tevent_immediate) + data_size); + if (req == NULL) { + return NULL; + } + + *req = (struct tevent_req) { + .internal = { + .private_type = type, + .create_location = location, + .state = TEVENT_REQ_IN_PROGRESS, + .trigger = tevent_create_immediate(req), + }, + }; + + data = talloc_zero_size(req, data_size); + + /* + * 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; + + talloc_set_destructor(req, tevent_req_destructor); + + parent = talloc_get_type(talloc_parent(mem_ctx), struct tevent_req); + if ((parent != NULL) && (parent->internal.profile != NULL)) { + bool ok = tevent_req_set_profile(req); + + if (!ok) { + TALLOC_FREE(req); + return NULL; + } + req->internal.profile->parent = parent->internal.profile; + DLIST_ADD_END(parent->internal.profile->subprofiles, + req->internal.profile); + } + + *ppdata = data; + return req; +} + +static int tevent_req_destructor(struct tevent_req *req) +{ + tevent_req_received(req); + return 0; +} + +void _tevent_req_notify_callback(struct tevent_req *req, const char *location) +{ + req->internal.finish_location = location; + if (req->internal.defer_callback_ev) { + (void)tevent_req_post(req, req->internal.defer_callback_ev); + req->internal.defer_callback_ev = NULL; + return; + } + if (req->async.fn != NULL) { + req->async.fn(req); + } +} + +static void tevent_req_cleanup(struct tevent_req *req) +{ + if (req->private_cleanup.fn == NULL) { + return; + } + + if (req->private_cleanup.state >= req->internal.state) { + /* + * Don't call the cleanup_function multiple times for the same + * state recursively + */ + return; + } + + req->private_cleanup.state = req->internal.state; + req->private_cleanup.fn(req, req->internal.state); +} + +static void tevent_req_finish(struct tevent_req *req, + enum tevent_req_state state, + const char *location) +{ + struct tevent_req_profile *p; + /* + * make sure we do not timeout after + * the request was already finished + */ + TALLOC_FREE(req->internal.timer); + + req->internal.state = state; + req->internal.finish_location = location; + + tevent_req_cleanup(req); + + p = req->internal.profile; + + if (p != NULL) { + p->stop_location = location; + p->stop_time = tevent_timeval_current(); + p->state = state; + p->user_error = req->internal.error; + + if (p->parent != NULL) { + talloc_steal(p->parent, p); + req->internal.profile = NULL; + } + } + + _tevent_req_notify_callback(req, location); +} + +void _tevent_req_done(struct tevent_req *req, + const char *location) +{ + tevent_req_finish(req, TEVENT_REQ_DONE, location); +} + +bool _tevent_req_error(struct tevent_req *req, + uint64_t error, + const char *location) +{ + if (error == 0) { + return false; + } + + req->internal.error = error; + tevent_req_finish(req, TEVENT_REQ_USER_ERROR, location); + return true; +} + +void _tevent_req_oom(struct tevent_req *req, const char *location) +{ + tevent_req_finish(req, TEVENT_REQ_NO_MEMORY, location); +} + +bool _tevent_req_nomem(const void *p, + struct tevent_req *req, + const char *location) +{ + if (p != NULL) { + return false; + } + _tevent_req_oom(req, location); + return true; +} + +/** + * @internal + * + * @brief Immediate event callback. + * + * @param[in] ev The event context to use. + * + * @param[in] im The immediate event. + * + * @param[in] priv The async request to be finished. + */ +static void tevent_req_trigger(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + struct tevent_req *req = + talloc_get_type_abort(private_data, + struct tevent_req); + + tevent_req_finish(req, req->internal.state, + req->internal.finish_location); +} + +struct tevent_req *tevent_req_post(struct tevent_req *req, + struct tevent_context *ev) +{ + tevent_schedule_immediate(req->internal.trigger, + ev, tevent_req_trigger, req); + return req; +} + +void tevent_req_defer_callback(struct tevent_req *req, + struct tevent_context *ev) +{ + req->internal.defer_callback_ev = ev; +} + +bool tevent_req_is_in_progress(struct tevent_req *req) +{ + if (req->internal.state == TEVENT_REQ_IN_PROGRESS) { + return true; + } + + return false; +} + +void tevent_req_received(struct tevent_req *req) +{ + talloc_set_destructor(req, NULL); + + req->private_print = NULL; + req->private_cancel = NULL; + + TALLOC_FREE(req->internal.trigger); + TALLOC_FREE(req->internal.timer); + + req->internal.state = TEVENT_REQ_RECEIVED; + + tevent_req_cleanup(req); + + TALLOC_FREE(req->data); +} + +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev) +{ + while (tevent_req_is_in_progress(req)) { + int ret; + + ret = tevent_loop_once(ev); + if (ret != 0) { + return false; + } + } + + return true; +} + +bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, + uint64_t *error) +{ + if (req->internal.state == TEVENT_REQ_DONE) { + return false; + } + if (req->internal.state == TEVENT_REQ_USER_ERROR) { + *error = req->internal.error; + } + *state = req->internal.state; + return true; +} + +static void tevent_req_timedout(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval now, + void *private_data) +{ + struct tevent_req *req = + talloc_get_type_abort(private_data, + struct tevent_req); + + TALLOC_FREE(req->internal.timer); + + tevent_req_finish(req, TEVENT_REQ_TIMED_OUT, __FUNCTION__); +} + +bool tevent_req_set_endtime(struct tevent_req *req, + struct tevent_context *ev, + struct timeval endtime) +{ + TALLOC_FREE(req->internal.timer); + + req->internal.timer = tevent_add_timer(ev, req, endtime, + tevent_req_timedout, + req); + if (tevent_req_nomem(req->internal.timer, req)) { + return false; + } + + 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; + req->async.private_data = pvt; +} + +void *_tevent_req_callback_data(struct tevent_req *req) +{ + return req->async.private_data; +} + +void *_tevent_req_data(struct tevent_req *req) +{ + return req->data; +} + +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn) +{ + req->private_print = fn; +} + +void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn) +{ + req->private_cancel = fn; +} + +bool _tevent_req_cancel(struct tevent_req *req, const char *location) +{ + if (req->private_cancel == NULL) { + return false; + } + + return req->private_cancel(req); +} + +void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn) +{ + req->private_cleanup.state = req->internal.state; + req->private_cleanup.fn = fn; +} + +static int tevent_req_profile_destructor(struct tevent_req_profile *p); + +bool tevent_req_set_profile(struct tevent_req *req) +{ + struct tevent_req_profile *p; + + if (req->internal.profile != NULL) { + tevent_req_error(req, EINVAL); + return false; + } + + p = tevent_req_profile_create(req); + + if (tevent_req_nomem(p, req)) { + return false; + } + + p->req_name = talloc_get_name(req->data); + p->start_location = req->internal.create_location; + p->start_time = tevent_timeval_current(); + + req->internal.profile = p; + + return true; +} + +static int tevent_req_profile_destructor(struct tevent_req_profile *p) +{ + if (p->parent != NULL) { + DLIST_REMOVE(p->parent->subprofiles, p); + p->parent = NULL; + } + + while (p->subprofiles != NULL) { + p->subprofiles->parent = NULL; + DLIST_REMOVE(p->subprofiles, p->subprofiles); + } + + return 0; +} + +struct tevent_req_profile *tevent_req_move_profile(struct tevent_req *req, + TALLOC_CTX *mem_ctx) +{ + return talloc_move(mem_ctx, &req->internal.profile); +} + +const struct tevent_req_profile *tevent_req_get_profile( + struct tevent_req *req) +{ + return req->internal.profile; +} + +void tevent_req_profile_get_name(const struct tevent_req_profile *profile, + const char **req_name) +{ + if (req_name != NULL) { + *req_name = profile->req_name; + } +} + +void tevent_req_profile_get_start(const struct tevent_req_profile *profile, + const char **start_location, + struct timeval *start_time) +{ + if (start_location != NULL) { + *start_location = profile->start_location; + } + if (start_time != NULL) { + *start_time = profile->start_time; + } +} + +void tevent_req_profile_get_stop(const struct tevent_req_profile *profile, + const char **stop_location, + struct timeval *stop_time) +{ + if (stop_location != NULL) { + *stop_location = profile->stop_location; + } + if (stop_time != NULL) { + *stop_time = profile->stop_time; + } +} + +void tevent_req_profile_get_status(const struct tevent_req_profile *profile, + pid_t *pid, + enum tevent_req_state *state, + uint64_t *user_error) +{ + if (pid != NULL) { + *pid = profile->pid; + } + if (state != NULL) { + *state = profile->state; + } + if (user_error != NULL) { + *user_error = profile->user_error; + } +} + +const struct tevent_req_profile *tevent_req_profile_get_subprofiles( + const struct tevent_req_profile *profile) +{ + return profile->subprofiles; +} + +const struct tevent_req_profile *tevent_req_profile_next( + const struct tevent_req_profile *profile) +{ + return profile->next; +} + +struct tevent_req_profile *tevent_req_profile_create(TALLOC_CTX *mem_ctx) +{ + struct tevent_req_profile *result; + + result = talloc_zero(mem_ctx, struct tevent_req_profile); + if (result == NULL) { + return NULL; + } + talloc_set_destructor(result, tevent_req_profile_destructor); + + return result; +} + +bool tevent_req_profile_set_name(struct tevent_req_profile *profile, + const char *req_name) +{ + profile->req_name = talloc_strdup(profile, req_name); + return (profile->req_name != NULL); +} + +bool tevent_req_profile_set_start(struct tevent_req_profile *profile, + const char *start_location, + struct timeval start_time) +{ + profile->start_time = start_time; + + profile->start_location = talloc_strdup(profile, start_location); + return (profile->start_location != NULL); +} + +bool tevent_req_profile_set_stop(struct tevent_req_profile *profile, + const char *stop_location, + struct timeval stop_time) +{ + profile->stop_time = stop_time; + + profile->stop_location = talloc_strdup(profile, stop_location); + return (profile->stop_location != NULL); +} + +void tevent_req_profile_set_status(struct tevent_req_profile *profile, + pid_t pid, + enum tevent_req_state state, + uint64_t user_error) +{ + profile->pid = pid; + profile->state = state; + profile->user_error = user_error; +} + +void tevent_req_profile_append_sub(struct tevent_req_profile *parent_profile, + struct tevent_req_profile **sub_profile) +{ + struct tevent_req_profile *sub; + + sub = talloc_move(parent_profile, sub_profile); + + sub->parent = parent_profile; + DLIST_ADD_END(parent_profile->subprofiles, sub); +} diff --git a/ldb-2.0.8/lib/tevent/tevent_signal.c b/ldb-2.0.8/lib/tevent/tevent_signal.c new file mode 100644 index 0000000..7ebb13d --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_signal.c @@ -0,0 +1,518 @@ +/* + Unix SMB/CIFS implementation. + + common events code for signal events + + Copyright (C) Andrew Tridgell 2007 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/wait.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +/* maximum number of SA_SIGINFO signals to hold in the queue. + NB. This *MUST* be a power of 2, in order for the ring buffer + wrap to work correctly. Thanks to Petr Vandrovec + for this. */ + +#define TEVENT_SA_INFO_QUEUE_COUNT 256 + +size_t tevent_num_signals(void) +{ + return TEVENT_NUM_SIGNALS; +} + +size_t tevent_sa_info_queue_count(void) +{ + return TEVENT_SA_INFO_QUEUE_COUNT; +} + +struct tevent_sigcounter { + uint32_t count; + uint32_t seen; +}; + +#if defined(HAVE___SYNC_FETCH_AND_ADD) +#define TEVENT_SIG_INCREMENT(s) __sync_fetch_and_add(&((s).count), 1) +#elif defined(HAVE_ATOMIC_ADD_32) +#define TEVENT_SIG_INCREMENT(s) atomic_add_32(&((s).count), 1) +#else +#define TEVENT_SIG_INCREMENT(s) (s).count++ +#endif +#define TEVENT_SIG_SEEN(s, n) (s).seen += (n) +#define TEVENT_SIG_PENDING(s) ((s).seen != (s).count) + +struct tevent_common_signal_list { + struct tevent_common_signal_list *prev, *next; + struct tevent_signal *se; +}; + +/* + the poor design of signals means that this table must be static global +*/ +static struct tevent_sig_state { + struct tevent_common_signal_list *sig_handlers[TEVENT_NUM_SIGNALS+1]; + struct sigaction *oldact[TEVENT_NUM_SIGNALS+1]; + struct tevent_sigcounter signal_count[TEVENT_NUM_SIGNALS+1]; + struct tevent_sigcounter got_signal; +#ifdef SA_SIGINFO + /* with SA_SIGINFO we get quite a lot of info per signal */ + siginfo_t *sig_info[TEVENT_NUM_SIGNALS+1]; + struct tevent_sigcounter sig_blocked[TEVENT_NUM_SIGNALS+1]; +#endif +} *sig_state; + +/* + return number of sigcounter events not processed yet +*/ +static uint32_t tevent_sig_count(struct tevent_sigcounter s) +{ + return s.count - s.seen; +} + +/* + signal handler - redirects to registered signals +*/ +static void tevent_common_signal_handler(int signum) +{ + struct tevent_common_signal_list *sl; + struct tevent_context *ev = NULL; + int saved_errno = errno; + + TEVENT_SIG_INCREMENT(sig_state->signal_count[signum]); + TEVENT_SIG_INCREMENT(sig_state->got_signal); + + /* Write to each unique event context. */ + 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; + tevent_common_wakeup(ev); + } + } + + errno = saved_errno; +} + +#ifdef SA_SIGINFO +/* + signal handler with SA_SIGINFO - redirects to registered signals +*/ +static void tevent_common_signal_handler_info(int signum, siginfo_t *info, + void *uctx) +{ + uint32_t count = tevent_sig_count(sig_state->signal_count[signum]); + /* sig_state->signal_count[signum].seen % TEVENT_SA_INFO_QUEUE_COUNT + * is the base of the unprocessed signals in the ringbuffer. */ + uint32_t ofs = (sig_state->signal_count[signum].seen + count) % + TEVENT_SA_INFO_QUEUE_COUNT; + sig_state->sig_info[signum][ofs] = *info; + + tevent_common_signal_handler(signum); + + /* handle SA_SIGINFO */ + if (count+1 == TEVENT_SA_INFO_QUEUE_COUNT) { + /* we've filled the info array - block this signal until + these ones are delivered */ +#ifdef HAVE_UCONTEXT_T + /* + * This is the only way for this to work. + * By default signum is blocked inside this + * signal handler using a temporary mask, + * but what we really need to do now is + * block it in the callers mask, so it + * stays blocked when the temporary signal + * handler mask is replaced when we return + * from here. The callers mask can be found + * in the ucontext_t passed in as the + * void *uctx argument. + */ + ucontext_t *ucp = (ucontext_t *)uctx; + sigaddset(&ucp->uc_sigmask, signum); +#else + /* + * WARNING !!! WARNING !!!! + * + * This code doesn't work. + * By default signum is blocked inside this + * signal handler, but calling sigprocmask + * modifies the temporary signal mask being + * used *inside* this handler, which will be + * replaced by the callers signal mask once + * we return from here. See Samba + * bug #9550 for details. + */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, signum); + sigprocmask(SIG_BLOCK, &set, NULL); +#endif + TEVENT_SIG_INCREMENT(sig_state->sig_blocked[signum]); + } +} +#endif + +static int tevent_common_signal_list_destructor(struct tevent_common_signal_list *sl) +{ + if (sig_state->sig_handlers[sl->se->signum]) { + DLIST_REMOVE(sig_state->sig_handlers[sl->se->signum], sl); + } + return 0; +} + +/* + destroy a signal event +*/ +static int tevent_signal_destructor(struct tevent_signal *se) +{ + if (se->destroyed) { + tevent_common_check_double_free(se, "tevent_signal double free"); + goto done; + } + se->destroyed = true; + + TALLOC_FREE(se->additional_data); + + if (se->event_ctx != NULL) { + DLIST_REMOVE(se->event_ctx->signal_events, se); + } + + if (sig_state->sig_handlers[se->signum] == NULL) { + /* 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]); + } +#ifdef SA_SIGINFO + if (se->sa_flags & SA_SIGINFO) { + if (sig_state->sig_info[se->signum]) { + TALLOC_FREE(sig_state->sig_info[se->signum]); + } + } +#endif + } + + se->event_ctx = NULL; +done: + if (se->busy) { + return -1; + } + se->wrapper = NULL; + + return 0; +} + +/* + add a signal event + return NULL on failure (memory allocation error) +*/ +struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + 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; + return NULL; + } + + /* the sig_state needs to be on a global context as it can last across + multiple event contexts */ + if (sig_state == NULL) { + sig_state = talloc_zero(NULL, struct tevent_sig_state); + if (sig_state == NULL) { + return NULL; + } + } + + se = talloc_zero(mem_ctx?mem_ctx:ev, struct tevent_signal); + if (se == NULL) return NULL; + + sl = talloc_zero(se, struct tevent_common_signal_list); + if (!sl) { + talloc_free(se); + return NULL; + } + sl->se = se; + + *se = (struct tevent_signal) { + .event_ctx = ev, + .signum = signum, + .sa_flags = sa_flags, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .location = location, + .additional_data= sl, + }; + + /* Ensure, no matter the destruction order, that we always have a handle on the global sig_state */ + if (!talloc_reference(se, sig_state)) { + talloc_free(se); + return NULL; + } + + /* only install a signal handler if not already installed */ + if (sig_state->sig_handlers[signum] == NULL) { + struct sigaction act; + ZERO_STRUCT(act); + act.sa_handler = tevent_common_signal_handler; + act.sa_flags = sa_flags; +#ifdef SA_SIGINFO + if (sa_flags & SA_SIGINFO) { + act.sa_handler = NULL; + act.sa_sigaction = tevent_common_signal_handler_info; + if (sig_state->sig_info[signum] == NULL) { + sig_state->sig_info[signum] = + talloc_zero_array(sig_state, siginfo_t, + TEVENT_SA_INFO_QUEUE_COUNT); + if (sig_state->sig_info[signum] == NULL) { + talloc_free(se); + return NULL; + } + } + } +#endif + sig_state->oldact[signum] = talloc_zero(sig_state, struct sigaction); + if (sig_state->oldact[signum] == NULL) { + talloc_free(se); + 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; + } + } + + DLIST_ADD(se->event_ctx->signal_events, se); + + /* Make sure the signal doesn't come in while we're mangling list. */ + sigemptyset(&set); + sigaddset(&set, signum); + sigprocmask(SIG_BLOCK, &set, &oldset); + DLIST_ADD(sig_state->sig_handlers[signum], sl); + sigprocmask(SIG_SETMASK, &oldset, NULL); + + talloc_set_destructor(se, tevent_signal_destructor); + talloc_set_destructor(sl, tevent_common_signal_list_destructor); + + return se; +} + +int tevent_common_invoke_signal_handler(struct tevent_signal *se, + int signum, int count, void *siginfo, + bool *removed) +{ + struct tevent_context *handler_ev = se->event_ctx; + bool remove = false; + + if (removed != NULL) { + *removed = false; + } + + if (se->event_ctx == NULL) { + return 0; + } + + se->busy = true; + if (se->wrapper != NULL) { + handler_ev = se->wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, se->wrapper); + se->wrapper->ops->before_signal_handler( + se->wrapper->wrap_ev, + se->wrapper->private_state, + se->wrapper->main_ev, + se, + signum, + count, + siginfo, + se->handler_name, + se->location); + } + se->handler(handler_ev, se, signum, count, siginfo, se->private_data); + if (se->wrapper != NULL) { + se->wrapper->ops->after_signal_handler( + se->wrapper->wrap_ev, + se->wrapper->private_state, + se->wrapper->main_ev, + se, + signum, + count, + siginfo, + se->handler_name, + se->location); + tevent_wrapper_pop_use_internal(handler_ev, se->wrapper); + } + se->busy = false; + +#ifdef SA_RESETHAND + if (se->sa_flags & SA_RESETHAND) { + remove = true; + } +#endif + + if (se->destroyed) { + talloc_set_destructor(se, NULL); + remove = true; + } + + if (remove) { + TALLOC_FREE(se); + if (removed != NULL) { + *removed = true; + } + } + + return 0; +} + +/* + check if a signal is pending + return != 0 if a signal was pending +*/ +int tevent_common_check_signal(struct tevent_context *ev) +{ + int i; + + if (!sig_state || !TEVENT_SIG_PENDING(sig_state->got_signal)) { + return 0; + } + + for (i=0;isignal_count[i]; + uint32_t count = tevent_sig_count(counter); + int ret; +#ifdef SA_SIGINFO + /* Ensure we null out any stored siginfo_t entries + * after processing for debugging purposes. */ + bool clear_processed_siginfo = false; +#endif + + if (count == 0) { + continue; + } + for (sl=sig_state->sig_handlers[i];sl;sl=next) { + struct tevent_signal *se = sl->se; + + next = sl->next; + +#ifdef SA_SIGINFO + if (se->sa_flags & SA_SIGINFO) { + uint32_t j; + + clear_processed_siginfo = true; + + for (j=0;jsignal_count[i].seen + * % TEVENT_SA_INFO_QUEUE_COUNT is + * the base position of the unprocessed + * signals in the ringbuffer. */ + uint32_t ofs = (counter.seen + j) + % TEVENT_SA_INFO_QUEUE_COUNT; + bool removed = false; + + ret = tevent_common_invoke_signal_handler( + se, i, 1, + (void*)&sig_state->sig_info[i][ofs], + &removed); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_signal_handler() failed"); + } + if (removed) { + break; + } + } + continue; + } +#endif + + ret = tevent_common_invoke_signal_handler(se, i, count, + NULL, NULL); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_signal_handler() failed"); + } + } + +#ifdef SA_SIGINFO + if (clear_processed_siginfo && sig_state->sig_info[i] != NULL) { + uint32_t j; + for (j=0;jsig_info[i][ofs], + '\0', + sizeof(siginfo_t)); + } + } +#endif + + TEVENT_SIG_SEEN(sig_state->signal_count[i], count); + TEVENT_SIG_SEEN(sig_state->got_signal, count); + +#ifdef SA_SIGINFO + if (TEVENT_SIG_PENDING(sig_state->sig_blocked[i])) { + /* We'd filled the queue, unblock the + signal now the queue is empty again. + Note we MUST do this after the + TEVENT_SIG_SEEN(sig_state->signal_count[i], count) + call to prevent a new signal running + out of room in the sig_state->sig_info[i][] + ring buffer. */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, i); + TEVENT_SIG_SEEN(sig_state->sig_blocked[i], + tevent_sig_count(sig_state->sig_blocked[i])); + sigprocmask(SIG_UNBLOCK, &set, NULL); + } +#endif + } + + return 1; +} + +void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se) +{ + tevent_signal_destructor(se); + talloc_set_destructor(se, NULL); + return; +} diff --git a/ldb-2.0.8/lib/tevent/tevent_standard.c b/ldb-2.0.8/lib/tevent/tevent_standard.c new file mode 100644 index 0000000..3872020 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_standard.c @@ -0,0 +1,238 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Stefan Metzmacher 2013 + Copyright (C) Jeremy Allison 2013 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +/* + This is SAMBA's default event loop code + + - we try to use epoll if configure detected support for it + otherwise we use poll() + - if epoll is broken on the system or the kernel doesn't support it + at runtime we fallback to poll() +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_util.h" +#include "tevent_internal.h" + +struct std_event_glue { + const struct tevent_ops *epoll_ops; + const struct tevent_ops *poll_ops; + struct tevent_ops *glue_ops; + bool fallback_replay; +}; + +static int std_event_context_init(struct tevent_context *ev); + +static const struct tevent_ops std_event_ops = { + .context_init = std_event_context_init, +}; + +/* + If this function gets called. epoll failed at runtime. + Move us to using poll instead. If we return false here, + caller should abort(). +*/ +#ifdef HAVE_EPOLL +static bool std_fallback_to_poll(struct tevent_context *ev, bool replay) +{ + void *glue_ptr = talloc_parent(ev->ops); + struct std_event_glue *glue = + talloc_get_type_abort(glue_ptr, + struct std_event_glue); + int ret; + struct tevent_fd *fde; + + glue->fallback_replay = replay; + + /* First switch all the ops to poll. */ + glue->epoll_ops = NULL; + + /* + * Set custom_ops the same as poll. + */ + *glue->glue_ops = *glue->poll_ops; + glue->glue_ops->context_init = std_event_context_init; + + /* Next initialize the poll backend. */ + ret = glue->poll_ops->context_init(ev); + if (ret != 0) { + return false; + } + + /* + * Now we have to change all the existing file descriptor + * events from the epoll backend to the poll backend. + */ + for (fde = ev->fd_events; fde; fde = fde->next) { + bool ok; + + /* Re-add this event as a poll backend event. */ + ok = tevent_poll_event_add_fd_internal(ev, fde); + if (!ok) { + return false; + } + } + + return true; +} +#endif + +static int std_event_loop_once(struct tevent_context *ev, const char *location) +{ + void *glue_ptr = talloc_parent(ev->ops); + struct std_event_glue *glue = + talloc_get_type_abort(glue_ptr, + struct std_event_glue); + 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; + } + + if (!glue->fallback_replay) { + /* + * The problem happened while modifying an event. + * An event handler was triggered in this case + * and there is no need to call loop_once() again. + */ + return ret; + } + + return glue->poll_ops->loop_once(ev, location); +} + +static int std_event_loop_wait(struct tevent_context *ev, const char *location) +{ + void *glue_ptr = talloc_parent(ev->ops); + struct std_event_glue *glue = + talloc_get_type_abort(glue_ptr, + struct std_event_glue); + 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; + } + + return glue->poll_ops->loop_wait(ev, location); +} +/* + Initialize the epoll backend and allow it to call a + switch function if epoll fails at runtime. +*/ +static int std_event_context_init(struct tevent_context *ev) +{ + struct std_event_glue *glue; + int ret; + + /* + * If this is the first initialization + * we need to set up the allocated ops + * pointers. + */ + + if (ev->ops == &std_event_ops) { + glue = talloc_zero(ev, struct std_event_glue); + if (glue == NULL) { + return -1; + } + + glue->epoll_ops = tevent_find_ops_byname("epoll"); + + glue->poll_ops = tevent_find_ops_byname("poll"); + if (glue->poll_ops == NULL) { + return -1; + } + + /* + * Allocate space for our custom ops. + * Allocate as a child of our epoll_ops pointer + * so we can easily get to it using talloc_parent. + */ + glue->glue_ops = talloc_zero(glue, struct tevent_ops); + if (glue->glue_ops == NULL) { + talloc_free(glue); + return -1; + } + + ev->ops = glue->glue_ops; + } else { + void *glue_ptr = talloc_parent(ev->ops); + glue = talloc_get_type_abort(glue_ptr, struct std_event_glue); + } + + if (glue->epoll_ops != NULL) { + /* + * Set custom_ops the same as epoll, + * except re-init using std_event_context_init() + * and use std_event_loop_once() to add the + * ability to fallback to a poll backend on + * epoll runtime error. + */ + *glue->glue_ops = *glue->epoll_ops; + glue->glue_ops->context_init = std_event_context_init; + glue->glue_ops->loop_once = std_event_loop_once; + glue->glue_ops->loop_wait = std_event_loop_wait; + + ret = glue->epoll_ops->context_init(ev); + if (ret == -1) { + goto fallback; + } +#ifdef HAVE_EPOLL + tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll); +#endif + + return ret; + } + +fallback: + glue->epoll_ops = NULL; + + /* + * Set custom_ops the same as poll. + */ + *glue->glue_ops = *glue->poll_ops; + glue->glue_ops->context_init = std_event_context_init; + + return glue->poll_ops->context_init(ev); +} + +_PRIVATE_ bool tevent_standard_init(void) +{ + return tevent_register_backend("standard", &std_event_ops); +} diff --git a/ldb-2.0.8/lib/tevent/tevent_threads.c b/ldb-2.0.8/lib/tevent/tevent_threads.c new file mode 100644 index 0000000..a89990f --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_threads.c @@ -0,0 +1,601 @@ +/* + tevent event library. + + Copyright (C) Jeremy Allison 2015 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "talloc.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +#ifdef HAVE_PTHREAD +#include "system/threads.h" + +struct tevent_immediate_list { + struct tevent_immediate_list *next, *prev; + tevent_immediate_handler_t handler; + struct tevent_immediate *im; + void *private_ptr; +}; + +struct tevent_thread_proxy { + pthread_mutex_t mutex; + struct tevent_context *dest_ev_ctx; + int read_fd; + int write_fd; + struct tevent_fd *pipe_read_fde; + /* Pending events list. */ + struct tevent_immediate_list *im_list; + /* Completed events list. */ + struct tevent_immediate_list *tofree_im_list; + struct tevent_immediate *free_im; +}; + +static void free_im_list(struct tevent_immediate_list **pp_list_head) +{ + struct tevent_immediate_list *im_entry = NULL; + struct tevent_immediate_list *im_next = NULL; + + for (im_entry = *pp_list_head; im_entry; im_entry = im_next) { + im_next = im_entry->next; + DLIST_REMOVE(*pp_list_head, im_entry); + TALLOC_FREE(im_entry); + } +} + +static void free_list_handler(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + struct tevent_thread_proxy *tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + int ret; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } + + free_im_list(&tp->tofree_im_list); + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } +} + +static void schedule_immediate_functions(struct tevent_thread_proxy *tp) +{ + struct tevent_immediate_list *im_entry = NULL; + struct tevent_immediate_list *im_next = NULL; + + for (im_entry = tp->im_list; im_entry; im_entry = im_next) { + im_next = im_entry->next; + DLIST_REMOVE(tp->im_list, im_entry); + + tevent_schedule_immediate(im_entry->im, + tp->dest_ev_ctx, + im_entry->handler, + im_entry->private_ptr); + + /* Move from pending list to free list. */ + DLIST_ADD(tp->tofree_im_list, im_entry); + } + if (tp->tofree_im_list != NULL) { + /* + * Once the current immediate events + * are processed, we need to reschedule + * ourselves to free them. This works + * as tevent_schedule_immediate() + * always adds events to the *END* of + * the immediate events list. + */ + tevent_schedule_immediate(tp->free_im, + tp->dest_ev_ctx, + free_list_handler, + tp); + } +} + +static void pipe_read_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_ptr) +{ + struct tevent_thread_proxy *tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + ssize_t len = 64; + int ret; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } + + /* + * Clear out all data in the pipe. We + * don't really care if this returns -1. + */ + while (len == 64) { + char buf[64]; + len = read(tp->read_fd, buf, 64); + }; + + schedule_immediate_functions(tp); + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } +} + +static int tevent_thread_proxy_destructor(struct tevent_thread_proxy *tp) +{ + int ret; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return 0; + } + + TALLOC_FREE(tp->pipe_read_fde); + + if (tp->read_fd != -1) { + (void)close(tp->read_fd); + tp->read_fd = -1; + } + if (tp->write_fd != -1) { + (void)close(tp->write_fd); + tp->write_fd = -1; + } + + /* Hmmm. It's probably an error if we get here with + any non-NULL immediate entries.. */ + + free_im_list(&tp->im_list); + free_im_list(&tp->tofree_im_list); + + TALLOC_FREE(tp->free_im); + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return 0; + } + + ret = pthread_mutex_destroy(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return 0; + } + + return 0; +} + +/* + * Create a struct that can be passed to other threads + * to allow them to signal the struct tevent_context * + * passed in. + */ + +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx) +{ + int ret; + int pipefds[2]; + struct tevent_thread_proxy *tp; + + if (dest_ev_ctx->wrapper.glue != NULL) { + /* + * stacking of wrappers is not supported + */ + tevent_debug(dest_ev_ctx->wrapper.glue->main_ev, + TEVENT_DEBUG_FATAL, + "%s() not allowed on a wrapper context\n", + __func__); + errno = EINVAL; + return NULL; + } + + tp = talloc_zero(dest_ev_ctx, struct tevent_thread_proxy); + if (tp == NULL) { + return NULL; + } + + ret = pthread_mutex_init(&tp->mutex, NULL); + if (ret != 0) { + goto fail; + } + + tp->dest_ev_ctx = dest_ev_ctx; + tp->read_fd = -1; + tp->write_fd = -1; + + talloc_set_destructor(tp, tevent_thread_proxy_destructor); + + ret = pipe(pipefds); + if (ret == -1) { + goto fail; + } + + tp->read_fd = pipefds[0]; + tp->write_fd = pipefds[1]; + + ret = ev_set_blocking(pipefds[0], false); + if (ret != 0) { + goto fail; + } + ret = ev_set_blocking(pipefds[1], false); + if (ret != 0) { + goto fail; + } + if (!ev_set_close_on_exec(pipefds[0])) { + goto fail; + } + if (!ev_set_close_on_exec(pipefds[1])) { + goto fail; + } + + tp->pipe_read_fde = tevent_add_fd(dest_ev_ctx, + tp, + tp->read_fd, + TEVENT_FD_READ, + pipe_read_handler, + tp); + if (tp->pipe_read_fde == NULL) { + goto fail; + } + + /* + * Create an immediate event to free + * completed lists. + */ + tp->free_im = tevent_create_immediate(tp); + if (tp->free_im == NULL) { + goto fail; + } + + return tp; + + fail: + + TALLOC_FREE(tp); + return NULL; +} + +/* + * This function schedules an immediate event to be called with argument + * *pp_private in the thread context of dest_ev_ctx. Caller doesn't + * wait for activation to take place, this is simply fire-and-forget. + * + * pp_im must be a pointer to an immediate event talloced on + * a context owned by the calling thread, or the NULL context. + * Ownership of *pp_im will be transfered to the tevent library. + * + * pp_private can be null, or contents of *pp_private must be + * talloc'ed memory on a context owned by the calling thread + * or the NULL context. If non-null, ownership of *pp_private will + * be transfered to the tevent library. + * + * If you want to return a message, have the destination use the + * same function call to send back to the caller. + */ + + +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + tevent_immediate_handler_t handler, + void *pp_private_data) +{ + struct tevent_immediate_list *im_entry; + int ret; + char c; + ssize_t written; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } + + if (tp->write_fd == -1) { + /* In the process of being destroyed. Ignore. */ + goto end; + } + + /* Create a new immediate_list entry. MUST BE ON THE NULL CONTEXT */ + im_entry = talloc_zero(NULL, struct tevent_immediate_list); + if (im_entry == NULL) { + goto end; + } + + im_entry->handler = handler; + im_entry->im = talloc_move(im_entry, pp_im); + + if (pp_private_data != NULL) { + void **pptr = (void **)pp_private_data; + im_entry->private_ptr = talloc_move(im_entry, pptr); + } + + DLIST_ADD(tp->im_list, im_entry); + + /* And notify the dest_ev_ctx to wake up. */ + c = '\0'; + do { + written = write(tp->write_fd, &c, 1); + } while (written == -1 && errno == EINTR); + + end: + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + } +} +#else +/* !HAVE_PTHREAD */ +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx) +{ + errno = ENOSYS; + return NULL; +} + +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + tevent_immediate_handler_t handler, + void *pp_private_data) +{ + ; +} +#endif + +static int tevent_threaded_context_destructor( + struct tevent_threaded_context *tctx) +{ + struct tevent_context *main_ev = tevent_wrapper_main_ev(tctx->event_ctx); + int ret; + + if (main_ev != NULL) { + DLIST_REMOVE(main_ev->threaded_contexts, tctx); + } + + /* + * We have to coordinate with _tevent_threaded_schedule_immediate's + * unlock of the event_ctx_mutex. We're in the main thread here, + * and we can be scheduled before the helper thread finalizes its + * call _tevent_threaded_schedule_immediate. This means we would + * pthreadpool_destroy a locked mutex, which is illegal. + */ + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + 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_context *main_ev = tevent_wrapper_main_ev(ev); + struct tevent_threaded_context *tctx; + int ret; + + ret = tevent_common_wakeup_init(main_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; + + ret = pthread_mutex_init(&tctx->event_ctx_mutex, NULL); + if (ret != 0) { + TALLOC_FREE(tctx); + return NULL; + } + + DLIST_ADD(main_ev->threaded_contexts, tctx); + talloc_set_destructor(tctx, tevent_threaded_context_destructor); + + return tctx; +#else + errno = ENOSYS; + return NULL; +#endif +} + +static int tevent_threaded_schedule_immediate_destructor(struct tevent_immediate *im) +{ + if (im->event_ctx != NULL) { + abort(); + } + return 0; +} + +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 + const char *create_location = im->create_location; + struct tevent_context *main_ev = NULL; + struct tevent_wrapper_glue *glue = NULL; + int ret, wakeup_fd; + + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + if (tctx->event_ctx == NULL) { + /* + * Our event context is already gone. + */ + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + return; + } + + glue = tctx->event_ctx->wrapper.glue; + + if ((im->event_ctx != NULL) || (handler == NULL)) { + abort(); + } + if (im->destroyed) { + abort(); + } + if (im->busy) { + abort(); + } + + main_ev = tevent_wrapper_main_ev(tctx->event_ctx); + + *im = (struct tevent_immediate) { + .event_ctx = tctx->event_ctx, + .wrapper = glue, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .create_location = create_location, + .schedule_location = location, + }; + + /* + * Make sure the event won't be destroyed while + * it's part of the ev->scheduled_immediates list. + * _tevent_schedule_immediate() will reset the destructor + * in tevent_common_threaded_activate_immediate(). + */ + talloc_set_destructor(im, tevent_threaded_schedule_immediate_destructor); + + ret = pthread_mutex_lock(&main_ev->scheduled_mutex); + if (ret != 0) { + abort(); + } + + DLIST_ADD_END(main_ev->scheduled_immediates, im); + wakeup_fd = main_ev->wakeup_fd; + + ret = pthread_mutex_unlock(&main_ev->scheduled_mutex); + if (ret != 0) { + abort(); + } + + ret = pthread_mutex_unlock(&tctx->event_ctx_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(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; + struct tevent_immediate copy = *im; + + DLIST_REMOVE(ev->scheduled_immediates, im); + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Schedule immediate event \"%s\": %p from thread into main\n", + im->handler_name, im); + im->handler_name = NULL; + _tevent_schedule_immediate(im, + ev, + copy.handler, + copy.private_data, + copy.handler_name, + copy.schedule_location); + } + + 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/ldb-2.0.8/lib/tevent/tevent_timed.c b/ldb-2.0.8/lib/tevent/tevent_timed.c new file mode 100644 index 0000000..a78d286 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_timed.c @@ -0,0 +1,449 @@ +/* + Unix SMB/CIFS implementation. + + common events code for timed events + + Copyright (C) Andrew Tridgell 2003-2006 + Copyright (C) Stefan Metzmacher 2005-2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/time.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +/** + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +int tevent_timeval_compare(const struct timeval *tv1, const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return 1; + if (tv1->tv_sec < tv2->tv_sec) return -1; + if (tv1->tv_usec > tv2->tv_usec) return 1; + if (tv1->tv_usec < tv2->tv_usec) return -1; + return 0; +} + +/** + return a zero timeval +*/ +struct timeval tevent_timeval_zero(void) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + return tv; +} + +/** + return a timeval for the current time +*/ +struct timeval tevent_timeval_current(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv; +} + +/** + return a timeval struct with the given elements +*/ +struct timeval tevent_timeval_set(uint32_t secs, uint32_t usecs) +{ + struct timeval tv; + tv.tv_sec = secs; + tv.tv_usec = usecs; + return tv; +} + +/** + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +struct timeval tevent_timeval_until(const struct timeval *tv1, + const struct timeval *tv2) +{ + struct timeval t; + if (tevent_timeval_compare(tv1, tv2) >= 0) { + return tevent_timeval_zero(); + } + t.tv_sec = tv2->tv_sec - tv1->tv_sec; + if (tv1->tv_usec > tv2->tv_usec) { + t.tv_sec--; + t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); + } else { + t.tv_usec = tv2->tv_usec - tv1->tv_usec; + } + return t; +} + +/** + return true if a timeval is zero +*/ +bool tevent_timeval_is_zero(const struct timeval *tv) +{ + return tv->tv_sec == 0 && tv->tv_usec == 0; +} + +struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, + uint32_t usecs) +{ + struct timeval tv2 = *tv; + tv2.tv_sec += secs; + tv2.tv_usec += usecs; + tv2.tv_sec += tv2.tv_usec / 1000000; + tv2.tv_usec = tv2.tv_usec % 1000000; + + return tv2; +} + +/** + return a timeval in the future with a specified offset +*/ +struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs) +{ + struct timeval tv = tevent_timeval_current(); + return tevent_timeval_add(&tv, secs, usecs); +} + +/* + destroy a timed event +*/ +static int tevent_common_timed_destructor(struct tevent_timer *te) +{ + if (te->destroyed) { + tevent_common_check_double_free(te, "tevent_timer double free"); + goto done; + } + te->destroyed = true; + + if (te->event_ctx == NULL) { + return 0; + } + + tevent_debug(te->event_ctx, TEVENT_DEBUG_TRACE, + "Destroying timer event %p \"%s\"\n", + te, te->handler_name); + + if (te->event_ctx->last_zero_timer == te) { + te->event_ctx->last_zero_timer = DLIST_PREV(te); + } + DLIST_REMOVE(te->event_ctx->timer_events, te); + + te->event_ctx = NULL; +done: + if (te->busy) { + return -1; + } + te->wrapper = NULL; + + return 0; +} + +static void tevent_common_insert_timer(struct tevent_context *ev, + struct tevent_timer *te, + bool optimize_zero) +{ + struct tevent_timer *prev_te = NULL; + + if (te->destroyed) { + tevent_abort(ev, "tevent_timer use after free"); + return; + } + + /* keep the list ordered */ + if (optimize_zero && tevent_timeval_is_zero(&te->next_event)) { + /* + * Some callers use zero tevent_timer + * instead of tevent_immediate events. + * + * As these can happen very often, + * we remember the last zero timer + * in the list. + */ + 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 + * timers are added at the end of the list + */ + for (cur_te = DLIST_TAIL(ev->timer_events); + cur_te != NULL; + cur_te = DLIST_PREV(cur_te)) + { + int ret; + + /* + * if the new event comes before the current + * we continue searching + */ + ret = tevent_timeval_compare(&te->next_event, + &cur_te->next_event); + if (ret < 0) { + continue; + } + + break; + } + + prev_te = cur_te; + } + + 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 = (struct tevent_timer) { + .event_ctx = ev, + .next_event = next_event, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .location = location, + }; + + 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); + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Added timed event \"%s\": %p\n", + handler_name, te); + return te; +} + +struct tevent_timer *tevent_common_add_timer(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) +{ + /* + * do not use optimization, there are broken Samba + * versions which use tevent_common_add_timer() + * without using tevent_common_loop_timer_delay(), + * it just uses DLIST_REMOVE(ev->timer_events, te) + * and would leave ev->last_zero_timer behind. + */ + return tevent_common_add_timer_internal(ev, mem_ctx, next_event, + handler, private_data, + handler_name, location, + false); +} + +struct tevent_timer *tevent_common_add_timer_v2(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) +{ + /* + * Here we turn on last_zero_timer optimization + */ + return tevent_common_add_timer_internal(ev, mem_ctx, next_event, + handler, private_data, + handler_name, location, + 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); +} + +int tevent_common_invoke_timer_handler(struct tevent_timer *te, + struct timeval current_time, + bool *removed) +{ + struct tevent_context *handler_ev = te->event_ctx; + + if (removed != NULL) { + *removed = false; + } + + if (te->event_ctx == NULL) { + return 0; + } + + /* + * We need to remove the timer from the list before calling the + * handler because in a semi-async inner event loop called from the + * handler we don't want to come across this event again -- vl + */ + if (te->event_ctx->last_zero_timer == te) { + te->event_ctx->last_zero_timer = DLIST_PREV(te); + } + DLIST_REMOVE(te->event_ctx->timer_events, te); + + tevent_debug(te->event_ctx, TEVENT_DEBUG_TRACE, + "Running timer event %p \"%s\"\n", + te, te->handler_name); + + /* + * If the timed event was registered for a zero current_time, + * then we pass a zero timeval here too! To avoid the + * overhead of gettimeofday() calls. + * + * otherwise we pass the current time + */ + te->busy = true; + if (te->wrapper != NULL) { + handler_ev = te->wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, te->wrapper); + te->wrapper->ops->before_timer_handler( + te->wrapper->wrap_ev, + te->wrapper->private_state, + te->wrapper->main_ev, + te, + te->next_event, + current_time, + te->handler_name, + te->location); + } + te->handler(handler_ev, te, current_time, te->private_data); + if (te->wrapper != NULL) { + te->wrapper->ops->after_timer_handler( + te->wrapper->wrap_ev, + te->wrapper->private_state, + te->wrapper->main_ev, + te, + te->next_event, + current_time, + te->handler_name, + te->location); + tevent_wrapper_pop_use_internal(handler_ev, te->wrapper); + } + te->busy = false; + + tevent_debug(te->event_ctx, TEVENT_DEBUG_TRACE, + "Ending timer event %p \"%s\"\n", + te, te->handler_name); + + te->wrapper = NULL; + te->event_ctx = NULL; + talloc_set_destructor(te, NULL); + TALLOC_FREE(te); + + if (removed != NULL) { + *removed = true; + } + + return 0; +} +/* + do a single event loop using the events defined in ev + + return the delay until the next timed event, + or zero if a timed event was triggered +*/ +struct timeval tevent_common_loop_timer_delay(struct tevent_context *ev) +{ + struct timeval current_time = tevent_timeval_zero(); + struct tevent_timer *te = ev->timer_events; + int ret; + + if (!te) { + /* have a default tick time of 30 seconds. This guarantees + that code that uses its own timeout checking will be + able to proceed eventually */ + return tevent_timeval_set(30, 0); + } + + /* + * work out the right timeout for the next timed event + * + * avoid the syscall to gettimeofday() if the timed event should + * be triggered directly + * + * if there's a delay till the next timed event, we're done + * with just returning the delay + */ + if (!tevent_timeval_is_zero(&te->next_event)) { + struct timeval delay; + + current_time = tevent_timeval_current(); + + delay = tevent_timeval_until(¤t_time, &te->next_event); + if (!tevent_timeval_is_zero(&delay)) { + return delay; + } + } + + /* + * ok, we have a timed event that we'll process ... + */ + ret = tevent_common_invoke_timer_handler(te, current_time, NULL); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_timer_handler() failed"); + } + + return tevent_timeval_zero(); +} + diff --git a/ldb-2.0.8/lib/tevent/tevent_util.c b/ldb-2.0.8/lib/tevent/tevent_util.c new file mode 100644 index 0000000..16af8f3 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_util.c @@ -0,0 +1,107 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "talloc.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" +#include + +/** + return the number of elements in a string list +*/ +size_t ev_str_list_length(const char **list) +{ + size_t ret; + for (ret=0;list && list[ret];ret++) /* noop */ ; + return ret; +} + +/** + add an entry to a string list +*/ +const char **ev_str_list_add(const char **list, const char *s) +{ + size_t len = ev_str_list_length(list); + const char **ret; + + ret = talloc_realloc(NULL, list, const char *, len+2); + if (ret == NULL) return NULL; + + ret[len] = talloc_strdup(ret, s); + if (ret[len] == NULL) return NULL; + + ret[len+1] = NULL; + + return ret; +} + + +/** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY +**/ + +int ev_set_blocking(int fd, bool set) +{ + int val; +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + if(set) /* Turn blocking on - ie. clear nonblock flag */ + val &= ~FLAG_TO_SET; + else + val |= FLAG_TO_SET; + return fcntl( fd, F_SETFL, val); +#undef FLAG_TO_SET +} + +bool ev_set_close_on_exec(int fd) +{ +#ifdef FD_CLOEXEC + int val; + + val = fcntl(fd, F_GETFD, 0); + if (val >= 0) { + val |= FD_CLOEXEC; + val = fcntl(fd, F_SETFD, val); + if (val != -1) { + return true; + } + } +#endif + return false; +} diff --git a/ldb-2.0.8/lib/tevent/tevent_util.h b/ldb-2.0.8/lib/tevent/tevent_util.h new file mode 100644 index 0000000..eef4a00 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_util.h @@ -0,0 +1,185 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 1998-2010 + Copyright (C) Jelmer Vernooij 2005 + + 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 . +*/ + +/* To use these macros you must have a structure containing a next and + prev pointer */ + +#ifndef _DLINKLIST_H +#define _DLINKLIST_H + +/* + February 2010 - changed list format to have a prev pointer from the + list head. This makes DLIST_ADD_END() O(1) even though we only have + one list pointer. + + The scheme is as follows: + + 1) with no entries in the list: + list_head == NULL + + 2) with 1 entry in the list: + list_head->next == NULL + list_head->prev == list_head + + 3) with 2 entries in the list: + list_head->next == element2 + list_head->prev == element2 + element2->prev == list_head + element2->next == NULL + + 4) with N entries in the list: + list_head->next == element2 + list_head->prev == elementN + elementN->prev == element{N-1} + elementN->next == NULL + + This allows us to find the tail of the list by using + list_head->prev, which means we can add to the end of the list in + O(1) time + */ + + +/* + add an element at the front of a list +*/ +#define DLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (p)->prev = (list) = (p); \ + (p)->next = NULL; \ + } else { \ + (p)->prev = (list)->prev; \ + (list)->prev = (p); \ + (p)->next = (list); \ + (list) = (p); \ + } \ +} while (0) + +/* + remove an element from a list + Note that the element doesn't have to be in the list. If it + isn't then this is a no-op +*/ +#define DLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + (list) = (p)->next; \ + } else if ((p)->prev && (list) && (p) == (list)->prev) { \ + (p)->prev->next = NULL; \ + (list)->prev = (p)->prev; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) != (list)) (p)->next = (p)->prev = NULL; \ +} while (0) + +/* + find the head of the list given any element in it. + Note that this costs O(N), so you should avoid this macro + if at all possible! +*/ +#define DLIST_HEAD(p, result_head) \ +do { \ + (result_head) = (p); \ + while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ +} while(0) + +/* return the last element in the list */ +#define DLIST_TAIL(list) ((list)?(list)->prev:NULL) + +/* return the previous element in the list. */ +#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) + +/* insert 'p' after the given element 'el' in a list. If el is NULL then + this is the same as a DLIST_ADD() */ +#define DLIST_ADD_AFTER(list, p, el) \ +do { \ + if (!(list) || !(el)) { \ + DLIST_ADD(list, p); \ + } else { \ + (p)->prev = (el); \ + (p)->next = (el)->next; \ + (el)->next = (p); \ + if ((p)->next) (p)->next->prev = (p); \ + if ((list)->prev == (el)) (list)->prev = (p); \ + }\ +} while (0) + + +/* + add to the end of a list. +*/ +#define DLIST_ADD_END(list, p) \ +do { \ + if (!(list)) { \ + DLIST_ADD(list, p); \ + } else { \ + DLIST_ADD_AFTER(list, p, (list)->prev); \ + } \ +} while (0) + +/* promote an element to the front of a list */ +#define DLIST_PROMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD(list, p); \ +} while (0) + +/* + demote an element to the end of a list. +*/ +#define DLIST_DEMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD_END(list, p); \ +} while (0) + +/* + concatenate two lists - putting all elements of the 2nd list at the + end of the first list. +*/ +#define DLIST_CONCATENATE(list1, list2) \ +do { \ + if (!(list1)) { \ + (list1) = (list2); \ + } else { \ + (list1)->prev->next = (list2); \ + if (list2) { \ + void *_tmplist = (void *)(list1)->prev; \ + (list1)->prev = (list2)->prev; \ + (list2)->prev = _tmplist; \ + } \ + } \ +} while (0) + +#endif /* _DLINKLIST_H */ + +const char **ev_str_list_add(const char **list, const char *s); +int ev_set_blocking(int fd, bool set); +size_t ev_str_list_length(const char **list); +bool ev_set_close_on_exec(int fd); + +/* Defined here so we can build against older talloc versions that don't + * have this define yet. */ +#ifndef TALLOC_FREE +#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) +#endif diff --git a/ldb-2.0.8/lib/tevent/tevent_wakeup.c b/ldb-2.0.8/lib/tevent/tevent_wakeup.c new file mode 100644 index 0000000..e217f33 --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_wakeup.c @@ -0,0 +1,67 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct tevent_wakeup_state { + struct timeval wakeup_time; +}; + +struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval wakeup_time) +{ + struct tevent_req *req; + struct tevent_wakeup_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct tevent_wakeup_state); + if (!req) { + return NULL; + } + state->wakeup_time = wakeup_time; + + if (!tevent_req_set_endtime(req, ev, wakeup_time)) { + return tevent_req_post(req, ev); + } + return req; +} + +bool tevent_wakeup_recv(struct tevent_req *req) +{ + enum tevent_req_state state; + uint64_t error; + + if (tevent_req_is_error(req, &state, &error)) { + if (state == TEVENT_REQ_TIMED_OUT) { + return true; + } + } + + return false; +} + diff --git a/ldb-2.0.8/lib/tevent/tevent_wrapper.c b/ldb-2.0.8/lib/tevent/tevent_wrapper.c new file mode 100644 index 0000000..a0e915f --- /dev/null +++ b/ldb-2.0.8/lib/tevent/tevent_wrapper.c @@ -0,0 +1,571 @@ +/* + Infrastructure for event context wrappers + + Copyright (C) Stefan Metzmacher 2014 + + ** NOTE! The following LGPL license applies to the tevent + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#ifdef HAVE_PTHREAD +#include "system/threads.h" +#endif +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +static int tevent_wrapper_glue_context_init(struct tevent_context *ev) +{ + tevent_abort(ev, "tevent_wrapper_glue_context_init() called"); + errno = ENOSYS; + return -1; +} + +static struct tevent_fd *tevent_wrapper_glue_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_wrapper_glue *glue = ev->wrapper.glue; + struct tevent_fd *fde = NULL; + + if (glue->destroyed) { + tevent_abort(ev, "add_fd wrapper use after free"); + return NULL; + } + + if (glue->main_ev == NULL) { + errno = EINVAL; + return NULL; + } + + fde = _tevent_add_fd(glue->main_ev, mem_ctx, fd, flags, + handler, private_data, + handler_name, location); + if (fde == NULL) { + return NULL; + } + + fde->wrapper = glue; + + return fde; +} + +static struct tevent_timer *tevent_wrapper_glue_add_timer(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) +{ + struct tevent_wrapper_glue *glue = ev->wrapper.glue; + struct tevent_timer *te = NULL; + + if (glue->destroyed) { + tevent_abort(ev, "add_timer wrapper use after free"); + return NULL; + } + + if (glue->main_ev == NULL) { + errno = EINVAL; + return NULL; + } + + te = _tevent_add_timer(glue->main_ev, mem_ctx, next_event, + handler, private_data, + handler_name, location); + if (te == NULL) { + return NULL; + } + + te->wrapper = glue; + + return te; +} + +static void tevent_wrapper_glue_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_wrapper_glue *glue = ev->wrapper.glue; + + if (glue->destroyed) { + tevent_abort(ev, "scheduke_immediate wrapper use after free"); + return; + } + + if (glue->main_ev == NULL) { + tevent_abort(ev, location); + errno = EINVAL; + return; + } + + _tevent_schedule_immediate(im, glue->main_ev, + handler, private_data, + handler_name, location); + + im->wrapper = glue; + + return; +} + +static struct tevent_signal *tevent_wrapper_glue_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_wrapper_glue *glue = ev->wrapper.glue; + struct tevent_signal *se = NULL; + + if (glue->destroyed) { + tevent_abort(ev, "add_signal wrapper use after free"); + return NULL; + } + + if (glue->main_ev == NULL) { + errno = EINVAL; + return NULL; + } + + se = _tevent_add_signal(glue->main_ev, mem_ctx, + signum, sa_flags, + handler, private_data, + handler_name, location); + if (se == NULL) { + return NULL; + } + + se->wrapper = glue; + + return se; +} + +static int tevent_wrapper_glue_loop_once(struct tevent_context *ev, const char *location) +{ + tevent_abort(ev, "tevent_wrapper_glue_loop_once() called"); + errno = ENOSYS; + return -1; +} + +static int tevent_wrapper_glue_loop_wait(struct tevent_context *ev, const char *location) +{ + tevent_abort(ev, "tevent_wrapper_glue_loop_wait() called"); + errno = ENOSYS; + return -1; +} + +static const struct tevent_ops tevent_wrapper_glue_ops = { + .context_init = tevent_wrapper_glue_context_init, + .add_fd = tevent_wrapper_glue_add_fd, + .set_fd_close_fn = tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, + .set_fd_flags = tevent_common_fd_set_flags, + .add_timer = tevent_wrapper_glue_add_timer, + .schedule_immediate = tevent_wrapper_glue_schedule_immediate, + .add_signal = tevent_wrapper_glue_add_signal, + .loop_once = tevent_wrapper_glue_loop_once, + .loop_wait = tevent_wrapper_glue_loop_wait, +}; + +static int tevent_wrapper_context_destructor(struct tevent_context *wrap_ev) +{ + struct tevent_wrapper_glue *glue = wrap_ev->wrapper.glue; + struct tevent_context *main_ev = NULL; + struct tevent_fd *fd = NULL, *fn = NULL; + struct tevent_timer *te = NULL, *tn = NULL; + struct tevent_immediate *ie = NULL, *in = NULL; + struct tevent_signal *se = NULL, *sn = NULL; +#ifdef HAVE_PTHREAD + struct tevent_threaded_context *tctx = NULL, *tctxn = NULL; +#endif + + if (glue == NULL) { + tevent_abort(wrap_ev, + "tevent_wrapper_context_destructor() active on main"); + /* static checker support, return below is never reached */ + return -1; + } + + if (glue->destroyed && glue->busy) { + tevent_common_check_double_free(wrap_ev, + "tevent_context wrapper double free"); + } + glue->destroyed = true; + + if (glue->busy) { + return -1; + } + + main_ev = glue->main_ev; + if (main_ev == NULL) { + return 0; + } + + tevent_debug(wrap_ev, TEVENT_DEBUG_TRACE, + "Destroying wrapper context %p \"%s\"\n", + wrap_ev, talloc_get_name(glue->private_state)); + + glue->main_ev = NULL; + DLIST_REMOVE(main_ev->wrapper.list, glue); + +#ifdef HAVE_PTHREAD + for (tctx = main_ev->threaded_contexts; tctx != NULL; tctx = tctxn) { + int ret; + + tctxn = tctx->next; + + if (tctx->event_ctx != glue->wrap_ev) { + continue; + } + + 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(main_ev->threaded_contexts, tctx); + } +#endif + + for (fd = main_ev->fd_events; fd; fd = fn) { + fn = fd->next; + + if (fd->wrapper != glue) { + continue; + } + + tevent_fd_set_flags(fd, 0); + + fd->wrapper = NULL; + fd->event_ctx = NULL; + DLIST_REMOVE(main_ev->fd_events, fd); + } + + for (te = main_ev->timer_events; te; te = tn) { + tn = te->next; + + if (te->wrapper != glue) { + continue; + } + + te->wrapper = NULL; + te->event_ctx = NULL; + + if (main_ev->last_zero_timer == te) { + main_ev->last_zero_timer = DLIST_PREV(te); + } + DLIST_REMOVE(main_ev->timer_events, te); + } + + for (ie = main_ev->immediate_events; ie; ie = in) { + in = ie->next; + + if (ie->wrapper != glue) { + continue; + } + + ie->wrapper = NULL; + ie->event_ctx = NULL; + ie->cancel_fn = NULL; + DLIST_REMOVE(main_ev->immediate_events, ie); + } + + for (se = main_ev->signal_events; se; se = sn) { + sn = se->next; + + if (se->wrapper != glue) { + continue; + } + + se->wrapper = NULL; + tevent_cleanup_pending_signal_handlers(se); + } + + return 0; +} + +struct tevent_context *_tevent_context_wrapper_create(struct tevent_context *main_ev, + TALLOC_CTX *mem_ctx, + const struct tevent_wrapper_ops *ops, + void *pstate, + size_t psize, + const char *type, + const char *location) +{ + void **ppstate = (void **)pstate; + struct tevent_context *ev = NULL; + + if (main_ev->wrapper.glue != NULL) { + /* + * stacking of wrappers is not supported + */ + tevent_debug(main_ev->wrapper.glue->main_ev, TEVENT_DEBUG_FATAL, + "%s: %s() stacking not allowed\n", + __func__, location); + errno = EINVAL; + return NULL; + } + + if (main_ev->nesting.allowed) { + /* + * wrappers conflict with nesting + */ + tevent_debug(main_ev, TEVENT_DEBUG_FATAL, + "%s: %s() conflicts with nesting\n", + __func__, location); + errno = EINVAL; + return NULL; + } + + ev = talloc_zero(mem_ctx, struct tevent_context); + if (ev == NULL) { + return NULL; + } + ev->ops = &tevent_wrapper_glue_ops; + + ev->wrapper.glue = talloc_zero(ev, struct tevent_wrapper_glue); + if (ev->wrapper.glue == NULL) { + talloc_free(ev); + return NULL; + } + + talloc_set_destructor(ev, tevent_wrapper_context_destructor); + + ev->wrapper.glue->wrap_ev = ev; + ev->wrapper.glue->main_ev = main_ev; + ev->wrapper.glue->ops = ops; + ev->wrapper.glue->private_state = talloc_zero_size(ev->wrapper.glue, psize); + if (ev->wrapper.glue->private_state == NULL) { + talloc_free(ev); + return NULL; + } + talloc_set_name_const(ev->wrapper.glue->private_state, type); + + DLIST_ADD_END(main_ev->wrapper.list, ev->wrapper.glue); + + *ppstate = ev->wrapper.glue->private_state; + return ev; +} + +bool tevent_context_is_wrapper(struct tevent_context *ev) +{ + if (ev->wrapper.glue != NULL) { + return true; + } + + return false; +} + +_PRIVATE_ +struct tevent_context *tevent_wrapper_main_ev(struct tevent_context *ev) +{ + if (ev == NULL) { + return NULL; + } + + if (ev->wrapper.glue == NULL) { + return ev; + } + + return ev->wrapper.glue->main_ev; +} + +/* + * 32 stack elements should be more than enough + * + * e.g. Samba uses just 8 elements for [un]become_{root,user}() + */ +#define TEVENT_WRAPPER_STACK_SIZE 32 + +static struct tevent_wrapper_stack { + const void *ev_ptr; + const struct tevent_wrapper_glue *wrapper; +} wrapper_stack[TEVENT_WRAPPER_STACK_SIZE]; + +static size_t wrapper_stack_idx; + +_PRIVATE_ +void tevent_wrapper_push_use_internal(struct tevent_context *ev, + struct tevent_wrapper_glue *wrapper) +{ + /* + * ev and wrapper need to belong together! + * It's also fine to only have a raw ev + * without a wrapper. + */ + if (unlikely(ev->wrapper.glue != wrapper)) { + tevent_abort(ev, "tevent_wrapper_push_use_internal() invalid arguments"); + return; + } + + if (wrapper != NULL) { + if (unlikely(wrapper->busy)) { + tevent_abort(ev, "wrapper already busy!"); + return; + } + wrapper->busy = true; + } + + if (unlikely(wrapper_stack_idx >= TEVENT_WRAPPER_STACK_SIZE)) { + tevent_abort(ev, "TEVENT_WRAPPER_STACK_SIZE overflow"); + return; + } + + wrapper_stack[wrapper_stack_idx] = (struct tevent_wrapper_stack) { + .ev_ptr = ev, + .wrapper = wrapper, + }; + wrapper_stack_idx++; +} + +_PRIVATE_ +void tevent_wrapper_pop_use_internal(const struct tevent_context *__ev_ptr, + struct tevent_wrapper_glue *wrapper) +{ + struct tevent_context *main_ev = NULL; + + /* + * Note that __ev_ptr might a a stale pointer and should not + * be touched, we just compare the pointer value in order + * to enforce the stack order. + */ + + if (wrapper != NULL) { + main_ev = wrapper->main_ev; + } + + if (unlikely(wrapper_stack_idx == 0)) { + tevent_abort(main_ev, "tevent_wrapper stack already empty"); + return; + } + wrapper_stack_idx--; + + if (wrapper != NULL) { + wrapper->busy = false; + } + + if (wrapper_stack[wrapper_stack_idx].ev_ptr != __ev_ptr) { + tevent_abort(main_ev, "tevent_wrapper_pop_use mismatch ev!"); + return; + } + if (wrapper_stack[wrapper_stack_idx].wrapper != wrapper) { + tevent_abort(main_ev, "tevent_wrapper_pop_use mismatch wrap!"); + return; + } + + if (wrapper == NULL) { + return; + } + + if (wrapper->destroyed) { + /* + * Notice that we can't use TALLOC_FREE() + * here because wrapper is a talloc child + * of wrapper->wrap_ev. + */ + talloc_free(wrapper->wrap_ev); + } +} + +bool _tevent_context_push_use(struct tevent_context *ev, + const char *location) +{ + bool ok; + + if (ev->wrapper.glue == NULL) { + tevent_wrapper_push_use_internal(ev, NULL); + return true; + } + + if (ev->wrapper.glue->main_ev == NULL) { + return false; + } + + tevent_wrapper_push_use_internal(ev, ev->wrapper.glue); + ok = ev->wrapper.glue->ops->before_use(ev->wrapper.glue->wrap_ev, + ev->wrapper.glue->private_state, + ev->wrapper.glue->main_ev, + location); + if (!ok) { + tevent_wrapper_pop_use_internal(ev, ev->wrapper.glue); + return false; + } + + return true; +} + +void _tevent_context_pop_use(struct tevent_context *ev, + const char *location) +{ + tevent_wrapper_pop_use_internal(ev, ev->wrapper.glue); + + if (ev->wrapper.glue == NULL) { + return; + } + + if (ev->wrapper.glue->main_ev == NULL) { + return; + } + + ev->wrapper.glue->ops->after_use(ev->wrapper.glue->wrap_ev, + ev->wrapper.glue->private_state, + ev->wrapper.glue->main_ev, + location); +} + +bool tevent_context_same_loop(struct tevent_context *ev1, + struct tevent_context *ev2) +{ + struct tevent_context *main_ev1 = tevent_wrapper_main_ev(ev1); + struct tevent_context *main_ev2 = tevent_wrapper_main_ev(ev2); + + if (main_ev1 == NULL) { + return false; + } + + if (main_ev1 == main_ev2) { + return true; + } + + return false; +} diff --git a/ldb-2.0.8/lib/tevent/wscript b/ldb-2.0.8/lib/tevent/wscript new file mode 100644 index 0000000..ded182a --- /dev/null +++ b/ldb-2.0.8/lib/tevent/wscript @@ -0,0 +1,142 @@ +#!/usr/bin/env python + +APPNAME = 'tevent' +VERSION = '0.10.0' + +import sys, os + +# find the buildtools directory +top = '.' +while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5: + top = top + '/..' +sys.path.insert(0, top + '/buildtools/wafsamba') + +out = 'bin' + +import wafsamba +from wafsamba import samba_dist, samba_utils +from waflib import Options, Logs, Context + +samba_dist.DIST_DIRS('lib/tevent:. lib/replace:lib/replace lib/talloc:lib/talloc buildtools:buildtools third_party/waf:third_party/waf') + +def options(opt): + opt.BUILTIN_DEFAULT('replace') + opt.PRIVATE_EXTENSION_DEFAULT('tevent', noextension='tevent') + opt.RECURSE('lib/replace') + opt.RECURSE('lib/talloc') + + +def configure(conf): + conf.RECURSE('lib/replace') + conf.RECURSE('lib/talloc') + + conf.env.standalone_tevent = conf.IN_LAUNCH_DIR() + + if not conf.env.standalone_tevent: + if conf.CHECK_BUNDLED_SYSTEM_PKG('tevent', minversion=VERSION, + onlyif='talloc', implied_deps='replace talloc'): + conf.define('USING_SYSTEM_TEVENT', 1) + if not conf.env.disable_python and \ + conf.CHECK_BUNDLED_SYSTEM_PYTHON('pytevent', 'tevent', minversion=VERSION): + conf.define('USING_SYSTEM_PYTEVENT', 1) + + if conf.CHECK_FUNCS('epoll_create', headers='sys/epoll.h'): + conf.DEFINE('HAVE_EPOLL', 1) + + tevent_num_signals = 64 + v = conf.CHECK_VALUEOF('NSIG', headers='signal.h') + if v is not None: + tevent_num_signals = max(tevent_num_signals, v) + v = conf.CHECK_VALUEOF('_NSIG', headers='signal.h') + if v is not None: + tevent_num_signals = max(tevent_num_signals, v) + v = conf.CHECK_VALUEOF('SIGRTMAX', headers='signal.h') + if v is not None: + tevent_num_signals = max(tevent_num_signals, v) + v = conf.CHECK_VALUEOF('SIGRTMIN', headers='signal.h') + if v is not None: + tevent_num_signals = max(tevent_num_signals, v*2) + + if not conf.CONFIG_SET('USING_SYSTEM_TEVENT'): + conf.DEFINE('TEVENT_NUM_SIGNALS', tevent_num_signals) + + conf.SAMBA_CHECK_PYTHON() + conf.SAMBA_CHECK_PYTHON_HEADERS() + + conf.SAMBA_CONFIG_H() + + conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS() + +def build(bld): + bld.RECURSE('lib/replace') + bld.RECURSE('lib/talloc') + + SRC = '''tevent.c tevent_debug.c tevent_fd.c tevent_immediate.c + tevent_queue.c tevent_req.c tevent_wrapper.c + tevent_poll.c tevent_threads.c + tevent_signal.c tevent_standard.c tevent_timed.c tevent_util.c tevent_wakeup.c''' + + if bld.CONFIG_SET('HAVE_EPOLL'): + SRC += ' tevent_epoll.c' + + if bld.CONFIG_SET('HAVE_SOLARIS_PORTS'): + SRC += ' tevent_port.c' + + if bld.env.standalone_tevent: + bld.env.PKGCONFIGDIR = '${LIBDIR}/pkgconfig' + private_library = False + else: + 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=tevent_deps, + enabled= not bld.CONFIG_SET('USING_SYSTEM_TEVENT'), + includes='.', + abi_directory='ABI', + abi_match='tevent_* _tevent_*', + vnum=VERSION, + public_headers=('' if private_library else 'tevent.h'), + public_headers_install=not private_library, + pc_files='tevent.pc', + private_library=private_library) + + if not bld.CONFIG_SET('USING_SYSTEM_PYTEVENT') and not bld.env.disable_python: + bld.SAMBA_PYTHON('_tevent', + 'pytevent.c', + deps='tevent', + realname='_tevent.so', + cflags='-DPACKAGE_VERSION=\"%s\"' % VERSION) + + + bld.INSTALL_WILDCARD('${PYTHONARCHDIR}', 'tevent.py', flat=False) + + # install out various python scripts for use by make test + bld.SAMBA_SCRIPT('tevent_python', + pattern='tevent.py', + installdir='python') + + +def test(ctx): + '''test tevent''' + print("The tevent testsuite is part of smbtorture in samba4") + + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') + + pyret = samba_utils.RUN_PYTHON_TESTS(['bindings.py']) + sys.exit(pyret) + + +def dist(): + '''makes a tarball for distribution''' + samba_dist.dist() + +def reconfigure(ctx): + '''reconfigure if config scripts have changed''' + samba_utils.reconfigure(ctx) diff --git a/ldb-2.0.8/lib/util/attr.h b/ldb-2.0.8/lib/util/attr.h new file mode 100644 index 0000000..8e542c1 --- /dev/null +++ b/ldb-2.0.8/lib/util/attr.h @@ -0,0 +1,101 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij 2007 + + 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 . +*/ + +#ifndef __UTIL_ATTR_H__ +#define __UTIL_ATTR_H__ + +#ifndef _UNUSED_ +#ifdef __GNUC__ +/** gcc attribute used on function parameters so that it does not emit + * warnings about them being unused. **/ +# define _UNUSED_ __attribute__ ((unused)) +#else +# define _UNUSED_ +/** Feel free to add definitions for other compilers here. */ +#endif +#endif +#ifndef UNUSED +#define UNUSED(param) param _UNUSED_ +#endif + +#ifndef _DEPRECATED_ +#ifdef HAVE___ATTRIBUTE__ +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif + +#ifndef _WARN_UNUSED_RESULT_ +#ifdef HAVE___ATTRIBUTE__ +#define _WARN_UNUSED_RESULT_ __attribute__ ((warn_unused_result)) +#else +#define _WARN_UNUSED_RESULT_ +#endif +#endif + +#ifndef _NORETURN_ +#ifdef HAVE___ATTRIBUTE__ +#define _NORETURN_ __attribute__ ((noreturn)) +#else +#define _NORETURN_ +#endif +#endif + +#ifndef _PURE_ +#ifdef HAVE___ATTRIBUTE__ +#define _PURE_ __attribute__((pure)) +#else +#define _PURE_ +#endif +#endif + +#ifndef NONNULL +#ifdef HAVE___ATTRIBUTE__ +#define NONNULL(param) param __attribute__((nonnull)) +#else +#define NONNULL(param) param +#endif +#endif + +#ifndef PRINTF_ATTRIBUTE +#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 + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#ifndef FORMAT_ATTRIBUTE +#ifdef HAVE___ATTRIBUTE__ +/** Use gcc attribute to check printf fns. a1 is argument to format() + * in the above macro. This is needed to support Heimdal's printf + * decorations. Note that some gcc 2.x versions don't handle this + * properly. **/ +#define FORMAT_ATTRIBUTE(a) __attribute__ ((format a)) +#else +#define FORMAT_ATTRIBUTE(a) +#endif +#endif + +#endif /* __UTIL_ATTR_H__ */ diff --git a/ldb-2.0.8/lib/util/binsearch.h b/ldb-2.0.8/lib/util/binsearch.h new file mode 100644 index 0000000..8ae9da2 --- /dev/null +++ b/ldb-2.0.8/lib/util/binsearch.h @@ -0,0 +1,121 @@ +/* + Unix SMB/CIFS implementation. + + a generic binary search macro + + Copyright (C) Andrew Tridgell 2009 + + ** NOTE! The following LGPL license applies to the binsearch.h + ** header. 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 + Lesser 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 . +*/ + +#ifndef _BINSEARCH_H +#define _BINSEARCH_H + +/* a binary array search, where the array is an array of pointers to structures, + and we want to find a match for 'target' on 'field' in those structures. + + Inputs: + array: base pointer to an array of structures + arrray_size: number of elements in the array + field: the name of the field in the structure we are keying off + target: the field value we are looking for + comparison_fn: the comparison function + result: where the result of the search is put + + if the element is found, then 'result' is set to point to the found array element. If not, + then 'result' is set to NULL. + + The array is assumed to be sorted by the same comparison_fn as the + search (with, for example, qsort) + */ +#define BINARY_ARRAY_SEARCH_P(array, array_size, field, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + if (array_size) { for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i]->field); \ + if (_r == 0) { (result) = array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + }} } while (0) + +/* + like BINARY_ARRAY_SEARCH_P, but assumes that the array is an array + of structures, rather than pointers to structures + + result points to the found structure, or NULL + */ +#define BINARY_ARRAY_SEARCH(array, array_size, field, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + if (array_size) { for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i].field); \ + if (_r == 0) { (result) = &array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + }} } while (0) + +/* + like BINARY_ARRAY_SEARCH_P, but assumes that the array is an array + of elements, rather than pointers to structures + + result points to the found structure, or NULL + */ +#define BINARY_ARRAY_SEARCH_V(array, array_size, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + if (array_size) { for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i]); \ + if (_r == 0) { (result) = &array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + }} } while (0) + + +/* + like BINARY_ARRAY_SEARCH_V, but if an exact result is not found, the 'next' + argument will point to the element after the place where the exact result + would have been. If an exact result is found, 'next' will be NULL. If the + target is beyond the end of the list, both 'exact' and 'next' will be NULL. + Unlike other binsearch macros, where there are several elements that compare + the same, the exact result will always point to the first one. + + If you don't care to distinguish between the 'greater than' and 'equals' + cases, you can use the same pointer for both 'exact' and 'next'. + + As with all the binsearch macros, the comparison function is always called + with the search term first. + */ +#define BINARY_ARRAY_SEARCH_GTE(array, array_size, target, comparison_fn, \ + exact, next) do { \ + int32_t _b, _e; \ + (exact) = NULL; (next) = NULL; \ + if ((array_size) > 0) { \ + for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b + _e) / 2; \ + int _r = comparison_fn(target, &array[_i]); \ + if (_r == 0) { \ + (exact) = &array[_i]; \ + _e = _i - 1; \ + } else if (_r < 0) { _e = _i - 1; \ + } else { _b = _i + 1; } \ + } \ + if ((exact) == NULL &&_b < (array_size)) { \ + (next) = &array[_b]; \ + } } } while (0) + +#endif diff --git a/ldb-2.0.8/mainpage.dox b/ldb-2.0.8/mainpage.dox new file mode 100644 index 0000000..bbd8d9c --- /dev/null +++ b/ldb-2.0.8/mainpage.dox @@ -0,0 +1,80 @@ +/** + +\mainpage ldb + +\section Overview + +ldb is a LDAP-like embedded database. It is not at all LDAP standards +compliant, so if you want a standards compliant database then please +see the excellent OpenLDAP +project.

+ +What ldb does is provide a fast database with an LDAP-like API +designed to be used within an application. In some ways it can be seen +as a intermediate solution between key-value pair databases and a real +LDAP database.

+ +ldb is the database engine used in Samba4. + +\section Features + +The main features that separate ldb from other solutions are: + - Safe multi-reader, multi-writer, using byte range locking + - LDAP-like API + - fast operation + - choice of local tdb, local sqlite3 or remote LDAP backends + - integration with talloc + - schema-less operation, for trivial setup + - modules for extensions (such as schema support) + - easy setup of indexes and attribute properties + - ldbedit tool for database editing (reminiscent of 'vipw') + - ldif for import/export + +\section Documentation + +ldb has limited programmer and administrator documentation: + - a list of functions + - a list of examples + - a list of data structures + - a list of constants + +If you need more information than is presented in this document, you +may wish to look at the source code, especially the source code in the +tools directory. + +ldb makes use of the LDAP Data Interchange Format (LDIF), which is +documented in RFC +2849. + +\section Support + +ldb does not currently have its own mailing list or bug tracking +system. For now, please use the samba-technical +mailing list, and the Samba +bugzilla bug tracking system. + +\section Download + +You can download the latest release either via rsync or anonymous +svn. To fetch via svn use the following commands: + +\verbatim + svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/ldb ldb + svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb tdb + svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/talloc talloc +\endverbatim + +To fetch via rsync use these commands: + +\verbatim + rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/ldb . + rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/tdb . + rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/talloc . +\endverbatim + +\section Credits + +ldb is another product of the prolific Andrew Tridgell. + +*/ diff --git a/ldb-2.0.8/man/ldb.3.xml b/ldb-2.0.8/man/ldb.3.xml new file mode 100644 index 0000000..b832d0c --- /dev/null +++ b/ldb-2.0.8/man/ldb.3.xml @@ -0,0 +1,265 @@ + + + + + + ldb + 3 + LDB + System Administration tools + 1.1 + + + + ldb + The Samba Project + A light-weight database library + + + + #include <ldb.h> + + + + description + + +ldb is a light weight embedded database library and API. With a +programming interface that is very similar to LDAP, ldb can store its +data either in a tdb(3) database or in a real LDAP database. + + + +When used with the tdb backend ldb does not require any database +daemon. Instead, ldb function calls are processed immediately by the +ldb library, which does IO directly on the database, while allowing +multiple readers/writers using operating system byte range locks. This +leads to an API with very low overheads, often resulting in speeds of +more than 10x what can be achieved with a more traditional LDAP +architecture. + + + +In a taxonomy of databases ldb would sit half way between key/value +pair databases (such as berkley db or tdb) and a full LDAP +database. With a structured attribute oriented API like LDAP and good +indexing capabilities, ldb can be used for quite sophisticated +applications that need a light weight database, without the +administrative overhead of a full LDAP installation. + + + +Included with ldb are a number of useful command line tools for +manipulating a ldb database. These tools are similar in style to the +equivalent ldap command line tools. + + + +In its default mode of operation with a tdb backend, ldb can also be +seen as a "schema-less LDAP". By default ldb does not require a +schema, which greatly reduces the complexity of getting started with +ldb databases. As the complexity of you application grows you can take +advantage of some of the optional schema-like attributes that ldb +offers, or you can migrate to using the full LDAP api while keeping +your exiting ldb code. + + + +If you are new to ldb, then I suggest starting with the manual pages +for ldbsearch(1) and ldbedit(1), and experimenting with a local +database. Then I suggest you look at the ldb_connect(3) and +ldb_search(3) manual pages. + + + + + TOOLS + + + + ldbsearch(1) + - command line ldb search utility + + + + ldbedit(1) + - edit all or part of a ldb database using your favourite editor + + + + ldbadd(1) + - add records to a ldb database using LDIF formatted input + + + + ldbdel(1) + - delete records from a ldb database + + + + ldbmodify(1) + - modify records in a ldb database using LDIF formatted input + + + + + + FUNCTIONS + + + + ldb_connect(3) + - connect to a ldb backend + + + + ldb_search(3) + - perform a database search + + + + ldb_add(3) + - add a record to the database + + + + ldb_delete(3) + - delete a record from the database + + + + ldb_modify(3) + - modify a record in the database + + + + ldb_errstring(3) + - retrieve extended error information from the last operation + + + + ldb_ldif_write(3) + - write a LDIF formatted message + + + + ldb_ldif_write_file(3) + - write a LDIF formatted message to a file + + + + ldb_ldif_read(3) + - read a LDIF formatted message + + + + ldb_ldif_read_free(3) + - free the result of a ldb_ldif_read() + + + + ldb_ldif_read_file(3) + - read a LDIF message from a file + + + + ldb_ldif_read_string(3) + - read a LDIF message from a string + + + + ldb_msg_find_element(3) + - find an element in a ldb_message + + + + ldb_val_equal_exact(3) + - compare two ldb_val structures + + + + ldb_msg_find_val(3) + - find an element by value + + + + ldb_msg_add_empty(3) + - add an empty message element to a ldb_message + + + + + ldb_msg_add(3) + - add a non-empty message element to a ldb_message + + + + + ldb_msg_element_compare(3) + - compare two ldb_message_element structures + + + + + ldb_msg_find_int(3) + - return an integer value from a ldb_message + + + + + ldb_msg_find_uint(3) + - return an unsigned integer value from a ldb_message + + + + + ldb_msg_find_double(3) + - return a double value from a ldb_message + + + + + ldb_msg_find_string(3) + - return a string value from a ldb_message + + + + + ldb_set_alloc(3) + - set the memory allocation function to be used by ldb + + + + + ldb_set_debug(3) + - set a debug handler to be used by ldb + + + + + ldb_set_debug_stderr(3) + - set a debug handler for stderr output + + + + + + Author + + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + +ldb is released under the GNU Lesser General Public License version 2 +or later. Please see the file COPYING for license details. + + + diff --git a/ldb-2.0.8/man/ldbadd.1.xml b/ldb-2.0.8/man/ldbadd.1.xml new file mode 100644 index 0000000..4736b3b --- /dev/null +++ b/ldb-2.0.8/man/ldbadd.1.xml @@ -0,0 +1,108 @@ + + + + + + ldbadd + 1 + LDB + System Administration tools + 1.1 + + + + + ldbadd + Command-line utility for adding records to an LDB + + + + + ldbadd + -h + -H LDB-URL + ldif-file1 + ldif-file2 + ... + + + + + DESCRIPTION + + ldbadd adds records to an ldb(3) database. It reads + the ldif(5) files specified on the command line and adds + the records from these files to the LDB database, which is specified + by the -H option or the LDB_URL environment variable. + + + If - is specified as a ldb file, the ldif input is read from + standard input. + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(3) for details. + + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overridden by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 1.1 of LDB. + + + + SEE ALSO + + ldb(3), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/ldb-2.0.8/man/ldbdel.1.xml b/ldb-2.0.8/man/ldbdel.1.xml new file mode 100644 index 0000000..c4cd450 --- /dev/null +++ b/ldb-2.0.8/man/ldbdel.1.xml @@ -0,0 +1,108 @@ + + + + + + ldbdel + 1 + LDB + System Administration tools + 1.1 + + + + + ldbdel + Command-line program for deleting LDB records + + + + + ldbdel + -h + -H LDB-URL + dn + ... + + + + + DESCRIPTION + + ldbdel deletes records from an ldb(3) database. + It deletes the records identified by the dn's specified + on the command-line. + + ldbdel uses either the database that is specified with + the -H option or the database specified by the LDB_URL environment + variable. + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(3) for details. + + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overridden by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 1.1 of LDB. + + + + SEE ALSO + + ldb(3), ldbmodify, ldbadd, ldif(5) + + + + + AUTHOR + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + ldbdel was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/ldb-2.0.8/man/ldbedit.1.xml b/ldb-2.0.8/man/ldbedit.1.xml new file mode 100644 index 0000000..627d20c --- /dev/null +++ b/ldb-2.0.8/man/ldbedit.1.xml @@ -0,0 +1,203 @@ + + + + + + ldbedit + 1 + LDB + System Administration tools + 1.1 + + + + + ldbedit + Edit LDB databases using your preferred editor + + + + + ldbedit + -? + --usage + -s base|one|sub + -b basedn + -a + -e editor + -H LDB-URL + expression + attributes + + + + + DESCRIPTION + + ldbedit is a utility that allows you to edit LDB entries (in + tdb files, sqlite files or LDAP servers) using your preferred editor. + ldbedit generates an LDIF file based on your query, allows you to edit + the LDIF, and then merges that LDIF back into the LDB backend. + + + + + + + OPTIONS + + + + -? + --help + + + Show list of available options, and a phrase describing what that option + does. + + + + + + --usage + + + Show list of available options. This is similar to the help option, + however it does not provide any description, and is hence shorter. + + + + + + -H <ldb-url> + + + LDB URL to connect to. For a tdb database, + this will be of the form + tdb://filename. + For a LDAP connection over unix domain + sockets, this will be of the form + ldapi://socket. For + a (potentially remote) LDAP connection over + TCP, this will be of the form + ldap://hostname. For + an SQLite database, this will be of the form + sqlite://filename. + + + + + + -s one|sub|base + Search scope to use. One-level, subtree or base. + + + + -a + -all + + Edit all records. This allows you to + apply the same change to a number of records + at once. You probably want to combine this + with an expression of the form + "objectclass=*". + + + + + + -e editor + --editor editor + + Specify the editor that should be used (overrides + the VISUAL and EDITOR environment + variables). If this option is not used, and + neither VISUAL nor EDITOR environment variables + are set, then the vi editor will be used. + + + + + + -b basedn + Specify Base Distinguished Name to use. + + + + -v + --verbose + + Make ldbedit more verbose about the + operations that are being performed. Without + this option, ldbedit will only provide a + summary change line. + + + + + + + + + + ENVIRONMENT + + + + LDB_URL + + LDB URL to connect to. This can be + overridden by using the -H command-line option.) + + + + + VISUAL and EDITOR + + + Environment variables used to determine what + editor to use. VISUAL takes precedence over + EDITOR, and both are overridden by the + -e command-line option. + + + + + + + + + VERSION + + This man page is correct for version 1.1 of LDB. + + + + SEE ALSO + + ldb(3), ldbmodify(1), ldbdel(1), ldif(5), vi(1) + + + + + AUTHOR + + + ldb was written by + Andrew Tridgell. + + + + If you wish to report a problem or make a suggestion then please see + the web site for + current contact and maintainer information. + + + + This manpage was written by Jelmer Vernooij and updated + by Brad Hards. + + + + + diff --git a/ldb-2.0.8/man/ldbmodify.1.xml b/ldb-2.0.8/man/ldbmodify.1.xml new file mode 100644 index 0000000..ddeeee7 --- /dev/null +++ b/ldb-2.0.8/man/ldbmodify.1.xml @@ -0,0 +1,96 @@ + + + + + + ldbmodify + 1 + LDB + System Administration tools + 1.1 + + + + + ldbmodify + Modify records in a LDB database + + + + + ldbmodify + -H LDB-URL + ldif-file + + + + + DESCRIPTION + + + ldbmodify changes, adds and deletes records in a LDB database. + The changes that should be made to the LDB database are read from + the specified LDIF-file. If - is specified as the filename, input is read from stdin. + + + For now, see ldapmodify(1) for details on the LDIF file format. + + + + + + OPTIONS + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(3) for details. + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overridden by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 1.1 of LDB. + + + + SEE ALSO + + ldb(3), ldbedit + + + + + AUTHOR + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/ldb-2.0.8/man/ldbrename.1.xml b/ldb-2.0.8/man/ldbrename.1.xml new file mode 100644 index 0000000..897c40e --- /dev/null +++ b/ldb-2.0.8/man/ldbrename.1.xml @@ -0,0 +1,110 @@ + + + + + + ldbrename + 1 + LDB + System Administration tools + 1.1 + + + + + ldbrename + Edit LDB databases using your favorite editor + + + + + ldbrename + -h + -o options + olddn + newdn + + + + + DESCRIPTION + + ldbrename is a utility that allows you to rename trees in + an LDB database based by DN. This utility takes + two arguments: the original + DN name of the top element and the DN to change it to. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(3) for details. + + + + + -o options + Extra ldb options, such as + modules. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overridden by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 1.1 of LDB. + + + + SEE ALSO + + ldb(3), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/ldb-2.0.8/man/ldbsearch.1.xml b/ldb-2.0.8/man/ldbsearch.1.xml new file mode 100644 index 0000000..b853992 --- /dev/null +++ b/ldb-2.0.8/man/ldbsearch.1.xml @@ -0,0 +1,122 @@ + + + + + + ldbsearch + 1 + LDB + System Administration tools + 1.1 + + + + + ldbsearch + Search for records in a LDB database + + + + + ldbsearch + -h + -s base|one|sub + -b basedn + -i + -H LDB-URL + expression + attributes + + + + + DESCRIPTION + + ldbsearch searches a LDB database for records matching the + specified expression (see the ldapsearch(1) manpage for + a description of the expression format). For each + record, the specified attributes are printed. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(3) for details. + + + + + -s one|sub|base + Search scope to use. One-level, subtree or base. + + + + -i + Read search expressions from stdin. + + + + -b basedn + Specify Base DN to use. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overridden by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 1.1 of LDB. + + + + SEE ALSO + + ldb(3), ldbedit(1) + + + + + AUTHOR + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/ldb-2.0.8/modules/asq.c b/ldb-2.0.8/modules/asq.c new file mode 100644 index 0000000..7482de8 --- /dev/null +++ b/ldb-2.0.8/modules/asq.c @@ -0,0 +1,416 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005-2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb attribute scoped query control module + * + * Description: this module searches all the objects pointed by + * the DNs contained in the references attribute + * + * Author: Simo Sorce + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_module.h" + +struct asq_context { + + enum {ASQ_SEARCH_BASE, ASQ_SEARCH_MULTI} step; + + struct ldb_module *module; + struct ldb_request *req; + + struct ldb_asq_control *asq_ctrl; + + const char * const *req_attrs; + char *req_attribute; + enum { + ASQ_CTRL_SUCCESS = 0, + ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX = 21, + ASQ_CTRL_UNWILLING_TO_PERFORM = 53, + ASQ_CTRL_AFFECTS_MULTIPLE_DSA = 71 + } asq_ret; + + struct ldb_reply *base_res; + + struct ldb_request **reqs; + unsigned int num_reqs; + unsigned int cur_req; + + struct ldb_control **controls; +}; + +static struct asq_context *asq_context_init(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct asq_context *ac; + + ldb = ldb_module_get_ctx(module); + + ac = talloc_zero(req, struct asq_context); + if (ac == NULL) { + ldb_oom(ldb); + return NULL; + } + + ac->module = module; + ac->req = req; + + return ac; +} + +static int asq_search_continue(struct asq_context *ac); + +static int asq_search_terminate(struct asq_context *ac) +{ + struct ldb_asq_control *asq; + unsigned int i; + + if (ac->controls) { + for (i = 0; ac->controls[i]; i++) /* count em */ ; + } else { + i = 0; + } + + ac->controls = talloc_realloc(ac, ac->controls, struct ldb_control *, i + 2); + + if (ac->controls == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->controls[i] = talloc(ac->controls, struct ldb_control); + if (ac->controls[i] == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->controls[i]->oid = LDB_CONTROL_ASQ_OID; + ac->controls[i]->critical = 0; + + asq = talloc_zero(ac->controls[i], struct ldb_asq_control); + if (asq == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + asq->result = ac->asq_ret; + + ac->controls[i]->data = asq; + + ac->controls[i + 1] = NULL; + + return ldb_module_done(ac->req, ac->controls, NULL, LDB_SUCCESS); +} + +static int asq_base_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct asq_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct asq_context); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + ac->base_res = talloc_move(ac, &ares); + break; + + case LDB_REPLY_REFERRAL: + /* ignore referrals */ + talloc_free(ares); + break; + + case LDB_REPLY_DONE: + + talloc_free(ares); + + /* next step */ + ret = asq_search_continue(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + break; + + } + return LDB_SUCCESS; +} + +static int asq_reqs_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct asq_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct asq_context); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + /* pass the message up to the original callback as we + * do not have to elaborate on it any further */ + ret = ldb_module_send_entry(ac->req, ares->message, ares->controls); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + talloc_free(ares); + break; + + case LDB_REPLY_REFERRAL: + /* ignore referrals */ + talloc_free(ares); + break; + + case LDB_REPLY_DONE: + + talloc_free(ares); + + ret = asq_search_continue(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + break; + } + + return LDB_SUCCESS; +} + +static int asq_build_first_request(struct asq_context *ac, struct ldb_request **base_req) +{ + struct ldb_context *ldb; + const char **base_attrs; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + ac->req_attrs = ac->req->op.search.attrs; + ac->req_attribute = talloc_strdup(ac, ac->asq_ctrl->source_attribute); + if (ac->req_attribute == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + base_attrs = talloc_array(ac, const char *, 2); + if (base_attrs == NULL) return LDB_ERR_OPERATIONS_ERROR; + + base_attrs[0] = talloc_strdup(base_attrs, ac->asq_ctrl->source_attribute); + if (base_attrs[0] == NULL) return LDB_ERR_OPERATIONS_ERROR; + + base_attrs[1] = NULL; + + ret = ldb_build_search_req(base_req, ldb, ac, + ac->req->op.search.base, + LDB_SCOPE_BASE, + NULL, + (const char * const *)base_attrs, + NULL, + ac, asq_base_callback, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + + return LDB_SUCCESS; +} + +static int asq_build_multiple_requests(struct asq_context *ac, bool *terminated) +{ + struct ldb_context *ldb; + struct ldb_control **saved_controls; + struct ldb_control *control; + struct ldb_dn *dn; + struct ldb_message_element *el; + unsigned int i; + int ret; + + if (ac->base_res == NULL) { + return LDB_ERR_NO_SUCH_OBJECT; + } + + ldb = ldb_module_get_ctx(ac->module); + + el = ldb_msg_find_element(ac->base_res->message, ac->req_attribute); + /* no values found */ + if (el == NULL) { + ac->asq_ret = ASQ_CTRL_SUCCESS; + *terminated = true; + return asq_search_terminate(ac); + } + + ac->num_reqs = el->num_values; + ac->cur_req = 0; + ac->reqs = talloc_array(ac, struct ldb_request *, ac->num_reqs); + if (ac->reqs == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + for (i = 0; i < el->num_values; i++) { + + dn = ldb_dn_new(ac, ldb, + (const char *)el->values[i].data); + if ( ! ldb_dn_validate(dn)) { + ac->asq_ret = ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX; + *terminated = true; + return asq_search_terminate(ac); + } + + ret = ldb_build_search_req_ex(&ac->reqs[i], + ldb, ac, + dn, LDB_SCOPE_BASE, + ac->req->op.search.tree, + ac->req_attrs, + ac->req->controls, + ac, asq_reqs_callback, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* remove the ASQ control itself */ + control = ldb_request_get_control(ac->req, LDB_CONTROL_ASQ_OID); + if (!ldb_save_controls(control, ac->reqs[i], &saved_controls)) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + return LDB_SUCCESS; +} + +static int asq_search_continue(struct asq_context *ac) +{ + struct ldb_context *ldb; + bool terminated = false; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + switch (ac->step) { + case ASQ_SEARCH_BASE: + + /* build up the requests call chain */ + ret = asq_build_multiple_requests(ac, &terminated); + if (ret != LDB_SUCCESS || terminated) { + return ret; + } + + ac->step = ASQ_SEARCH_MULTI; + + return ldb_request(ldb, ac->reqs[ac->cur_req]); + + case ASQ_SEARCH_MULTI: + + ac->cur_req++; + + if (ac->cur_req == ac->num_reqs) { + /* done */ + return asq_search_terminate(ac); + } + + return ldb_request(ldb, ac->reqs[ac->cur_req]); + } + + return LDB_ERR_OPERATIONS_ERROR; +} + +static int asq_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct ldb_request *base_req; + struct ldb_control *control; + struct asq_context *ac; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* check if there's an ASQ control */ + control = ldb_request_get_control(req, LDB_CONTROL_ASQ_OID); + if (control == NULL) { + /* not found go on */ + return ldb_next_request(module, req); + } + + ac = asq_context_init(module, req); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* check the search is well formed */ + if (req->op.search.scope != LDB_SCOPE_BASE) { + ac->asq_ret = ASQ_CTRL_UNWILLING_TO_PERFORM; + return asq_search_terminate(ac); + } + + ac->asq_ctrl = talloc_get_type(control->data, struct ldb_asq_control); + if (!ac->asq_ctrl) { + return LDB_ERR_PROTOCOL_ERROR; + } + + ret = asq_build_first_request(ac, &base_req); + if (ret != LDB_SUCCESS) { + return ret; + } + + ac->step = ASQ_SEARCH_BASE; + + return ldb_request(ldb, base_req); +} + +static int asq_init(struct ldb_module *module) +{ + struct ldb_context *ldb; + int ret; + + ldb = ldb_module_get_ctx(module); + + ret = ldb_mod_register_control(module, LDB_CONTROL_ASQ_OID); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "asq: Unable to register control with rootdse!"); + } + + return ldb_next_init(module); +} + +static const struct ldb_module_ops ldb_asq_module_ops = { + .name = "asq", + .search = asq_search, + .init_context = asq_init +}; + +int ldb_asq_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_module(&ldb_asq_module_ops); +} diff --git a/ldb-2.0.8/modules/paged_searches.c b/ldb-2.0.8/modules/paged_searches.c new file mode 100644 index 0000000..f8f3895 --- /dev/null +++ b/ldb-2.0.8/modules/paged_searches.c @@ -0,0 +1,391 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005-2008 + Copyright (C) Andrew Bartlett 2009 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: paged_searches + * + * Component: ldb paged searches module + * + * Description: this module detects if the remote ldap server supports + * paged results and use them to transparently access all objects + * + * Author: Simo Sorce + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_module.h" + +#define PS_DEFAULT_PAGE_SIZE 500 +/* 500 objects per query seem to be a decent compromise + * the default AD limit per request is 1000 entries */ + +struct private_data { + + bool paged_supported; +}; + +struct ps_context { + struct ldb_module *module; + struct ldb_request *req; + + bool pending; + + char **saved_referrals; + unsigned int num_referrals; + + struct ldb_request *down_req; +}; + +static int check_ps_continuation(struct ps_context *ac, struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct ldb_control *rep_control, *req_control; + struct ldb_paged_control *paged_rep_control = NULL, *paged_req_control = NULL; + ldb = ldb_module_get_ctx(ac->module); + + rep_control = ldb_reply_get_control(ares, LDB_CONTROL_PAGED_RESULTS_OID); + if (rep_control) { + paged_rep_control = talloc_get_type(rep_control->data, struct ldb_paged_control); + } + + req_control = ldb_request_get_control(req, LDB_CONTROL_PAGED_RESULTS_OID); + if (req_control == NULL) { + ldb_set_errstring(ldb, "paged_searches: control is missing"); + return LDB_ERR_OPERATIONS_ERROR; + } + + paged_req_control = talloc_get_type(req_control->data, struct ldb_paged_control); + + if (!rep_control || !paged_rep_control) { + if (paged_req_control->cookie) { + /* something wrong here - why give us a control back befre, but not one now? */ + ldb_set_errstring(ldb, "paged_searches: ERROR: We got back a control from a previous page, but this time no control was returned!"); + return LDB_ERR_OPERATIONS_ERROR; + } else { + /* No cookie received yet, valid to just return the full data set */ + + /* we are done */ + ac->pending = false; + return LDB_SUCCESS; + } + } + + if (paged_rep_control->cookie_len == 0) { + /* we are done */ + ac->pending = false; + return LDB_SUCCESS; + } + + /* more processing required */ + /* let's fill in the request control with the new cookie */ + /* if there's a reply control we must find a request + * control matching it */ + + if (paged_req_control->cookie) { + talloc_free(paged_req_control->cookie); + } + + paged_req_control->cookie = talloc_memdup(req_control, + paged_rep_control->cookie, + paged_rep_control->cookie_len); + paged_req_control->cookie_len = paged_rep_control->cookie_len; + + ac->pending = true; + return LDB_SUCCESS; +} + +static int store_referral(struct ps_context *ac, char *referral) +{ + ac->saved_referrals = talloc_realloc(ac, ac->saved_referrals, char *, ac->num_referrals + 2); + if (!ac->saved_referrals) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->saved_referrals[ac->num_referrals] = talloc_strdup(ac->saved_referrals, referral); + if (!ac->saved_referrals[ac->num_referrals]) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->num_referrals++; + ac->saved_referrals[ac->num_referrals] = NULL; + + return LDB_SUCCESS; +} + +static int send_referrals(struct ps_context *ac) +{ + struct ldb_reply *ares; + int ret; + unsigned int i; + + for (i = 0; i < ac->num_referrals; i++) { + ares = talloc_zero(ac->req, struct ldb_reply); + if (!ares) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ares->type = LDB_REPLY_REFERRAL; + ares->referral = ac->saved_referrals[i]; + + ret = ldb_module_send_referral(ac->req, ares->referral); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + +static int ps_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ps_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct ps_context); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + ret = ldb_module_send_entry(ac->req, ares->message, ares->controls); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + break; + + case LDB_REPLY_REFERRAL: + ret = store_referral(ac, ares->referral); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + break; + + case LDB_REPLY_DONE: + + ret = check_ps_continuation(ac, req, ares); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + + if (ac->pending) { + + ret = ldb_next_request(ac->module, ac->down_req); + + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, + NULL, NULL, ret); + } + + } else { + + /* send referrals */ + ret = send_referrals(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, + NULL, NULL, ret); + } + + /* send REPLY_DONE */ + return ldb_module_done(ac->req, ares->controls, + ares->response, LDB_SUCCESS); + } + break; + } + + talloc_free(ares); + return LDB_SUCCESS; +} + +static int ps_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct private_data *private_data; + struct ps_context *ac; + struct ldb_paged_control *control; + int ret; + + private_data = talloc_get_type(ldb_module_get_private(module), struct private_data); + ldb = ldb_module_get_ctx(module); + + /* check if paging is supported */ + if (!private_data || !private_data->paged_supported) { + /* do not touch this request paged controls not + * supported or we + * are just not setup yet */ + return ldb_next_request(module, req); + } + + ac = talloc_zero(req, struct ps_context); + if (ac == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->module = module; + ac->req = req; + ac->pending = false; + ac->saved_referrals = NULL; + ac->num_referrals = 0; + + ldb = ldb_module_get_ctx(ac->module); + + control = talloc(ac, struct ldb_paged_control); + if (!control) { + return LDB_ERR_OPERATIONS_ERROR; + } + + control->size = PS_DEFAULT_PAGE_SIZE; + control->cookie = NULL; + control->cookie_len = 0; + + ret = ldb_build_search_req_ex(&ac->down_req, ldb, ac, + ac->req->op.search.base, + ac->req->op.search.scope, + ac->req->op.search.tree, + ac->req->op.search.attrs, + ac->req->controls, + ac, + ps_callback, + ac->req); + LDB_REQ_SET_LOCATION(ac->down_req); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_request_add_control(ac->down_req, LDB_CONTROL_PAGED_RESULTS_OID, + true, control); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(ac->down_req, control); + + return ldb_next_request(ac->module, ac->down_req); +} + +static int check_supported_paged(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct private_data *data; + + data = talloc_get_type(req->context, struct private_data); + + if (!ares) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + if (ldb_msg_check_string_attribute(ares->message, + "supportedControl", + LDB_CONTROL_PAGED_RESULTS_OID)) { + data->paged_supported = true; + } + break; + + case LDB_REPLY_REFERRAL: + /* ignore */ + break; + + case LDB_REPLY_DONE: + return ldb_request_done(req, LDB_SUCCESS); + } + + talloc_free(ares); + return LDB_SUCCESS; +} + +static int ps_init(struct ldb_module *module) +{ + struct ldb_context *ldb; + static const char *attrs[] = { "supportedControl", NULL }; + struct private_data *data; + struct ldb_dn *base; + int ret; + struct ldb_request *req; + + ldb = ldb_module_get_ctx(module); + + data = talloc(module, struct private_data); + if (data == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + data->paged_supported = false; + + ldb_module_set_private(module, data); + + base = ldb_dn_new(module, ldb, ""); + if (base == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_build_search_req(&req, ldb, module, + base, LDB_SCOPE_BASE, + "(objectClass=*)", + attrs, NULL, + data, check_supported_paged, + NULL); + LDB_REQ_SET_LOCATION(req); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_next_request(module, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_free(base); + talloc_free(req); + + return ldb_next_init(module); +} + +static const struct ldb_module_ops ldb_paged_searches_module_ops = { + .name = "paged_searches", + .search = ps_search, + .init_context = ps_init +}; + +int ldb_paged_searches_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_module(&ldb_paged_searches_module_ops); +} diff --git a/ldb-2.0.8/modules/rdn_name.c b/ldb-2.0.8/modules/rdn_name.c new file mode 100644 index 0000000..e69ad93 --- /dev/null +++ b/ldb-2.0.8/modules/rdn_name.c @@ -0,0 +1,610 @@ +/* + ldb database library + + Copyright (C) Andrew Bartlett 2005-2009 + Copyright (C) Simo Sorce 2006-2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: rdn_name + * + * Component: ldb rdn name module + * + * Description: keep a consistent name attribute on objects manpulations + * + * Author: Andrew Bartlett + * + * Modifications: + * - made the module async + * Simo Sorce Mar 2006 + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_module.h" + +struct rename_context { + struct ldb_module *module; + struct ldb_request *req; + + struct ldb_reply *ares; +}; + +static int rdn_name_add_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct rename_context *ac; + + ac = talloc_get_type(req->context, struct rename_context); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->type == LDB_REPLY_REFERRAL) { + return ldb_module_send_referral(ac->req, ares->referral); + } + + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + if (ares->type != LDB_REPLY_DONE) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + return ldb_module_done(ac->req, ares->controls, + ares->response, LDB_SUCCESS); +} + +static int rdn_name_add(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct ldb_request *down_req; + struct rename_context *ac; + struct ldb_message *msg; + struct ldb_message_element *attribute; + const struct ldb_schema_attribute *a; + const char *rdn_name; + const struct ldb_val *rdn_val_p; + struct ldb_val rdn_val; + unsigned int i; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.add.message->dn)) { + return ldb_next_request(module, req); + } + + ac = talloc_zero(req, struct rename_context); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->module = module; + ac->req = req; + + msg = ldb_msg_copy_shallow(req, req->op.add.message); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + rdn_name = ldb_dn_get_rdn_name(msg->dn); + if (rdn_name == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + rdn_val_p = ldb_dn_get_rdn_val(msg->dn); + if (rdn_val_p == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + if (rdn_val_p->length == 0) { + ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", + ldb_dn_get_linearized(req->op.add.message->dn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + rdn_val = ldb_val_dup(msg, rdn_val_p); + + /* Perhaps someone above us tried to set this? Then ignore it */ + ldb_msg_remove_attr(msg, "name"); + + ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + a = ldb_schema_attribute_by_name(ldb, rdn_name); + if (a == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + attribute = ldb_msg_find_element(msg, rdn_name); + if (!attribute) { + /* add entry with normalised RDN information if possible */ + 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); + } + if (ret != LDB_SUCCESS) { + return ret; + } + } else { + /* normalise attribute name if possible */ + if (a->name != NULL && strcmp(a->name, "*") != 0) { + attribute->name = a->name; + } + /* normalise attribute value */ + for (i = 0; i < attribute->num_values; i++) { + bool matched; + if (a->syntax->operator_fn) { + ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a, + &rdn_val, &attribute->values[i], &matched); + if (ret != LDB_SUCCESS) return ret; + } else { + matched = (a->syntax->comparison_fn(ldb, msg, + &rdn_val, &attribute->values[i]) == 0); + } + if (matched) { + /* overwrite so it matches in case */ + attribute->values[i] = rdn_val; + break; + } + } + if (i == attribute->num_values) { + char *rdn_errstring = talloc_asprintf(ac, + "RDN mismatch on %s: %s (%.*s) should match one of:", + ldb_dn_get_linearized(msg->dn), rdn_name, + (int)rdn_val.length, (const char *)rdn_val.data); + for (i = 0; i < attribute->num_values; i++) { + rdn_errstring = talloc_asprintf_append( + rdn_errstring, " (%.*s)", + (int)attribute->values[i].length, + (const char *)attribute->values[i].data); + } + ldb_set_errstring(ldb, rdn_errstring); + /* Match AD's error here */ + return LDB_ERR_INVALID_DN_SYNTAX; + } + } + + ret = ldb_build_add_req(&down_req, ldb, req, + msg, + req->controls, + ac, rdn_name_add_callback, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(down_req, msg); + + /* go on with the call chain */ + return ldb_next_request(module, down_req); +} + +static int rdn_modify_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct rename_context *ac; + + ac = talloc_get_type(req->context, struct rename_context); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->type == LDB_REPLY_REFERRAL) { + return ldb_module_send_referral(ac->req, ares->referral); + } + + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + /* the only supported reply right now is a LDB_REPLY_DONE */ + if (ares->type != LDB_REPLY_DONE) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + /* send saved controls eventually */ + return ldb_module_done(ac->req, ac->ares->controls, + ac->ares->response, LDB_SUCCESS); +} + +static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + 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; + int ret; + + ac = talloc_get_type(req->context, struct rename_context); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + goto error; + } + + if (ares->type == LDB_REPLY_REFERRAL) { + return ldb_module_send_referral(ac->req, ares->referral); + } + + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + /* the only supported reply right now is a LDB_REPLY_DONE */ + if (ares->type != LDB_REPLY_DONE) { + goto error; + } + + /* save reply for caller */ + ac->ares = talloc_steal(ac, ares); + + msg = ldb_msg_new(ac); + if (msg == NULL) { + goto error; + } + msg->dn = ldb_dn_copy(msg, ac->req->op.rename.newdn); + if (msg->dn == NULL) { + goto error; + } + + rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn); + if (rdn_name == NULL) { + 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; + } + if (rdn_val_p->length == 0) { + ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", + ldb_dn_get_linearized(req->op.rename.olddn)); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_NAMING_VIOLATION); + } + rdn_val = ldb_val_dup(msg, rdn_val_p); + + if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { + goto error; + } + if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) { + goto error; + } + if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { + goto error; + } + if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) { + goto error; + } + + ret = ldb_build_mod_req(&mod_req, ldb, + ac, msg, NULL, + ac, rdn_modify_callback, + req); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + talloc_steal(mod_req, msg); + + /* go on with the call chain */ + return ldb_next_request(ac->module, mod_req); + +error: + return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); +} + +static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct rename_context *ac; + struct ldb_request *down_req; + int ret; + + ldb = ldb_module_get_ctx(module); + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.rename.newdn)) { + return ldb_next_request(module, req); + } + + ac = talloc_zero(req, struct rename_context); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->module = module; + ac->req = req; + + ret = ldb_build_rename_req(&down_req, + ldb, + ac, + req->op.rename.olddn, + req->op.rename.newdn, + req->controls, + ac, + rdn_rename_callback, + req); + + if (ret != LDB_SUCCESS) { + return ret; + } + + /* rename first, modify "name" if rename is ok */ + 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); + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.mod.message->dn)) { + 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; + } + if (rdn_val_p->length == 0) { + ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", + ldb_dn_get_linearized(req->op.mod.message->dn)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + + e = ldb_msg_find_element(req->op.mod.message, "distinguishedName"); + if (e != NULL) { + ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead", + ldb_dn_get_linearized(req->op.mod.message->dn)); + if (e->flags == LDB_FLAG_MOD_REPLACE) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } else { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + } + + if (ldb_msg_find_element(req->op.mod.message, "name")) { + ldb_asprintf_errstring(ldb, "Modify of 'name' on %s not permitted, must use 'rename' operation instead", + ldb_dn_get_linearized(req->op.mod.message->dn)); + return LDB_ERR_NOT_ALLOWED_ON_RDN; + } + + if (ldb_msg_find_element(req->op.mod.message, ldb_dn_get_rdn_name(req->op.mod.message->dn))) { + ldb_asprintf_errstring(ldb, "Modify of RDN '%s' on %s not permitted, must use 'rename' operation instead", + ldb_dn_get_rdn_name(req->op.mod.message->dn), ldb_dn_get_linearized(req->op.mod.message->dn)); + return LDB_ERR_NOT_ALLOWED_ON_RDN; + } + + /* All OK, they kept their fingers out of the special attributes */ + return ldb_next_request(module, req); +} + +static int rdn_name_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + const char *rdn_name; + const struct ldb_val *rdn_val_p; + + ldb = ldb_module_get_ctx(module); + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.search.base)) { + return ldb_next_request(module, req); + } + + rdn_name = ldb_dn_get_rdn_name(req->op.search.base); + rdn_val_p = ldb_dn_get_rdn_val(req->op.search.base); + if ((rdn_name != NULL) && (rdn_val_p == NULL)) { + return LDB_ERR_OPERATIONS_ERROR; + } + if ((rdn_val_p != NULL) && (rdn_val_p->length == 0)) { + ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", + ldb_dn_get_linearized(req->op.search.base)); + return LDB_ERR_INVALID_DN_SYNTAX; + } + + return ldb_next_request(module, req); +} + +static const struct ldb_module_ops ldb_rdn_name_module_ops = { + .name = "rdn_name", + .add = rdn_name_add, + .modify = rdn_name_modify, + .rename = rdn_name_rename, + .search = rdn_name_search +}; + +int ldb_rdn_name_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_module(&ldb_rdn_name_module_ops); +} diff --git a/ldb-2.0.8/modules/skel.c b/ldb-2.0.8/modules/skel.c new file mode 100644 index 0000000..1ce3ec1 --- /dev/null +++ b/ldb-2.0.8/modules/skel.c @@ -0,0 +1,147 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb skel module + * + * Description: example module + * + * Author: Simo Sorce + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_module.h" + +struct private_data { + + char *some_private_data; +}; + +/* search */ +static int skel_search(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +/* add */ +static int skel_add(struct ldb_module *module, struct ldb_request *req){ + return ldb_next_request(module, req); +} + +/* modify */ +static int skel_modify(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +/* delete */ +static int skel_delete(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +/* rename */ +static int skel_rename(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +/* start a transaction */ +static int skel_start_trans(struct ldb_module *module) +{ + return ldb_next_start_trans(module); +} + +/* end a transaction */ +static int skel_end_trans(struct ldb_module *module) +{ + return ldb_next_end_trans(module); +} + +/* delete a transaction */ +static int skel_del_trans(struct ldb_module *module) +{ + return ldb_next_del_trans(module); +} + +static int skel_destructor(struct ldb_module *ctx) +{ + struct private_data *data; + + data = talloc_get_type(ldb_module_get_private(ctx), struct private_data); + + /* put your clean-up functions here */ + if (data->some_private_data) talloc_free(data->some_private_data); + + return 0; +} + +static int skel_request(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +static int skel_init(struct ldb_module *module) +{ + struct ldb_context *ldb; + struct private_data *data; + + ldb = ldb_module_get_ctx(module); + + data = talloc(module, struct private_data); + if (data == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + data->some_private_data = NULL; + ldb_module_set_private(module, data); + + talloc_set_destructor (module, skel_destructor); + + return ldb_next_init(module); +} + +static const struct ldb_module_ops ldb_skel_module_ops = { + .name = "skel", + .init_context = skel_init, + .search = skel_search, + .add = skel_add, + .modify = skel_modify, + .del = skel_delete, + .rename = skel_rename, + .request = skel_request, + .start_transaction = skel_start_trans, + .end_transaction = skel_end_trans, + .del_transaction = skel_del_trans, +}; + +int ldb_skel_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_module(&ldb_skel_module_ops); +} diff --git a/ldb-2.0.8/modules/sort.c b/ldb-2.0.8/modules/sort.c new file mode 100644 index 0000000..cb6f8df --- /dev/null +++ b/ldb-2.0.8/modules/sort.c @@ -0,0 +1,402 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005-2008 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb server side sort control module + * + * Description: this module sorts the results of a search + * + * Author: Simo Sorce + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb_module.h" + +struct opaque { + struct ldb_context *ldb; + const struct ldb_attrib_handler *h; + const char *attribute; + int reverse; + int result; +}; + +struct sort_context { + struct ldb_module *module; + + const char *attributeName; + const char *orderingRule; + int reverse; + + struct ldb_request *req; + struct ldb_message **msgs; + char **referrals; + unsigned int num_msgs; + unsigned int num_refs; + const char *extra_sort_key; + + const struct ldb_schema_attribute *a; + int sort_result; +}; + +static int build_response(void *mem_ctx, struct ldb_control ***ctrls, int result, const char *desc) +{ + struct ldb_control **controls; + struct ldb_sort_resp_control *resp; + unsigned int i; + + if (*ctrls) { + controls = *ctrls; + for (i = 0; controls[i]; i++); + controls = talloc_realloc(mem_ctx, controls, struct ldb_control *, i + 2); + } else { + i = 0; + controls = talloc_array(mem_ctx, struct ldb_control *, 2); + } + if (! controls ) + return LDB_ERR_OPERATIONS_ERROR; + + *ctrls = controls; + + controls[i+1] = NULL; + controls[i] = talloc(controls, struct ldb_control); + if (! controls[i] ) + return LDB_ERR_OPERATIONS_ERROR; + + controls[i]->oid = LDB_CONTROL_SORT_RESP_OID; + controls[i]->critical = 0; + + resp = talloc(controls[i], struct ldb_sort_resp_control); + if (! resp ) + return LDB_ERR_OPERATIONS_ERROR; + + resp->result = result; + resp->attr_desc = talloc_strdup(resp, desc); + + if (! resp->attr_desc ) + return LDB_ERR_OPERATIONS_ERROR; + + controls[i]->data = resp; + + return LDB_SUCCESS; +} + +static int sort_compare(struct ldb_message **msg1, struct ldb_message **msg2, void *opaque) +{ + struct sort_context *ac = talloc_get_type(opaque, struct sort_context); + struct ldb_message_element *el1, *el2; + struct ldb_context *ldb; + + ldb = ldb_module_get_ctx(ac->module); + + if (ac->sort_result != 0) { + /* an error occurred previously, + * let's exit the sorting by returning always 0 */ + return 0; + } + + el1 = ldb_msg_find_element(*msg1, ac->attributeName); + el2 = ldb_msg_find_element(*msg2, ac->attributeName); + + if (!el1 && el2) { + return 1; + } + if (el1 && !el2) { + return -1; + } + if (!el1 && !el2) { + return 0; + } + + if (ac->reverse) + return ac->a->syntax->comparison_fn(ldb, ac, &el2->values[0], &el1->values[0]); + + return ac->a->syntax->comparison_fn(ldb, ac, &el1->values[0], &el2->values[0]); +} + +static int server_sort_results(struct sort_context *ac) +{ + struct ldb_context *ldb; + struct ldb_reply *ares; + unsigned int i; + int ret; + + ldb = ldb_module_get_ctx(ac->module); + + ac->a = ldb_schema_attribute_by_name(ldb, ac->attributeName); + ac->sort_result = 0; + + LDB_TYPESAFE_QSORT(ac->msgs, ac->num_msgs, ac, sort_compare); + + if (ac->sort_result != LDB_SUCCESS) { + return ac->sort_result; + } + + for (i = 0; i < ac->num_msgs; i++) { + ares = talloc_zero(ac, struct ldb_reply); + if (!ares) { + return LDB_ERR_OPERATIONS_ERROR; + } + + 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; + } + } + + for (i = 0; i < ac->num_refs; i++) { + ares = talloc_zero(ac, struct ldb_reply); + if (!ares) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ares->type = LDB_REPLY_REFERRAL; + ares->referral = talloc_move(ares, &ac->referrals[i]); + + ret = ldb_module_send_referral(ac->req, ares->referral); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + +static int server_sort_search_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct sort_context *ac; + struct ldb_context *ldb; + int ret; + + ac = talloc_get_type(req->context, struct sort_context); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + ac->msgs = talloc_realloc(ac, ac->msgs, struct ldb_message *, ac->num_msgs + 2); + if (! ac->msgs) { + talloc_free(ares); + ldb_oom(ldb); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ac->msgs[ac->num_msgs] = talloc_steal(ac->msgs, ares->message); + ac->num_msgs++; + ac->msgs[ac->num_msgs] = NULL; + + break; + + case LDB_REPLY_REFERRAL: + ac->referrals = talloc_realloc(ac, ac->referrals, char *, ac->num_refs + 2); + if (! ac->referrals) { + talloc_free(ares); + ldb_oom(ldb); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ac->referrals[ac->num_refs] = talloc_steal(ac->referrals, ares->referral); + ac->num_refs++; + ac->referrals[ac->num_refs] = NULL; + + break; + + case LDB_REPLY_DONE: + + ret = server_sort_results(ac); + return ldb_module_done(ac->req, ares->controls, + ares->response, ret); + } + + talloc_free(ares); + return LDB_SUCCESS; +} + +static int server_sort_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_control *control; + struct ldb_server_sort_control **sort_ctrls; + struct ldb_control **saved_controls; + struct ldb_request *down_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); + + /* check if there's a server sort control */ + control = ldb_request_get_control(req, LDB_CONTROL_SERVER_SORT_OID); + if (control == NULL) { + /* not found go on */ + return ldb_next_request(module, req); + } + + ac = talloc_zero(req, struct sort_context); + if (ac == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->module = module; + ac->req = req; + + sort_ctrls = talloc_get_type(control->data, struct ldb_server_sort_control *); + if (!sort_ctrls) { + return LDB_ERR_PROTOCOL_ERROR; + } + + /* FIXME: we do not support more than one attribute for sorting right now */ + /* FIXME: we need to check if the attribute type exist or return an error */ + + if (sort_ctrls[1] != NULL) { + if (control->critical) { + struct ldb_control **controls = NULL; + + /* callback immediately */ + ret = build_response(req, &controls, + LDB_ERR_UNWILLING_TO_PERFORM, + "sort control is not complete yet"); + if (ret != LDB_SUCCESS) { + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + return ldb_module_done(req, controls, NULL, ret); + } else { + /* just pass the call down and don't do any sorting */ + return ldb_next_request(module, 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; + + ret = ldb_build_search_req_ex(&down_req, ldb, ac, + req->op.search.base, + req->op.search.scope, + req->op.search.tree, + attrs, + req->controls, + ac, + server_sort_search_callback, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* save it locally and remove it from the list */ + /* we do not need to replace them later as we + * are keeping the original req intact */ + if (!ldb_save_controls(control, down_req, &saved_controls)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_next_request(module, down_req); +} + +static int server_sort_init(struct ldb_module *module) +{ + struct ldb_context *ldb; + int ret; + + ldb = ldb_module_get_ctx(module); + + ret = ldb_mod_register_control(module, LDB_CONTROL_SERVER_SORT_OID); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_WARNING, + "server_sort:" + "Unable to register control with rootdse!"); + } + + return ldb_next_init(module); +} + +static const struct ldb_module_ops ldb_server_sort_module_ops = { + .name = "server_sort", + .search = server_sort_search, + .init_context = server_sort_init +}; + +int ldb_server_sort_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_module(&ldb_server_sort_module_ops); +} diff --git a/ldb-2.0.8/nssldb/README.txt b/ldb-2.0.8/nssldb/README.txt new file mode 100644 index 0000000..ddba62b --- /dev/null +++ b/ldb-2.0.8/nssldb/README.txt @@ -0,0 +1,34 @@ + +This test code requires a tdb that is configured for to use the asq module. +You can do that adding the following record to a tdb: + +dn: @MODULES +@LIST: asq + +Other modules can be used as well (like rdn_name for example) + +The uidNumber 0 and the gidNumber 0 are considered invalid. + +The user records should contain the followin attributes: +uid (required) the user name +userPassword (optional) the user password (if not present "LDB" is + returned in the password field) +uidNumber (required) the user uid +gidNumber (required) the user primary gid +gecos (optional) the GECOS +homeDirectory (required) the home directory +loginShell (required) the login shell +memberOf (required) all the groups the user is member of should + be reported here using their DNs. The + primary group as well. + +The group accounts should contain the following attributes: +cn (required) the group name +uesrPassword (optional) the group password (if not present "LDB" is + returned in the password field) +gidNumber (required) the group gid +member (optional) the DNs of the member users, also the ones + that have this group as primary + + +SSS diff --git a/ldb-2.0.8/nssldb/ldb-grp.c b/ldb-2.0.8/nssldb/ldb-grp.c new file mode 100644 index 0000000..5e7556d --- /dev/null +++ b/ldb-2.0.8/nssldb/ldb-grp.c @@ -0,0 +1,429 @@ +/* + LDB nsswitch module + + Copyright (C) Simo Sorce 2006 + + 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 program. If not, see . +*/ + +#include "ldb-nss.h" + +extern struct _ldb_nss_context *_ldb_nss_ctx; + +const char *_ldb_nss_gr_attrs[] = { + "cn", + "userPassword", + "gidNumber", + NULL +}; + +const char *_ldb_nss_mem_attrs[] = { + "uid", + NULL +}; + +#define _NSS_LDB_ENOMEM(amem) \ + do { \ + if ( ! amem) { \ + errno = ENOMEM; \ + talloc_free(memctx); \ + return NSS_STATUS_UNAVAIL; \ + } \ + } while(0) + +/* This setgrent, getgrent, endgrent is not very efficient */ + +NSS_STATUS _nss_ldb_setgrent(void) +{ + int ret; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + _ldb_nss_ctx->gr_cur = 0; + if (_ldb_nss_ctx->gr_res != NULL) { + talloc_free(_ldb_nss_ctx->gr_res); + _ldb_nss_ctx->gr_res = NULL; + } + + ret = ldb_search(_ldb_nss_ctx->ldb, + _ldb_nss_ctx->ldb, + &_ldb_nss_ctx->gr_res, + _ldb_nss_ctx->base, + LDB_SCOPE_SUBTREE, + _ldb_nss_gr_attrs, + _LDB_NSS_GRENT_FILTER); + if (ret != LDB_SUCCESS) { + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _nss_ldb_endgrent(void) +{ + int ret; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + _ldb_nss_ctx->gr_cur = 0; + if (_ldb_nss_ctx->gr_res) { + talloc_free(_ldb_nss_ctx->gr_res); + _ldb_nss_ctx->gr_res = NULL; + } + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _nss_ldb_getgrent_r(struct group *result_buf, char *buffer, size_t buflen, int *errnop) +{ + int ret; + struct ldb_result *res; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + *errnop = 0; + + if (_ldb_nss_ctx->gr_cur >= _ldb_nss_ctx->gr_res->count) { + /* already returned all entries */ + return NSS_STATUS_NOTFOUND; + } + + res = talloc_zero(_ldb_nss_ctx->gr_res, struct ldb_result); + if ( ! res) { + errno = *errnop = ENOMEM; + _ldb_nss_ctx->gr_cur++; /* skip this entry */ + return NSS_STATUS_UNAVAIL; + } + + ret = _ldb_nss_group_request(&res, + _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur]->dn, + _ldb_nss_mem_attrs, + "member"); + + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno; + talloc_free(res); + _ldb_nss_ctx->gr_cur++; /* skip this entry */ + return ret; + } + + ret = _ldb_nss_fill_group(result_buf, + buffer, + buflen, + errnop, + _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur], + res); + + talloc_free(res); + + if (ret != NSS_STATUS_SUCCESS) { + if (ret != NSS_STATUS_TRYAGAIN) { + _ldb_nss_ctx->gr_cur++; /* skip this entry */ + } + return ret; + } + + /* this entry is ok, increment counter to nex entry */ + _ldb_nss_ctx->gr_cur++; + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _nss_ldb_getgrnam_r(const char *name, struct group *result_buf, char *buffer, size_t buflen, int *errnop) +{ + int ret; + char *filter; + TALLOC_CTX *ctx; + struct ldb_result *gr_res; + struct ldb_result *mem_res; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + ctx = talloc_new(_ldb_nss_ctx->ldb); + if ( ! ctx) { + *errnop = errno = ENOMEM; + return NSS_STATUS_UNAVAIL; + } + + /* build the filter for this uid */ + filter = talloc_asprintf(ctx, _LDB_NSS_GRNAM_FILTER, name); + if (filter == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOMEM; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* search the entry */ + ret = ldb_search(_ldb_nss_ctx->ldb, + _ldb_nss_ctx->ldb, + &gr_res, + _ldb_nss_ctx->base, + LDB_SCOPE_SUBTREE, + _ldb_nss_gr_attrs, + filter); + if (ret != LDB_SUCCESS) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + talloc_steal(ctx, gr_res); + + /* if none found return */ + if (gr_res->count == 0) { + *errnop = errno = ENOENT; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + if (gr_res->count != 1) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + mem_res = talloc_zero(ctx, struct ldb_result); + if ( ! mem_res) { + errno = *errnop = ENOMEM; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + ret = _ldb_nss_group_request(&mem_res, + gr_res->msgs[0]->dn, + _ldb_nss_mem_attrs, + "member"); + + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno; + goto done; + } + + ret = _ldb_nss_fill_group(result_buf, + buffer, + buflen, + errnop, + gr_res->msgs[0], + mem_res); + + if (ret != NSS_STATUS_SUCCESS) { + goto done; + } + + ret = NSS_STATUS_SUCCESS; +done: + talloc_free(ctx); + return ret; +} + +NSS_STATUS _nss_ldb_getgrgid_r(gid_t gid, struct group *result_buf, char *buffer, size_t buflen, int *errnop) +{ + int ret; + char *filter; + TALLOC_CTX *ctx; + struct ldb_result *gr_res; + struct ldb_result *mem_res; + + if (gid == 0) { /* we don't serve root gid by policy */ + *errnop = errno = ENOENT; + return NSS_STATUS_NOTFOUND; + } + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + ctx = talloc_new(_ldb_nss_ctx->ldb); + if ( ! ctx) { + *errnop = errno = ENOMEM; + return NSS_STATUS_UNAVAIL; + } + + /* build the filter for this uid */ + filter = talloc_asprintf(ctx, _LDB_NSS_GRGID_FILTER, gid); + if (filter == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOMEM; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* search the entry */ + ret = ldb_search(_ldb_nss_ctx->ldb, + _ldb_nss_ctx->ldb, + &gr_res, + _ldb_nss_ctx->base, + LDB_SCOPE_SUBTREE, + _ldb_nss_gr_attrs, + filter); + if (ret != LDB_SUCCESS) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + talloc_steal(ctx, gr_res); + + /* if none found return */ + if (gr_res->count == 0) { + *errnop = errno = ENOENT; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + if (gr_res->count != 1) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + mem_res = talloc_zero(ctx, struct ldb_result); + if ( ! mem_res) { + errno = *errnop = ENOMEM; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + ret = _ldb_nss_group_request(&mem_res, + gr_res->msgs[0]->dn, + _ldb_nss_mem_attrs, + "member"); + + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno; + goto done; + } + + ret = _ldb_nss_fill_group(result_buf, + buffer, + buflen, + errnop, + gr_res->msgs[0], + mem_res); + + if (ret != NSS_STATUS_SUCCESS) { + goto done; + } + + ret = NSS_STATUS_SUCCESS; +done: + talloc_free(ctx); + return ret; +} + +NSS_STATUS _nss_ldb_initgroups_dyn(const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop) +{ + int ret; + char *filter; + const char * attrs[] = { "uidNumber", "gidNumber", NULL }; + struct ldb_result *uid_res; + struct ldb_result *mem_res; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result); + if ( ! mem_res) { + errno = *errnop = ENOMEM; + return NSS_STATUS_UNAVAIL; + } + + /* build the filter for this name */ + filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user); + if (filter == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* search the entry */ + ret = ldb_search(_ldb_nss_ctx->ldb, + _ldb_nss_ctx->ldb, + &uid_res, + _ldb_nss_ctx->base, + LDB_SCOPE_SUBTREE, + attrs, + filter); + if (ret != LDB_SUCCESS) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + talloc_steal(mem_res, uid_res); + + /* if none found return */ + if (uid_res->count == 0) { + *errnop = errno = ENOENT; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + if (uid_res->count != 1) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + ret = _ldb_nss_group_request(&mem_res, + uid_res->msgs[0]->dn, + attrs, + "memberOf"); + + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno; + goto done; + } + + ret = _ldb_nss_fill_initgr(group, + limit, + start, + size, + groups, + errnop, + mem_res); + + if (ret != NSS_STATUS_SUCCESS) { + goto done; + } + + ret = NSS_STATUS_SUCCESS; + +done: + talloc_free(mem_res); + return ret; +} diff --git a/ldb-2.0.8/nssldb/ldb-nss.c b/ldb-2.0.8/nssldb/ldb-nss.c new file mode 100644 index 0000000..92b0635 --- /dev/null +++ b/ldb-2.0.8/nssldb/ldb-nss.c @@ -0,0 +1,395 @@ +/* + LDB nsswitch module + + Copyright (C) Simo Sorce 2006 + + 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 program. If not, see . +*/ + +#include "ldb-nss.h" + +struct _ldb_nss_context *_ldb_nss_ctx = NULL; + +NSS_STATUS _ldb_nss_init(void) +{ + int ret; + + pid_t mypid = getpid(); + + if (_ldb_nss_ctx != NULL) { + if (_ldb_nss_ctx->pid == mypid) { + /* already initialized */ + return NSS_STATUS_SUCCESS; + } else { + /* we are in a forked child now, reinitialize */ + talloc_free(_ldb_nss_ctx); + _ldb_nss_ctx = NULL; + } + } + + _ldb_nss_ctx = talloc_named(NULL, 0, "_ldb_nss_ctx(%u)", mypid); + if (_ldb_nss_ctx == NULL) { + return NSS_STATUS_UNAVAIL; + } + + _ldb_nss_ctx->pid = mypid; + + _ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx, NULL); + if (_ldb_nss_ctx->ldb == NULL) { + goto failed; + } + + ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL); + if (ret != LDB_SUCCESS) { + goto failed; + } + + _ldb_nss_ctx->base = ldb_dn_new(_ldb_nss_ctx, _ldb_nss_ctx->ldb, _LDB_NSS_BASEDN); + if ( ! ldb_dn_validate(_ldb_nss_ctx->base)) { + goto failed; + } + + _ldb_nss_ctx->pw_cur = 0; + _ldb_nss_ctx->pw_res = NULL; + _ldb_nss_ctx->gr_cur = 0; + _ldb_nss_ctx->gr_res = NULL; + + return NSS_STATUS_SUCCESS; + +failed: + /* talloc_free(_ldb_nss_ctx); */ + _ldb_nss_ctx = NULL; + return NSS_STATUS_UNAVAIL; +} + +NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result, + char *buffer, + int buflen, + int *errnop, + struct ldb_message *msg) +{ + int len; + int bufpos; + const char *tmp; + + bufpos = 0; + + /* get username */ + tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL); + if (tmp == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + return NSS_STATUS_UNAVAIL; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->pw_name = &buffer[bufpos]; + bufpos += len; + + /* get userPassword */ + tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL); + if (tmp == NULL) { + tmp = "LDB"; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->pw_passwd = &buffer[bufpos]; + bufpos += len; + + /* this backend never serves an uid 0 user */ + result->pw_uid = ldb_msg_find_attr_as_int(msg, "uidNumber", 0); + if (result->pw_uid == 0) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + return NSS_STATUS_UNAVAIL; + } + + result->pw_gid = ldb_msg_find_attr_as_int(msg, "gidNumber", 0); + if (result->pw_gid == 0) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + return NSS_STATUS_UNAVAIL; + } + + /* get gecos */ + tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL); + if (tmp == NULL) { + tmp = ""; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->pw_gecos = &buffer[bufpos]; + bufpos += len; + + /* get homeDirectory */ + tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL); + if (tmp == NULL) { + tmp = ""; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->pw_dir = &buffer[bufpos]; + bufpos += len; + + /* get shell */ + tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL); + if (tmp == NULL) { + tmp = ""; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->pw_shell = &buffer[bufpos]; + bufpos += len; + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _ldb_nss_fill_group(struct group *result, + char *buffer, + int buflen, + int *errnop, + struct ldb_message *group, + struct ldb_result *members) +{ + const char *tmp; + size_t len; + size_t bufpos; + size_t lsize; + unsigned int i; + + bufpos = 0; + + /* get group name */ + tmp = ldb_msg_find_attr_as_string(group, "cn", NULL); + if (tmp == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + return NSS_STATUS_UNAVAIL; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->gr_name = &buffer[bufpos]; + bufpos += len; + + /* get userPassword */ + tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL); + if (tmp == NULL) { + tmp = "LDB"; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->gr_passwd = &buffer[bufpos]; + bufpos += len; + + result->gr_gid = ldb_msg_find_attr_as_int(group, "gidNumber", 0); + if (result->gr_gid == 0) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + return NSS_STATUS_UNAVAIL; + } + + /* check if there is enough memory for the list of pointers */ + lsize = (members->count + 1) * sizeof(char *); + + /* align buffer on pointer boundary */ + bufpos += (sizeof(char*) - ((unsigned long)(buffer) % sizeof(char*))); + if ((buflen - bufpos) < lsize) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + + result->gr_mem = (char **)&buffer[bufpos]; + bufpos += lsize; + + for (i = 0; i < members->count; i++) { + tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL); + if (tmp == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + return NSS_STATUS_UNAVAIL; + } + len = strlen(tmp)+1; + if (bufpos + len > buflen) { + /* buffer too small */ + *errnop = errno = EAGAIN; + return NSS_STATUS_TRYAGAIN; + } + memcpy(&buffer[bufpos], tmp, len); + result->gr_mem[i] = &buffer[bufpos]; + bufpos += len; + } + + result->gr_mem[i] = NULL; + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _ldb_nss_fill_initgr(gid_t group, + long int limit, + long int *start, + long int *size, + gid_t **groups, + int *errnop, + struct ldb_result *grlist) +{ + NSS_STATUS ret; + unsigned int i; + + for (i = 0; i < grlist->count; i++) { + + if (limit && (*start > limit)) { + /* TODO: warn no all groups were reported */ + *errnop = 0; + ret = NSS_STATUS_SUCCESS; + goto done; + } + + if (*start == *size) { + /* buffer full, enlarge it */ + long int gs; + gid_t *gm; + + gs = (*size) + 32; + if (limit && (gs > limit)) { + gs = limit; + } + + gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t)); + if ( ! gm) { + *errnop = ENOMEM; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + *groups = gm; + *size = gs; + } + + (*groups)[*start] = ldb_msg_find_attr_as_int(grlist->msgs[i], "gidNumber", 0); + if ((*groups)[*start] == 0 || (*groups)[*start] == group) { + /* skip root group or primary group */ + continue; + } + (*start)++; + + } + + *errnop = 0; + ret = NSS_STATUS_SUCCESS; +done: + return ret; +} + +#define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0) + +NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res, + struct ldb_dn *group_dn, + const char * const *attrs, + const char *mattr) +{ + struct ldb_control **ctrls; + struct ldb_control *ctrl; + struct ldb_asq_control *asqc; + struct ldb_request *req; + int ret; + struct ldb_result *res = *_res; + + ctrls = talloc_array(res, struct ldb_control *, 2); + _LDB_NSS_ALLOC_CHECK(ctrls); + + ctrl = talloc(ctrls, struct ldb_control); + _LDB_NSS_ALLOC_CHECK(ctrl); + + asqc = talloc(ctrl, struct ldb_asq_control); + _LDB_NSS_ALLOC_CHECK(asqc); + + asqc->source_attribute = talloc_strdup(asqc, mattr); + _LDB_NSS_ALLOC_CHECK(asqc->source_attribute); + + asqc->request = 1; + asqc->src_attr_len = strlen(asqc->source_attribute); + ctrl->oid = LDB_CONTROL_ASQ_OID; + ctrl->critical = 1; + ctrl->data = asqc; + ctrls[0] = ctrl; + ctrls[1] = NULL; + + ret = ldb_build_search_req( + &req, + _ldb_nss_ctx->ldb, + res, + group_dn, + LDB_SCOPE_BASE, + "(objectClass=*)", + attrs, + ctrls, + res, + ldb_search_default_callback); + + if (ret != LDB_SUCCESS) { + errno = ENOENT; + return NSS_STATUS_UNAVAIL; + } + + ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0); + + ret = ldb_request(_ldb_nss_ctx->ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } else { + talloc_free(req); + return NSS_STATUS_UNAVAIL; + } + + talloc_free(req); + return NSS_STATUS_SUCCESS; +} + diff --git a/ldb-2.0.8/nssldb/ldb-nss.h b/ldb-2.0.8/nssldb/ldb-nss.h new file mode 100644 index 0000000..583876f --- /dev/null +++ b/ldb-2.0.8/nssldb/ldb-nss.h @@ -0,0 +1,84 @@ +/* + LDB nsswitch module + + Copyright (C) Simo Sorce 2006 + + 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 program. If not, see . +*/ + +#ifndef _LDB_NSS +#define _LDB_NSS + +#include "includes.h" +#include "ldb/include/includes.h" + +#include +#include +#include + +#define _LDB_NSS_URL "etc/users.ldb" +#define _LDB_NSS_BASEDN "CN=Users,CN=System" +#define _LDB_NSS_PWENT_FILTER "(&(objectClass=posixAccount)(!(uidNumber=0))(!(gidNumber=0)))" +#define _LDB_NSS_PWUID_FILTER "(&(objectClass=posixAccount)(uidNumber=%d)(!(gidNumber=0)))" +#define _LDB_NSS_PWNAM_FILTER "(&(objectClass=posixAccount)(uid=%s)(!(uidNumber=0))(!(gidNumber=0)))" + +#define _LDB_NSS_GRENT_FILTER "(&(objectClass=posixGroup)(!(gidNumber=0)))" +#define _LDB_NSS_GRGID_FILTER "(&(objectClass=posixGroup)(gidNumber=%d)))" +#define _LDB_NSS_GRNAM_FILTER "(&(objectClass=posixGroup)(cn=%s)(!(gidNumber=0)))" + +typedef enum nss_status NSS_STATUS; + +struct _ldb_nss_context { + + pid_t pid; + + struct ldb_context *ldb; + struct ldb_dn *base; + + int pw_cur; + struct ldb_result *pw_res; + + int gr_cur; + struct ldb_result *gr_res; +}; + +NSS_STATUS _ldb_nss_init(void); + +NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result, + char *buffer, + int buflen, + int *errnop, + struct ldb_message *msg); + +NSS_STATUS _ldb_nss_fill_group(struct group *result, + char *buffer, + int buflen, + int *errnop, + struct ldb_message *group, + struct ldb_result *members); + +NSS_STATUS _ldb_nss_fill_initgr(gid_t group, + long int limit, + long int *start, + long int *size, + gid_t **groups, + int *errnop, + struct ldb_result *grlist); + +NSS_STATUS _ldb_nss_group_request(struct ldb_result **res, + struct ldb_dn *group_dn, + const char * const *attrs, + const char *mattr); + +#endif /* _LDB_NSS */ diff --git a/ldb-2.0.8/nssldb/ldb-pwd.c b/ldb-2.0.8/nssldb/ldb-pwd.c new file mode 100644 index 0000000..6ab103a --- /dev/null +++ b/ldb-2.0.8/nssldb/ldb-pwd.c @@ -0,0 +1,242 @@ +/* + LDB nsswitch module + + Copyright (C) Simo Sorce 2006 + + 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 program. If not, see . +*/ + +#include "ldb-nss.h" + +extern struct _ldb_nss_context *_ldb_nss_ctx; + +const char *_ldb_nss_pw_attrs[] = { + "uid", + "userPassword", + "uidNumber", + "gidNumber", + "gecos", + "homeDirectory", + "loginShell", + NULL +}; + +NSS_STATUS _nss_ldb_setpwent(void) +{ + int ret; + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + _ldb_nss_ctx->pw_cur = 0; + if (_ldb_nss_ctx->pw_res != NULL) { + talloc_free(_ldb_nss_ctx->pw_res); + _ldb_nss_ctx->pw_res = NULL; + } + + ret = ldb_search(_ldb_nss_ctx->ldb, + _ldb_nss_ctx->ldb, + &_ldb_nss_ctx->pw_res, + _ldb_nss_ctx->base, + LDB_SCOPE_SUBTREE, + _ldb_nss_pw_attrs, + _LDB_NSS_PWENT_FILTER); + if (ret != LDB_SUCCESS) { + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _nss_ldb_endpwent(void) +{ + int ret; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + _ldb_nss_ctx->pw_cur = 0; + if (_ldb_nss_ctx->pw_res) { + talloc_free(_ldb_nss_ctx->pw_res); + _ldb_nss_ctx->pw_res = NULL; + } + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _nss_ldb_getpwent_r(struct passwd *result_buf, + char *buffer, + int buflen, + int *errnop) +{ + int ret; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + *errnop = 0; + + if (_ldb_nss_ctx->pw_cur >= _ldb_nss_ctx->pw_res->count) { + /* already returned all entries */ + return NSS_STATUS_NOTFOUND; + } + + ret = _ldb_nss_fill_passwd(result_buf, + buffer, + buflen, + errnop, + _ldb_nss_ctx->pw_res->msgs[_ldb_nss_ctx->pw_cur]); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + _ldb_nss_ctx->pw_cur++; + + return NSS_STATUS_SUCCESS; +} + +NSS_STATUS _nss_ldb_getpwuid_r(uid_t uid, struct passwd *result_buf, char *buffer, size_t buflen, int *errnop) +{ + int ret; + char *filter; + struct ldb_result *res; + + if (uid == 0) { /* we don't serve root uid by policy */ + *errnop = errno = ENOENT; + return NSS_STATUS_NOTFOUND; + } + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + /* build the filter for this uid */ + filter = talloc_asprintf(_ldb_nss_ctx, _LDB_NSS_PWUID_FILTER, uid); + if (filter == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOMEM; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* search the entry */ + ret = ldb_search(_ldb_nss_ctx->ldb, + _ldb_nss_ctx->ldb, + &res, + _ldb_nss_ctx->base, + LDB_SCOPE_SUBTREE, + _ldb_nss_pw_attrs, + filter); + if (ret != LDB_SUCCESS) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* if none found return */ + if (res->count == 0) { + *errnop = errno = ENOENT; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + if (res->count != 1) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* fill in the passwd struct */ + ret = _ldb_nss_fill_passwd(result_buf, + buffer, + buflen, + errnop, + res->msgs[0]); + +done: + talloc_free(filter); + talloc_free(res); + return ret; +} + +NSS_STATUS _nss_ldb_getpwnam_r(const char *name, struct passwd *result_buf, char *buffer, size_t buflen, int *errnop) +{ + int ret; + char *filter; + struct ldb_result *res; + + ret = _ldb_nss_init(); + if (ret != NSS_STATUS_SUCCESS) { + return ret; + } + + /* build the filter for this name */ + filter = talloc_asprintf(_ldb_nss_ctx, _LDB_NSS_PWNAM_FILTER, name); + if (filter == NULL) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* search the entry */ + ret = ldb_search(_ldb_nss_ctx->ldb, + _ldb_nss_ctx->ldb, + &res, + _ldb_nss_ctx->base, + LDB_SCOPE_SUBTREE, + _ldb_nss_pw_attrs, + filter); + if (ret != LDB_SUCCESS) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* if none found return */ + if (res->count == 0) { + *errnop = errno = ENOENT; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + if (res->count != 1) { + /* this is a fatal error */ + *errnop = errno = ENOENT; + ret = NSS_STATUS_UNAVAIL; + goto done; + } + + /* fill in the passwd struct */ + ret = _ldb_nss_fill_passwd(result_buf, + buffer, + buflen, + errnop, + res->msgs[0]); + +done: + talloc_free(filter); + talloc_free(res); + return ret; +} + diff --git a/ldb-2.0.8/pyldb-util.pc.in b/ldb-2.0.8/pyldb-util.pc.in new file mode 100644 index 0000000..60ec702 --- /dev/null +++ b/ldb-2.0.8/pyldb-util.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +modulesdir=@LDB_MODULESDIR@ + +Name: pyldb-util@PYTHON_SO_ABI_FLAG@ +Description: Python bindings for LDB +Version: @PACKAGE_VERSION@ +Requires: ldb +Libs: @LIB_RPATH@ -L${libdir} -lpyldb-util@PYTHON_LIBNAME_SO_ABI_FLAG@ +Cflags: -I${includedir} +URL: http://ldb.samba.org/ diff --git a/ldb-2.0.8/pyldb.c b/ldb-2.0.8/pyldb.c new file mode 100644 index 0000000..868e366 --- /dev/null +++ b/ldb-2.0.8/pyldb.c @@ -0,0 +1,4470 @@ +/* + Unix SMB/CIFS implementation. + + Python interface to ldb. + + Copyright (C) 2005,2006 Tim Potter + Copyright (C) 2006 Simo Sorce + Copyright (C) 2007-2010 Jelmer Vernooij + Copyright (C) 2009-2010 Matthias Dieter Wallnöfer + Copyright (C) 2009-2011 Andrew Tridgell + Copyright (C) 2009-2011 Andrew Bartlett + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include +#include "ldb_private.h" +#include "ldb_handlers.h" +#include "pyldb.h" +#include "dlinklist.h" + +/* discard signature of 'func' in favour of 'target_sig' */ +#define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func + +struct py_ldb_search_iterator_reply; + +typedef struct { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + PyLdbObject *ldb; + struct { + struct ldb_request *req; + struct py_ldb_search_iterator_reply *next; + struct py_ldb_search_iterator_reply *result; + PyObject *exception; + } state; +} PyLdbSearchIteratorObject; + +struct py_ldb_search_iterator_reply { + struct py_ldb_search_iterator_reply *prev, *next; + PyLdbSearchIteratorObject *py_iter; + PyObject *obj; +}; + +void initldb(void); +static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg); +static PyObject *PyExc_LdbError; + +static PyTypeObject PyLdbControl; +static PyTypeObject PyLdbResult; +static PyTypeObject PyLdbSearchIterator; +static PyTypeObject PyLdbMessage; +#define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage) +static PyTypeObject PyLdbModule; +static PyTypeObject PyLdbDn; +#define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn) +static PyTypeObject PyLdb; +#define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb) +static PyTypeObject PyLdbMessageElement; +#define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement) + +static PyTypeObject PyLdbTree; +static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx); +static PyObject *PyLdbModule_FromModule(struct ldb_module *mod); +static struct ldb_message_element *PyObject_AsMessageElement( + TALLOC_CTX *mem_ctx, + PyObject *set_obj, + unsigned int flags, + const char *attr_name); +static PyTypeObject PyLdbBytesType; + +#if PY_MAJOR_VERSION >= 3 +#define PyInt_FromLong PyLong_FromLong + +#define PYARG_STR_UNI "es" + +static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size) +{ + PyObject* result = NULL; + PyObject* args = NULL; + args = Py_BuildValue("(y#)", msg, size); + result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL); + Py_DECREF(args); + return result; +} +#else +#define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize + +#define PYARG_STR_UNI "et" + +#endif + +static PyObject *richcmp(int cmp_val, int op) +{ + int ret; + switch (op) { + case Py_LT: ret = cmp_val < 0; break; + case Py_LE: ret = cmp_val <= 0; break; + case Py_EQ: ret = cmp_val == 0; break; + case Py_NE: ret = cmp_val != 0; break; + case Py_GT: ret = cmp_val > 0; break; + case Py_GE: ret = cmp_val >= 0; break; + default: + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + return PyBool_FromLong(ret); +} + + +static PyObject *py_ldb_control_str(PyLdbControlObject *self) +{ + if (self->data != NULL) { + char* control = ldb_control_to_string(self->mem_ctx, self->data); + if (control == NULL) { + PyErr_NoMemory(); + return NULL; + } + return PyUnicode_FromString(control); + } else { + return PyUnicode_FromString("ldb control"); + } +} + +static void py_ldb_control_dealloc(PyLdbControlObject *self) +{ + if (self->mem_ctx != NULL) { + talloc_free(self->mem_ctx); + } + self->data = NULL; + Py_TYPE(self)->tp_free(self); +} + +/* Create a text (rather than bytes) interface for a LDB result object */ +static PyObject *wrap_text(const char *type, PyObject *wrapped) +{ + PyObject *mod, *cls, *constructor, *inst; + mod = PyImport_ImportModule("_ldb_text"); + if (mod == NULL) + return NULL; + cls = PyObject_GetAttrString(mod, type); + Py_DECREF(mod); + if (cls == NULL) { + Py_DECREF(mod); + return NULL; + } + constructor = PyObject_GetAttrString(cls, "_wrap"); + Py_DECREF(cls); + if (constructor == NULL) { + return NULL; + } + inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped); + Py_DECREF(constructor); + return inst; +} + +static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyUnicode_FromString(self->data->oid); +} + +static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyBool_FromLong(self->data->critical); +} + +static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure) +{ + if (PyObject_IsTrue(value)) { + self->data->critical = true; + } else { + self->data->critical = false; + } + return 0; +} + +static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + char *data = NULL; + const char * const kwnames[] = { "ldb", "data", NULL }; + struct ldb_control *parsed_controls; + PyLdbControlObject *ret; + PyObject *py_ldb; + TALLOC_CTX *mem_ctx; + struct ldb_context *ldb_ctx; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s", + discard_const_p(char *, kwnames), + &PyLdb, &py_ldb, &data)) + return NULL; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb); + parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data); + + if (!parsed_controls) { + talloc_free(mem_ctx); + PyErr_SetString(PyExc_ValueError, "unable to parse control string"); + return NULL; + } + + ret = PyObject_New(PyLdbControlObject, type); + if (ret == NULL) { + PyErr_NoMemory(); + talloc_free(mem_ctx); + return NULL; + } + + ret->mem_ctx = mem_ctx; + + ret->data = talloc_move(mem_ctx, &parsed_controls); + if (ret->data == NULL) { + Py_DECREF(ret); + PyErr_NoMemory(); + talloc_free(mem_ctx); + return NULL; + } + + return (PyObject *)ret; +} + +static PyGetSetDef py_ldb_control_getset[] = { + { + .name = discard_const_p(char, "oid"), + .get = (getter)py_ldb_control_get_oid, + }, + { + .name = discard_const_p(char, "critical"), + .get = (getter)py_ldb_control_get_critical, + .set = (setter)py_ldb_control_set_critical, + }, + { .name = NULL }, +}; + +static PyTypeObject PyLdbControl = { + .tp_name = "ldb.control", + .tp_dealloc = (destructor)py_ldb_control_dealloc, + .tp_getattro = PyObject_GenericGetAttr, + .tp_basicsize = sizeof(PyLdbControlObject), + .tp_getset = py_ldb_control_getset, + .tp_doc = "LDB control.", + .tp_str = (reprfunc)py_ldb_control_str, + .tp_new = py_ldb_control_new, + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, +}; + +static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx) +{ + if (ret == LDB_ERR_PYTHON_EXCEPTION) + return; /* Python exception should already be set, just keep that */ + + PyErr_SetObject(error, + Py_BuildValue(discard_const_p(char, "(i,s)"), ret, + ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx))); +} +static PyObject *py_ldb_bytes_str(PyBytesObject *self) +{ + char *msg = NULL; + Py_ssize_t size; + int result = 0; + if (!PyBytes_Check(self)) { + PyErr_Format(PyExc_TypeError,"Unexpected type"); + return NULL; + } + result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size); + if (result != 0) { + PyErr_Format(PyExc_TypeError, "Failed to extract bytes"); + return NULL; + } + return PyUnicode_FromStringAndSize(msg, size); +} + +static PyTypeObject PyLdbBytesType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "ldb.bytes", + .tp_doc = "str/bytes (with custom str)", + .tp_str = (reprfunc)py_ldb_bytes_str, + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, +}; + +static PyObject *PyObject_FromLdbValue(const struct ldb_val *val) +{ + return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length); +} + +static PyObject *PyStr_FromLdbValue(const struct ldb_val *val) +{ + return PyUnicode_FromStringAndSize((const char *)val->data, val->length); +} + +/** + * Create a Python object from a ldb_result. + * + * @param result LDB result to convert + * @return Python object with converted result (a list object) + */ +static PyObject *PyLdbControl_FromControl(struct ldb_control *control) +{ + TALLOC_CTX *ctl_ctx = talloc_new(NULL); + PyLdbControlObject *ctrl; + if (ctl_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0); + if (ctrl == NULL) { + talloc_free(ctl_ctx); + PyErr_NoMemory(); + return NULL; + } + ctrl->mem_ctx = ctl_ctx; + ctrl->data = talloc_steal(ctrl->mem_ctx, control); + if (ctrl->data == NULL) { + Py_DECREF(ctrl); + PyErr_NoMemory(); + return NULL; + } + return (PyObject*) ctrl; +} + +/** + * Create a Python object from a ldb_result. + * + * @param result LDB result to convert + * @return Python object with converted result (a list object) + */ +static PyObject *PyLdbResult_FromResult(struct ldb_result *result) +{ + PyLdbResultObject *ret; + PyObject *list, *controls, *referals; + Py_ssize_t i; + + if (result == NULL) { + Py_RETURN_NONE; + } + + ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + + list = PyList_New(result->count); + if (list == NULL) { + PyErr_NoMemory(); + Py_DECREF(ret); + return NULL; + } + + for (i = 0; i < result->count; i++) { + PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i])); + } + + ret->mem_ctx = talloc_new(NULL); + if (ret->mem_ctx == NULL) { + Py_DECREF(list); + Py_DECREF(ret); + PyErr_NoMemory(); + return NULL; + } + + ret->msgs = list; + + if (result->controls) { + i = 0; + while (result->controls[i]) { + i++; + } + controls = PyList_New(i); + if (controls == NULL) { + Py_DECREF(ret); + PyErr_NoMemory(); + return NULL; + } + for (i=0; result->controls[i]; i++) { + PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]); + if (ctrl == NULL) { + Py_DECREF(ret); + Py_DECREF(controls); + PyErr_NoMemory(); + return NULL; + } + PyList_SetItem(controls, i, ctrl); + } + } else { + /* + * No controls so we keep an empty list + */ + controls = PyList_New(0); + if (controls == NULL) { + Py_DECREF(ret); + PyErr_NoMemory(); + return NULL; + } + } + + ret->controls = controls; + + i = 0; + + while (result->refs && result->refs[i]) { + i++; + } + + referals = PyList_New(i); + if (referals == NULL) { + Py_DECREF(ret); + PyErr_NoMemory(); + return NULL; + } + + for (i = 0;result->refs && result->refs[i]; i++) { + PyList_SetItem(referals, i, PyUnicode_FromString(result->refs[i])); + } + ret->referals = referals; + return (PyObject *)ret; +} + +/** + * Create a LDB Result from a Python object. + * If conversion fails, NULL will be returned and a Python exception set. + * + * Note: the result object only includes the messages at the moment; extended + * result, controls and referrals are ignored. + * + * @param mem_ctx Memory context in which to allocate the LDB Result + * @param obj Python object to convert + * @return a ldb_result, or NULL if the conversion failed + */ +static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, + PyObject *obj) +{ + struct ldb_result *res; + Py_ssize_t i; + + if (obj == Py_None) + return NULL; + + res = talloc_zero(mem_ctx, struct ldb_result); + res->count = PyList_Size(obj); + res->msgs = talloc_array(res, struct ldb_message *, res->count); + for (i = 0; i < res->count; i++) { + PyObject *item = PyList_GetItem(obj, i); + res->msgs[i] = pyldb_Message_AsMessage(item); + } + return res; +} + +static PyObject *py_ldb_dn_validate(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyBool_FromLong(ldb_dn_validate(self->dn)); +} + +static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyBool_FromLong(ldb_dn_is_valid(self->dn)); +} + +static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyBool_FromLong(ldb_dn_is_special(self->dn)); +} + +static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyBool_FromLong(ldb_dn_is_null(self->dn)); +} + +static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyUnicode_FromString(ldb_dn_get_casefold(self->dn)); +} + +static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self) +{ + return PyUnicode_FromString(ldb_dn_get_linearized(self->dn)); +} + +static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyUnicode_FromString(ldb_dn_canonical_string(self->dn, self->dn)); +} + +static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyUnicode_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn)); +} + +static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs) +{ + const char * const kwnames[] = { "mode", NULL }; + int mode = 1; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", + discard_const_p(char *, kwnames), + &mode)) + return NULL; + return PyUnicode_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode)); +} + +static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args) +{ + char *name; + const struct ldb_val *val; + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + val = ldb_dn_get_extended_component(self->dn, name); + if (val == NULL) { + Py_RETURN_NONE; + } + + return PyBytes_FromStringAndSize((const char *)val->data, val->length); +} + +static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args) +{ + char *name; + int err; + uint8_t *value = NULL; + Py_ssize_t size = 0; + + if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size)) + return NULL; + + if (value == NULL) { + err = ldb_dn_set_extended_component(self->dn, name, NULL); + } else { + struct ldb_val val; + val.data = (uint8_t *)value; + val.length = size; + err = ldb_dn_set_extended_component(self->dn, name, &val); + } + + if (err != LDB_SUCCESS) { + PyErr_SetString(PyExc_TypeError, "Failed to set extended component"); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_dn_repr(PyLdbDnObject *self) +{ + PyObject *str = PyUnicode_FromString(ldb_dn_get_linearized(self->dn)); + PyObject *repr, *result; + if (str == NULL) + return NULL; + repr = PyObject_Repr(str); + if (repr == NULL) { + Py_DECREF(str); + return NULL; + } + result = PyUnicode_FromFormat("Dn(%s)", PyUnicode_AsUTF8(repr)); + Py_DECREF(str); + Py_DECREF(repr); + return result; +} + +static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args) +{ + char *name; + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + return PyBool_FromLong(ldb_dn_check_special(self->dn, name)); +} + +static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op) +{ + int ret; + if (!pyldb_Dn_Check(dn2)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + ret = ldb_dn_compare(pyldb_Dn_AsDn(dn1), pyldb_Dn_AsDn(dn2)); + return richcmp(ret, op); +} + +static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self); + struct ldb_dn *parent; + PyLdbDnObject *py_ret; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + parent = ldb_dn_get_parent(mem_ctx, dn); + if (parent == NULL) { + talloc_free(mem_ctx); + Py_RETURN_NONE; + } + + py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0); + if (py_ret == NULL) { + PyErr_NoMemory(); + talloc_free(mem_ctx); + return NULL; + } + py_ret->mem_ctx = mem_ctx; + py_ret->dn = parent; + return (PyObject *)py_ret; +} + +static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args) +{ + PyObject *py_other; + struct ldb_dn *dn, *other; + if (!PyArg_ParseTuple(args, "O", &py_other)) + return NULL; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other)) + return NULL; + + return PyBool_FromLong(ldb_dn_add_child(dn, other)); +} + +static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args) +{ + PyObject *py_other; + struct ldb_dn *other, *dn; + if (!PyArg_ParseTuple(args, "O", &py_other)) + return NULL; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other)) + return NULL; + + return PyBool_FromLong(ldb_dn_add_base(dn, other)); +} + +static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args) +{ + struct ldb_dn *dn; + int i; + if (!PyArg_ParseTuple(args, "i", &i)) + return NULL; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + return PyBool_FromLong(ldb_dn_remove_base_components(dn, i)); +} + +static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args) +{ + PyObject *py_base; + struct ldb_dn *dn, *base; + if (!PyArg_ParseTuple(args, "O", &py_base)) + return NULL; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base)) + return NULL; + + return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0); +} + +static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args) +{ + struct ldb_dn *dn; + const char *name; + unsigned int num = 0; + + if (!PyArg_ParseTuple(args, "I", &num)) + return NULL; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + name = ldb_dn_get_component_name(dn, num); + if (name == NULL) { + Py_RETURN_NONE; + } + + return PyUnicode_FromString(name); +} + +static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args) +{ + struct ldb_dn *dn; + const struct ldb_val *val; + unsigned int num = 0; + + if (!PyArg_ParseTuple(args, "I", &num)) + return NULL; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + val = ldb_dn_get_component_val(dn, num); + if (val == NULL) { + Py_RETURN_NONE; + } + + return PyStr_FromLdbValue(val); +} + +static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args) +{ + unsigned int num = 0; + char *name = NULL, *value = NULL; + struct ldb_val val = { NULL, }; + int err; + Py_ssize_t size = 0; + + if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size)) + return NULL; + + val.data = (unsigned char*) value; + val.length = size; + + err = ldb_dn_set_component(self->dn, num, name, val); + if (err != LDB_SUCCESS) { + PyErr_SetString(PyExc_TypeError, "Failed to set component"); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_dn *dn; + const char *name; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + name = ldb_dn_get_rdn_name(dn); + if (name == NULL) { + Py_RETURN_NONE; + } + + return PyUnicode_FromString(name); +} + +static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_dn *dn; + const struct ldb_val *val; + + dn = pyldb_Dn_AsDn((PyObject *)self); + + val = ldb_dn_get_rdn_val(dn); + if (val == NULL) { + Py_RETURN_NONE; + } + + return PyStr_FromLdbValue(val); +} + +static PyMethodDef py_ldb_dn_methods[] = { + { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS, + "S.validate() -> bool\n" + "Validate DN is correct." }, + { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS, + "S.is_valid() -> bool\n" }, + { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS, + "S.is_special() -> bool\n" + "Check whether this is a special LDB DN." }, + { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS, + "Check whether this is a null DN." }, + { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS, + NULL }, + { "get_linearized", PY_DISCARD_FUNC_SIG(PyCFunction, + py_ldb_dn_get_linearized), + METH_NOARGS, + NULL }, + { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS, + "S.canonical_str() -> string\n" + "Canonical version of this DN (like a posix path)." }, + { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS, + "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"}, + { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS, + "S.canonical_ex_str() -> string\n" + "Canonical version of this DN (like a posix path, with terminating newline)." }, + { "extended_str", PY_DISCARD_FUNC_SIG(PyCFunction, + py_ldb_dn_extended_str), + METH_VARARGS | METH_KEYWORDS, + "S.extended_str(mode=1) -> string\n" + "Extended version of this DN" }, + { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS, + "S.parent() -> dn\n" + "Get the parent for this DN." }, + { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS, + "S.add_child(dn) -> None\n" + "Add a child DN to this DN." }, + { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS, + "S.add_base(dn) -> None\n" + "Add a base DN to this DN." }, + { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS, + "S.remove_base_components(int) -> bool\n" + "Remove a number of DN components from the base of this DN." }, + { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS, + "S.check_special(name) -> bool\n\n" + "Check if name is a special DN name"}, + { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS, + "S.get_extended_component(name) -> string\n\n" + "returns a DN extended component as a binary string"}, + { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS, + "S.set_extended_component(name, value) -> None\n\n" + "set a DN extended component as a binary string"}, + { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS, + "S.get_component_name(num) -> string\n" + "get the attribute name of the specified component" }, + { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS, + "S.get_component_value(num) -> string\n" + "get the attribute value of the specified component as a binary string" }, + { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS, + "S.get_component_value(num, name, value) -> None\n" + "set the attribute name and value of the specified component" }, + { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS, + "S.get_rdn_name() -> string\n" + "get the RDN attribute name" }, + { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS, + "S.get_rdn_value() -> string\n" + "get the RDN attribute value as a binary string" }, + { NULL } +}; + +static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self) +{ + return ldb_dn_get_comp_num(pyldb_Dn_AsDn((PyObject *)self)); +} + +/* + copy a DN as a python object + */ +static PyObject *py_ldb_dn_copy(struct ldb_dn *dn) +{ + PyLdbDnObject *py_ret; + + py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0); + if (py_ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + py_ret->mem_ctx = talloc_new(NULL); + py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn); + return (PyObject *)py_ret; +} + +static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other) +{ + struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self), + *other; + PyLdbDnObject *py_ret; + + if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other)) + return NULL; + + py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0); + if (py_ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + py_ret->mem_ctx = talloc_new(NULL); + py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn); + ldb_dn_add_base(py_ret->dn, other); + return (PyObject *)py_ret; +} + +static PySequenceMethods py_ldb_dn_seq = { + .sq_length = (lenfunc)py_ldb_dn_len, + .sq_concat = (binaryfunc)py_ldb_dn_concat, +}; + +static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + struct ldb_dn *ret = NULL; + char *str = NULL; + PyObject *py_ldb = NULL; + struct ldb_context *ldb_ctx = NULL; + TALLOC_CTX *mem_ctx = NULL; + PyLdbDnObject *py_ret = NULL; + const char * const kwnames[] = { "ldb", "dn", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O"PYARG_STR_UNI, + discard_const_p(char *, kwnames), + &py_ldb, "utf8", &str)) + goto out; + + if (!PyLdb_Check(py_ldb)) { + PyErr_SetString(PyExc_TypeError, "Expected Ldb"); + goto out; + } + + ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb); + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + goto out; + } + + ret = ldb_dn_new(mem_ctx, ldb_ctx, str); + if (!ldb_dn_validate(ret)) { + talloc_free(mem_ctx); + PyErr_SetString(PyExc_ValueError, "unable to parse dn string"); + goto out; + } + + py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0); + if (py_ret == NULL) { + talloc_free(mem_ctx); + PyErr_NoMemory(); + goto out; + } + py_ret->mem_ctx = mem_ctx; + py_ret->dn = ret; +out: + if (str != NULL) { + PyMem_Free(discard_const_p(char, str)); + } + return (PyObject *)py_ret; +} + +static void py_ldb_dn_dealloc(PyLdbDnObject *self) +{ + talloc_free(self->mem_ctx); + PyObject_Del(self); +} + +static PyTypeObject PyLdbDn = { + .tp_name = "ldb.Dn", + .tp_methods = py_ldb_dn_methods, + .tp_str = (reprfunc)py_ldb_dn_get_linearized, + .tp_repr = (reprfunc)py_ldb_dn_repr, + .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp, + .tp_as_sequence = &py_ldb_dn_seq, + .tp_doc = "A LDB distinguished name.", + .tp_new = py_ldb_dn_new, + .tp_dealloc = (destructor)py_ldb_dn_dealloc, + .tp_basicsize = sizeof(PyLdbDnObject), + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +/* Debug */ +static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0); +static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) +{ + PyObject *fn = (PyObject *)context; + PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyUnicode_FromFormatV(fmt, ap)); +} + +static PyObject *py_ldb_debug_func; + +static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args) +{ + PyObject *cb; + struct ldb_context *ldb_ctx; + + if (!PyArg_ParseTuple(args, "O", &cb)) + return NULL; + + if (py_ldb_debug_func != NULL) { + Py_DECREF(py_ldb_debug_func); + } + + Py_INCREF(cb); + /* FIXME: DECREF cb when exiting program */ + py_ldb_debug_func = cb; + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, + ldb_set_debug(ldb_ctx, py_ldb_debug, cb), + ldb_ctx); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args) +{ + unsigned int perms; + if (!PyArg_ParseTuple(args, "I", &perms)) + return NULL; + + ldb_set_create_perms(pyldb_Ldb_AsLdbContext(self), perms); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args) +{ + char *modules_dir; + if (!PyArg_ParseTuple(args, "s", &modules_dir)) + return NULL; + + ldb_set_modules_dir(pyldb_Ldb_AsLdbContext(self), modules_dir); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_transaction_start(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self); + int ldb_err; + ldb_err = ldb_transaction_start(ldb_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_transaction_commit(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self); + int ldb_err; + ldb_err = ldb_transaction_commit(ldb_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self); + int ldb_err; + ldb_err = ldb_transaction_prepare_commit(ldb_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_transaction_cancel(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self); + int ldb_err; + ldb_err = ldb_transaction_cancel(ldb_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self); + int ldb_err; + ldb_err = ldb_setup_wellknown_attributes(ldb_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_repr(PyLdbObject *self) +{ + return PyUnicode_FromString(""); +} + +static PyObject *py_ldb_get_root_basedn(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AsLdbContext(self)); + if (dn == NULL) + Py_RETURN_NONE; + return py_ldb_dn_copy(dn); +} + + +static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AsLdbContext(self)); + if (dn == NULL) + Py_RETURN_NONE; + return py_ldb_dn_copy(dn); +} + +static PyObject *py_ldb_get_config_basedn(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AsLdbContext(self)); + if (dn == NULL) + Py_RETURN_NONE; + return py_ldb_dn_copy(dn); +} + +static PyObject *py_ldb_get_default_basedn(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AsLdbContext(self)); + if (dn == NULL) + Py_RETURN_NONE; + return py_ldb_dn_copy(dn); +} + +static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list, + const char *paramname) +{ + const char **ret; + Py_ssize_t i; + if (!PyList_Check(list)) { + PyErr_Format(PyExc_TypeError, "%s is not a list", paramname); + return NULL; + } + ret = talloc_array(NULL, const char *, PyList_Size(list)+1); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + + for (i = 0; i < PyList_Size(list); i++) { + const char *str = NULL; + Py_ssize_t size; + PyObject *item = PyList_GetItem(list, i); + if (!PyUnicode_Check(item)) { + PyErr_Format(PyExc_TypeError, "%s should be strings", paramname); + talloc_free(ret); + return NULL; + } + str = PyUnicode_AsUTF8AndSize(item, &size); + if (str == NULL) { + talloc_free(ret); + return NULL; + } + ret[i] = talloc_strndup(ret, str, size); + } + ret[i] = NULL; + return ret; +} + +static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + const char * const kwnames[] = { "url", "flags", "options", NULL }; + char *url = NULL; + PyObject *py_options = Py_None; + const char **options; + unsigned int flags = 0; + int ret; + struct ldb_context *ldb; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__", + discard_const_p(char *, kwnames), + &url, &flags, &py_options)) + return -1; + + ldb = pyldb_Ldb_AsLdbContext(self); + + if (py_options == Py_None) { + options = NULL; + } else { + options = PyList_AsStrList(ldb, py_options, "options"); + if (options == NULL) + return -1; + } + + if (url != NULL) { + ret = ldb_connect(ldb, url, flags, options); + if (ret != LDB_SUCCESS) { + PyErr_SetLdbError(PyExc_LdbError, ret, ldb); + return -1; + } + } else { + ldb_set_flags(ldb, flags); + } + + talloc_free(options); + return 0; +} + +static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyLdbObject *ret; + struct ldb_context *ldb; + ret = (PyLdbObject *)type->tp_alloc(type, 0); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + ret->mem_ctx = talloc_new(NULL); + ldb = ldb_init(ret->mem_ctx, NULL); + + if (ldb == NULL) { + PyErr_NoMemory(); + return NULL; + } + + ret->ldb_ctx = ldb; + return (PyObject *)ret; +} + +static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + char *url = NULL; + unsigned int flags = 0; + PyObject *py_options = Py_None; + int ret; + const char **options; + const char * const kwnames[] = { "url", "flags", "options", NULL }; + struct ldb_context *ldb_ctx; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO", + discard_const_p(char *, kwnames), + &url, &flags, &py_options)) + return NULL; + + if (py_options == Py_None) { + options = NULL; + } else { + options = PyList_AsStrList(NULL, py_options, "options"); + if (options == NULL) + return NULL; + } + + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + ret = ldb_connect(ldb_ctx, url, flags, options); + talloc_free(options); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_msg; + PyObject *py_controls = Py_None; + struct ldb_context *ldb_ctx; + struct ldb_request *req; + struct ldb_control **parsed_controls; + struct ldb_message *msg; + int ret; + TALLOC_CTX *mem_ctx; + bool validate=true; + const char * const kwnames[] = { "message", "controls", "validate", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob", + discard_const_p(char *, kwnames), + &py_msg, &py_controls, &validate)) + return NULL; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + + if (py_controls == Py_None) { + parsed_controls = NULL; + } else { + const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } + parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); + talloc_free(controls); + } + + if (!PyLdbMessage_Check(py_msg)) { + PyErr_SetString(PyExc_TypeError, "Expected Ldb Message"); + talloc_free(mem_ctx); + return NULL; + } + msg = pyldb_Message_AsMessage(py_msg); + + if (validate) { + ret = ldb_msg_sanity_check(ldb_ctx, msg); + if (ret != LDB_SUCCESS) { + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + talloc_free(mem_ctx); + return NULL; + } + } + + ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls, + NULL, ldb_op_default_callback, NULL); + if (ret != LDB_SUCCESS) { + PyErr_SetString(PyExc_TypeError, "failed to build request"); + talloc_free(mem_ctx); + return NULL; + } + + /* do request and autostart a transaction */ + /* Then let's LDB handle the message error in case of pb as they are meaningful */ + + ret = ldb_transaction_start(ldb_ctx); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + ret = ldb_request(ldb_ctx, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret == LDB_SUCCESS) { + ret = ldb_transaction_commit(ldb_ctx); + } else { + ldb_transaction_cancel(ldb_ctx); + } + + talloc_free(mem_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); + + Py_RETURN_NONE; +} + + +/** + * Obtain a ldb message from a Python Dictionary object. + * + * @param mem_ctx Memory context + * @param py_obj Python Dictionary object + * @param ldb_ctx LDB context + * @param mod_flags Flags to be set on every message element + * @return ldb_message on success or NULL on failure + */ +static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx, + PyObject *py_obj, + struct ldb_context *ldb_ctx, + unsigned int mod_flags) +{ + struct ldb_message *msg; + unsigned int msg_pos = 0; + Py_ssize_t dict_pos = 0; + PyObject *key, *value; + struct ldb_message_element *msg_el; + PyObject *dn_value = PyDict_GetItemString(py_obj, "dn"); + + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + PyErr_NoMemory(); + return NULL; + } + msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj)); + + if (dn_value) { + if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) { + PyErr_SetString(PyExc_TypeError, "unable to import dn object"); + return NULL; + } + if (msg->dn == NULL) { + PyErr_SetString(PyExc_TypeError, "dn set but not found"); + return NULL; + } + } else { + PyErr_SetString(PyExc_TypeError, "no dn set"); + return NULL; + } + + while (PyDict_Next(py_obj, &dict_pos, &key, &value)) { + const char *key_str = PyUnicode_AsUTF8(key); + if (ldb_attr_cmp(key_str, "dn") != 0) { + msg_el = PyObject_AsMessageElement(msg->elements, value, + mod_flags, key_str); + if (msg_el == NULL) { + PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str); + return NULL; + } + memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el)); + msg_pos++; + } + } + + msg->num_elements = msg_pos; + + return msg; +} + +static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_obj; + int ret; + struct ldb_context *ldb_ctx; + struct ldb_request *req; + struct ldb_message *msg = NULL; + PyObject *py_controls = Py_None; + TALLOC_CTX *mem_ctx; + struct ldb_control **parsed_controls; + const char * const kwnames[] = { "message", "controls", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", + discard_const_p(char *, kwnames), + &py_obj, &py_controls)) + return NULL; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + + if (py_controls == Py_None) { + parsed_controls = NULL; + } else { + const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } + parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); + talloc_free(controls); + } + + if (PyLdbMessage_Check(py_obj)) { + msg = pyldb_Message_AsMessage(py_obj); + } else if (PyDict_Check(py_obj)) { + msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD); + } else { + PyErr_SetString(PyExc_TypeError, + "Dictionary or LdbMessage object expected!"); + } + + if (!msg) { + /* we should have a PyErr already set */ + talloc_free(mem_ctx); + return NULL; + } + + ret = ldb_msg_sanity_check(ldb_ctx, msg); + if (ret != LDB_SUCCESS) { + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + talloc_free(mem_ctx); + return NULL; + } + + ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls, + NULL, ldb_op_default_callback, NULL); + if (ret != LDB_SUCCESS) { + PyErr_SetString(PyExc_TypeError, "failed to build request"); + talloc_free(mem_ctx); + return NULL; + } + + /* do request and autostart a transaction */ + /* Then let's LDB handle the message error in case of pb as they are meaningful */ + + ret = ldb_transaction_start(ldb_ctx); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + ret = ldb_request(ldb_ctx, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret == LDB_SUCCESS) { + ret = ldb_transaction_commit(ldb_ctx); + } else { + ldb_transaction_cancel(ldb_ctx); + } + + talloc_free(mem_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_dn; + struct ldb_dn *dn; + int ret; + struct ldb_context *ldb_ctx; + struct ldb_request *req; + PyObject *py_controls = Py_None; + TALLOC_CTX *mem_ctx; + struct ldb_control **parsed_controls; + const char * const kwnames[] = { "dn", "controls", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", + discard_const_p(char *, kwnames), + &py_dn, &py_controls)) + return NULL; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + + if (py_controls == Py_None) { + parsed_controls = NULL; + } else { + const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } + parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); + talloc_free(controls); + } + + if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) { + talloc_free(mem_ctx); + return NULL; + } + + ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls, + NULL, ldb_op_default_callback, NULL); + if (ret != LDB_SUCCESS) { + PyErr_SetString(PyExc_TypeError, "failed to build request"); + talloc_free(mem_ctx); + return NULL; + } + + /* do request and autostart a transaction */ + /* Then let's LDB handle the message error in case of pb as they are meaningful */ + + ret = ldb_transaction_start(ldb_ctx); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + ret = ldb_request(ldb_ctx, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret == LDB_SUCCESS) { + ret = ldb_transaction_commit(ldb_ctx); + } else { + ldb_transaction_cancel(ldb_ctx); + } + + talloc_free(mem_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_dn1, *py_dn2; + struct ldb_dn *dn1, *dn2; + int ret; + TALLOC_CTX *mem_ctx; + PyObject *py_controls = Py_None; + struct ldb_control **parsed_controls; + struct ldb_context *ldb_ctx; + struct ldb_request *req; + const char * const kwnames[] = { "dn1", "dn2", "controls", NULL }; + + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O", + discard_const_p(char *, kwnames), + &py_dn1, &py_dn2, &py_controls)) + return NULL; + + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + if (py_controls == Py_None) { + parsed_controls = NULL; + } else { + const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } + parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); + talloc_free(controls); + } + + + if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) { + talloc_free(mem_ctx); + return NULL; + } + + if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) { + talloc_free(mem_ctx); + return NULL; + } + + ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls, + NULL, ldb_op_default_callback, NULL); + if (ret != LDB_SUCCESS) { + PyErr_SetString(PyExc_TypeError, "failed to build request"); + talloc_free(mem_ctx); + return NULL; + } + + /* do request and autostart a transaction */ + /* Then let's LDB handle the message error in case of pb as they are meaningful */ + + ret = ldb_transaction_start(ldb_ctx); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + ret = ldb_request(ldb_ctx, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret == LDB_SUCCESS) { + ret = ldb_transaction_commit(ldb_ctx); + } else { + ldb_transaction_cancel(ldb_ctx); + } + + talloc_free(mem_ctx); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args) +{ + char *name; + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args) +{ + char *attribute, *syntax; + unsigned int flags; + int ret; + struct ldb_context *ldb_ctx; + + if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax)) + return NULL; + + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); + + Py_RETURN_NONE; +} + +static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif) +{ + if (ldif == NULL) { + Py_RETURN_NONE; + } else { + /* We don't want this attached to the 'ldb' any more */ + PyObject *obj = PyLdbMessage_FromMessage(ldif->msg); + PyObject *result = + Py_BuildValue(discard_const_p(char, "(iO)"), + ldif->changetype, + obj); + Py_CLEAR(obj); + return result; + } +} + + +static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args) +{ + int changetype; + PyObject *py_msg; + struct ldb_ldif ldif; + PyObject *ret; + char *string; + TALLOC_CTX *mem_ctx; + + if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype)) + return NULL; + + if (!PyLdbMessage_Check(py_msg)) { + PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg"); + return NULL; + } + + ldif.msg = pyldb_Message_AsMessage(py_msg); + ldif.changetype = changetype; + + mem_ctx = talloc_new(NULL); + + string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif); + if (!string) { + PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF"); + return NULL; + } + + ret = PyUnicode_FromString(string); + + talloc_free(mem_ctx); + + return ret; +} + +static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args) +{ + PyObject *list, *ret; + struct ldb_ldif *ldif; + const char *s; + struct ldb_dn *last_dn = NULL; + + TALLOC_CTX *mem_ctx; + + if (!PyArg_ParseTuple(args, "s", &s)) + return NULL; + + mem_ctx = talloc_new(NULL); + if (!mem_ctx) { + Py_RETURN_NONE; + } + + list = PyList_New(0); + while (s && *s != '\0') { + ldif = ldb_ldif_read_string(self->ldb_ctx, &s); + talloc_steal(mem_ctx, ldif); + if (ldif) { + int res = 0; + PyObject *py_ldif = ldb_ldif_to_pyobject(ldif); + if (py_ldif == NULL) { + Py_CLEAR(list); + PyErr_BadArgument(); + talloc_free(mem_ctx); + return NULL; + } + res = PyList_Append(list, py_ldif); + Py_CLEAR(py_ldif); + if (res == -1) { + Py_CLEAR(list); + talloc_free(mem_ctx); + return NULL; + } + last_dn = ldif->msg->dn; + } else { + const char *last_dn_str = NULL; + const char *err_string = NULL; + if (last_dn == NULL) { + PyErr_SetString(PyExc_ValueError, + "unable to parse LDIF " + "string at first chunk"); + Py_CLEAR(list); + talloc_free(mem_ctx); + return NULL; + } + + last_dn_str + = ldb_dn_get_linearized(last_dn); + + err_string + = talloc_asprintf(mem_ctx, + "unable to parse ldif " + "string AFTER %s", + last_dn_str); + + PyErr_SetString(PyExc_ValueError, + err_string); + talloc_free(mem_ctx); + Py_CLEAR(list); + return NULL; + } + } + talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */ + ret = PyObject_GetIter(list); + Py_DECREF(list); + return ret; +} + +static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args) +{ + int ldb_ret; + PyObject *py_msg_old; + PyObject *py_msg_new; + struct ldb_message *diff; + struct ldb_context *ldb; + PyObject *py_ret; + + if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new)) + return NULL; + + if (!PyLdbMessage_Check(py_msg_old)) { + PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message"); + return NULL; + } + + if (!PyLdbMessage_Check(py_msg_new)) { + PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message"); + return NULL; + } + + ldb = pyldb_Ldb_AsLdbContext(self); + ldb_ret = ldb_msg_difference(ldb, ldb, + pyldb_Message_AsMessage(py_msg_old), + pyldb_Message_AsMessage(py_msg_new), + &diff); + if (ldb_ret != LDB_SUCCESS) { + PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff"); + return NULL; + } + + py_ret = PyLdbMessage_FromMessage(diff); + + talloc_unlink(ldb, diff); + + return py_ret; +} + +static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args) +{ + const struct ldb_schema_attribute *a; + struct ldb_val old_val; + struct ldb_val new_val; + TALLOC_CTX *mem_ctx; + PyObject *ret; + char *element_name; + PyObject *val; + Py_ssize_t size; + int result; + + if (!PyArg_ParseTuple(args, "sO", &element_name, &val)) + return NULL; + + result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size); + old_val.length = size; + + if (result != 0) { + PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String"); + return NULL; + } + + a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name); + + if (a == NULL) { + Py_RETURN_NONE; + } + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) { + talloc_free(mem_ctx); + Py_RETURN_NONE; + } + + ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length); + + talloc_free(mem_ctx); + + return ret; +} + +static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_base = Py_None; + int scope = LDB_SCOPE_DEFAULT; + char *expr = NULL; + PyObject *py_attrs = Py_None; + PyObject *py_controls = Py_None; + const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL }; + int ret; + struct ldb_result *res; + struct ldb_request *req; + const char **attrs; + struct ldb_context *ldb_ctx; + struct ldb_control **parsed_controls; + struct ldb_dn *base; + PyObject *py_ret; + TALLOC_CTX *mem_ctx; + + /* type "int" rather than "enum" for "scope" is intentional */ + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO", + discard_const_p(char *, kwnames), + &py_base, &scope, &expr, &py_attrs, &py_controls)) + return NULL; + + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + + if (py_attrs == Py_None) { + attrs = NULL; + } else { + attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs"); + if (attrs == NULL) { + talloc_free(mem_ctx); + return NULL; + } + } + + if (py_base == Py_None) { + base = ldb_get_default_basedn(ldb_ctx); + } else { + if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) { + talloc_free(mem_ctx); + return NULL; + } + } + + if (py_controls == Py_None) { + parsed_controls = NULL; + } else { + const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } + parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); + talloc_free(controls); + } + + res = talloc_zero(mem_ctx, struct ldb_result); + if (res == NULL) { + PyErr_NoMemory(); + talloc_free(mem_ctx); + return NULL; + } + + ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx, + base, + scope, + expr, + attrs, + parsed_controls, + res, + ldb_search_default_callback, + NULL); + + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + talloc_steal(req, attrs); + + ret = ldb_request(ldb_ctx, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + py_ret = PyLdbResult_FromResult(res); + + talloc_free(mem_ctx); + + return py_ret; +} + +static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply) +{ + if (reply->py_iter != NULL) { + DLIST_REMOVE(reply->py_iter->state.next, reply); + if (reply->py_iter->state.result == reply) { + reply->py_iter->state.result = NULL; + } + reply->py_iter = NULL; + } + + if (reply->obj != NULL) { + Py_DECREF(reply->obj); + reply->obj = NULL; + } + + return 0; +} + +static int py_ldb_search_iterator_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context; + struct ldb_result result = { .msgs = NULL }; + struct py_ldb_search_iterator_reply *reply = NULL; + + if (ares == NULL) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->error != LDB_SUCCESS) { + int ret = ares->error; + TALLOC_FREE(ares); + return ldb_request_done(req, ret); + } + + reply = talloc_zero(py_iter->mem_ctx, + struct py_ldb_search_iterator_reply); + if (reply == NULL) { + TALLOC_FREE(ares); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + reply->py_iter = py_iter; + talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor); + + switch (ares->type) { + case LDB_REPLY_ENTRY: + reply->obj = PyLdbMessage_FromMessage(ares->message); + if (reply->obj == NULL) { + TALLOC_FREE(ares); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + DLIST_ADD_END(py_iter->state.next, reply); + TALLOC_FREE(ares); + return LDB_SUCCESS; + + case LDB_REPLY_REFERRAL: + reply->obj = PyUnicode_FromString(ares->referral); + if (reply->obj == NULL) { + TALLOC_FREE(ares); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + DLIST_ADD_END(py_iter->state.next, reply); + TALLOC_FREE(ares); + return LDB_SUCCESS; + + case LDB_REPLY_DONE: + result = (struct ldb_result) { .controls = ares->controls }; + reply->obj = PyLdbResult_FromResult(&result); + if (reply->obj == NULL) { + TALLOC_FREE(ares); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + py_iter->state.result = reply; + TALLOC_FREE(ares); + return ldb_request_done(req, LDB_SUCCESS); + } + + TALLOC_FREE(ares); + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); +} + +static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_base = Py_None; + int scope = LDB_SCOPE_DEFAULT; + int timeout = 0; + char *expr = NULL; + PyObject *py_attrs = Py_None; + PyObject *py_controls = Py_None; + const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL }; + int ret; + const char **attrs; + struct ldb_context *ldb_ctx; + struct ldb_control **parsed_controls; + struct ldb_dn *base; + PyLdbSearchIteratorObject *py_iter; + + /* type "int" rather than "enum" for "scope" is intentional */ + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi", + discard_const_p(char *, kwnames), + &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout)) + return NULL; + + py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0); + if (py_iter == NULL) { + PyErr_NoMemory(); + return NULL; + } + py_iter->ldb = self; + Py_INCREF(self); + ZERO_STRUCT(py_iter->state); + py_iter->mem_ctx = talloc_new(NULL); + if (py_iter->mem_ctx == NULL) { + Py_DECREF(py_iter); + PyErr_NoMemory(); + return NULL; + } + + ldb_ctx = pyldb_Ldb_AsLdbContext(self); + + if (py_attrs == Py_None) { + attrs = NULL; + } else { + attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs"); + if (attrs == NULL) { + Py_DECREF(py_iter); + PyErr_NoMemory(); + return NULL; + } + } + + if (py_base == Py_None) { + base = ldb_get_default_basedn(ldb_ctx); + } else { + if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) { + Py_DECREF(py_iter); + PyErr_NoMemory(); + return NULL; + } + } + + if (py_controls == Py_None) { + parsed_controls = NULL; + } else { + const char **controls = NULL; + + controls = PyList_AsStrList(py_iter->mem_ctx, + py_controls, "controls"); + if (controls == NULL) { + Py_DECREF(py_iter); + PyErr_NoMemory(); + return NULL; + } + + parsed_controls = ldb_parse_control_strings(ldb_ctx, + py_iter->mem_ctx, + controls); + if (controls[0] != NULL && parsed_controls == NULL) { + Py_DECREF(py_iter); + PyErr_NoMemory(); + return NULL; + } + talloc_free(controls); + } + + ret = ldb_build_search_req(&py_iter->state.req, + ldb_ctx, + py_iter->mem_ctx, + base, + scope, + expr, + attrs, + parsed_controls, + py_iter, + py_ldb_search_iterator_callback, + NULL); + if (ret != LDB_SUCCESS) { + Py_DECREF(py_iter); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout); + + ret = ldb_request(ldb_ctx, py_iter->state.req); + if (ret != LDB_SUCCESS) { + Py_DECREF(py_iter); + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return NULL; + } + + return (PyObject *)py_iter; +} + +static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args) +{ + char *name; + void *data; + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name); + + if (data == NULL) + Py_RETURN_NONE; + + /* FIXME: More interpretation */ + + Py_RETURN_TRUE; +} + +static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args) +{ + char *name; + PyObject *data; + + if (!PyArg_ParseTuple(args, "sO", &name, &data)) + return NULL; + + /* FIXME: More interpretation */ + + ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_modules(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self); + PyObject *ret = PyList_New(0); + struct ldb_module *mod; + + if (ret == NULL) { + return PyErr_NoMemory(); + } + for (mod = ldb->modules; mod; mod = mod->next) { + PyObject *item = PyLdbModule_FromModule(mod); + int res = 0; + if (item == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "Failed to load LdbModule"); + Py_CLEAR(ret); + return NULL; + } + res = PyList_Append(ret, item); + Py_CLEAR(item); + if (res == -1) { + Py_CLEAR(ret); + return NULL; + } + } + + return ret; +} + +static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args) +{ + struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self); + int type, ret; + uint64_t value; + + if (!PyArg_ParseTuple(args, "i", &type)) + return NULL; + + /* FIXME: More interpretation */ + + ret = ldb_sequence_number(ldb, type, &value); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb); + + return PyLong_FromLongLong(value); +} + + +static const struct ldb_dn_extended_syntax test_dn_syntax = { + .name = "TEST", + .read_fn = ldb_handler_copy, + .write_clear_fn = ldb_handler_copy, + .write_hex_fn = ldb_handler_copy, +}; + +static PyObject *py_ldb_register_test_extensions(PyLdbObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self); + int ret; + + ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb); + + Py_RETURN_NONE; +} + + +static PyMethodDef py_ldb_methods[] = { + { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, + "S.set_debug(callback) -> None\n" + "Set callback for LDB debug messages.\n" + "The callback should accept a debug level and debug text." }, + { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS, + "S.set_create_perms(mode) -> None\n" + "Set mode to use when creating new LDB files." }, + { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS, + "S.set_modules_dir(path) -> None\n" + "Set path LDB should search for modules" }, + { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS, + "S.transaction_start() -> None\n" + "Start a new transaction." }, + { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS, + "S.transaction_prepare_commit() -> None\n" + "prepare to commit a new transaction (2-stage commit)." }, + { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, + "S.transaction_commit() -> None\n" + "commit a new transaction." }, + { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS, + "S.transaction_cancel() -> None\n" + "cancel a new transaction." }, + { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS, + NULL }, + { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS, + NULL }, + { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS, + NULL }, + { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS, + NULL }, + { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS, + NULL }, + { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect), + METH_VARARGS|METH_KEYWORDS, + "S.connect(url, flags=0, options=None) -> None\n" + "Connect to a LDB URL." }, + { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify), + METH_VARARGS|METH_KEYWORDS, + "S.modify(message, controls=None, validate=False) -> None\n" + "Modify an entry." }, + { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add), + METH_VARARGS|METH_KEYWORDS, + "S.add(message, controls=None) -> None\n" + "Add an entry." }, + { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete), + METH_VARARGS|METH_KEYWORDS, + "S.delete(dn, controls=None) -> None\n" + "Remove an entry." }, + { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename), + METH_VARARGS|METH_KEYWORDS, + "S.rename(old_dn, new_dn, controls=None) -> None\n" + "Rename an entry." }, + { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search), + METH_VARARGS|METH_KEYWORDS, + "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n" + "Search in a database.\n" + "\n" + ":param base: Optional base DN to search\n" + ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n" + ":param expression: Optional search expression\n" + ":param attrs: Attributes to return (defaults to all)\n" + ":param controls: Optional list of controls\n" + ":return: ldb.Result object\n" + }, + { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction, + py_ldb_search_iterator), + METH_VARARGS|METH_KEYWORDS, + "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n" + "Search in a database.\n" + "\n" + ":param base: Optional base DN to search\n" + ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n" + ":param expression: Optional search expression\n" + ":param attrs: Attributes to return (defaults to all)\n" + ":param controls: Optional list of controls\n" + ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n" + ":return: ldb.SearchIterator object that provides results when they arrive\n" + }, + { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS, + NULL }, + { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS, + NULL }, + { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS, + NULL }, + { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS, + "S.parse_ldif(ldif) -> iter(messages)\n" + "Parse a string formatted using LDIF." }, + { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS, + "S.write_ldif(message, changetype) -> ldif\n" + "Print the message as a string formatted using LDIF." }, + { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS, + "S.msg_diff(Message) -> Message\n" + "Return an LDB Message of the difference between two Message objects." }, + { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS, + "S.get_opaque(name) -> value\n" + "Get an opaque value set on this LDB connection. \n" + ":note: The returned value may not be useful in Python." + }, + { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS, + "S.set_opaque(name, value) -> None\n" + "Set an opaque value on this LDB connection. \n" + ":note: Passing incorrect values may cause crashes." }, + { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS, + "S.modules() -> list\n" + "Return the list of modules on this LDB connection " }, + { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS, + "S.sequence_number(type) -> value\n" + "Return the value of the sequence according to the requested type" }, + { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS, + "S._register_test_extensions() -> None\n" + "Register internal extensions used in testing" }, + { NULL }, +}; + +static PyObject *PyLdbModule_FromModule(struct ldb_module *mod) +{ + PyLdbModuleObject *ret; + + ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + ret->mem_ctx = talloc_new(NULL); + ret->mod = talloc_reference(ret->mem_ctx, mod); + return (PyObject *)ret; +} + +static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure) +{ + struct ldb_module *mod = pyldb_Ldb_AsLdbContext(self)->modules; + if (mod == NULL) { + Py_RETURN_NONE; + } + return PyLdbModule_FromModule(mod); +} + +static PyGetSetDef py_ldb_getset[] = { + { + .name = discard_const_p(char, "firstmodule"), + .get = (getter)py_ldb_get_firstmodule, + }, + { .name = NULL }, +}; + +static int py_ldb_contains(PyLdbObject *self, PyObject *obj) +{ + struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self); + struct ldb_dn *dn; + struct ldb_result *result; + unsigned int count; + int ret; + + if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) { + return -1; + } + + ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, + NULL); + if (ret != LDB_SUCCESS) { + PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); + return -1; + } + + count = result->count; + + talloc_free(result); + + if (count > 1) { + PyErr_Format(PyExc_RuntimeError, + "Searching for [%s] dn gave %u results!", + ldb_dn_get_linearized(dn), + count); + return -1; + } + + return count; +} + +static PySequenceMethods py_ldb_seq = { + .sq_contains = (objobjproc)py_ldb_contains, +}; + +static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx) +{ + PyLdbObject *ret; + + ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + ret->mem_ctx = talloc_new(NULL); + ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx); + return (PyObject *)ret; +} + +static void py_ldb_dealloc(PyLdbObject *self) +{ + talloc_free(self->mem_ctx); + Py_TYPE(self)->tp_free(self); +} + +static PyTypeObject PyLdb = { + .tp_name = "ldb.Ldb", + .tp_methods = py_ldb_methods, + .tp_repr = (reprfunc)py_ldb_repr, + .tp_new = py_ldb_new, + .tp_init = (initproc)py_ldb_init, + .tp_dealloc = (destructor)py_ldb_dealloc, + .tp_getset = py_ldb_getset, + .tp_getattro = PyObject_GenericGetAttr, + .tp_basicsize = sizeof(PyLdbObject), + .tp_doc = "Connection to a LDB database.", + .tp_as_sequence = &py_ldb_seq, + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, +}; + +static void py_ldb_result_dealloc(PyLdbResultObject *self) +{ + talloc_free(self->mem_ctx); + Py_DECREF(self->msgs); + Py_DECREF(self->referals); + Py_DECREF(self->controls); + Py_TYPE(self)->tp_free(self); +} + +static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure) +{ + Py_INCREF(self->msgs); + return self->msgs; +} + +static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure) +{ + Py_INCREF(self->controls); + return self->controls; +} + +static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure) +{ + Py_INCREF(self->referals); + return self->referals; +} + +static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure) +{ + Py_ssize_t size; + if (self->msgs == NULL) { + PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context"); + return NULL; + } + size = PyList_Size(self->msgs); + return PyInt_FromLong(size); +} + +static PyGetSetDef py_ldb_result_getset[] = { + { + .name = discard_const_p(char, "controls"), + .get = (getter)py_ldb_result_get_controls, + }, + { + .name = discard_const_p(char, "msgs"), + .get = (getter)py_ldb_result_get_msgs, + }, + { + .name = discard_const_p(char, "referals"), + .get = (getter)py_ldb_result_get_referals, + }, + { + .name = discard_const_p(char, "count"), + .get = (getter)py_ldb_result_get_count, + }, + { .name = NULL }, +}; + +static PyObject *py_ldb_result_iter(PyLdbResultObject *self) +{ + return PyObject_GetIter(self->msgs); +} + +static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self) +{ + return PySequence_Size(self->msgs); +} + +static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx) +{ + return PySequence_GetItem(self->msgs, idx); +} + +static PySequenceMethods py_ldb_result_seq = { + .sq_length = (lenfunc)py_ldb_result_len, + .sq_item = (ssizeargfunc)py_ldb_result_find, +}; + +static PyObject *py_ldb_result_repr(PyLdbObject *self) +{ + return PyUnicode_FromString(""); +} + + +static PyTypeObject PyLdbResult = { + .tp_name = "ldb.Result", + .tp_repr = (reprfunc)py_ldb_result_repr, + .tp_dealloc = (destructor)py_ldb_result_dealloc, + .tp_iter = (getiterfunc)py_ldb_result_iter, + .tp_getset = py_ldb_result_getset, + .tp_getattro = PyObject_GenericGetAttr, + .tp_basicsize = sizeof(PyLdbResultObject), + .tp_as_sequence = &py_ldb_result_seq, + .tp_doc = "LDB result.", + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, +}; + +static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self) +{ + Py_XDECREF(self->state.exception); + TALLOC_FREE(self->mem_ctx); + ZERO_STRUCT(self->state); + Py_DECREF(self->ldb); + Py_TYPE(self)->tp_free(self); +} + +static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self) +{ + PyObject *py_ret = NULL; + + if (self->state.req == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "ldb.SearchIterator request already finished"); + return NULL; + } + + /* + * TODO: do we want a non-blocking mode? + * In future we may add an optional 'nonblocking' + * argument to search_iterator(). + * + * For now we keep it simple and wait for at + * least one reply. + */ + + while (self->state.next == NULL) { + int ret; + + if (self->state.result != NULL) { + /* + * We (already) got a final result from the server. + * + * We stop the iteration and let + * py_ldb_search_iterator_result() will deliver + * the result details. + */ + TALLOC_FREE(self->state.req); + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + + ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE); + if (ret != LDB_SUCCESS) { + struct ldb_context *ldb_ctx; + TALLOC_FREE(self->state.req); + ldb_ctx = pyldb_Ldb_AsLdbContext(self->ldb); + /* + * We stop the iteration and let + * py_ldb_search_iterator_result() will deliver + * the exception. + */ + self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"), + ret, ldb_errstring(ldb_ctx)); + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + } + + py_ret = self->state.next->obj; + self->state.next->obj = NULL; + /* no TALLOC_FREE() as self->state.next is a list */ + talloc_free(self->state.next); + return py_ret; +} + +static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self, + PyObject *Py_UNUSED(ignored)) +{ + PyObject *py_ret = NULL; + + if (self->state.req != NULL) { + PyErr_SetString(PyExc_RuntimeError, + "ldb.SearchIterator request running"); + return NULL; + } + + if (self->state.next != NULL) { + PyErr_SetString(PyExc_RuntimeError, + "ldb.SearchIterator not fully consumed."); + return NULL; + } + + if (self->state.exception != NULL) { + PyErr_SetObject(PyExc_LdbError, self->state.exception); + self->state.exception = NULL; + return NULL; + } + + if (self->state.result == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "ldb.SearchIterator result already consumed"); + return NULL; + } + + py_ret = self->state.result->obj; + self->state.result->obj = NULL; + TALLOC_FREE(self->state.result); + return py_ret; +} + +static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self, + PyObject *Py_UNUSED(ignored)) +{ + if (self->state.req == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "ldb.SearchIterator request already finished"); + return NULL; + } + + Py_XDECREF(self->state.exception); + TALLOC_FREE(self->mem_ctx); + ZERO_STRUCT(self->state); + Py_RETURN_NONE; +} + +static PyMethodDef py_ldb_search_iterator_methods[] = { + { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS, + "S.result() -> ldb.Result (without msgs and referrals)\n" }, + { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS, + "S.abandon()\n" }, + { NULL } +}; + +static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self) +{ + return PyUnicode_FromString(""); +} + +static PyTypeObject PyLdbSearchIterator = { + .tp_name = "ldb.SearchIterator", + .tp_repr = (reprfunc)py_ldb_search_iterator_repr, + .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc, + .tp_iter = PyObject_SelfIter, + .tp_iternext = (iternextfunc)py_ldb_search_iterator_next, + .tp_methods = py_ldb_search_iterator_methods, + .tp_basicsize = sizeof(PyLdbSearchIteratorObject), + .tp_doc = "LDB search_iterator.", + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, +}; + +static PyObject *py_ldb_module_repr(PyLdbModuleObject *self) +{ + return PyUnicode_FromFormat("", + pyldb_Module_AsModule(self)->ops->name); +} + +static PyObject *py_ldb_module_str(PyLdbModuleObject *self) +{ + return PyUnicode_FromString(pyldb_Module_AsModule(self)->ops->name); +} + +static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self, + PyObject *Py_UNUSED(ignored)) +{ + pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self)); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self, + PyObject *Py_UNUSED(ignored)) +{ + pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self)); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self, + PyObject *Py_UNUSED(ignored)) +{ + pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self)); + Py_RETURN_NONE; +} + +static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_base, *py_tree, *py_attrs, *py_ret; + int ret, scope; + struct ldb_request *req; + const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL }; + struct ldb_module *mod; + const char * const*attrs; + + /* type "int" rather than "enum" for "scope" is intentional */ + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO", + discard_const_p(char *, kwnames), + &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs)) + return NULL; + + mod = self->mod; + + if (py_attrs == Py_None) { + attrs = NULL; + } else { + attrs = PyList_AsStrList(NULL, py_attrs, "attrs"); + if (attrs == NULL) + return NULL; + } + + ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base), + scope, NULL /* expr */, attrs, + NULL /* controls */, NULL, NULL, NULL); + + talloc_steal(req, attrs); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb); + + req->op.search.res = NULL; + + ret = mod->ops->search(mod, req); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb); + + py_ret = PyLdbResult_FromResult(req->op.search.res); + + talloc_free(req); + + return py_ret; +} + + +static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args) +{ + struct ldb_request *req; + PyObject *py_message; + int ret; + struct ldb_module *mod; + + if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message)) + return NULL; + + req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_ADD; + req->op.add.message = pyldb_Message_AsMessage(py_message); + + mod = pyldb_Module_AsModule(self); + ret = mod->ops->add(mod, req); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) +{ + int ret; + struct ldb_request *req; + PyObject *py_message; + struct ldb_module *mod; + + if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message)) + return NULL; + + req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_MODIFY; + req->op.mod.message = pyldb_Message_AsMessage(py_message); + + mod = pyldb_Module_AsModule(self); + ret = mod->ops->modify(mod, req); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) +{ + int ret; + struct ldb_request *req; + PyObject *py_dn; + + if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn)) + return NULL; + + req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_DELETE; + req->op.del.dn = pyldb_Dn_AsDn(py_dn); + + ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args) +{ + int ret; + struct ldb_request *req; + PyObject *py_dn1, *py_dn2; + + if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2)) + return NULL; + + req = talloc_zero(NULL, struct ldb_request); + + req->operation = LDB_RENAME; + req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1); + req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2); + + ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req); + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL); + + Py_RETURN_NONE; +} + +static PyMethodDef py_ldb_module_methods[] = { + { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_module_search), + METH_VARARGS|METH_KEYWORDS, NULL }, + { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL }, + { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL }, + { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL }, + { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL }, + { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL }, + { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL }, + { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL }, + { NULL }, +}; + +static void py_ldb_module_dealloc(PyLdbModuleObject *self) +{ + talloc_free(self->mem_ctx); + PyObject_Del(self); +} + +static PyTypeObject PyLdbModule = { + .tp_name = "ldb.LdbModule", + .tp_methods = py_ldb_module_methods, + .tp_repr = (reprfunc)py_ldb_module_repr, + .tp_str = (reprfunc)py_ldb_module_str, + .tp_basicsize = sizeof(PyLdbModuleObject), + .tp_dealloc = (destructor)py_ldb_module_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "LDB module (extension)", +}; + + +/** + * Create a ldb_message_element from a Python object. + * + * This will accept any sequence objects that contains strings, or + * a string object. + * + * A reference to set_obj will be borrowed. + * + * @param mem_ctx Memory context + * @param set_obj Python object to convert + * @param flags ldb_message_element flags to set + * @param attr_name Name of the attribute + * @return New ldb_message_element, allocated as child of mem_ctx + */ +static struct ldb_message_element *PyObject_AsMessageElement( + TALLOC_CTX *mem_ctx, + PyObject *set_obj, + unsigned int flags, + const char *attr_name) +{ + struct ldb_message_element *me; + const char *msg = NULL; + Py_ssize_t size; + int result; + + if (pyldb_MessageElement_Check(set_obj)) { + PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj; + /* We have to talloc_reference() the memory context, not the pointer + * which may not actually be it's own context */ + if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) { + return pyldb_MessageElement_AsMessageElement(set_obj); + } + return NULL; + } + + me = talloc(mem_ctx, struct ldb_message_element); + if (me == NULL) { + PyErr_NoMemory(); + return NULL; + } + + me->name = talloc_strdup(me, attr_name); + me->flags = flags; + if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) { + me->num_values = 1; + me->values = talloc_array(me, struct ldb_val, me->num_values); + if (PyBytes_Check(set_obj)) { + char *_msg = NULL; + result = PyBytes_AsStringAndSize(set_obj, &_msg, &size); + if (result != 0) { + talloc_free(me); + return NULL; + } + msg = _msg; + } else { + msg = PyUnicode_AsUTF8AndSize(set_obj, &size); + if (msg == NULL) { + talloc_free(me); + return NULL; + } + } + me->values[0].data = talloc_memdup(me, + (const uint8_t *)msg, + size+1); + me->values[0].length = size; + } else if (PySequence_Check(set_obj)) { + Py_ssize_t i; + me->num_values = PySequence_Size(set_obj); + me->values = talloc_array(me, struct ldb_val, me->num_values); + for (i = 0; i < me->num_values; i++) { + PyObject *obj = PySequence_GetItem(set_obj, i); + if (PyBytes_Check(obj)) { + char *_msg = NULL; + result = PyBytes_AsStringAndSize(obj, &_msg, &size); + if (result != 0) { + talloc_free(me); + return NULL; + } + msg = _msg; + } else if (PyUnicode_Check(obj)) { + msg = PyUnicode_AsUTF8AndSize(obj, &size); + if (msg == NULL) { + talloc_free(me); + return NULL; + } + } else { + PyErr_Format(PyExc_TypeError, + "Expected string as element %zd in list", i); + talloc_free(me); + return NULL; + } + me->values[i].data = talloc_memdup(me, + (const uint8_t *)msg, + size+1); + me->values[i].length = size; + } + } else { + PyErr_Format(PyExc_TypeError, + "String or List type expected for '%s' attribute", attr_name); + talloc_free(me); + me = NULL; + } + + return me; +} + + +static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, + struct ldb_message_element *me) +{ + Py_ssize_t i; + PyObject *result; + + /* Python << 2.5 doesn't have PySet_New and PySet_Add. */ + result = PyList_New(me->num_values); + + for (i = 0; i < me->num_values; i++) { + PyList_SetItem(result, i, + PyObject_FromLdbValue(&me->values[i])); + } + + return result; +} + +static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args) +{ + unsigned int i; + if (!PyArg_ParseTuple(args, "I", &i)) + return NULL; + if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values) + Py_RETURN_NONE; + + return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i])); +} + +static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args) +{ + struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self); + return PyInt_FromLong(el->flags); +} + +static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args) +{ + unsigned int flags; + struct ldb_message_element *el; + if (!PyArg_ParseTuple(args, "I", &flags)) + return NULL; + + el = pyldb_MessageElement_AsMessageElement(self); + el->flags = flags; + Py_RETURN_NONE; +} + +static PyMethodDef py_ldb_msg_element_methods[] = { + { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL }, + { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL }, + { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL }, + { NULL }, +}; + +static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self) +{ + return pyldb_MessageElement_AsMessageElement(self)->num_values; +} + +static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx) +{ + struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self); + if (idx < 0 || idx >= el->num_values) { + PyErr_SetString(PyExc_IndexError, "Out of range"); + return NULL; + } + return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length); +} + +static PySequenceMethods py_ldb_msg_element_seq = { + .sq_length = (lenfunc)py_ldb_msg_element_len, + .sq_item = (ssizeargfunc)py_ldb_msg_element_find, +}; + +static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op) +{ + int ret; + if (!pyldb_MessageElement_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self), + pyldb_MessageElement_AsMessageElement(other)); + return richcmp(ret, op); +} + +static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self) +{ + PyObject *el = ldb_msg_element_to_set(NULL, + pyldb_MessageElement_AsMessageElement(self)); + PyObject *ret = PyObject_GetIter(el); + Py_DECREF(el); + return ret; +} + +static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx) +{ + PyLdbMessageElementObject *ret; + ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + ret->mem_ctx = talloc_new(NULL); + if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) { + PyErr_NoMemory(); + return NULL; + } + ret->el = el; + return (PyObject *)ret; +} + +static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *py_elements = NULL; + struct ldb_message_element *el; + unsigned int flags = 0; + char *name = NULL; + const char * const kwnames[] = { "elements", "flags", "name", NULL }; + PyLdbMessageElementObject *ret; + TALLOC_CTX *mem_ctx; + const char *msg = NULL; + Py_ssize_t size; + int result; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs", + discard_const_p(char *, kwnames), + &py_elements, &flags, &name)) + return NULL; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + el = talloc_zero(mem_ctx, struct ldb_message_element); + if (el == NULL) { + PyErr_NoMemory(); + talloc_free(mem_ctx); + return NULL; + } + + if (py_elements != NULL) { + Py_ssize_t i; + if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) { + char *_msg = NULL; + el->num_values = 1; + el->values = talloc_array(el, struct ldb_val, 1); + if (el->values == NULL) { + talloc_free(mem_ctx); + PyErr_NoMemory(); + return NULL; + } + if (PyBytes_Check(py_elements)) { + result = PyBytes_AsStringAndSize(py_elements, &_msg, &size); + msg = _msg; + } else { + msg = PyUnicode_AsUTF8AndSize(py_elements, &size); + result = (msg == NULL) ? -1 : 0; + } + if (result != 0) { + talloc_free(mem_ctx); + return NULL; + } + el->values[0].data = talloc_memdup(el->values, + (const uint8_t *)msg, size + 1); + el->values[0].length = size; + } else if (PySequence_Check(py_elements)) { + el->num_values = PySequence_Size(py_elements); + el->values = talloc_array(el, struct ldb_val, el->num_values); + if (el->values == NULL) { + talloc_free(mem_ctx); + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < el->num_values; i++) { + PyObject *item = PySequence_GetItem(py_elements, i); + if (item == NULL) { + talloc_free(mem_ctx); + return NULL; + } + if (PyBytes_Check(item)) { + char *_msg = NULL; + result = PyBytes_AsStringAndSize(item, &_msg, &size); + msg = _msg; + } else if (PyUnicode_Check(item)) { + msg = PyUnicode_AsUTF8AndSize(item, &size); + result = (msg == NULL) ? -1 : 0; + } else { + PyErr_Format(PyExc_TypeError, + "Expected string as element %zd in list", i); + result = -1; + } + if (result != 0) { + talloc_free(mem_ctx); + return NULL; + } + el->values[i].data = talloc_memdup(el, + (const uint8_t *)msg, size+1); + el->values[i].length = size; + } + } else { + PyErr_SetString(PyExc_TypeError, + "Expected string or list"); + talloc_free(mem_ctx); + return NULL; + } + } + + el->flags = flags; + el->name = talloc_strdup(el, name); + + ret = PyObject_New(PyLdbMessageElementObject, type); + if (ret == NULL) { + talloc_free(mem_ctx); + return NULL; + } + + ret->mem_ctx = mem_ctx; + ret->el = el; + return (PyObject *)ret; +} + +static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self) +{ + char *element_str = NULL; + Py_ssize_t i; + struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self); + PyObject *ret, *repr; + + for (i = 0; i < el->num_values; i++) { + PyObject *o = py_ldb_msg_element_find(self, i); + repr = PyObject_Repr(o); + if (element_str == NULL) + element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr)); + else + element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr)); + Py_DECREF(repr); + } + + if (element_str != NULL) { + ret = PyUnicode_FromFormat("MessageElement([%s])", element_str); + talloc_free(element_str); + } else { + ret = PyUnicode_FromString("MessageElement([])"); + } + + return ret; +} + +static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self) +{ + struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self); + + if (el->num_values == 1) + return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length); + else + Py_RETURN_NONE; +} + +static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self) +{ + talloc_free(self->mem_ctx); + PyObject_Del(self); +} + +static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure) +{ + return wrap_text("MessageElementTextWrapper", self); +} + +static PyGetSetDef py_ldb_msg_element_getset[] = { + { + .name = discard_const_p(char, "text"), + .get = (getter)py_ldb_msg_element_get_text, + }, + { .name = NULL } +}; + +static PyTypeObject PyLdbMessageElement = { + .tp_name = "ldb.MessageElement", + .tp_basicsize = sizeof(PyLdbMessageElementObject), + .tp_dealloc = (destructor)py_ldb_msg_element_dealloc, + .tp_repr = (reprfunc)py_ldb_msg_element_repr, + .tp_str = (reprfunc)py_ldb_msg_element_str, + .tp_methods = py_ldb_msg_element_methods, + .tp_getset = py_ldb_msg_element_getset, + .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp, + .tp_iter = (getiterfunc)py_ldb_msg_element_iter, + .tp_as_sequence = &py_ldb_msg_element_seq, + .tp_new = py_ldb_msg_element_new, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "An element of a Message", +}; + + +static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args) +{ + PyObject *py_ldb; + PyObject *py_dict; + PyObject *py_ret; + struct ldb_message *msg; + struct ldb_context *ldb_ctx; + unsigned int mod_flags = LDB_FLAG_MOD_REPLACE; + + if (!PyArg_ParseTuple(args, "O!O!|I", + &PyLdb, &py_ldb, &PyDict_Type, &py_dict, + &mod_flags)) { + return NULL; + } + + if (!PyLdb_Check(py_ldb)) { + PyErr_SetString(PyExc_TypeError, "Expected Ldb"); + return NULL; + } + + /* mask only flags we are going to use */ + mod_flags = LDB_FLAG_MOD_TYPE(mod_flags); + if (!mod_flags) { + PyErr_SetString(PyExc_ValueError, + "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE" + " expected as mod_flag value"); + return NULL; + } + + ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb); + + msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags); + if (!msg) { + return NULL; + } + + py_ret = PyLdbMessage_FromMessage(msg); + + talloc_unlink(ldb_ctx, msg); + + return py_ret; +} + +static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args) +{ + char *name; + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + ldb_msg_remove_attr(self->msg, name); + + Py_RETURN_NONE; +} + +static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_message *msg = pyldb_Message_AsMessage(self); + Py_ssize_t i, j = 0; + PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0)); + if (msg->dn != NULL) { + PyList_SetItem(obj, j, PyUnicode_FromString("dn")); + j++; + } + for (i = 0; i < msg->num_elements; i++) { + PyList_SetItem(obj, j, PyUnicode_FromString(msg->elements[i].name)); + j++; + } + return obj; +} + +static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name) +{ + struct ldb_message_element *el; + const char *name; + struct ldb_message *msg = pyldb_Message_AsMessage(self); + name = PyUnicode_AsUTF8(py_name); + if (name == NULL) { + PyErr_SetNone(PyExc_TypeError); + return NULL; + } + if (!ldb_attr_cmp(name, "dn")) + return pyldb_Dn_FromDn(msg->dn); + el = ldb_msg_find_element(msg, name); + if (el == NULL) { + return NULL; + } + return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements); +} + +static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name) +{ + PyObject *ret = py_ldb_msg_getitem_helper(self, py_name); + if (ret == NULL) { + PyErr_SetString(PyExc_KeyError, "No such element"); + return NULL; + } + return ret; +} + +static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *def = NULL; + const char *kwnames[] = { "name", "default", "idx", NULL }; + const char *name = NULL; + int idx = -1; + struct ldb_message *msg = pyldb_Message_AsMessage(self); + struct ldb_message_element *el; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg", + discard_const_p(char *, kwnames), &name, &def, &idx)) { + return NULL; + } + + if (strcasecmp(name, "dn") == 0) { + return pyldb_Dn_FromDn(msg->dn); + } + + el = ldb_msg_find_element(msg, name); + + if (el == NULL || (idx != -1 && el->num_values <= idx)) { + if (def != NULL) { + Py_INCREF(def); + return def; + } + Py_RETURN_NONE; + } + + if (idx == -1) { + return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements); + } + + return PyObject_FromLdbValue(&el->values[idx]); +} + +static PyObject *py_ldb_msg_items(PyLdbMessageObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_message *msg = pyldb_Message_AsMessage(self); + Py_ssize_t i, j = 0; + PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1)); + if (l == NULL) { + return PyErr_NoMemory(); + } + if (msg->dn != NULL) { + PyObject *value = NULL; + PyObject *obj = pyldb_Dn_FromDn(msg->dn); + int res = 0; + value = Py_BuildValue("(sO)", "dn", obj); + Py_CLEAR(obj); + if (value == NULL) { + Py_CLEAR(l); + return NULL; + } + res = PyList_SetItem(l, 0, value); + if (res == -1) { + Py_CLEAR(l); + return NULL; + } + j++; + } + for (i = 0; i < msg->num_elements; i++, j++) { + PyObject *value = NULL; + PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements); + int res = 0; + Py_CLEAR(py_el); + value = Py_BuildValue("(sO)", msg->elements[i].name, py_el); + if (value == NULL ) { + Py_CLEAR(l); + return NULL; + } + res = PyList_SetItem(l, 0, value); + if (res == -1) { + Py_CLEAR(l); + return NULL; + } + } + return l; +} + +static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self, + PyObject *Py_UNUSED(ignored)) +{ + struct ldb_message *msg = pyldb_Message_AsMessage(self); + Py_ssize_t i = 0; + PyObject *l = PyList_New(msg->num_elements); + for (i = 0; i < msg->num_elements; i++) { + PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements)); + } + return l; +} + +static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args) +{ + struct ldb_message *msg = pyldb_Message_AsMessage(self); + PyLdbMessageElementObject *py_element; + int i, ret; + struct ldb_message_element *el; + struct ldb_message_element *el_new; + + if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element)) + return NULL; + + el = py_element->el; + if (el == NULL) { + PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object"); + return NULL; + } + if (el->name == NULL) { + PyErr_SetString(PyExc_ValueError, + "The element has no name"); + return NULL; + } + ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL); + + /* now deep copy all attribute values */ + el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values); + if (el_new->values == NULL) { + PyErr_NoMemory(); + return NULL; + } + el_new->num_values = el->num_values; + + for (i = 0; i < el->num_values; i++) { + el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]); + if (el_new->values[i].data == NULL + && el->values[i].length != 0) { + PyErr_NoMemory(); + return NULL; + } + } + + Py_RETURN_NONE; +} + +static PyMethodDef py_ldb_msg_methods[] = { + { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS, + "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n" + "Class method to create ldb.Message object from Dictionary.\n" + "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."}, + { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, + "S.keys() -> list\n\n" + "Return sequence of all attribute names." }, + { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, + "S.remove(name)\n\n" + "Remove all entries for attributes with the specified name."}, + { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get), + METH_VARARGS | METH_KEYWORDS, + "msg.get(name,default=None,idx=None) -> string\n" + "idx is the index into the values array\n" + "if idx is None, then a list is returned\n" + "if idx is not None, then the element with that index is returned\n" + "if you pass the special name 'dn' then the DN object is returned\n"}, + { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL }, + { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL }, + { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS, + "S.add(element)\n\n" + "Add an element to this message." }, + { NULL }, +}; + +static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self) +{ + PyObject *list, *iter; + + list = py_ldb_msg_keys(self, NULL); + iter = PyObject_GetIter(list); + Py_DECREF(list); + return iter; +} + +static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value) +{ + const char *attr_name; + + attr_name = PyUnicode_AsUTF8(name); + if (attr_name == NULL) { + PyErr_SetNone(PyExc_TypeError); + return -1; + } + + if (value == NULL) { + /* delitem */ + ldb_msg_remove_attr(self->msg, attr_name); + } else { + int ret; + struct ldb_message_element *el = PyObject_AsMessageElement(self->msg, + value, 0, attr_name); + if (el == NULL) { + return -1; + } + ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name); + ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags); + if (ret != LDB_SUCCESS) { + PyErr_SetLdbError(PyExc_LdbError, ret, NULL); + return -1; + } + } + return 0; +} + +static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self) +{ + return pyldb_Message_AsMessage(self)->num_elements; +} + +static PyMappingMethods py_ldb_msg_mapping = { + .mp_length = (lenfunc)py_ldb_msg_length, + .mp_subscript = (binaryfunc)py_ldb_msg_getitem, + .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem, +}; + +static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + const char * const kwnames[] = { "dn", NULL }; + struct ldb_message *ret; + TALLOC_CTX *mem_ctx; + PyObject *pydn = NULL; + PyLdbMessageObject *py_ret; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", + discard_const_p(char *, kwnames), + &pydn)) + return NULL; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + ret = ldb_msg_new(mem_ctx); + if (ret == NULL) { + talloc_free(mem_ctx); + PyErr_NoMemory(); + return NULL; + } + + if (pydn != NULL) { + struct ldb_dn *dn; + if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) { + talloc_free(mem_ctx); + return NULL; + } + ret->dn = talloc_reference(ret, dn); + } + + py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0); + if (py_ret == NULL) { + PyErr_NoMemory(); + talloc_free(mem_ctx); + return NULL; + } + + py_ret->mem_ctx = mem_ctx; + py_ret->msg = ret; + return (PyObject *)py_ret; +} + +static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg) +{ + PyLdbMessageObject *ret; + + ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + ret->mem_ctx = talloc_new(NULL); + ret->msg = talloc_reference(ret->mem_ctx, msg); + return (PyObject *)ret; +} + +static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure) +{ + struct ldb_message *msg = pyldb_Message_AsMessage(self); + return pyldb_Dn_FromDn(msg->dn); +} + +static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure) +{ + struct ldb_message *msg = pyldb_Message_AsMessage(self); + if (!pyldb_Dn_Check(value)) { + PyErr_SetString(PyExc_TypeError, "expected dn"); + return -1; + } + + msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value)); + return 0; +} + +static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure) +{ + return wrap_text("MessageTextWrapper", self); +} + +static PyGetSetDef py_ldb_msg_getset[] = { + { + .name = discard_const_p(char, "dn"), + .get = (getter)py_ldb_msg_get_dn, + .set = (setter)py_ldb_msg_set_dn, + }, + { + .name = discard_const_p(char, "text"), + .get = (getter)py_ldb_msg_get_text, + }, + { .name = NULL }, +}; + +static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self) +{ + PyObject *dict = PyDict_New(), *ret, *repr; + if (PyDict_Update(dict, (PyObject *)self) != 0) + return NULL; + repr = PyObject_Repr(dict); + if (repr == NULL) { + Py_DECREF(dict); + return NULL; + } + ret = PyUnicode_FromFormat("Message(%s)", PyUnicode_AsUTF8(repr)); + Py_DECREF(repr); + Py_DECREF(dict); + return ret; +} + +static void py_ldb_msg_dealloc(PyLdbMessageObject *self) +{ + talloc_free(self->mem_ctx); + PyObject_Del(self); +} + +static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1, + PyLdbMessageObject *py_msg2, int op) +{ + struct ldb_message *msg1, *msg2; + unsigned int i; + int ret; + + if (!PyLdbMessage_Check(py_msg2)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + msg1 = pyldb_Message_AsMessage(py_msg1), + msg2 = pyldb_Message_AsMessage(py_msg2); + + if ((msg1->dn != NULL) || (msg2->dn != NULL)) { + ret = ldb_dn_compare(msg1->dn, msg2->dn); + if (ret != 0) { + return richcmp(ret, op); + } + } + + ret = msg1->num_elements - msg2->num_elements; + if (ret != 0) { + return richcmp(ret, op); + } + + for (i = 0; i < msg1->num_elements; i++) { + ret = ldb_msg_element_compare_name(&msg1->elements[i], + &msg2->elements[i]); + if (ret != 0) { + return richcmp(ret, op); + } + + ret = ldb_msg_element_compare(&msg1->elements[i], + &msg2->elements[i]); + if (ret != 0) { + return richcmp(ret, op); + } + } + + return richcmp(0, op); +} + +static PyTypeObject PyLdbMessage = { + .tp_name = "ldb.Message", + .tp_methods = py_ldb_msg_methods, + .tp_getset = py_ldb_msg_getset, + .tp_as_mapping = &py_ldb_msg_mapping, + .tp_basicsize = sizeof(PyLdbMessageObject), + .tp_dealloc = (destructor)py_ldb_msg_dealloc, + .tp_new = py_ldb_msg_new, + .tp_repr = (reprfunc)py_ldb_msg_repr, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_iter = (getiterfunc)py_ldb_msg_iter, + .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp, + .tp_doc = "A LDB Message", +}; + +static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree) +{ + PyLdbTreeObject *ret; + + ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + + ret->mem_ctx = talloc_new(NULL); + ret->tree = talloc_reference(ret->mem_ctx, tree); + return (PyObject *)ret; +} + +static void py_ldb_tree_dealloc(PyLdbTreeObject *self) +{ + talloc_free(self->mem_ctx); + PyObject_Del(self); +} + +static PyTypeObject PyLdbTree = { + .tp_name = "ldb.Tree", + .tp_basicsize = sizeof(PyLdbTreeObject), + .tp_dealloc = (destructor)py_ldb_tree_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "A search tree", +}; + +/* Ldb_module */ +static int py_module_search(struct ldb_module *mod, struct ldb_request *req) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result, *py_base, *py_attrs, *py_tree; + + py_base = pyldb_Dn_FromDn(req->op.search.base); + + if (py_base == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + py_tree = PyLdbTree_FromTree(req->op.search.tree); + + if (py_tree == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + if (req->op.search.attrs == NULL) { + py_attrs = Py_None; + } else { + int i, len; + for (len = 0; req->op.search.attrs[len]; len++); + py_attrs = PyList_New(len); + for (i = 0; i < len; i++) + PyList_SetItem(py_attrs, i, PyUnicode_FromString(req->op.search.attrs[i])); + } + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"), + discard_const_p(char, "OiOO"), + py_base, req->op.search.scope, py_tree, py_attrs); + + Py_DECREF(py_attrs); + Py_DECREF(py_tree); + Py_DECREF(py_base); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + req->op.search.res = PyLdbResult_AsResult(NULL, py_result); + if (req->op.search.res == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_add(struct ldb_module *mod, struct ldb_request *req) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result, *py_msg; + + py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message)); + + if (py_msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"), + discard_const_p(char, "O"), + py_msg); + + Py_DECREF(py_msg); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_modify(struct ldb_module *mod, struct ldb_request *req) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result, *py_msg; + + py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message)); + + if (py_msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"), + discard_const_p(char, "O"), + py_msg); + + Py_DECREF(py_msg); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_del(struct ldb_module *mod, struct ldb_request *req) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result, *py_dn; + + py_dn = pyldb_Dn_FromDn(req->op.del.dn); + + if (py_dn == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"), + discard_const_p(char, "O"), + py_dn); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_rename(struct ldb_module *mod, struct ldb_request *req) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result, *py_olddn, *py_newdn; + + py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn); + + if (py_olddn == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn); + + if (py_newdn == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"), + discard_const_p(char, "OO"), + py_olddn, py_newdn); + + Py_DECREF(py_olddn); + Py_DECREF(py_newdn); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_request(struct ldb_module *mod, struct ldb_request *req) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result; + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"), + discard_const_p(char, "")); + + Py_XDECREF(py_result); + + return LDB_ERR_OPERATIONS_ERROR; +} + +static int py_module_extended(struct ldb_module *mod, struct ldb_request *req) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result; + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"), + discard_const_p(char, "")); + + Py_XDECREF(py_result); + + return LDB_ERR_OPERATIONS_ERROR; +} + +static int py_module_start_transaction(struct ldb_module *mod) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result; + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"), + discard_const_p(char, "")); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_end_transaction(struct ldb_module *mod) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result; + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"), + discard_const_p(char, "")); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_del_transaction(struct ldb_module *mod) +{ + PyObject *py_ldb = (PyObject *)mod->private_data; + PyObject *py_result; + + py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"), + discard_const_p(char, "")); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + Py_DECREF(py_result); + + return LDB_SUCCESS; +} + +static int py_module_destructor(struct ldb_module *mod) +{ + Py_DECREF((PyObject *)mod->private_data); + return 0; +} + +static int py_module_init(struct ldb_module *mod) +{ + PyObject *py_class = (PyObject *)mod->ops->private_data; + PyObject *py_result, *py_next, *py_ldb; + + py_ldb = PyLdb_FromLdbContext(mod->ldb); + + if (py_ldb == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + py_next = PyLdbModule_FromModule(mod->next); + + if (py_next == NULL) + return LDB_ERR_OPERATIONS_ERROR; + + py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"), + py_ldb, py_next); + + if (py_result == NULL) { + return LDB_ERR_PYTHON_EXCEPTION; + } + + mod->private_data = py_result; + + talloc_set_destructor(mod, py_module_destructor); + + return ldb_next_init(mod); +} + +static PyObject *py_register_module(PyObject *module, PyObject *args) +{ + int ret; + struct ldb_module_ops *ops; + PyObject *input; + PyObject *tmp; + + if (!PyArg_ParseTuple(args, "O", &input)) + return NULL; + + ops = talloc_zero(NULL, struct ldb_module_ops); + if (ops == NULL) { + PyErr_NoMemory(); + return NULL; + } + + tmp = PyObject_GetAttrString(input, discard_const_p(char, "name")); + ops->name = talloc_strdup(ops, PyUnicode_AsUTF8(tmp)); + + Py_XDECREF(tmp); + Py_INCREF(input); + ops->private_data = input; + ops->init_context = py_module_init; + ops->search = py_module_search; + ops->add = py_module_add; + ops->modify = py_module_modify; + ops->del = py_module_del; + ops->rename = py_module_rename; + ops->request = py_module_request; + ops->extended = py_module_extended; + ops->start_transaction = py_module_start_transaction; + ops->end_transaction = py_module_end_transaction; + ops->del_transaction = py_module_del_transaction; + + ret = ldb_register_module(ops); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(ops); + } + + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL); + + Py_RETURN_NONE; +} + +static PyObject *py_timestring(PyObject *module, PyObject *args) +{ + /* most times "time_t" is a signed integer type with 32 or 64 bit: + * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */ + long int t_val; + char *tresult; + PyObject *ret; + if (!PyArg_ParseTuple(args, "l", &t_val)) + return NULL; + tresult = ldb_timestring(NULL, (time_t) t_val); + ret = PyUnicode_FromString(tresult); + talloc_free(tresult); + return ret; +} + +static PyObject *py_string_to_time(PyObject *module, PyObject *args) +{ + char *str; + if (!PyArg_ParseTuple(args, "s", &str)) + return NULL; + + return PyInt_FromLong(ldb_string_to_time(str)); +} + +static PyObject *py_valid_attr_name(PyObject *self, PyObject *args) +{ + char *name; + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + return PyBool_FromLong(ldb_valid_attr_name(name)); +} + +/* + encode a string using RFC2254 rules + */ +static PyObject *py_binary_encode(PyObject *self, PyObject *args) +{ + char *str, *encoded; + Py_ssize_t size = 0; + struct ldb_val val; + PyObject *ret; + + if (!PyArg_ParseTuple(args, "s#", &str, &size)) + return NULL; + val.data = (uint8_t *)str; + val.length = size; + + encoded = ldb_binary_encode(NULL, val); + if (encoded == NULL) { + PyErr_SetString(PyExc_TypeError, "unable to encode binary string"); + return NULL; + } + ret = PyUnicode_FromString(encoded); + talloc_free(encoded); + return ret; +} + +/* + decode a string using RFC2254 rules + */ +static PyObject *py_binary_decode(PyObject *self, PyObject *args) +{ + char *str; + struct ldb_val val; + PyObject *ret; + + if (!PyArg_ParseTuple(args, "s", &str)) + return NULL; + + val = ldb_binary_decode(NULL, str); + if (val.data == NULL) { + PyErr_SetString(PyExc_TypeError, "unable to decode binary string"); + return NULL; + } + ret = PyBytes_FromStringAndSize((const char*)val.data, val.length); + talloc_free(val.data); + return ret; +} + +static PyMethodDef py_ldb_global_methods[] = { + { "register_module", py_register_module, METH_VARARGS, + "S.register_module(module) -> None\n\n" + "Register a LDB module."}, + { "timestring", py_timestring, METH_VARARGS, + "S.timestring(int) -> string\n\n" + "Generate a LDAP time string from a UNIX timestamp" }, + { "string_to_time", py_string_to_time, METH_VARARGS, + "S.string_to_time(string) -> int\n\n" + "Parse a LDAP time string into a UNIX timestamp." }, + { "valid_attr_name", py_valid_attr_name, METH_VARARGS, + "S.valid_attr_name(name) -> bool\n\nn" + "Check whether the supplied name is a valid attribute name." }, + { "open", PY_DISCARD_FUNC_SIG(PyCFunction,py_ldb_new), + METH_VARARGS|METH_KEYWORDS, + "S.open() -> Ldb\n\n" + "Open a new LDB context." }, + { "binary_encode", py_binary_encode, METH_VARARGS, + "S.binary_encode(string) -> string\n\n" + "Perform a RFC2254 binary encoding on a string" }, + { "binary_decode", py_binary_decode, METH_VARARGS, + "S.binary_decode(string) -> string\n\n" + "Perform a RFC2254 binary decode on a string" }, + { NULL } +}; + +#define MODULE_DOC "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server." + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "ldb", + .m_doc = MODULE_DOC, + .m_size = -1, + .m_methods = py_ldb_global_methods, +}; +#endif + +static PyObject* module_init(void) +{ + PyObject *m; + + PyLdbBytesType.tp_base = &PyBytes_Type; + if (PyType_Ready(&PyLdbBytesType) < 0) { + return NULL; + } + + if (PyType_Ready(&PyLdbDn) < 0) + return NULL; + + if (PyType_Ready(&PyLdbMessage) < 0) + return NULL; + + if (PyType_Ready(&PyLdbMessageElement) < 0) + return NULL; + + if (PyType_Ready(&PyLdb) < 0) + return NULL; + + if (PyType_Ready(&PyLdbModule) < 0) + return NULL; + + if (PyType_Ready(&PyLdbTree) < 0) + return NULL; + + if (PyType_Ready(&PyLdbResult) < 0) + return NULL; + + if (PyType_Ready(&PyLdbSearchIterator) < 0) + return NULL; + + if (PyType_Ready(&PyLdbControl) < 0) + return NULL; + +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC); +#endif + if (m == NULL) + return NULL; + +#define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val) + + ADD_LDB_INT(SEQ_HIGHEST_SEQ); + ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP); + ADD_LDB_INT(SEQ_NEXT); + ADD_LDB_INT(SCOPE_DEFAULT); + ADD_LDB_INT(SCOPE_BASE); + ADD_LDB_INT(SCOPE_ONELEVEL); + ADD_LDB_INT(SCOPE_SUBTREE); + + ADD_LDB_INT(CHANGETYPE_NONE); + ADD_LDB_INT(CHANGETYPE_ADD); + ADD_LDB_INT(CHANGETYPE_DELETE); + ADD_LDB_INT(CHANGETYPE_MODIFY); + + ADD_LDB_INT(FLAG_MOD_ADD); + ADD_LDB_INT(FLAG_MOD_REPLACE); + ADD_LDB_INT(FLAG_MOD_DELETE); + ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF); + + ADD_LDB_INT(ATTR_FLAG_HIDDEN); + ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX); + ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE); + ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF); + + ADD_LDB_INT(SUCCESS); + ADD_LDB_INT(ERR_OPERATIONS_ERROR); + ADD_LDB_INT(ERR_PROTOCOL_ERROR); + ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED); + ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED); + ADD_LDB_INT(ERR_COMPARE_FALSE); + ADD_LDB_INT(ERR_COMPARE_TRUE); + ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED); + ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED); + ADD_LDB_INT(ERR_REFERRAL); + ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED); + ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION); + ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED); + ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS); + ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE); + ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE); + ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING); + ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION); + ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS); + ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX); + ADD_LDB_INT(ERR_NO_SUCH_OBJECT); + ADD_LDB_INT(ERR_ALIAS_PROBLEM); + ADD_LDB_INT(ERR_INVALID_DN_SYNTAX); + ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM); + ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION); + ADD_LDB_INT(ERR_INVALID_CREDENTIALS); + ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS); + ADD_LDB_INT(ERR_BUSY); + ADD_LDB_INT(ERR_UNAVAILABLE); + ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM); + ADD_LDB_INT(ERR_LOOP_DETECT); + ADD_LDB_INT(ERR_NAMING_VIOLATION); + ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION); + ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF); + ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN); + ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS); + ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED); + ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS); + ADD_LDB_INT(ERR_OTHER); + + ADD_LDB_INT(FLG_RDONLY); + ADD_LDB_INT(FLG_NOSYNC); + ADD_LDB_INT(FLG_RECONNECT); + ADD_LDB_INT(FLG_NOMMAP); + ADD_LDB_INT(FLG_SHOW_BINARY); + ADD_LDB_INT(FLG_ENABLE_TRACING); + ADD_LDB_INT(FLG_DONT_CREATE_DB); + + ADD_LDB_INT(PACKING_FORMAT); + ADD_LDB_INT(PACKING_FORMAT_V2); + + /* Historical misspelling */ + PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM); + + PyModule_AddStringConstant(m, "__docformat__", "restructuredText"); + + PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL); + PyModule_AddObject(m, "LdbError", PyExc_LdbError); + + Py_INCREF(&PyLdb); + Py_INCREF(&PyLdbDn); + Py_INCREF(&PyLdbModule); + Py_INCREF(&PyLdbMessage); + Py_INCREF(&PyLdbMessageElement); + Py_INCREF(&PyLdbTree); + Py_INCREF(&PyLdbResult); + Py_INCREF(&PyLdbControl); + + PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb); + PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn); + PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage); + PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement); + PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule); + PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree); + PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl); + + PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION); + +#define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val) + + ADD_LDB_STRING(SYNTAX_DN); + ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING); + ADD_LDB_STRING(SYNTAX_INTEGER); + ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER); + ADD_LDB_STRING(SYNTAX_BOOLEAN); + ADD_LDB_STRING(SYNTAX_OCTET_STRING); + ADD_LDB_STRING(SYNTAX_UTC_TIME); + ADD_LDB_STRING(OID_COMPARATOR_AND); + ADD_LDB_STRING(OID_COMPARATOR_OR); + + return m; +} + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC PyInit_ldb(void); +PyMODINIT_FUNC PyInit_ldb(void) +{ + return module_init(); +} +#else +void initldb(void); +void initldb(void) +{ + module_init(); +} +#endif diff --git a/ldb-2.0.8/pyldb.h b/ldb-2.0.8/pyldb.h new file mode 100644 index 0000000..4fc89ec --- /dev/null +++ b/ldb-2.0.8/pyldb.h @@ -0,0 +1,109 @@ +/* + Unix SMB/CIFS implementation. + + Python interface to ldb. + + Copyright (C) 2007-2008 Jelmer Vernooij + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#ifndef _PYLDB_H_ +#define _PYLDB_H_ + +#include + +typedef struct { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + struct ldb_context *ldb_ctx; +} PyLdbObject; + +#define pyldb_Ldb_AsLdbContext(pyobj) ((PyLdbObject *)pyobj)->ldb_ctx + +typedef struct { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + struct ldb_dn *dn; +} PyLdbDnObject; + +PyObject *pyldb_Dn_FromDn(struct ldb_dn *); +bool pyldb_Object_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, struct ldb_context *ldb_ctx, struct ldb_dn **dn); +#define pyldb_Dn_AsDn(pyobj) ((PyLdbDnObject *)pyobj)->dn + +typedef struct { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + struct ldb_message *msg; +} PyLdbMessageObject; +#define pyldb_Message_AsMessage(pyobj) ((PyLdbMessageObject *)pyobj)->msg + +typedef struct { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + struct ldb_module *mod; +} 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 { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + struct ldb_parse_tree *tree; +} PyLdbTreeObject; +#define pyldb_Tree_AsTree(pyobj) ((PyLdbTreeObject *)pyobj)->tree + +typedef struct { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + PyObject *msgs; + PyObject *referals; + PyObject *controls; +} PyLdbResultObject; + +typedef struct { + PyObject_HEAD + TALLOC_CTX *mem_ctx; + struct ldb_control *data; +} PyLdbControlObject; + +#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 ? */ +#define LDB_ERR_PYTHON_EXCEPTION 142 + +#endif /* _PYLDB_H_ */ diff --git a/ldb-2.0.8/pyldb_util.c b/ldb-2.0.8/pyldb_util.c new file mode 100644 index 0000000..f8d0664 --- /dev/null +++ b/ldb-2.0.8/pyldb_util.c @@ -0,0 +1,113 @@ +/* + Unix SMB/CIFS implementation. + + Python interface to ldb - utility functions. + + Copyright (C) 2007-2010 Jelmer Vernooij + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include +#include "ldb.h" +#include "pyldb.h" + +static PyObject *ldb_module = NULL; + +/** + * Find out PyTypeObject in ldb module for a given typename + */ +static PyTypeObject * PyLdb_GetPyType(const char *typename) +{ + PyObject *py_obj = NULL; + + if (ldb_module == NULL) { + ldb_module = PyImport_ImportModule("ldb"); + if (ldb_module == NULL) { + return NULL; + } + } + + py_obj = PyObject_GetAttrString(ldb_module, typename); + + return (PyTypeObject*)py_obj; +} + +/** + * Obtain a ldb DN from a Python object. + * + * @param mem_ctx Memory context + * @param object Python object + * @param ldb_ctx LDB context + * @return Whether or not the conversion succeeded + */ +bool pyldb_Object_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, + struct ldb_context *ldb_ctx, struct ldb_dn **dn) +{ + struct ldb_dn *odn; + PyTypeObject *PyLdb_Dn_Type; + + if (ldb_ctx != NULL && (PyUnicode_Check(object))) { + odn = ldb_dn_new(mem_ctx, ldb_ctx, PyUnicode_AsUTF8(object)); + *dn = odn; + return true; + } + + if (ldb_ctx != NULL && PyBytes_Check(object)) { + odn = ldb_dn_new(mem_ctx, ldb_ctx, PyBytes_AsString(object)); + *dn = odn; + return true; + } + + PyLdb_Dn_Type = PyLdb_GetPyType("Dn"); + if (PyLdb_Dn_Type == NULL) { + return false; + } + + if (PyObject_TypeCheck(object, PyLdb_Dn_Type)) { + *dn = pyldb_Dn_AsDn(object); + return true; + } + + PyErr_SetString(PyExc_TypeError, "Expected DN"); + return false; +} + +PyObject *pyldb_Dn_FromDn(struct ldb_dn *dn) +{ + PyLdbDnObject *py_ret; + PyTypeObject *PyLdb_Dn_Type; + + if (dn == NULL) { + Py_RETURN_NONE; + } + + PyLdb_Dn_Type = PyLdb_GetPyType("Dn"); + if (PyLdb_Dn_Type == NULL) { + return NULL; + } + + py_ret = (PyLdbDnObject *)PyLdb_Dn_Type->tp_alloc(PyLdb_Dn_Type, 0); + if (py_ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + py_ret->mem_ctx = talloc_new(NULL); + py_ret->dn = talloc_reference(py_ret->mem_ctx, dn); + return (PyObject *)py_ret; +} diff --git a/ldb-2.0.8/tests/guidindexpackv1.ldb b/ldb-2.0.8/tests/guidindexpackv1.ldb new file mode 100644 index 0000000..4c79dfe Binary files /dev/null and b/ldb-2.0.8/tests/guidindexpackv1.ldb differ diff --git a/ldb-2.0.8/tests/init.ldif b/ldb-2.0.8/tests/init.ldif new file mode 100644 index 0000000..97b4561 --- /dev/null +++ b/ldb-2.0.8/tests/init.ldif @@ -0,0 +1,41 @@ +dn: o=University of Michigan,c=TEST +objectclass: organization +objectclass: domainRelatedObject +l: Ann Arbor, Michigan +st: Michigan +o: University of Michigan +o: UMICH +o: UM +o: U-M +o: U of M +description: The University of Michigan at Ann Arbor +postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 + 09 $ US +telephonenumber: +1 313 764-1817 +associateddomain: example.com + +# there was an empty "seeAlso" here + +dn: ou=People,o=University of Michigan,c=TEST +objectclass: organizationalUnit +objectclass: extensibleObject +ou: People +uidNumber: 0 +gidNumber: 0 + +dn: ou=Ldb Test,ou=People,o=University of Michigan,c=TEST +objectclass: organizationalUnit +objectclass: extensibleObject +ou: People +ou: Ldb Test +uidNumber: 0 +gidNumber: 0 + +dn: ou=LdbTspace,ou=People,o=University of Michigan,c=TEST +objectclass: organizationalUnit +objectclass: extensibleObject +ou: People +ou: LdbTspace +description: test white space removal in comparisons +uidNumber: 0 +gidNumber: 0 diff --git a/ldb-2.0.8/tests/init_slapd.sh b/ldb-2.0.8/tests/init_slapd.sh new file mode 100755 index 0000000..cf06acd --- /dev/null +++ b/ldb-2.0.8/tests/init_slapd.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +if [ -z "$LDBDIR" ]; then + LDBDIR=`dirname $0`/.. + export LDBDIR +fi + +rm -rf tests/tmp/db +mkdir -p tests/tmp/db + +if [ -f tests/tmp/slapd.pid ]; then + kill `cat tests/tmp/slapd.pid` + sleep 1 +fi +if [ -f tests/tmp/slapd.pid ]; then + kill -9 `cat tests/tmp/slapd.pid` + rm -f tests/tmp/slapd.pid +fi + +# we don't consider a slapadd failure as a test suite failure, as it +# has nothing to do with ldb + +MODCONF=tests/tmp/modules.conf +rm -f $MODCONF +touch $MODCONF || exit 1 + +slaptest -u -f $LDBDIR/tests/slapd.conf > /dev/null 2>&1 || { + echo "enabling sladp modules" +cat > $MODCONF < 2019 + * + * 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 . + * + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + */ +#include +#include +#include +#include +#include + +#include "../include/ldb.h" +#include "../include/ldb_module.h" + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; +}; + +/* + * NOTE WELL: + * + * This test checks the current behaviour of the function, however + * this is not in a public ABI and many of the tested behaviours are + * not ideal. If the behaviour is deliberatly improved, this test + * should be updated without worry to the new better behaviour. + * + * In particular the test is particularly to ensure the current + * behaviour is memory-safe. + */ + +static int setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + *state = test_ctx; + return 0; +} + +static int teardown(void **state) +{ + talloc_free(*state); + return 0; +} + + +/* + * Test against a record with only one attribute, matching the one in + * the list + */ +static void test_filter_attrs_one_attr_matched(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"foo", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + assert_int_equal(filtered_msg->num_elements, 1); + assert_string_equal(filtered_msg->elements[0].name, "foo"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value, sizeof(value)); +} + +/* + * Test against a record with only one attribute, matching the one of + * the multiple attributes in the list + */ +static void test_filter_attrs_one_attr_matched_of_many(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"foo", "bar", "baz", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + assert_int_equal(filtered_msg->num_elements, 1); + assert_string_equal(filtered_msg->elements[0].name, "foo"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value, sizeof(value)); +} + +/* + * Test against a record with only one attribute, matching both + * attributes in the list + */ +static void test_filter_attrs_two_attr_matched_attrs(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + /* deliberatly the other order */ + const char *attrs[] = {"bar", "foo", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "foo", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 2); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "foo"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes, only of which is in + * the list + */ +static void test_filter_attrs_two_attr_matched_one_attr(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + /* deliberatly the other order */ + const char *attrs[] = {"bar", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "foo", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 1); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes, both matching the one + * specified attribute in the list (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + /* deliberatly the other order */ + const char *attrs[] = {"bar", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This should fail the pidgenhole test */ + assert_int_equal(ret, -1); + assert_null(filtered_msg->elements); +} + +/* + * Test against a record with two attributes, both matching the one + * specified attribute in the list (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_dup(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"bar", "bar", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This does not fail the pidgenhole test */ + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(filtered_msg->num_elements, 2); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes, both matching one of the + * specified attributes in the list (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"bar", "foo", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This does not fail the pidgenhole test */ + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(filtered_msg->num_elements, 2); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes against * (but not the + * other named attribute) (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_star(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", "foo", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + /* Needed as * implies distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This does not fail the pidgenhole test */ + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(filtered_msg->num_elements, 3); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); + /* + * assert the ldb_filter_attrs does not modify filtered_msg.dn + * in this case + */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); +} + +/* + * Test against a record with only one attribute, matching the * in + * the list + */ +static void test_filter_attrs_one_attr_matched_star(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + /* Needed as * implies distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 2); + + /* + * assert the ldb_filter_attrs does not modify filtered_msg.dn + * in this case + */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "foo", + NULL), + value); +} + +/* + * Test against a record with two attributes, matching the * in + * the list + */ +static void test_filter_attrs_two_attr_matched_star(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + struct ldb_message_element elements[] = { + { + .name = "foo", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + /* Needed as * implies distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 3); + + /* + * assert the ldb_filter_attrs does not modify filtered_msg.dn + * in this case + */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "foo", + NULL), + value1); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "bar", + NULL), + value2); +} + +/* + * Test against a record with only one attribute, matching the * in + * the list, but without the DN being pre-filled. Fails due to need + * to contstruct the distinguishedName + */ +static void test_filter_attrs_one_attr_matched_star_no_dn(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, -1); + assert_null(filtered_msg->elements); +} + +/* + * Test against a record with only one attribute, matching the * in + * the list plus requsesting distinguishedName + */ +static void test_filter_attrs_one_attr_matched_star_dn(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", "distinguishedName", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + /* Needed for distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 2); + + /* show that ldb_filter_attrs does not modify in.dn */ + assert_ptr_equal(filtered_msg->dn, in.dn); + + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "foo", + NULL), + value); +} + +/* + * Test against a record with only one attribute, but returning + * distinguishedName from the list (only) + */ +static void test_filter_attrs_one_attr_matched_dn(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"distinguishedName", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + /* Needed for distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 1); + + /* show that ldb_filter_attrs does not modify in.dn */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(filtered_msg->elements[0].name, "distinguishedName"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_string_equal(filtered_msg->elements[0].values[0].data, + ldb_dn_get_linearized(in.dn)); +} + +/* + * Test against a record with only one attribute, not matching the + * empty attribute list + */ +static void test_filter_attrs_one_attr_empty_list(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 0); + assert_null(filtered_msg->dn); + assert_null(filtered_msg->elements); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_of_many, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_attr_matched_attrs, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_attr_matched_one_attr, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_one_attr, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_dup, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_one_of_two, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_star, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_star, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_attr_matched_star, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_star_no_dn, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_star_dn, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_dn, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_empty_list, + setup, + teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_key_value_sub_txn_mdb_test.valgrind b/ldb-2.0.8/tests/ldb_key_value_sub_txn_mdb_test.valgrind new file mode 100644 index 0000000..1747076 --- /dev/null +++ b/ldb-2.0.8/tests/ldb_key_value_sub_txn_mdb_test.valgrind @@ -0,0 +1,97 @@ +{ + Memory allocated by setup + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:setup +} +{ + Memory allocated by setup + Memcheck:Leak + match-leak-kinds: possible + fun:realloc + ... + fun:setup +} +{ + Memory allocated by ldb_init + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_init +} +{ + Memory allocated by ldb_init + Memcheck:Leak + match-leak-kinds: possible + fun:realloc + ... + fun:ldb_init +} +{ + Memory allocated by noconn_setup + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:noconn_setup +} +{ + Memory allocated by parse, which allocates on the NULL context + Memcheck:Leak + match-leak-kinds: all + fun:malloc + ... + fun:parse +} +{ + Memory allocated by tdb_parse_data + Memcheck:Leak + match-leak-kinds: all + fun:malloc + ... + fun:tdb_parse_data +} +{ + Memory allocated by ldb_connect + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_connect +} +{ + Memory allocated by ldb_connect + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:ldb_connect +} +{ + Memory allocated by ldb_kv_cache_load + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_kv_cache_load +} +{ + Memory allocated by ldb_kv_index_load + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_kv_index_load +} +{ + Memory allocated by ldb_asprintf_errstring + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_asprintf_errstring +} + diff --git a/ldb-2.0.8/tests/ldb_key_value_sub_txn_test.c b/ldb-2.0.8/tests/ldb_key_value_sub_txn_test.c new file mode 100644 index 0000000..e71f81b --- /dev/null +++ b/ldb-2.0.8/tests/ldb_key_value_sub_txn_test.c @@ -0,0 +1,843 @@ +/* + * Tests exercising the ldb key value operations. + * + * Copyright (C) Andrew Bartlett 2018 + * + * 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 . + * + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ + +/* + */ +#include +#include +#include +#include + +#include +#define NO_FAILURE INT_MAX +#define FAILURE_LDB_ERR LDB_ERR_OTHER + +/* + * To test failure in ldb_kv_add, ldb_kv_delete, ldb_kv_modify and ldb_kv_rename + * we use the following global variables and macros to trigger a failure in + * the ldb_kv__internal functions. This allows testing of the sub + * transaction commits and roll backs in those operations. + * + * NOTE: Not all back ends support nested/sub transactions + */ +int cmocka_unit_test_fail_add_internal_after = NO_FAILURE; +#define CMOCKA_UNIT_TEST_ADD_INTERNAL_FAIL \ + {\ + cmocka_unit_test_fail_add_internal_after--;\ + if (cmocka_unit_test_fail_add_internal_after <= 0) {\ + assert_int_equal(LDB_SUCCESS, ret);\ + ret = FAILURE_LDB_ERR;\ + }\ + }\ + +int cmocka_unit_test_fail_delete_internal_after = NO_FAILURE; +#define CMOCKA_UNIT_TEST_DELETE_INTERNAL_FAIL \ + {\ + cmocka_unit_test_fail_delete_internal_after--;\ + if (cmocka_unit_test_fail_delete_internal_after <= 0) {\ + assert_int_equal(LDB_SUCCESS, ret);\ + ret = FAILURE_LDB_ERR;\ + }\ + }\ + +int cmocka_unit_test_fail_rename_internal_after = NO_FAILURE; +#define CMOCKA_UNIT_TEST_RENAME_INTERNAL_FAIL \ + {\ + cmocka_unit_test_fail_rename_internal_after--;\ + if (cmocka_unit_test_fail_rename_internal_after <= 0) {\ + assert_int_equal(LDB_SUCCESS, ret);\ + ret = FAILURE_LDB_ERR;\ + }\ + }\ + +int cmocka_unit_test_fail_modify_internal_after = NO_FAILURE; +#define CMOCKA_UNIT_TEST_MODIFY_INTERNAL_FAIL \ + {\ + cmocka_unit_test_fail_modify_internal_after--;\ + if (cmocka_unit_test_fail_modify_internal_after <= 0) {\ + assert_int_equal(LDB_SUCCESS, ret);\ + ret = FAILURE_LDB_ERR;\ + }\ + }\ + +#include "ldb_key_value/ldb_kv.c" + + +#define DEFAULT_BE "tdb" + +#ifndef TEST_BE +#define TEST_BE DEFAULT_BE +#endif /* TEST_BE */ + +#define NUM_RECS 1024 + + +struct test_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; + + const char *dbfile; + const char *lockfile; /* lockfile is separate */ + + const char *dbpath; +}; + +/* + * Remove the database files + */ +static void unlink_old_db(struct test_ctx *test_ctx) +{ + int ret; + + errno = 0; + ret = unlink(test_ctx->lockfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } + + errno = 0; + ret = unlink(test_ctx->dbfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } +} + +/* + * Test setup + */ +static int noconn_setup(void **state) +{ + struct test_ctx *test_ctx; + cmocka_unit_test_fail_add_internal_after = NO_FAILURE; + cmocka_unit_test_fail_delete_internal_after = NO_FAILURE; + cmocka_unit_test_fail_rename_internal_after = NO_FAILURE; + cmocka_unit_test_fail_modify_internal_after = NO_FAILURE; + + test_ctx = talloc_zero(NULL, struct test_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb"); + assert_non_null(test_ctx->dbfile); + + test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock", + test_ctx->dbfile); + assert_non_null(test_ctx->lockfile); + + test_ctx->dbpath = talloc_asprintf(test_ctx, + TEST_BE"://%s", test_ctx->dbfile); + assert_non_null(test_ctx->dbpath); + + unlink_old_db(test_ctx); + *state = test_ctx; + return 0; +} + +/* + * Test teardown + */ +static int noconn_teardown(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + + unlink_old_db(test_ctx); + talloc_free(test_ctx); + return 0; +} + +/* + * Test setup + */ +static int setup(void **state) +{ + struct test_ctx *test_ctx; + int ret; + struct ldb_ldif *ldif; + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" + "\n"; + + noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) { + ret = ldb_add(test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + *state = test_ctx; + return 0; +} + +/* + * Test teardown + */ +static int teardown(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + noconn_teardown((void **) &test_ctx); + return 0; +} + +/* + * Build an ldb_kv_context that can be passed to the ldb_kv operation under test + */ +static struct ldb_kv_context* build_ldb_kv_context( + TALLOC_CTX *ctx, + struct ldb_module *module, + struct ldb_request *req) +{ + struct ldb_kv_context *ldb_kv_ctx = NULL; + + ldb_kv_ctx = talloc_zero(ctx, struct ldb_kv_context); + assert_non_null(ldb_kv_ctx); + + ldb_kv_ctx->module = module; + ldb_kv_ctx->req = req; + + return ldb_kv_ctx; +} + +/* + * Build an add request + */ +static struct ldb_request *build_add_request( + TALLOC_CTX *ctx, + struct ldb_context *ldb, + const char* dc, + const char* uuid, + const char* cn) +{ + int ret; + struct ldb_message *msg; + struct ldb_request *req; + + msg = ldb_msg_new(ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, ldb, "dc=%s", dc); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", cn); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", uuid); + assert_int_equal(ret, 0); + + ret = ldb_msg_sanity_check(ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_build_add_req( + &req, ldb, ldb, msg, NULL, NULL, ldb_op_default_callback, NULL); + assert_int_equal(ret, LDB_SUCCESS); + return req; +} + +/* + * Build a delete request + */ +static struct ldb_request *build_delete_request( + TALLOC_CTX *ctx, + struct ldb_context *ldb, + const char* dc) +{ + int ret = LDB_SUCCESS; + struct ldb_dn *dn = NULL; + struct ldb_request *req = NULL; + + dn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", dc); + assert_non_null(dn); + + ret = ldb_build_del_req( + &req, ldb, ctx, dn, NULL, NULL, ldb_op_default_callback, NULL); + assert_int_equal(ret, LDB_SUCCESS); + return req; +} + +/* + * Build a rename request + */ +static struct ldb_request *build_rename_request( + TALLOC_CTX *ctx, + struct ldb_context *ldb, + const char* old_dc, + const char* new_dc) +{ + int ret = LDB_SUCCESS; + struct ldb_dn *old_dn = NULL; + struct ldb_dn *new_dn = NULL; + struct ldb_request *req = NULL; + + old_dn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", old_dc); + assert_non_null(old_dn); + + new_dn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", new_dc); + assert_non_null(new_dn); + + ret = ldb_build_rename_req( + &req, + ldb, + ctx, + old_dn, + new_dn, + NULL, + NULL, + ldb_op_default_callback, + NULL); + assert_int_equal(ret, LDB_SUCCESS); + return req; +} + +/* + * Build a ldb modify request + */ +static struct ldb_request *build_modify_request( + TALLOC_CTX *ctx, + struct ldb_context *ldb, + const char* dc, + const char* cn) +{ + int ret; + struct ldb_message *msg; + struct ldb_request *req; + + msg = ldb_msg_new(ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, ldb, "dc=%s", dc); + assert_non_null(msg->dn); + + ret = ldb_msg_add_empty(msg, "cn", LDB_FLAG_MOD_REPLACE, NULL); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_add_string(msg, "cn", cn); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_sanity_check(ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_build_mod_req( + &req, ldb, ldb, msg, NULL, NULL, ldb_op_default_callback, NULL); + assert_int_equal(ret, LDB_SUCCESS); + return req; +} + +/* + * Delete a record from the database + */ +static void delete_record( + TALLOC_CTX *ctx, + struct ldb_context *ldb, + const char* dc) +{ + struct ldb_kv_context *ldb_kv_ctx = NULL; + struct ldb_dn *basedn = NULL; + struct ldb_result *result = NULL; + struct ldb_request *req = NULL; + int ret = LDB_SUCCESS; + + req = build_delete_request(ctx, ldb, dc); + ldb_kv_ctx = build_ldb_kv_context(ctx, ldb->modules, req); + + ret = ldb_transaction_start(ldb); + assert_int_equal(ret, LDB_SUCCESS); + + cmocka_unit_test_fail_delete_internal_after = NO_FAILURE; + cmocka_unit_test_fail_modify_internal_after = NO_FAILURE; + ret = ldb_kv_delete(ldb_kv_ctx); + assert_int_equal(ret, LDB_SUCCESS); + TALLOC_FREE(ldb_kv_ctx); + TALLOC_FREE(req); + + ret = ldb_transaction_commit(ldb); + assert_int_equal(ret, LDB_SUCCESS); + + /* + * Ensure that the record was actually deleted. + */ + basedn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", dc); + assert_non_null(basedn); + + /* + * DN search, indexed + */ + ret = ldb_search(ldb, ctx, &result, basedn, LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 0); + TALLOC_FREE(basedn); + TALLOC_FREE(result); +} + +/* + * Add a record to the database + */ +static void add_record( + TALLOC_CTX *ctx, + struct ldb_context *ldb, + const char* dc, + const char* uuid, + const char* cn) +{ + + struct ldb_request *req = NULL; + int ret = LDB_SUCCESS; + struct ldb_kv_context *ldb_kv_ctx = NULL; + struct ldb_dn *basedn = NULL; + struct ldb_result *result = NULL; + + req = build_add_request(ctx, ldb, dc, uuid, cn); + + ldb_req_set_location(req, "add_record"); + + assert_int_equal(ret, LDB_SUCCESS); + + + ldb_kv_ctx = build_ldb_kv_context(ctx, ldb->modules, req); + cmocka_unit_test_fail_add_internal_after = NO_FAILURE; + cmocka_unit_test_fail_modify_internal_after = NO_FAILURE; + + ret = ldb_transaction_start(ldb); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_kv_add(ldb_kv_ctx); + assert_int_equal(ret, LDB_SUCCESS); + TALLOC_FREE(ldb_kv_ctx); + TALLOC_FREE(req); + + ret = ldb_transaction_commit(ldb); + assert_int_equal(ret, LDB_SUCCESS); + + /* + * Ensure that the record was actually written. + */ + basedn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", dc); + assert_non_null(basedn); + + /* + * DN search, indexed + */ + ret = ldb_search(ldb, ctx, &result, basedn, LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 1); + TALLOC_FREE(result); + + + /* + * CN search unindexed + */ + ret = ldb_search( + ldb, + ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + NULL, + "(cn=%s)", + cn); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 1); + TALLOC_FREE(result); + TALLOC_FREE(basedn); +} + +/* + * Test that a failed add operation does not change the database. + */ +static void test_add_failure(void **state) +{ + int ret = LDB_SUCCESS; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_request *req = NULL; + struct ldb_dn *basedn = NULL; + struct ldb_result *result = NULL; + struct ldb_kv_context *ldb_kv_ctx = NULL; + + TALLOC_CTX *tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + req = build_add_request( + tmp_ctx, + test_ctx->ldb, + "test_add_failure", + "0123456789abcdef", + "test_add_failure_value"); + + ldb_req_set_location(req, "test_add_failure"); + + ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req); + cmocka_unit_test_fail_add_internal_after = 1; + + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_kv_add(ldb_kv_ctx); + + assert_int_equal(ret, FAILURE_LDB_ERR); + TALLOC_FREE(ldb_kv_ctx); + TALLOC_FREE(req); + + + /* + * a search for "cn=test_add_failure_value" should fail + * as the transaction containing the operation should have been + * rolled back leaving the database consistent + * + * This should be an un-indexed search so the index caches won't be + * used. + */ + basedn = ldb_dn_new_fmt( + tmp_ctx, + test_ctx->ldb, + "dc=%s", + "test_add_failure"); + assert_non_null(basedn); + + ret = ldb_search( + test_ctx->ldb, tmp_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + NULL, + "(cn=%s)", + "test_add_failure_value"); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 0); + TALLOC_FREE(basedn); + TALLOC_FREE(result); + + ldb_transaction_cancel(test_ctx->ldb); + TALLOC_FREE(tmp_ctx); +} + + +/* + * Test that a failed delete operation does not modify the database. + */ +static void test_delete_failure(void **state) +{ + int ret = LDB_SUCCESS; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_request *req = NULL; + struct ldb_dn *basedn = NULL; + struct ldb_result *result = NULL; + struct ldb_kv_context *ldb_kv_ctx = NULL; + + TALLOC_CTX *tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + add_record( + tmp_ctx, + test_ctx->ldb, + "test_delete_failure", + "0123456789abcded", + "test_delete_failure_value"); + + req = build_delete_request( + tmp_ctx, + test_ctx->ldb, + "test_delete_failure"); + + ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req); + cmocka_unit_test_fail_delete_internal_after = 1; + + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_kv_delete(ldb_kv_ctx); + assert_int_equal(ret, FAILURE_LDB_ERR); + TALLOC_FREE(ldb_kv_ctx); + TALLOC_FREE(req); + + /* + * a search for "cn=test_add_failure_value" should succeed + * as the transaction containing the operation should have been + * rolled back leaving the database consistent + * + * This should be an un-indexed search so the index caches won't be + * used. + */ + basedn = ldb_dn_new_fmt( + tmp_ctx, + test_ctx->ldb, + "dc=%s", + "test_delete_failure"); + assert_non_null(basedn); + + ret = ldb_search( + test_ctx->ldb, tmp_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + NULL, + "(cn=%s)", + "test_delete_failure_value"); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 1); + TALLOC_FREE(basedn); + TALLOC_FREE(result); + + + ldb_transaction_cancel(test_ctx->ldb); + delete_record( + tmp_ctx, + test_ctx->ldb, + "test_delete_failure"); + TALLOC_FREE(tmp_ctx); +} + +/* + * Test that a failed rename operation dies not change the database + */ +static void test_rename_failure(void **state) +{ + int ret = LDB_SUCCESS; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_request *req = NULL; + struct ldb_dn *basedn = NULL; + struct ldb_result *result = NULL; + struct ldb_kv_context *ldb_kv_ctx = NULL; + + TALLOC_CTX *tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + add_record( + tmp_ctx, + test_ctx->ldb, + "test_rename_failure", + "0123456789abcdec", + "test_rename_failure_value"); + + req = build_rename_request( + tmp_ctx, + test_ctx->ldb, + "test_rename_failure", + "test_rename_failure_renamed"); + + ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req); + cmocka_unit_test_fail_rename_internal_after = 1; + + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_kv_rename(ldb_kv_ctx); + assert_int_equal(ret, FAILURE_LDB_ERR); + TALLOC_FREE(ldb_kv_ctx); + TALLOC_FREE(req); + + /* + * The original record should be present + */ + basedn = ldb_dn_new_fmt( + tmp_ctx, + test_ctx->ldb, + "dc=%s", + "test_rename_failure"); + assert_non_null(basedn); + + ret = ldb_search( + test_ctx->ldb, tmp_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + NULL, + "(cn=%s)", + "test_rename_failure_value"); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 1); + TALLOC_FREE(basedn); + TALLOC_FREE(result); + + /* + * And the renamed record should not be present + */ + basedn = ldb_dn_new_fmt( + tmp_ctx, + test_ctx->ldb, + "dc=%s", + "test_rename_failure_renamed"); + assert_non_null(basedn); + + ret = ldb_search( + test_ctx->ldb, tmp_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + NULL, + "(cn=%s)", + "test_rename_failure_value"); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 0); + TALLOC_FREE(basedn); + TALLOC_FREE(result); + + ldb_transaction_cancel(test_ctx->ldb); + delete_record( + tmp_ctx, + test_ctx->ldb, + "test_rename_failure"); + TALLOC_FREE(tmp_ctx); +} + +/* + * Test that a failed modification operation does not change the database + */ +static void test_modify_failure(void **state) +{ + int ret = LDB_SUCCESS; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_request *req = NULL; + struct ldb_dn *basedn = NULL; + struct ldb_result *result = NULL; + struct ldb_kv_context *ldb_kv_ctx = NULL; + + TALLOC_CTX *tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + add_record( + tmp_ctx, + test_ctx->ldb, + "test_modify_failure", + "0123456789abcdeb", + "test_modify_failure_value"); + + req = build_modify_request( + tmp_ctx, + test_ctx->ldb, + "test_modify_failure", + "test_modify_failure_value_modified"); + + ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req); + cmocka_unit_test_fail_modify_internal_after = 2; + + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_kv_modify(ldb_kv_ctx); + assert_int_equal(ret, FAILURE_LDB_ERR); + TALLOC_FREE(ldb_kv_ctx); + TALLOC_FREE(req); + + + /* + * The original value should be present + */ + basedn = ldb_dn_new_fmt( + tmp_ctx, + test_ctx->ldb, + "dc=%s", + "test_modify_failure"); + assert_non_null(basedn); + + ret = ldb_search( + test_ctx->ldb, tmp_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + NULL, + "(cn=%s)", + "test_modify_failure_value"); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 1); + TALLOC_FREE(result); + + /* + * And the modified record should not be present + */ + ret = ldb_search( + test_ctx->ldb, tmp_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + NULL, + "(cn=%s)", + "test_modify_failure_value_modified"); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 0); + TALLOC_FREE(basedn); + TALLOC_FREE(result); + + ldb_transaction_cancel(test_ctx->ldb); + delete_record( + tmp_ctx, + test_ctx->ldb, + "test_modify_failure"); + TALLOC_FREE(tmp_ctx); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_add_failure, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_delete_failure, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_rename_failure, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_modify_failure, + setup, + teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_key_value_test.c b/ldb-2.0.8/tests/ldb_key_value_test.c new file mode 100644 index 0000000..3f31bb9 --- /dev/null +++ b/ldb-2.0.8/tests/ldb_key_value_test.c @@ -0,0 +1,388 @@ +/* + * Tests exercising the ldb key value operations. + * + * Copyright (C) Andrew Bartlett 2019 + * + * 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 . + * + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ + +/* + * + * Tests for the ldb key value layer + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "ldb_key_value/ldb_kv.c" +#include "ldb_key_value/ldb_kv_index.c" +#include "ldb_key_value/ldb_kv_search.c" + +#define DEFAULT_BE "tdb" + +#ifndef TEST_BE +#define TEST_BE DEFAULT_BE +#endif /* TEST_BE */ + +#define NUM_RECS 1024 +int ldb_kv_cache_reload(struct ldb_module *module) { + return LDB_SUCCESS; +} +int ldb_kv_cache_load(struct ldb_module *module) { + return LDB_SUCCESS; +} +int ldb_kv_check_at_attributes_values(const struct ldb_val *value) { + return LDB_SUCCESS; +} +int ldb_kv_increase_sequence_number(struct ldb_module *module) { + return LDB_SUCCESS; +} + +struct test_ctx { +}; + +static int setup(void **state) +{ + struct test_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct test_ctx); + *state = test_ctx; + return 0; +} + +static int teardown(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + + talloc_free(test_ctx); + return 0; +} + +/* + * Test that the index cache is opened by ldb_kv_index_transaction_start + * and correctly initialised with the passed index cache size. + */ +static void test_index_cache_init(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct ldb_module *module = NULL; + struct ldb_kv_private *ldb_kv = NULL; + int ret = LDB_SUCCESS; + + module = talloc_zero(test_ctx, struct ldb_module); + ldb_kv = talloc_zero(test_ctx, struct ldb_kv_private); + ldb_module_set_private(module, ldb_kv); + + ret = ldb_kv_index_transaction_start(module, 191); + assert_int_equal(LDB_SUCCESS, ret); + + assert_non_null(ldb_kv->idxptr); + assert_non_null(ldb_kv->idxptr->itdb); + assert_int_equal(191, tdb_hash_size(ldb_kv->idxptr->itdb)); + + TALLOC_FREE(ldb_kv); + TALLOC_FREE(module); +} + +static int mock_begin_write(struct ldb_kv_private* ldb_kv) { + return LDB_SUCCESS; +} +static int mock_abort_write(struct ldb_kv_private* ldb_kv) { + return LDB_SUCCESS; +} + +/* + * Test that the index cache is set to the default cache size at the start of + * a transaction. + */ +static void test_default_index_cache_size(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct ldb_module *module = NULL; + struct ldb_kv_private *ldb_kv = NULL; + int ret = LDB_SUCCESS; + const struct kv_db_ops ops = { + .begin_write = mock_begin_write, + .abort_write = mock_abort_write + }; + + module = talloc_zero(test_ctx, struct ldb_module); + ldb_kv = talloc_zero(test_ctx, struct ldb_kv_private); + ldb_kv->pid = getpid(); + ldb_kv->kv_ops = &ops; + ldb_kv->index_transaction_cache_size = DEFAULT_INDEX_CACHE_SIZE; + ldb_module_set_private(module, ldb_kv); + + ret = ldb_kv_start_trans(module); + assert_int_equal(LDB_SUCCESS, ret); + + assert_int_equal( + DEFAULT_INDEX_CACHE_SIZE, + tdb_hash_size(ldb_kv->idxptr->itdb)); + + ret = ldb_kv_del_trans(module); + assert_int_equal(LDB_SUCCESS, ret); + + TALLOC_FREE(ldb_kv); + TALLOC_FREE(module); +} + +static int db_size = 0; +static size_t mock_get_size(struct ldb_kv_private *ldb_kv) { + return db_size; +} + +static int mock_iterate( + struct ldb_kv_private *ldb_kv, + ldb_kv_traverse_fn fn, + void *ctx) { + return 1; +} + +/* + * Test that the index cache is correctly sized by the re_index call + */ +static void test_reindex_cache_size(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct ldb_module *module = NULL; + struct ldb_kv_private *ldb_kv = NULL; + int ret = LDB_SUCCESS; + const struct kv_db_ops ops = { + .iterate = mock_iterate, + .get_size = mock_get_size, + }; + + module = talloc_zero(test_ctx, struct ldb_module); + ldb_kv = talloc_zero(test_ctx, struct ldb_kv_private); + ldb_kv->kv_ops = &ops; + ldb_module_set_private(module, ldb_kv); + + /* + * Use a value less than the DEFAULT_INDEX_CACHE_SIZE + * Should get the DEFAULT_INDEX_CACHE_SIZE + */ + db_size = DEFAULT_INDEX_CACHE_SIZE - 1; + ret = ldb_kv_reindex(module); + assert_int_equal(LDB_SUCCESS, ret); + + assert_int_equal( + DEFAULT_INDEX_CACHE_SIZE, + tdb_hash_size(ldb_kv->idxptr->itdb)); + + /* + * Use a value greater than the DEFAULT_INDEX_CACHE_SIZE + * Should get the value specified. + */ + db_size = DEFAULT_INDEX_CACHE_SIZE + 1; + ret = ldb_kv_reindex(module); + assert_int_equal(LDB_SUCCESS, ret); + + assert_int_equal(db_size, tdb_hash_size(ldb_kv->idxptr->itdb)); + + TALLOC_FREE(ldb_kv); + TALLOC_FREE(module); +} + +/* + * Test that ldb_kv_init_store sets the default index transaction cache size + * if the option is not supplied. + */ +static void test_init_store_default_index_cache_size(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct ldb_module *module = NULL; + struct ldb_kv_private *ldb_kv = NULL; + struct ldb_context *ldb = NULL; + int ret = LDB_SUCCESS; + + module = talloc_zero(test_ctx, struct ldb_module); + ldb = talloc_zero(test_ctx, struct ldb_context); + ldb_kv = talloc_zero(test_ctx, struct ldb_kv_private); + + ret = ldb_kv_init_store(ldb_kv, "test", ldb, NULL, &module); + assert_int_equal(LDB_SUCCESS, ret); + + assert_int_equal( + DEFAULT_INDEX_CACHE_SIZE, + ldb_kv->index_transaction_cache_size); + + TALLOC_FREE(ldb_kv); + TALLOC_FREE(module); + TALLOC_FREE(ldb); +} + +/* + * Test that ldb_kv_init_store sets the index transaction cache size + * to the value specified in the option. + */ +static void test_init_store_set_index_cache_size(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct ldb_module *module = NULL; + struct ldb_kv_private *ldb_kv = NULL; + struct ldb_context *ldb = NULL; + const char *options[] = {"transaction_index_cache_size:1900", NULL}; + int ret = LDB_SUCCESS; + + module = talloc_zero(test_ctx, struct ldb_module); + ldb = talloc_zero(test_ctx, struct ldb_context); + ldb_kv = talloc_zero(test_ctx, struct ldb_kv_private); + + ret = ldb_kv_init_store(ldb_kv, "test", ldb, options, &module); + assert_int_equal(LDB_SUCCESS, ret); + + assert_int_equal( 1900, ldb_kv->index_transaction_cache_size); + + TALLOC_FREE(ldb_kv); + TALLOC_FREE(module); + TALLOC_FREE(ldb); +} + +/* + * Test that ldb_kv_init_store sets the default index transaction cache size + * if the value specified in the option is not a number. + */ +static void test_init_store_set_index_cache_size_non_numeric(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct ldb_module *module = NULL; + struct ldb_kv_private *ldb_kv = NULL; + struct ldb_context *ldb = NULL; + const char *options[] = {"transaction_index_cache_size:fred", NULL}; + int ret = LDB_SUCCESS; + + module = talloc_zero(test_ctx, struct ldb_module); + ldb = talloc_zero(test_ctx, struct ldb_context); + ldb_kv = talloc_zero(test_ctx, struct ldb_kv_private); + + ret = ldb_kv_init_store(ldb_kv, "test", ldb, options, &module); + assert_int_equal(LDB_SUCCESS, ret); + + assert_int_equal( + DEFAULT_INDEX_CACHE_SIZE, + ldb_kv->index_transaction_cache_size); + + TALLOC_FREE(ldb_kv); + TALLOC_FREE(module); + TALLOC_FREE(ldb); +} + +/* + * Test that ldb_kv_init_store sets the default index transaction cache size + * if the value specified is too large + */ +static void test_init_store_set_index_cache_size_range(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct ldb_module *module = NULL; + struct ldb_kv_private *ldb_kv = NULL; + struct ldb_context *ldb = NULL; + const char *options[] = { + "transaction_index_cache_size:0xfffffffffffffffffffffffffffff", + NULL}; + int ret = LDB_SUCCESS; + + module = talloc_zero(test_ctx, struct ldb_module); + ldb = talloc_zero(test_ctx, struct ldb_context); + ldb_kv = talloc_zero(test_ctx, struct ldb_kv_private); + + ret = ldb_kv_init_store(ldb_kv, "test", ldb, options, &module); + assert_int_equal(LDB_SUCCESS, ret); + + assert_int_equal( + DEFAULT_INDEX_CACHE_SIZE, + ldb_kv->index_transaction_cache_size); + + TALLOC_FREE(ldb_kv); + TALLOC_FREE(module); + TALLOC_FREE(ldb); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_index_cache_init, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_default_index_cache_size, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_reindex_cache_size, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_init_store_default_index_cache_size, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_init_store_set_index_cache_size, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_init_store_set_index_cache_size_non_numeric, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_init_store_set_index_cache_size_range, + setup, + teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_kv_ops_test.c b/ldb-2.0.8/tests/ldb_kv_ops_test.c new file mode 100644 index 0000000..98b5a43 --- /dev/null +++ b/ldb-2.0.8/tests/ldb_kv_ops_test.c @@ -0,0 +1,1804 @@ +/* + * Tests exercising the ldb key value operations. + * + * Copyright (C) Andrew Bartlett 2018 + * + * 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 . + * + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ + +/* + * A KV module is expected to have the following behaviour + * + * - A transaction must be open to perform any read, write or delete operation + * - Writes and Deletes should not be visible until a transaction is commited + * - Nested transactions are not permitted + * - transactions can be rolled back and commited. + * - supports iteration over all records in the database + * - supports the update_in_iterate operation allowing entries to be + * re-keyed. + * - has a get_size implementation that returns an estimate of the number of + * records in the database. Note that this can be an estimate rather than + * an accurate size. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ldb_tdb/ldb_tdb.h" +#include "ldb_key_value/ldb_kv.h" + + +#define DEFAULT_BE "tdb" + +#ifndef TEST_BE +#define TEST_BE DEFAULT_BE +#endif /* TEST_BE */ + +#define NUM_RECS 1024 + + +struct test_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; + + const char *dbfile; + const char *lockfile; /* lockfile is separate */ + + const char *dbpath; +}; + +static void unlink_old_db(struct test_ctx *test_ctx) +{ + int ret; + + errno = 0; + ret = unlink(test_ctx->lockfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } + + errno = 0; + ret = unlink(test_ctx->dbfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } +} + +static int noconn_setup(void **state) +{ + struct test_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct test_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb"); + assert_non_null(test_ctx->dbfile); + + test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock", + test_ctx->dbfile); + assert_non_null(test_ctx->lockfile); + + test_ctx->dbpath = talloc_asprintf(test_ctx, + TEST_BE"://%s", test_ctx->dbfile); + assert_non_null(test_ctx->dbpath); + + unlink_old_db(test_ctx); + *state = test_ctx; + return 0; +} + +static int noconn_teardown(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + + unlink_old_db(test_ctx); + talloc_free(test_ctx); + return 0; +} + +static int setup(void **state) +{ + struct test_ctx *test_ctx; + int ret; + struct ldb_ldif *ldif; + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" + "\n"; + + noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) { + ret = ldb_add(test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + *state = test_ctx; + return 0; +} + +static int teardown(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + noconn_teardown((void **) &test_ctx); + return 0; +} + +static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb) +{ + void *data = NULL; + struct ldb_kv_private *ldb_kv = NULL; + + data = ldb_module_get_private(ldb->modules); + assert_non_null(data); + + ldb_kv = talloc_get_type(data, struct ldb_kv_private); + assert_non_null(ldb_kv); + + return ldb_kv; +} + +static int parse(struct ldb_val key, + struct ldb_val data, + void *private_data) +{ + struct ldb_val* read = private_data; + + /* Yes, we leak this. That is OK */ + read->data = talloc_size(NULL, + data.length); + assert_non_null(read->data); + + memcpy(read->data, data.data, data.length); + read->length = data.length; + return LDB_SUCCESS; +} + +/* + * Parse function that just returns the int we pass it. + */ +static int parse_return(struct ldb_val key, + struct ldb_val data, + void *private_data) +{ + int *rcode = private_data; + return *rcode; +} + +/* + * Test that data can be written to the kv store and be read back. + */ +static void test_add_get(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + + struct ldb_val read; + int rcode; + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, 0); + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now read it back + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, 0); + + assert_int_equal(sizeof(value), read.length); + assert_memory_equal(value, read.data, sizeof(value)); + + /* + * Now check that the error code we return in the + * parse function is returned by fetch_and_parse. + */ + for (rcode=0; rcode<50; rcode++) { + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, + parse_return, + &rcode); + assert_int_equal(ret, rcode); + } + + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + talloc_free(tmp_ctx); +} + +/* + * Test that attempts to read data without a read transaction fail. + */ +static void test_read_outside_transaction(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + + struct ldb_val read; + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, 0); + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now read it back + * Note there is no read transaction active + */ + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR); + + talloc_free(tmp_ctx); +} + +/* + * Test that data can be deleted from the kv store + */ +static void test_delete(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + + struct ldb_val read; + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, 0); + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now read it back + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, 0); + assert_int_equal(sizeof(value), read.length); + assert_memory_equal(value, read.data, sizeof(value)); + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Now delete it. + */ + ret = ldb_kv->kv_ops->delete (ldb_kv, key); + assert_int_equal(ret, 0); + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now try to read it back + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT); + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + talloc_free(tmp_ctx); +} + +/* + * Check that writes are correctly rolled back when a transaction + * is rolled back. + */ +static void test_transaction_abort_write(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + + struct ldb_val read; + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, 0); + + /* + * And now read it back + */ + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, 0); + assert_int_equal(sizeof(value), read.length); + assert_memory_equal(value, read.data, sizeof(value)); + + + /* + * Now abort the transaction + */ + ret = ldb_kv->kv_ops->abort_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now read it back, should not be there + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT); + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + talloc_free(tmp_ctx); +} + +/* + * Check that deletes are correctly rolled back when a transaction is + * aborted. + */ +static void test_transaction_abort_delete(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + + struct ldb_val read; + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, 0); + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now read it back + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, 0); + assert_int_equal(sizeof(value), read.length); + assert_memory_equal(value, read.data, sizeof(value)); + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Now delete it. + */ + ret = ldb_kv->kv_ops->delete (ldb_kv, key); + assert_int_equal(ret, 0); + + /* + * And now read it back + */ + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT); + + /* + * Abort the transaction + */ + ret = ldb_kv->kv_ops->abort_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now try to read it back + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, 0); + assert_int_equal(sizeof(value), read.length); + assert_memory_equal(value, read.data, sizeof(value)); + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + talloc_free(tmp_ctx); +} + +/* + * Test that writes outside a transaction fail + */ +static void test_write_outside_transaction(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Attempt to write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR); + + talloc_free(tmp_ctx); +} + +/* + * Test data can not be deleted outside a transaction + */ +static void test_delete_outside_transaction(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + + struct ldb_val read; + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, 0); + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * And now read it back + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, 0); + assert_int_equal(sizeof(value), read.length); + assert_memory_equal(value, read.data, sizeof(value)); + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + /* + * Now attempt to delete a record + */ + ret = ldb_kv->kv_ops->delete (ldb_kv, key); + assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR); + + /* + * And now read it back + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read); + assert_int_equal(ret, 0); + assert_int_equal(sizeof(value), read.length); + assert_memory_equal(value, read.data, sizeof(value)); + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + talloc_free(tmp_ctx); +} + +static int traverse_fn(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val data, + void *ctx) +{ + + int *visits = ctx; + int i; + + if (strncmp("key ", (char *) key.data, 4) == 0) { + i = strtol((char *) &key.data[4], NULL, 10); + visits[i]++; + } + return LDB_SUCCESS; +} + +/* + * Test that iterate visits all the records. + */ +static void test_iterate(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + int i; + int num_recs = 1024; + int visits[num_recs]; + + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the records + */ + for (i = 0; i < num_recs; i++) { + struct ldb_val key; + struct ldb_val rec; + int flags = 0; + + visits[i] = 0; + key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i); + key.length = strlen((char *)key.data) + 1; + + rec.data = (uint8_t *) talloc_asprintf(tmp_ctx, + "data for record (%04d)", + i); + rec.length = strlen((char *)rec.data) + 1; + + ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags); + assert_int_equal(ret, 0); + + TALLOC_FREE(key.data); + TALLOC_FREE(rec.data); + } + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Now iterate over the kv store and ensure that all the + * records are visited. + */ + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->iterate(ldb_kv, traverse_fn, visits); + for (i = 0; i kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + TALLOC_FREE(tmp_ctx); +} + +static void do_iterate_range_test(void **state, int range_start, + int range_end, bool fail) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + int i; + int num_recs = 1024; + int skip_recs = 10; + int visits[num_recs]; + struct ldb_val sk, ek; + + TALLOC_CTX *tmp_ctx; + + for (i = 0; i < num_recs; i++){ + visits[i] = 0; + } + + /* + * No iterate_range on tdb + */ + if (strcmp(TEST_BE, "tdb") == 0) { + return; + } + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the records + */ + for (i = skip_recs; i <= num_recs - skip_recs; i++) { + struct ldb_val key; + struct ldb_val rec; + int flags = 0; + + key.data = (uint8_t *)talloc_asprintf(tmp_ctx, + "key %04d", + i); + key.length = strlen((char *)key.data); + + rec.data = (uint8_t *)talloc_asprintf(tmp_ctx, + "data for record (%04d)", + i); + rec.length = strlen((char *)rec.data) + 1; + + ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags); + assert_int_equal(ret, 0); + + TALLOC_FREE(key.data); + TALLOC_FREE(rec.data); + } + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + sk.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_start); + sk.length = strlen((char *)sk.data); + + ek.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_end); + ek.length = strlen((char *)ek.data) + 1; + + ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + ret = ldb_kv->kv_ops->iterate_range(ldb_kv, sk, ek, + traverse_fn, visits); + if (fail){ + assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR); + TALLOC_FREE(tmp_ctx); + return; + } else{ + assert_int_equal(ret, 0); + } + for (i = 0; i < num_recs; i++) { + if (i >= skip_recs && i <= num_recs - skip_recs && + i >= range_start && i <= range_end){ + assert_int_equal(1, visits[i]); + } else { + assert_int_equal(0, visits[i]); + } + } + + ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules); + assert_int_equal(ret, 0); + + TALLOC_FREE(tmp_ctx); +} + +/* + * Test that iterate_range visits all the records between two keys. + */ +static void test_iterate_range(void **state) +{ + do_iterate_range_test(state, 300, 900, false); + + /* + * test start_key = end_key + */ + do_iterate_range_test(state, 20, 20, false); + + /* + * test reverse range fails + */ + do_iterate_range_test(state, 50, 40, true); + + /* + * keys are between 10-1014 so test with keys outside that range + */ + do_iterate_range_test(state, 0, 20, false); + do_iterate_range_test(state, 1010, 1030, false); + do_iterate_range_test(state, 0, 1030, false); +} + +struct update_context { + struct ldb_context* ldb; + int visits[NUM_RECS]; +}; + +static int update_fn(struct ldb_kv_private *ldb_kv, + struct ldb_val key, + struct ldb_val data, + void *ctx) +{ + + struct ldb_val new_key; + struct ldb_module *module = NULL; + struct update_context *context =NULL; + int ret = LDB_SUCCESS; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(ldb_kv); + assert_non_null(tmp_ctx); + + context = talloc_get_type_abort(ctx, struct update_context); + + module = talloc_zero(tmp_ctx, struct ldb_module); + module->ldb = context->ldb; + + if (strncmp("key ", (char *) key.data, 4) == 0) { + int i = strtol((char *) &key.data[4], NULL, 10); + context->visits[i]++; + new_key.data = talloc_memdup(tmp_ctx, key.data, key.length); + new_key.length = key.length; + new_key.data[0] = 'K'; + + ret = ldb_kv->kv_ops->update_in_iterate( + ldb_kv, key, new_key, data, &module); + } + TALLOC_FREE(tmp_ctx); + return ret; +} + +/* + * Test that update_in_iterate behaves as expected. + */ +static void test_update_in_iterate(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + int i; + struct update_context *context = NULL; + + + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + context = talloc_zero(tmp_ctx, struct update_context); + assert_non_null(context); + context->ldb = test_ctx->ldb; + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the records + */ + for (i = 0; i < NUM_RECS; i++) { + struct ldb_val key; + struct ldb_val rec; + int flags = 0; + + key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i); + key.length = strlen((char *)key.data) + 1; + + rec.data = (uint8_t *) talloc_asprintf(tmp_ctx, + "data for record (%04d)", + i); + rec.length = strlen((char *)rec.data) + 1; + + ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags); + assert_int_equal(ret, 0); + + TALLOC_FREE(key.data); + TALLOC_FREE(rec.data); + } + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Now iterate over the kv store and ensure that all the + * records are visited. + */ + + /* + * Needs to be done inside a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + ret = ldb_kv->kv_ops->iterate(ldb_kv, update_fn, context); + for (i = 0; i < NUM_RECS; i++) { + assert_int_equal(1, context->visits[i]); + } + + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + TALLOC_FREE(tmp_ctx); +} + +/* + * Ensure that writes are not visible until the transaction has been + * committed. + */ +static void test_write_transaction_isolation(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + struct ldb_val key; + struct ldb_val val; + + const char *KEY1 = "KEY01"; + const char *VAL1 = "VALUE01"; + + const char *KEY2 = "KEY02"; + const char *VAL2 = "VALUE02"; + + /* + * Pipes etc to co-ordinate the processes + */ + int to_child[2]; + int to_parent[2]; + char buf[2]; + pid_t pid, w_pid; + int wstatus; + + TALLOC_CTX *tmp_ctx; + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + + /* + * Add a record to the database + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1); + key.length = strlen(KEY1) + 1; + + val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1); + val.length = strlen(VAL1) + 1; + + ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0); + assert_int_equal(ret, 0); + + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + + ret = pipe(to_child); + assert_int_equal(ret, 0); + ret = pipe(to_parent); + assert_int_equal(ret, 0); + /* + * Now fork a new process + */ + + pid = fork(); + if (pid == 0) { + + struct ldb_context *ldb = NULL; + close(to_child[1]); + close(to_parent[0]); + + /* + * Wait for the transaction to start + */ + ret = read(to_child[0], buf, 2); + if (ret != 2) { + print_error(__location__": read returned (%d)\n", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + ldb = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL); + if (ret != LDB_SUCCESS) { + print_error(__location__": ldb_connect returned (%d)\n", + ret); + exit(ret); + } + + ldb_kv = get_ldb_kv(ldb); + + ret = ldb_kv->kv_ops->lock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": lock_read returned (%d)\n", + ret); + exit(ret); + } + + /* + * Check that KEY1 is there + */ + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1); + key.length = strlen(KEY1) + 1; + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_SUCCESS) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + if ((strlen(VAL1) + 1) != val.length) { + print_error(__location__": KEY1 value lengths different" + ", expected (%d) actual(%d)\n", + (int)(strlen(VAL1) + 1), (int)val.length); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) { + print_error(__location__": KEY1 values different, " + "expected (%s) actual(%s)\n", + VAL1, + val.data); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_kv->kv_ops->unlock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + + /* + * Check that KEY2 is not there + */ + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2); + key.length = strlen(KEY2 + 1); + + ret = ldb_kv->kv_ops->lock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": lock_read returned (%d)\n", + ret); + exit(ret); + } + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + ret = ldb_kv->kv_ops->unlock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + + /* + * Signal the other process to commit the transaction + */ + ret = write(to_parent[1], "GO", 2); + if (ret != 2) { + print_error(__location__": write returned (%d)\n", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + /* + * Wait for the transaction to be commited + */ + ret = read(to_child[0], buf, 2); + if (ret != 2) { + print_error(__location__": read returned (%d)\n", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + /* + * Check that KEY1 is there + */ + ret = ldb_kv->kv_ops->lock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1); + key.length = strlen(KEY1) + 1; + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_SUCCESS) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + if ((strlen(VAL1) + 1) != val.length) { + print_error(__location__": KEY1 value lengths different" + ", expected (%d) actual(%d)\n", + (int)(strlen(VAL1) + 1), (int)val.length); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) { + print_error(__location__": KEY1 values different, " + "expected (%s) actual(%s)\n", + VAL1, + val.data); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_kv->kv_ops->unlock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + + + /* + * Check that KEY2 is there + */ + ret = ldb_kv->kv_ops->lock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2); + key.length = strlen(KEY2) + 1; + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_SUCCESS) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + if ((strlen(VAL2) + 1) != val.length) { + print_error(__location__": KEY2 value lengths different" + ", expected (%d) actual(%d)\n", + (int)(strlen(VAL2) + 1), (int)val.length); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) { + print_error(__location__": KEY2 values different, " + "expected (%s) actual(%s)\n", + VAL2, + val.data); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_kv->kv_ops->unlock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + + exit(0); + } + close(to_child[0]); + close(to_parent[1]); + + /* + * Begin a transaction and add a record to the database + * but leave the transaction open + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2); + key.length = strlen(KEY2) + 1; + + val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2); + val.length = strlen(VAL2) + 1; + + ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0); + assert_int_equal(ret, 0); + + /* + * Signal the child process + */ + ret = write(to_child[1], "GO", 2); + assert_int_equal(2, ret); + + /* + * Wait for the child process to check the DB state while the + * transaction is active + */ + ret = read(to_parent[0], buf, 2); + assert_int_equal(2, ret); + + /* + * commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(0, ret); + + /* + * Signal the child process + */ + ret = write(to_child[1], "GO", 2); + assert_int_equal(2, ret); + + w_pid = waitpid(pid, &wstatus, 0); + assert_int_equal(pid, w_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + + + TALLOC_FREE(tmp_ctx); +} + +/* + * Ensure that deletes are not visible until the transaction has been + * committed. + */ +static void test_delete_transaction_isolation(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + struct ldb_val key; + struct ldb_val val; + + const char *KEY1 = "KEY01"; + const char *VAL1 = "VALUE01"; + + const char *KEY2 = "KEY02"; + const char *VAL2 = "VALUE02"; + + /* + * Pipes etc to co-ordinate the processes + */ + int to_child[2]; + int to_parent[2]; + char buf[2]; + pid_t pid, w_pid; + int wstatus; + + TALLOC_CTX *tmp_ctx; + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + + /* + * Add records to the database + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1); + key.length = strlen(KEY1) + 1; + + val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1); + val.length = strlen(VAL1) + 1; + + ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0); + assert_int_equal(ret, 0); + + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2); + key.length = strlen(KEY2) + 1; + + val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2); + val.length = strlen(VAL2) + 1; + + ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0); + assert_int_equal(ret, 0); + + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + + ret = pipe(to_child); + assert_int_equal(ret, 0); + ret = pipe(to_parent); + assert_int_equal(ret, 0); + /* + * Now fork a new process + */ + + pid = fork(); + if (pid == 0) { + + struct ldb_context *ldb = NULL; + close(to_child[1]); + close(to_parent[0]); + + /* + * Wait for the transaction to be started + */ + ret = read(to_child[0], buf, 2); + if (ret != 2) { + print_error(__location__": read returned (%d)\n", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ldb = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL); + if (ret != LDB_SUCCESS) { + print_error(__location__": ldb_connect returned (%d)\n", + ret); + exit(ret); + } + + ldb_kv = get_ldb_kv(ldb); + + ret = ldb_kv->kv_ops->lock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": lock_read returned (%d)\n", + ret); + exit(ret); + } + + /* + * Check that KEY1 is there + */ + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1); + key.length = strlen(KEY1) + 1; + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_SUCCESS) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + if ((strlen(VAL1) + 1) != val.length) { + print_error(__location__": KEY1 value lengths different" + ", expected (%d) actual(%d)\n", + (int)(strlen(VAL1) + 1), (int)val.length); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) { + print_error(__location__": KEY1 values different, " + "expected (%s) actual(%s)\n", + VAL1, + val.data); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + /* + * Check that KEY2 is there + */ + + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2); + key.length = strlen(KEY2) + 1; + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_SUCCESS) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + if ((strlen(VAL2) + 1) != val.length) { + print_error(__location__": KEY2 value lengths different" + ", expected (%d) actual(%d)\n", + (int)(strlen(VAL2) + 1), (int)val.length); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) { + print_error(__location__": KEY2 values different, " + "expected (%s) actual(%s)\n", + VAL2, + val.data); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_kv->kv_ops->unlock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + + /* + * Signal the other process to commit the transaction + */ + ret = write(to_parent[1], "GO", 2); + if (ret != 2) { + print_error(__location__": write returned (%d)\n", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + /* + * Wait for the transaction to be commited + */ + ret = read(to_child[0], buf, 2); + if (ret != 2) { + print_error(__location__": read returned (%d)\n", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + /* + * Check that KEY1 is there + */ + ret = ldb_kv->kv_ops->lock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1); + key.length = strlen(KEY1) + 1; + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_SUCCESS) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + if ((strlen(VAL1) + 1) != val.length) { + print_error(__location__": KEY1 value lengths different" + ", expected (%d) actual(%d)\n", + (int)(strlen(VAL1) + 1), (int)val.length); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) { + print_error(__location__": KEY1 values different, " + "expected (%s) actual(%s)\n", + VAL1, + val.data); + exit(LDB_ERR_OPERATIONS_ERROR); + } + ret = ldb_kv->kv_ops->unlock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + + /* + * Check that KEY2 is not there + */ + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2); + key.length = strlen(KEY2 + 1); + + ret = ldb_kv->kv_ops->lock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": lock_read returned (%d)\n", + ret); + exit(ret); + } + + ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + print_error(__location__": fetch_and_parse returned " + "(%d)\n", + ret); + exit(ret); + } + + ret = ldb_kv->kv_ops->unlock_read(ldb->modules); + if (ret != LDB_SUCCESS) { + print_error(__location__": unlock_read returned (%d)\n", + ret); + exit(ret); + } + TALLOC_FREE(tmp_ctx); + exit(0); + } + close(to_child[0]); + close(to_parent[1]); + + /* + * Begin a transaction and delete a record from the database + * but leave the transaction open + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2); + key.length = strlen(KEY2) + 1; + + ret = ldb_kv->kv_ops->delete (ldb_kv, key); + assert_int_equal(ret, 0); + /* + * Signal the child process + */ + ret = write(to_child[1], "GO", 2); + assert_int_equal(2, ret); + + /* + * Wait for the child process to check the DB state while the + * transaction is active + */ + ret = read(to_parent[0], buf, 2); + assert_int_equal(2, ret); + + /* + * commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(0, ret); + + /* + * Signal the child process + */ + ret = write(to_child[1], "GO", 2); + assert_int_equal(2, ret); + + w_pid = waitpid(pid, &wstatus, 0); + assert_int_equal(pid, w_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + + + TALLOC_FREE(tmp_ctx); +} + + +/* + * Test that get_size returns a sensible estimate of the number of records + * in the database. + */ +static void test_get_size(void **state) +{ + int ret; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb); + uint8_t key_val[] = "TheKey"; + struct ldb_val key = { + .data = key_val, + .length = sizeof(key_val) + }; + + uint8_t value[] = "The record contents"; + struct ldb_val data = { + .data = value, + .length = sizeof(value) + }; + size_t size = 0; + + int flags = 0; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + size = ldb_kv->kv_ops->get_size(ldb_kv); +#if defined(TEST_LMDB) + assert_int_equal(2, size); +#else + /* + * The tdb implementation of get_size over estimates for sparse files + * which is perfectly acceptable for it's intended use. + */ + assert_true( size > 2500); +#endif + + /* + * Begin a transaction + */ + ret = ldb_kv->kv_ops->begin_write(ldb_kv); + assert_int_equal(ret, 0); + + /* + * Write the record + */ + ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags); + assert_int_equal(ret, 0); + + /* + * Commit the transaction + */ + ret = ldb_kv->kv_ops->finish_write(ldb_kv); + assert_int_equal(ret, 0); + + size = ldb_kv->kv_ops->get_size(ldb_kv); +#ifdef TEST_LMDB + assert_int_equal(3, size); +#endif + talloc_free(tmp_ctx); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_add_get, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_delete, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_transaction_abort_write, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_transaction_abort_delete, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_read_outside_transaction, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_write_outside_transaction, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_delete_outside_transaction, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_iterate, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_iterate_range, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_update_in_iterate, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_write_transaction_isolation, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_delete_transaction_isolation, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_get_size, + setup, + teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_kv_ops_test.valgrind b/ldb-2.0.8/tests/ldb_kv_ops_test.valgrind new file mode 100644 index 0000000..1747076 --- /dev/null +++ b/ldb-2.0.8/tests/ldb_kv_ops_test.valgrind @@ -0,0 +1,97 @@ +{ + Memory allocated by setup + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:setup +} +{ + Memory allocated by setup + Memcheck:Leak + match-leak-kinds: possible + fun:realloc + ... + fun:setup +} +{ + Memory allocated by ldb_init + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_init +} +{ + Memory allocated by ldb_init + Memcheck:Leak + match-leak-kinds: possible + fun:realloc + ... + fun:ldb_init +} +{ + Memory allocated by noconn_setup + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:noconn_setup +} +{ + Memory allocated by parse, which allocates on the NULL context + Memcheck:Leak + match-leak-kinds: all + fun:malloc + ... + fun:parse +} +{ + Memory allocated by tdb_parse_data + Memcheck:Leak + match-leak-kinds: all + fun:malloc + ... + fun:tdb_parse_data +} +{ + Memory allocated by ldb_connect + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_connect +} +{ + Memory allocated by ldb_connect + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:ldb_connect +} +{ + Memory allocated by ldb_kv_cache_load + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_kv_cache_load +} +{ + Memory allocated by ldb_kv_index_load + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_kv_index_load +} +{ + Memory allocated by ldb_asprintf_errstring + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_asprintf_errstring +} + diff --git a/ldb-2.0.8/tests/ldb_lmdb_size_test.c b/ldb-2.0.8/tests/ldb_lmdb_size_test.c new file mode 100644 index 0000000..af015fa --- /dev/null +++ b/ldb-2.0.8/tests/ldb_lmdb_size_test.c @@ -0,0 +1,210 @@ +/* + * lmdb backend specific tests for ldb + * Tests for truncated index keys + * + * Copyright (C) Andrew Bartlett 2018 + * + * 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 . + * + */ + +/* + * These tests confirm that database sizes of > 4GB are supported + * Due to the disk space requirement they are not run as part of the normal + * self test runs. + * + * Setup and tear down code copied from ldb_mod_op_test.c + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + + +#define TEST_BE "mdb" + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; + + const char *dbfile; + const char *lockfile; /* lockfile is separate */ + + const char *dbpath; +}; + +static void unlink_old_db(struct ldbtest_ctx *test_ctx) +{ + int ret; + + errno = 0; + ret = unlink(test_ctx->lockfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } + + errno = 0; + ret = unlink(test_ctx->dbfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } +} + +static int ldbtest_noconn_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb"); + assert_non_null(test_ctx->dbfile); + + test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock", + test_ctx->dbfile); + assert_non_null(test_ctx->lockfile); + + test_ctx->dbpath = talloc_asprintf(test_ctx, + TEST_BE"://%s", test_ctx->dbfile); + assert_non_null(test_ctx->dbpath); + + unlink_old_db(test_ctx); + *state = test_ctx; + return 0; +} + +static int ldbtest_noconn_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + + unlink_old_db(test_ctx); + talloc_free(test_ctx); + return 0; +} + +static int ldbtest_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + int ret; + + ldbtest_noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + *state = test_ctx; + return 0; +} + +static int ldbtest_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + ldbtest_noconn_teardown((void **) &test_ctx); + return 0; +} + +static void test_db_size_gt_4GB(void **state) +{ + int ret, x; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + const int MB = 1024 * 1024; + char *blob = NULL; + + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + + blob = talloc_zero_size(tmp_ctx, (MB + 1)); + assert_non_null(blob); + memset(blob, 'x', MB); + + + for (x = 0; x < 6144; x++) { + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=test%d", x); + assert_non_null(msg->dn); + + ldb_transaction_start(test_ctx->ldb); + ret = ldb_msg_add_string(msg, "blob", blob); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, 0); + ldb_transaction_commit(test_ctx->ldb); + + TALLOC_FREE(msg); + } + talloc_free(tmp_ctx); + { + struct stat s; + ret = stat(test_ctx->dbfile, &s); + assert_int_equal(ret, 0); + assert_true(s.st_size > (6144LL * MB)); + } +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_db_size_gt_4GB, + ldbtest_setup, + ldbtest_teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_lmdb_test.c b/ldb-2.0.8/tests/ldb_lmdb_test.c new file mode 100644 index 0000000..78758bb --- /dev/null +++ b/ldb-2.0.8/tests/ldb_lmdb_test.c @@ -0,0 +1,589 @@ +/* + * lmdb backend specific tests for ldb + * + * Copyright (C) Andrew Bartlett 2018 + * + * 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 . + * + */ + +/* + * lmdb backend specific tests for ldb + * + * Setup and tear down code copied from ldb_mod_op_test.c + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../ldb_tdb/ldb_tdb.h" +#include "../ldb_mdb/ldb_mdb.h" +#include "../ldb_key_value/ldb_kv.h" + +#define TEST_BE "mdb" + +#define LMDB_MAX_KEY_SIZE 511 + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; + + const char *dbfile; + const char *lockfile; /* lockfile is separate */ + + const char *dbpath; +}; + +static void unlink_old_db(struct ldbtest_ctx *test_ctx) +{ + int ret; + + errno = 0; + ret = unlink(test_ctx->lockfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } + + errno = 0; + ret = unlink(test_ctx->dbfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } +} + +static int ldbtest_noconn_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb"); + assert_non_null(test_ctx->dbfile); + + test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock", + test_ctx->dbfile); + assert_non_null(test_ctx->lockfile); + + test_ctx->dbpath = talloc_asprintf(test_ctx, + TEST_BE"://%s", test_ctx->dbfile); + assert_non_null(test_ctx->dbpath); + + unlink_old_db(test_ctx); + *state = test_ctx; + return 0; +} + +static int ldbtest_noconn_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + + unlink_old_db(test_ctx); + talloc_free(test_ctx); + return 0; +} + +static int ldbtest_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + int ret; + struct ldb_ldif *ldif; + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" + "\n"; + + ldbtest_noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) { + ret = ldb_add(test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + *state = test_ctx; + return 0; +} + +static int ldbtest_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + ldbtest_noconn_teardown((void **) &test_ctx); + return 0; +} + +static void test_ldb_add_key_len_gt_max(void **state) +{ + int ret; + int xs_size = 0; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + char *xs = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + /* + * The zero terminator is part of the key if we were not in + * GUID mode + */ + + xs_size = LMDB_MAX_KEY_SIZE - 7; /* "dn=dc=" and the zero terminator */ + xs_size += 1; /* want key on char too long */ + xs = talloc_zero_size(tmp_ctx, (xs_size + 1)); + memset(xs, 'x', xs_size); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=%s", xs); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcdef"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + talloc_free(tmp_ctx); +} + +static void test_ldb_add_key_len_2x_gt_max(void **state) +{ + int ret; + int xs_size = 0; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + char *xs = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + /* + * The zero terminator is part of the key if we were not in + * GUID mode + */ + + xs_size = 2 * LMDB_MAX_KEY_SIZE; + xs = talloc_zero_size(tmp_ctx, (xs_size + 1)); + memset(xs, 'x', xs_size); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=%s", xs); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcdef"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + talloc_free(tmp_ctx); +} + +static void test_ldb_add_key_len_eq_max(void **state) +{ + int ret; + int xs_size = 0; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + char *xs = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + /* + * The zero terminator is part of the key if we were not in + * GUID mode + */ + + xs_size = LMDB_MAX_KEY_SIZE - 7; /* "dn=dc=" and the zero terminator */ + xs = talloc_zero_size(tmp_ctx, (xs_size + 1)); + memset(xs, 'x', xs_size); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=%s", xs); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcdef"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, 0); + + talloc_free(tmp_ctx); +} + +static int ldbtest_setup_noguid(void **state) +{ + struct ldbtest_ctx *test_ctx; + int ret; + + ldbtest_noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + *state = test_ctx; + return 0; +} + +static void test_ldb_add_special_key_len_gt_max(void **state) +{ + int ret; + int xs_size = 0; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + char *xs = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + /* + * The zero terminator is part of the key if we were not in + * GUID mode + */ + + xs_size = LMDB_MAX_KEY_SIZE - 5; /* "dn=@" and the zero terminator */ + xs_size += 1; /* want key on char too long */ + xs = talloc_zero_size(tmp_ctx, (xs_size + 1)); + memset(xs, 'x', xs_size); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "@%s", xs); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR); + + talloc_free(tmp_ctx); +} + +static void test_ldb_add_special_key_len_eq_max(void **state) +{ + int ret; + int xs_size = 0; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + char *xs = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + /* + * The zero terminator is part of the key if we were not in + * GUID mode + */ + + xs_size = LMDB_MAX_KEY_SIZE - 5; /* "dn=@" and the zero terminator */ + xs = talloc_zero_size(tmp_ctx, (xs_size + 1)); + memset(xs, 'x', xs_size); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "@%s", xs); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + talloc_free(tmp_ctx); +} + +static void test_ldb_add_dn_no_guid_mode(void **state) +{ + int ret; + int xs_size = 0; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + char *xs = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + /* + * The zero terminator is part of the key if we were not in + * GUID mode + */ + + xs_size = LMDB_MAX_KEY_SIZE - 7; /* "dn=dc=" and the zero terminator */ + xs_size += 1; /* want key on char too long */ + xs = talloc_zero_size(tmp_ctx, (xs_size + 1)); + memset(xs, 'x', xs_size); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=%s", xs); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcdef"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, LDB_ERR_UNWILLING_TO_PERFORM); + + talloc_free(tmp_ctx); +} + +static struct MDB_env *get_mdb_env(struct ldb_context *ldb) +{ + void *data = NULL; + struct ldb_kv_private *ldb_kv = NULL; + struct lmdb_private *lmdb = NULL; + struct MDB_env *env = NULL; + + data = ldb_module_get_private(ldb->modules); + assert_non_null(data); + + ldb_kv = talloc_get_type(data, struct ldb_kv_private); + assert_non_null(ldb_kv); + + lmdb = ldb_kv->lmdb_private; + assert_non_null(lmdb); + + env = lmdb->env; + assert_non_null(env); + + return env; +} + +static void test_multiple_opens(void **state) +{ + struct ldb_context *ldb1 = NULL; + struct ldb_context *ldb2 = NULL; + struct ldb_context *ldb3 = NULL; + struct MDB_env *env1 = NULL; + struct MDB_env *env2 = NULL; + struct MDB_env *env3 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database again + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb2 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb2, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb3 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb3, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + /* + * We now have 3 ldb's open pointing to the same on disk database + * they should all share the same MDB_env + */ + env1 = get_mdb_env(ldb1); + env2 = get_mdb_env(ldb2); + env3 = get_mdb_env(ldb3); + + assert_ptr_equal(env1, env2); + assert_ptr_equal(env1, env3); +} + +static void test_multiple_opens_across_fork(void **state) +{ + struct ldb_context *ldb1 = NULL; + struct ldb_context *ldb2 = NULL; + struct MDB_env *env1 = NULL; + struct MDB_env *env2 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + int pipes[2]; + char buf[2]; + int wstatus; + pid_t pid, child_pid; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database again + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb2 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb2, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + env1 = get_mdb_env(ldb1); + env2 = get_mdb_env(ldb2); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + struct ldb_context *ldb3 = NULL; + struct MDB_env *env3 = NULL; + + close(pipes[0]); + ldb3 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb3, test_ctx->dbpath, 0, NULL); + if (ret != 0) { + print_error(__location__": ldb_connect returned (%d)\n", + ret); + exit(ret); + } + env3 = get_mdb_env(ldb3); + if (env1 != env2) { + print_error(__location__": env1 != env2\n"); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (env1 == env3) { + print_error(__location__": env1 == env3\n"); + exit(LDB_ERR_OPERATIONS_ERROR); + } + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_ldb_add_key_len_eq_max, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_key_len_gt_max, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_key_len_2x_gt_max, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_special_key_len_eq_max, + ldbtest_setup_noguid, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_special_key_len_gt_max, + ldbtest_setup_noguid, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_dn_no_guid_mode, + ldbtest_setup_noguid, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_multiple_opens, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_multiple_opens_across_fork, + ldbtest_setup, + ldbtest_teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_match_test.c b/ldb-2.0.8/tests/ldb_match_test.c new file mode 100644 index 0000000..e09f50c --- /dev/null +++ b/ldb-2.0.8/tests/ldb_match_test.c @@ -0,0 +1,191 @@ +/* + * Tests exercising the ldb match operations. + * + * + * Copyright (C) Catalyst.NET Ltd 2017 + * + * 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 . + * + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + */ +#include +#include +#include +#include +#include + +#include "../common/ldb_match.c" + +#include "../include/ldb.h" + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; +}; + +static int ldb_test_canonicalise( + struct ldb_context *ldb, + void *mem_ctx, + const struct ldb_val *in, + struct ldb_val *out) +{ + out->length = in->length; + out->data = in->data; + return 0; +} + +static int setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + struct ldb_schema_syntax *syntax = NULL; + int ret; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + syntax = talloc_zero(test_ctx, struct ldb_schema_syntax); + assert_non_null(syntax); + syntax->canonicalise_fn = ldb_test_canonicalise; + + ret = ldb_schema_attribute_add_with_syntax( + test_ctx->ldb, "a", LDB_ATTR_FLAG_FIXED, syntax); + assert_int_equal(LDB_SUCCESS, ret); + + *state = test_ctx; + return 0; +} + +static int teardown(void **state) +{ + talloc_free(*state); + return 0; +} + + +/* + * The wild card pattern "attribute=*" is parsed as an LDB_OP_PRESENT operation + * rather than a LDB_OP_???? + * + * This test serves to document that behaviour, and to confirm that + * ldb_wildcard_compare handles this case appropriately. + */ +static void test_wildcard_match_star(void **state) +{ + struct ldbtest_ctx *ctx = *state; + bool matched = false; + int ret; + + uint8_t value[] = "The value.......end"; + struct ldb_val val = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_parse_tree *tree = ldb_parse_tree(ctx, "a=*"); + assert_non_null(tree); + + ret = ldb_wildcard_compare(ctx->ldb, tree, val, &matched); + assert_false(matched); + assert_int_equal(LDB_ERR_INAPPROPRIATE_MATCHING, ret); +} + +/* + * Test basic wild card matching + * + */ +static void test_wildcard_match(void **state) +{ + struct ldbtest_ctx *ctx = *state; + bool matched = false; + + uint8_t value[] = "The value.......end"; + struct ldb_val val = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_parse_tree *tree = ldb_parse_tree(ctx, "objectClass=*end"); + assert_non_null(tree); + + ldb_wildcard_compare(ctx->ldb, tree, val, &matched); + assert_true(matched); +} + + +/* + * ldb_handler_copy and ldb_val_dup over allocate by one and add a trailing '\0' + * to the data, to make them safe to use the C string functions on. + * + * However testing for the trailing '\0' is not the correct way to test for + * the end of a value, the length should be checked instead. + */ +static void test_wildcard_match_end_condition(void **state) +{ + struct ldbtest_ctx *ctx = *state; + bool matched = false; + + uint8_t value[] = "hellomynameisbobx"; + struct ldb_val val = { + .data = talloc_memdup(NULL, value, sizeof(value)), + .length = (sizeof(value) - 2) + }; + struct ldb_parse_tree *tree = ldb_parse_tree(ctx, "a=*hello*mynameis*bob"); + assert_non_null(tree); + + ldb_wildcard_compare(ctx->ldb, tree, val, &matched); + assert_true(matched); +} + +/* + * Note: to run under valgrind use: + * valgrind \ + * --suppressions=lib/ldb/tests/ldb_match_test.valgrind \ + * bin/ldb_match_test + */ +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_wildcard_match_star, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_wildcard_match, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_wildcard_match_end_condition, + setup, + teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_match_test.valgrind b/ldb-2.0.8/tests/ldb_match_test.valgrind new file mode 100644 index 0000000..660bd5a --- /dev/null +++ b/ldb-2.0.8/tests/ldb_match_test.valgrind @@ -0,0 +1,16 @@ +{ + Memory allocated in set-up + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:setup +} +{ + Memory allocated by ldb_init + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:ldb_init +} diff --git a/ldb-2.0.8/tests/ldb_mod_op_test.c b/ldb-2.0.8/tests/ldb_mod_op_test.c new file mode 100644 index 0000000..b6a0d1e --- /dev/null +++ b/ldb-2.0.8/tests/ldb_mod_op_test.c @@ -0,0 +1,4721 @@ +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TEVENT_DEPRECATED 1 +#include + +#include +#include +#include +#include +#include + +#include + + +#define DEFAULT_BE "tdb" + +#ifndef TEST_BE +#define TEST_BE DEFAULT_BE +#endif /* TEST_BE */ + +#ifdef TEST_LMDB +#include "lmdb.h" +#include "../ldb_tdb/ldb_tdb.h" +#include "../ldb_mdb/ldb_mdb.h" +#endif + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; + + const char *dbfile; + const char *lockfile; /* lockfile is separate */ + + const char *dbpath; +}; + +static void unlink_old_db(struct ldbtest_ctx *test_ctx) +{ + int ret; + + errno = 0; + ret = unlink(test_ctx->lockfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } + + errno = 0; + ret = unlink(test_ctx->dbfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } +} + +static int ldbtest_noconn_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb"); + assert_non_null(test_ctx->dbfile); + + test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock", + test_ctx->dbfile); + assert_non_null(test_ctx->lockfile); + + test_ctx->dbpath = talloc_asprintf(test_ctx, + TEST_BE"://%s", test_ctx->dbfile); + assert_non_null(test_ctx->dbpath); + + unlink_old_db(test_ctx); + *state = test_ctx; + return 0; +} + +static int ldbtest_noconn_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + + unlink_old_db(test_ctx); + talloc_free(test_ctx); + return 0; +} + +static void test_connect(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + int ret; + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); +} + +static struct ldb_message *get_test_ldb_message(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb) +{ + struct ldb_message *msg = ldb_msg_new(mem_ctx); + int ret; + assert_non_null(msg); + + msg->dn = ldb_dn_new(msg, ldb, "dc=samba,dc=org"); + assert_non_null(msg->dn); + ret = ldb_msg_add_string(msg, "public", "key"); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_add_string(msg, "supersecret", "password"); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_add_string(msg, "binary", "\xff\xff\0"); + assert_int_equal(ret, LDB_SUCCESS); + return msg; +} + +static void test_ldif_message(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + char *got_ldif; + const char *expected_ldif = + "dn: dc=samba,dc=org\n" + "changetype: add\n" + "public: key\n" + "supersecret: password\n" + "binary:: //8=\n" + "\n"; + + struct ldb_message *msg = get_test_ldb_message(test_ctx, + test_ctx->ldb); + + got_ldif = ldb_ldif_message_string(test_ctx->ldb, + test_ctx, + LDB_CHANGETYPE_ADD, + msg); + assert_string_equal(got_ldif, expected_ldif); + TALLOC_FREE(got_ldif); +} + +static void test_ldif_message_redacted(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + int ret; + char *got_ldif; + const char *expected_ldif = + "dn: dc=samba,dc=org\n" + "changetype: add\n" + "public: key\n" + "# supersecret::: REDACTED SECRET ATTRIBUTE\n" + "binary:: //8=\n" + "\n"; + + const char *secret_attrs[] = { + "supersecret", + NULL + }; + + struct ldb_message *msg = ldb_msg_new(test_ctx); + + ldb_set_opaque(test_ctx->ldb, + LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, + secret_attrs); + + assert_non_null(msg); + + msg->dn = ldb_dn_new(msg, test_ctx->ldb, "dc=samba,dc=org"); + ret = ldb_msg_add_string(msg, "public", "key"); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_add_string(msg, "supersecret", "password"); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_add_string(msg, "binary", "\xff\xff\0"); + assert_int_equal(ret, LDB_SUCCESS); + got_ldif = ldb_ldif_message_redacted_string(test_ctx->ldb, + test_ctx, + LDB_CHANGETYPE_ADD, + msg); + assert_string_equal(got_ldif, expected_ldif); + TALLOC_FREE(got_ldif); + assert_int_equal(ret, 0); +} + +static int ldbtest_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + struct ldb_ldif *ldif; +#ifdef GUID_IDX + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" + "\n"; +#else + const char *index_ldif = "\n"; +#endif + int ret; + + ldbtest_noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) { + ret = ldb_add(test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + *state = test_ctx; + return 0; +} + +static int ldbtest_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + ldbtest_noconn_teardown((void **) &test_ctx); + return 0; +} + +static void test_ldb_add(void **state) +{ + int ret; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=test"); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcdef"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, 0); + + talloc_free(tmp_ctx); +} + +static void test_ldb_search(void **state) +{ + int ret; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + struct ldb_dn *basedn; + struct ldb_dn *basedn2; + struct ldb_result *result = NULL; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test"); + assert_non_null(basedn); + + ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, 0); + assert_non_null(result); + assert_int_equal(result->count, 0); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + msg->dn = basedn; + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val1"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcde1"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, 0); + + basedn2 = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test2"); + assert_non_null(basedn2); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + msg->dn = basedn2; + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val2"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcde2"); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, 0); + + ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, 0); + assert_non_null(result); + assert_int_equal(result->count, 1); + assert_string_equal(ldb_dn_get_linearized(result->msgs[0]->dn), + ldb_dn_get_linearized(basedn)); + + ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn2, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, 0); + assert_non_null(result); + assert_int_equal(result->count, 1); + assert_string_equal(ldb_dn_get_linearized(result->msgs[0]->dn), + ldb_dn_get_linearized(basedn2)); + + talloc_free(tmp_ctx); +} + +static int base_search_count(struct ldbtest_ctx *test_ctx, const char *entry_dn) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + int ret; + int count; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "%s", entry_dn); + assert_non_null(basedn); + + ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + + count = result->count; + talloc_free(tmp_ctx); + return count; +} + +static int sub_search_count(struct ldbtest_ctx *test_ctx, + const char *base_dn, + const char *filter) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + int ret; + int count; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "%s", base_dn); + assert_non_null(basedn); + + ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn, + LDB_SCOPE_SUBTREE, NULL, "%s", filter); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + + count = result->count; + talloc_free(tmp_ctx); + return count; +} + +/* In general it would be better if utility test functions didn't assert + * but only returned a value, then assert in the test shows correct + * line + */ +static void assert_dn_exists(struct ldbtest_ctx *test_ctx, + const char *entry_dn) +{ + int count; + + count = base_search_count(test_ctx, entry_dn); + assert_int_equal(count, 1); +} + +static void assert_dn_doesnt_exist(struct ldbtest_ctx *test_ctx, + const char *entry_dn) +{ + int count; + + count = base_search_count(test_ctx, entry_dn); + assert_int_equal(count, 0); +} + +static void add_dn_with_cn(struct ldbtest_ctx *test_ctx, + struct ldb_dn *dn, + const char *cn_value, + const char *uuid_value) +{ + int ret; + TALLOC_CTX *tmp_ctx; + struct ldb_message *msg; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + assert_dn_doesnt_exist(test_ctx, + ldb_dn_get_linearized(dn)); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + msg->dn = dn; + + ret = ldb_msg_add_string(msg, "cn", cn_value); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg, "objectUUID", uuid_value); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + assert_dn_exists(test_ctx, + ldb_dn_get_linearized(dn)); + talloc_free(tmp_ctx); +} + +static void test_ldb_del(void **state) +{ + int ret; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + const char *basedn = "dc=ldb_del_test"; + struct ldb_dn *dn; + + dn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "%s", basedn); + assert_non_null(dn); + + add_dn_with_cn(test_ctx, dn, + "test_del_cn_val", + "0123456789abcdef"); + + ret = ldb_delete(test_ctx->ldb, dn); + assert_int_equal(ret, LDB_SUCCESS); + + assert_dn_doesnt_exist(test_ctx, basedn); +} + +static void test_ldb_del_noexist(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_dn *basedn; + int ret; + + basedn = ldb_dn_new(test_ctx, test_ctx->ldb, "dc=nosuchplace"); + assert_non_null(basedn); + + ret = ldb_delete(test_ctx->ldb, basedn); + assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT); +} + +static void test_ldb_handle(void **state) +{ + int ret; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + struct ldb_dn *basedn; + struct ldb_request *request = NULL; + struct ldb_request *request2 = NULL; + struct ldb_result *res = NULL; + const char *attrs[] = { "cn", NULL }; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test"); + assert_non_null(basedn); + + res = talloc_zero(tmp_ctx, struct ldb_result); + assert_non_null(res); + + ret = ldb_build_search_req(&request, test_ctx->ldb, tmp_ctx, + basedn, LDB_SCOPE_BASE, + NULL, attrs, NULL, res, + ldb_search_default_callback, + NULL); + assert_int_equal(ret, 0); + + /* We are against ldb_tdb, so expect private event contexts */ + assert_ptr_not_equal(ldb_handle_get_event_context(request->handle), + ldb_get_event_context(test_ctx->ldb)); + + ret = ldb_build_search_req(&request2, test_ctx->ldb, tmp_ctx, + basedn, LDB_SCOPE_BASE, + NULL, attrs, NULL, res, + ldb_search_default_callback, + request); + assert_int_equal(ret, 0); + + /* Expect that same event context will be chained */ + assert_ptr_equal(ldb_handle_get_event_context(request->handle), + ldb_handle_get_event_context(request2->handle)); + + /* Now force this to use the global context */ + ldb_handle_use_global_event_context(request2->handle); + assert_ptr_equal(ldb_handle_get_event_context(request2->handle), + ldb_get_event_context(test_ctx->ldb)); + + talloc_free(tmp_ctx); +} + +static void test_ldb_build_search_req(void **state) +{ + int ret; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + struct ldb_dn *basedn; + struct ldb_request *request = NULL; + struct ldb_request *request2 = NULL; + struct ldb_result *res = NULL; + const char *attrs[] = { "cn", NULL }; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test"); + assert_non_null(basedn); + + res = talloc_zero(tmp_ctx, struct ldb_result); + assert_non_null(res); + + ret = ldb_build_search_req(&request, test_ctx->ldb, tmp_ctx, + basedn, LDB_SCOPE_BASE, + NULL, attrs, NULL, res, + ldb_search_default_callback, + NULL); + assert_int_equal(ret, 0); + + assert_int_equal(request->operation, LDB_SEARCH); + assert_ptr_equal(request->op.search.base, basedn); + assert_int_equal(request->op.search.scope, LDB_SCOPE_BASE); + assert_non_null(request->op.search.tree); + assert_ptr_equal(request->op.search.attrs, attrs); + assert_ptr_equal(request->context, res); + assert_ptr_equal(request->callback, ldb_search_default_callback); + + ret = ldb_build_search_req(&request2, test_ctx->ldb, tmp_ctx, + basedn, LDB_SCOPE_BASE, + NULL, attrs, NULL, res, + ldb_search_default_callback, + request); + assert_int_equal(ret, 0); + assert_ptr_equal(request, request2->handle->parent); + assert_int_equal(request->starttime, request2->starttime); + assert_int_equal(request->timeout, request2->timeout); + + talloc_free(tmp_ctx); +} + +static void add_keyval(struct ldbtest_ctx *test_ctx, + const char *key, + const char *val, + const char *uuid) +{ + int ret; + struct ldb_message *msg; + + msg = ldb_msg_new(test_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "%s=%s", key, val); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, key, val); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", uuid); + assert_int_equal(ret, 0); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, 0); + + talloc_free(msg); +} + +static struct ldb_result *get_keyval(struct ldbtest_ctx *test_ctx, + const char *key, + const char *val) +{ + int ret; + struct ldb_result *result; + struct ldb_dn *basedn; + + basedn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "%s=%s", key, val); + assert_non_null(basedn); + + ret = ldb_search(test_ctx->ldb, test_ctx, &result, basedn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, 0); + + return result; +} + +static void test_transactions(void **state) +{ + int ret; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_result *res; + + /* start lev-0 transaction */ + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, 0); + + add_keyval(test_ctx, "vegetable", "carrot", + "0123456789abcde0"); + + /* commit lev-0 transaction */ + ret = ldb_transaction_commit(test_ctx->ldb); + assert_int_equal(ret, 0); + + /* start another lev-1 nested transaction */ + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, 0); + + add_keyval(test_ctx, "fruit", "apple", + "0123456789abcde1"); + + /* abort lev-1 nested transaction */ + ret = ldb_transaction_cancel(test_ctx->ldb); + assert_int_equal(ret, 0); + + res = get_keyval(test_ctx, "vegetable", "carrot"); + assert_non_null(res); + assert_int_equal(res->count, 1); + + res = get_keyval(test_ctx, "fruit", "apple"); + assert_non_null(res); + assert_int_equal(res->count, 0); +} + +static void test_nested_transactions(void **state) +{ + int ret; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_result *res; + + /* start lev-0 transaction */ + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, 0); + + add_keyval(test_ctx, "vegetable", "carrot", + "0123456789abcde0"); + + + /* start another lev-1 nested transaction */ + ret = ldb_transaction_start(test_ctx->ldb); + assert_int_equal(ret, 0); + + add_keyval(test_ctx, "fruit", "apple", + "0123456789abcde1"); + + /* abort lev-1 nested transaction */ + ret = ldb_transaction_cancel(test_ctx->ldb); + assert_int_equal(ret, 0); + + /* commit lev-0 transaction */ + ret = ldb_transaction_commit(test_ctx->ldb); + assert_int_equal(ret, 0); + + res = get_keyval(test_ctx, "vegetable", "carrot"); + assert_non_null(res); + assert_int_equal(res->count, 1); + + /* This documents the current ldb behaviour, i.e. nested + * transactions are not supported. And the cancellation of the nested + * transaction has no effect. + */ + res = get_keyval(test_ctx, "fruit", "apple"); + assert_non_null(res); + assert_int_equal(res->count, 1); +} +struct ldb_mod_test_ctx { + struct ldbtest_ctx *ldb_test_ctx; + const char *entry_dn; +}; + +struct keyval { + const char *key; + const char *val; +}; + +static struct ldb_message *build_mod_msg(TALLOC_CTX *mem_ctx, + struct ldbtest_ctx *test_ctx, + const char *dn, + int modify_flags, + struct keyval *kvs) +{ + struct ldb_message *msg; + int ret; + int i; + + msg = ldb_msg_new(mem_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "%s", dn); + assert_non_null(msg->dn); + + for (i = 0; kvs[i].key != NULL; i++) { + if (modify_flags) { + ret = ldb_msg_add_empty(msg, kvs[i].key, + modify_flags, NULL); + assert_int_equal(ret, 0); + } + + if (kvs[i].val) { + ret = ldb_msg_add_string(msg, kvs[i].key, kvs[i].val); + assert_int_equal(ret, LDB_SUCCESS); + } + } + + return msg; +} + +static void ldb_test_add_data(TALLOC_CTX *mem_ctx, + struct ldbtest_ctx *ldb_test_ctx, + const char *basedn, + struct keyval *kvs) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_message *msg; + struct ldb_result *result = NULL; + int ret; + + tmp_ctx = talloc_new(mem_ctx); + assert_non_null(tmp_ctx); + + msg = build_mod_msg(tmp_ctx, ldb_test_ctx, + basedn, 0, kvs); + assert_non_null(msg); + + ret = ldb_add(ldb_test_ctx->ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_search(ldb_test_ctx->ldb, tmp_ctx, &result, msg->dn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(result); + assert_int_equal(result->count, 1); + assert_string_equal(ldb_dn_get_linearized(result->msgs[0]->dn), + ldb_dn_get_linearized(msg->dn)); + + talloc_free(tmp_ctx); +} + +static void ldb_test_remove_data(TALLOC_CTX *mem_ctx, + struct ldbtest_ctx *ldb_test_ctx, + const char *strdn) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_dn *basedn; + int ret; + size_t count; + + tmp_ctx = talloc_new(mem_ctx); + assert_non_null(tmp_ctx); + + basedn = ldb_dn_new_fmt(tmp_ctx, ldb_test_ctx->ldb, + "%s", strdn); + assert_non_null(basedn); + + ret = ldb_delete(ldb_test_ctx->ldb, basedn); + assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_NO_SUCH_OBJECT); + + count = base_search_count(ldb_test_ctx, ldb_dn_get_linearized(basedn)); + assert_int_equal(count, 0); + + talloc_free(tmp_ctx); +} + +static void mod_test_add_data(struct ldb_mod_test_ctx *mod_test_ctx, + struct keyval *kvs) +{ + ldb_test_add_data(mod_test_ctx, + mod_test_ctx->ldb_test_ctx, + mod_test_ctx->entry_dn, + kvs); +} + +static void mod_test_remove_data(struct ldb_mod_test_ctx *mod_test_ctx) +{ + ldb_test_remove_data(mod_test_ctx, + mod_test_ctx->ldb_test_ctx, + mod_test_ctx->entry_dn); +} + +static struct ldb_result *run_mod_test(struct ldb_mod_test_ctx *mod_test_ctx, + int modify_flags, + struct keyval *kvs) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_result *res; + struct ldb_message *mod_msg; + struct ldb_dn *basedn; + struct ldbtest_ctx *ldb_test_ctx; + int ret; + + ldb_test_ctx = mod_test_ctx->ldb_test_ctx; + + tmp_ctx = talloc_new(mod_test_ctx); + assert_non_null(tmp_ctx); + + mod_msg = build_mod_msg(tmp_ctx, ldb_test_ctx, mod_test_ctx->entry_dn, + modify_flags, kvs); + assert_non_null(mod_msg); + + ret = ldb_modify(ldb_test_ctx->ldb, mod_msg); + assert_int_equal(ret, LDB_SUCCESS); + + basedn = ldb_dn_new_fmt(tmp_ctx, ldb_test_ctx->ldb, + "%s", mod_test_ctx->entry_dn); + assert_non_null(basedn); + + ret = ldb_search(ldb_test_ctx->ldb, mod_test_ctx, &res, basedn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(res); + assert_int_equal(res->count, 1); + assert_string_equal(ldb_dn_get_linearized(res->msgs[0]->dn), + ldb_dn_get_linearized(mod_msg->dn)); + + talloc_free(tmp_ctx); + return res; +} + +static int ldb_modify_test_setup(void **state) +{ + struct ldbtest_ctx *ldb_test_ctx; + struct ldb_mod_test_ctx *mod_test_ctx; + struct keyval kvs[] = { + { "cn", "test_mod_cn" }, + { "objectUUID", "0123456789abcdef"}, + { NULL, NULL }, + }; + + ldbtest_setup((void **) &ldb_test_ctx); + + mod_test_ctx = talloc(ldb_test_ctx, struct ldb_mod_test_ctx); + assert_non_null(mod_test_ctx); + + mod_test_ctx->entry_dn = "dc=mod_test_entry"; + mod_test_ctx->ldb_test_ctx = ldb_test_ctx; + + mod_test_remove_data(mod_test_ctx); + mod_test_add_data(mod_test_ctx, kvs); + *state = mod_test_ctx; + return 0; +} + +static int ldb_modify_test_teardown(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct ldbtest_ctx *ldb_test_ctx; + + ldb_test_ctx = mod_test_ctx->ldb_test_ctx; + + mod_test_remove_data(mod_test_ctx); + talloc_free(mod_test_ctx); + + ldbtest_teardown((void **) &ldb_test_ctx); + return 0; +} + +static void test_ldb_modify_add_key(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct keyval mod_kvs[] = { + { "name", "test_mod_name" }, + { NULL, NULL }, + }; + struct ldb_result *res; + struct ldb_message_element *el; + + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_ADD, mod_kvs); + assert_non_null(res); + + /* Check cn is intact and name was added */ + assert_int_equal(res->count, 1); + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_non_null(el); + assert_int_equal(el->num_values, 1); + assert_string_equal(el->values[0].data, "test_mod_cn"); + + el = ldb_msg_find_element(res->msgs[0], "name"); + assert_non_null(el); + assert_int_equal(el->num_values, 1); + assert_string_equal(el->values[0].data, "test_mod_name"); +} + +static void test_ldb_modify_extend_key(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct keyval mod_kvs[] = { + { "cn", "test_mod_cn2" }, + { NULL, NULL }, + }; + struct ldb_result *res; + struct ldb_message_element *el; + + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_ADD, mod_kvs); + assert_non_null(res); + + /* Check cn was extended with another value */ + assert_int_equal(res->count, 1); + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_non_null(el); + assert_int_equal(el->num_values, 2); + assert_string_equal(el->values[0].data, "test_mod_cn"); + assert_string_equal(el->values[1].data, "test_mod_cn2"); +} + +static void test_ldb_modify_add_key_noval(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct ldb_message *mod_msg; + struct ldbtest_ctx *ldb_test_ctx; + struct ldb_message_element *el; + int ret; + + ldb_test_ctx = mod_test_ctx->ldb_test_ctx; + + mod_msg = ldb_msg_new(mod_test_ctx); + assert_non_null(mod_msg); + + mod_msg->dn = ldb_dn_new_fmt(mod_msg, ldb_test_ctx->ldb, + "%s", mod_test_ctx->entry_dn); + assert_non_null(mod_msg->dn); + + el = talloc_zero(mod_msg, struct ldb_message_element); + el->flags = LDB_FLAG_MOD_ADD; + assert_non_null(el); + el->name = talloc_strdup(el, "cn"); + assert_non_null(el->name); + + mod_msg->elements = el; + mod_msg->num_elements = 1; + + ret = ldb_modify(ldb_test_ctx->ldb, mod_msg); + assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION); +} + +static void test_ldb_modify_replace_key(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + const char *new_cn = "new_cn"; + struct keyval mod_kvs[] = { + { "cn", new_cn }, + { NULL, NULL }, + }; + struct ldb_result *res; + struct ldb_message_element *el; + + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, mod_kvs); + assert_non_null(res); + + /* Check cn was replaced */ + assert_int_equal(res->count, 1); + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_non_null(el); + assert_int_equal(el->num_values, 1); + assert_string_equal(el->values[0].data, new_cn); +} + +static void test_ldb_modify_replace_noexist_key(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct keyval mod_kvs[] = { + { "name", "name_val" }, + { NULL, NULL }, + }; + struct ldb_result *res; + struct ldb_message_element *el; + + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, mod_kvs); + assert_non_null(res); + + /* Check cn is intact and name was added */ + assert_int_equal(res->count, 1); + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_non_null(el); + assert_int_equal(el->num_values, 1); + assert_string_equal(el->values[0].data, "test_mod_cn"); + + el = ldb_msg_find_element(res->msgs[0], mod_kvs[0].key); + assert_non_null(el); + assert_int_equal(el->num_values, 1); + assert_string_equal(el->values[0].data, mod_kvs[0].val); +} + +static void test_ldb_modify_replace_zero_vals(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct ldb_message_element *el; + struct ldb_result *res; + struct keyval kvs[] = { + { "cn", NULL }, + { NULL, NULL }, + }; + + /* cn must be gone */ + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, kvs); + assert_non_null(res); + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_null(el); +} + +static void test_ldb_modify_replace_noexist_key_zero_vals(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct ldb_message_element *el; + struct ldb_result *res; + struct keyval kvs[] = { + { "noexist_key", NULL }, + { NULL, NULL }, + }; + + /* cn must be gone */ + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, kvs); + assert_non_null(res); + + /* cn should be intact */ + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_non_null(el); +} + +static void test_ldb_modify_del_key(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct ldb_message_element *el; + struct ldb_result *res; + struct keyval kvs[] = { + { "cn", NULL }, + { NULL, NULL }, + }; + + /* cn must be gone */ + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_DELETE, kvs); + assert_non_null(res); + + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_null(el); +} + +static void test_ldb_modify_del_keyval(void **state) +{ + struct ldb_mod_test_ctx *mod_test_ctx = \ + talloc_get_type_abort(*state, + struct ldb_mod_test_ctx); + struct ldb_message_element *el; + struct ldb_result *res; + struct keyval kvs[] = { + { "cn", "test_mod_cn" }, + { NULL, NULL }, + }; + + /* cn must be gone */ + res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_DELETE, kvs); + assert_non_null(res); + + el = ldb_msg_find_element(res->msgs[0], "cn"); + assert_null(el); +} + +struct search_test_ctx { + struct ldbtest_ctx *ldb_test_ctx; + const char *base_dn; +}; + +static char *get_full_dn(TALLOC_CTX *mem_ctx, + struct search_test_ctx *search_test_ctx, + const char *rdn) +{ + char *full_dn; + + full_dn = talloc_asprintf(mem_ctx, + "%s,%s", rdn, search_test_ctx->base_dn); + assert_non_null(full_dn); + + return full_dn; +} + +static void search_test_add_data(struct search_test_ctx *search_test_ctx, + const char *rdn, + struct keyval *kvs) +{ + char *full_dn; + + full_dn = get_full_dn(search_test_ctx, search_test_ctx, rdn); + + ldb_test_add_data(search_test_ctx, + search_test_ctx->ldb_test_ctx, + full_dn, + kvs); +} + +static void search_test_remove_data(struct search_test_ctx *search_test_ctx, + const char *rdn) +{ + char *full_dn; + + full_dn = talloc_asprintf(search_test_ctx, + "%s,%s", rdn, search_test_ctx->base_dn); + assert_non_null(full_dn); + + ldb_test_remove_data(search_test_ctx, + search_test_ctx->ldb_test_ctx, + full_dn); +} + +static int ldb_search_test_setup(void **state) +{ + struct ldbtest_ctx *ldb_test_ctx; + struct search_test_ctx *search_test_ctx; + struct keyval kvs[] = { + { "cn", "test_search_cn" }, + { "cn", "test_search_cn2" }, + { "uid", "test_search_uid" }, + { "uid", "test_search_uid2" }, + { "objectUUID", "0123456789abcde0"}, + { NULL, NULL }, + }; + struct keyval kvs2[] = { + { "cn", "test_search_2_cn" }, + { "cn", "test_search_2_cn2" }, + { "uid", "test_search_2_uid" }, + { "uid", "test_search_2_uid2" }, + { "objectUUID", "0123456789abcde1"}, + { NULL, NULL }, + }; + + ldbtest_setup((void **) &ldb_test_ctx); + + search_test_ctx = talloc(ldb_test_ctx, struct search_test_ctx); + assert_non_null(search_test_ctx); + + search_test_ctx->base_dn = "dc=search_test_entry"; + search_test_ctx->ldb_test_ctx = ldb_test_ctx; + + search_test_remove_data(search_test_ctx, "cn=test_search_cn"); + search_test_add_data(search_test_ctx, "cn=test_search_cn", kvs); + + search_test_remove_data(search_test_ctx, "cn=test_search_2_cn"); + search_test_add_data(search_test_ctx, "cn=test_search_2_cn", kvs2); + + *state = search_test_ctx; + return 0; +} + +static int ldb_search_test_teardown(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + struct ldbtest_ctx *ldb_test_ctx; + + ldb_test_ctx = search_test_ctx->ldb_test_ctx; + + search_test_remove_data(search_test_ctx, "cn=test_search_cn"); + search_test_remove_data(search_test_ctx, "cn=test_search_2_cn"); + ldbtest_teardown((void **) &ldb_test_ctx); + return 0; +} + +static void assert_attr_has_vals(struct ldb_message *msg, + const char *attr, + const char *vals[], + const size_t nvals) +{ + struct ldb_message_element *el; + size_t i; + + el = ldb_msg_find_element(msg, attr); + assert_non_null(el); + + assert_int_equal(el->num_values, nvals); + for (i = 0; i < nvals; i++) { + assert_string_equal(el->values[i].data, + vals[i]); + } +} + +static void assert_has_no_attr(struct ldb_message *msg, + const char *attr) +{ + struct ldb_message_element *el; + + el = ldb_msg_find_element(msg, attr); + assert_null(el); +} + +static bool has_dn(struct ldb_message *msg, const char *dn) +{ + const char *msgdn; + + msgdn = ldb_dn_get_linearized(msg->dn); + if (strcmp(dn, msgdn) == 0) { + return true; + } + + return false; +} + +static void test_search_match_none(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + size_t count; + + count = base_search_count(search_test_ctx->ldb_test_ctx, + "dc=no_such_entry"); + assert_int_equal(count, 0); +} + +static void test_search_match_one(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + int ret; + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + const char *cn_vals[] = { "test_search_cn", + "test_search_cn2" }; + const char *uid_vals[] = { "test_search_uid", + "test_search_uid2" }; + + basedn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(basedn); + + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, NULL, + "cn=test_search_cn"); + assert_int_equal(ret, 0); + assert_non_null(result); + assert_int_equal(result->count, 1); + + assert_attr_has_vals(result->msgs[0], "cn", cn_vals, 2); + assert_attr_has_vals(result->msgs[0], "uid", uid_vals, 2); +} + +static void test_search_match_filter(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + int ret; + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + const char *cn_vals[] = { "test_search_cn", + "test_search_cn2" }; + const char *attrs[] = { "cn", NULL }; + + basedn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(basedn); + + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, + attrs, + "cn=test_search_cn"); + assert_int_equal(ret, 0); + assert_non_null(result); + assert_int_equal(result->count, 1); + + assert_attr_has_vals(result->msgs[0], "cn", cn_vals, 2); + assert_has_no_attr(result->msgs[0], "uid"); +} + +static void assert_expected(struct search_test_ctx *search_test_ctx, + struct ldb_message *msg) +{ + char *full_dn1; + char *full_dn2; + const char *cn_vals[] = { "test_search_cn", + "test_search_cn2" }; + const char *uid_vals[] = { "test_search_uid", + "test_search_uid2" }; + const char *cn2_vals[] = { "test_search_2_cn", + "test_search_2_cn2" }; + const char *uid2_vals[] = { "test_search_2_uid", + "test_search_2_uid2" }; + + full_dn1 = get_full_dn(search_test_ctx, + search_test_ctx, + "cn=test_search_cn"); + + full_dn2 = get_full_dn(search_test_ctx, + search_test_ctx, + "cn=test_search_2_cn"); + + if (has_dn(msg, full_dn1) == true) { + assert_attr_has_vals(msg, "cn", cn_vals, 2); + assert_attr_has_vals(msg, "uid", uid_vals, 2); + } else if (has_dn(msg, full_dn2) == true) { + assert_attr_has_vals(msg, "cn", cn2_vals, 2); + assert_attr_has_vals(msg, "uid", uid2_vals, 2); + } else { + fail(); + } +} + +static void test_search_match_both(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + int ret; + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + + basedn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(basedn); + + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, NULL, + "cn=test_search_*"); + assert_int_equal(ret, 0); + assert_non_null(result); + assert_int_equal(result->count, 2); + + assert_expected(search_test_ctx, result->msgs[0]); + assert_expected(search_test_ctx, result->msgs[1]); +} + +static void test_search_match_basedn(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + int ret; + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + struct ldb_message *msg; + + basedn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "dc=nosuchdn"); + assert_non_null(basedn); + + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, NULL, + "cn=*"); + assert_int_equal(ret, 0); + + /* Add 'checkBaseOnSearch' to @OPTIONS */ + msg = ldb_msg_new(search_test_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, + search_test_ctx->ldb_test_ctx->ldb, + "@OPTIONS"); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "checkBaseOnSearch", "TRUE"); + assert_int_equal(ret, 0); + + ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb, msg); + assert_int_equal(ret, 0); + + /* Search again */ + /* The search should return LDB_ERR_NO_SUCH_OBJECT */ + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + &result, + basedn, + LDB_SCOPE_SUBTREE, NULL, + "cn=*"); + assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT); + + ret = ldb_delete(search_test_ctx->ldb_test_ctx->ldb, msg->dn); + assert_int_equal(ret, 0); +} + + +/* + * This test is complex. + * The purpose is to test for a deadlock detected between ldb_search() + * and ldb_transaction_commit(). The deadlock happens if in process + * (1) and (2): + * - (1) the all-record lock is taken in ltdb_search() + * - (2) the ldb_transaction_start() call is made + * - (1) an un-indexed search starts (forced here by doing it in + * the callback + * - (2) the ldb_transaction_commit() is called. + * This returns LDB_ERR_BUSY if the deadlock is detected + * + * With ldb 1.1.31 and tdb 1.3.12 we avoid this only due to a missing + * lock call in ltdb_search() due to a refcounting bug in + * ltdb_lock_read() + */ + +struct search_against_transaction_ctx { + struct ldbtest_ctx *test_ctx; + int res_count; + pid_t child_pid; + struct ldb_dn *basedn; +}; + +static int test_ldb_search_against_transaction_callback2(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct search_against_transaction_ctx *ctx = req->context; + switch (ares->type) { + case LDB_REPLY_ENTRY: + ctx->res_count++; + if (ctx->res_count != 1) { + return LDB_SUCCESS; + } + + break; + + case LDB_REPLY_REFERRAL: + break; + + case LDB_REPLY_DONE: + return ldb_request_done(req, LDB_SUCCESS); + } + + return 0; + +} + +/* + * This purpose of this callback is to trigger a transaction in + * the child process while the all-record lock is held, but before + * we take any locks in the tdb_traverse_read() handler. + * + * In tdb 1.3.12 tdb_traverse_read() take the read transaction lock + * however in ldb 1.1.31 ltdb_search() forgets to take the all-record + * lock (except the very first time) due to a ref-counting bug. + * + */ + +static int test_ldb_search_against_transaction_callback1(struct ldb_request *req, + struct ldb_reply *ares) +{ + int ret, ret2; + int pipes[2]; + char buf[2]; + struct search_against_transaction_ctx *ctx = req->context; + switch (ares->type) { + case LDB_REPLY_ENTRY: + break; + + case LDB_REPLY_REFERRAL: + return LDB_SUCCESS; + + case LDB_REPLY_DONE: + return ldb_request_done(req, LDB_SUCCESS); + } + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + ctx->child_pid = fork(); + if (ctx->child_pid == 0) { + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_message *msg; + TALLOC_FREE(ctx->test_ctx->ldb); + TALLOC_FREE(ctx->test_ctx->ev); + close(pipes[0]); + ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx); + if (ctx->test_ctx->ev == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ctx->test_ctx->ldb = ldb_init(ctx->test_ctx, + ctx->test_ctx->ev); + if (ctx->test_ctx->ldb == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_connect(ctx->test_ctx->ldb, + ctx->test_ctx->dbpath, 0, NULL); + if (ret != LDB_SUCCESS) { + exit(ret); + } + + tmp_ctx = talloc_new(ctx->test_ctx); + if (tmp_ctx == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb, + "dc=test"); + if (msg->dn == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + if (ret != 0) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_transaction_start(ctx->test_ctx->ldb); + if (ret != 0) { + exit(ret); + } + + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_msg_add_string(msg, "objectUUID", + "0123456789abcdef"); + if (ret != 0) { + exit(ret); + } + + ret = ldb_add(ctx->test_ctx->ldb, msg); + if (ret != 0) { + exit(ret); + } + + ret = ldb_transaction_commit(ctx->test_ctx->ldb); + exit(ret); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + /* This search must be unindexed (ie traverse in tdb) */ + ret = ldb_build_search_req(&req, + ctx->test_ctx->ldb, + ctx->test_ctx, + ctx->basedn, + LDB_SCOPE_SUBTREE, + "cn=*", NULL, + NULL, + ctx, + test_ldb_search_against_transaction_callback2, + NULL); + /* + * we don't assert on these return codes until after the search is + * finished, or the clean up will fail because we hold locks. + */ + + ret2 = ldb_request(ctx->test_ctx->ldb, req); + + if (ret2 == LDB_SUCCESS) { + ret2 = ldb_wait(req->handle, LDB_WAIT_ALL); + } + assert_int_equal(ret, 0); + assert_int_equal(ret2, 0); + assert_int_equal(ctx->res_count, 2); + + return LDB_SUCCESS; +} + +static void test_ldb_search_against_transaction(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + struct search_against_transaction_ctx + ctx = + { .res_count = 0, + .test_ctx = search_test_ctx->ldb_test_ctx + }; + + int ret; + struct ldb_request *req; + pid_t pid; + int wstatus; + struct ldb_dn *base_search_dn; + + tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev); + + base_search_dn + = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "cn=test_search_cn,%s", + search_test_ctx->base_dn); + assert_non_null(base_search_dn); + + ctx.basedn + = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(ctx.basedn); + + + /* This search must be indexed (ie no traverse in tdb) */ + ret = ldb_build_search_req(&req, + search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + base_search_dn, + LDB_SCOPE_BASE, + "cn=*", NULL, + NULL, + &ctx, + test_ldb_search_against_transaction_callback1, + NULL); + assert_int_equal(ret, 0); + ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + assert_int_equal(ret, 0); + assert_int_equal(ctx.res_count, 2); + + pid = waitpid(ctx.child_pid, &wstatus, 0); + assert_int_equal(pid, ctx.child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + + +} + +/* + * This test is also complex. + * The purpose is to test if a modify can occur during an ldb_search() + * This would be a failure if if in process + * (1) and (2): + * - (1) ltdb_search() starts and calls back for one entry + * - (2) one of the entries to be matched is modified + * - (1) the indexed search tries to return the modified entry, but + * it is no longer found, either: + * - despite it still matching (dn changed) + * - it no longer matching (attrs changed) + * + * We also try un-indexed to show that the behaviour differs on this + * point, which it should not (an index should only impact search + * speed). + */ + +struct modify_during_search_test_ctx { + struct ldbtest_ctx *test_ctx; + int res_count; + pid_t child_pid; + struct ldb_dn *basedn; + bool got_cn; + bool got_2_cn; + bool rename; +}; + +/* + * This purpose of this callback is to trigger a write in + * the child process while a search is in progress. + * + * In tdb 1.3.12 tdb_traverse_read() take the read transaction lock + * however in ldb 1.1.31 ltdb_search() forgets to take the all-record + * lock (except the very first time) due to a ref-counting bug. + * + * We assume that if the write will proceed, it will proceed in a 3 + * second window after the function is called. + */ + +static int test_ldb_modify_during_search_callback1(struct ldb_request *req, + struct ldb_reply *ares) +{ + int ret; + int pipes[2]; + char buf[2]; + struct modify_during_search_test_ctx *ctx = req->context; + switch (ares->type) { + case LDB_REPLY_ENTRY: + { + const struct ldb_val *cn_val + = ldb_dn_get_component_val(ares->message->dn, 0); + const char *cn = (char *)cn_val->data; + ctx->res_count++; + if (strcmp(cn, "test_search_cn") == 0) { + ctx->got_cn = true; + } else if (strcmp(cn, "test_search_2_cn") == 0) { + ctx->got_2_cn = true; + } + if (ctx->res_count == 2) { + return LDB_SUCCESS; + } + break; + } + case LDB_REPLY_REFERRAL: + return LDB_SUCCESS; + + case LDB_REPLY_DONE: + return ldb_request_done(req, LDB_SUCCESS); + } + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + ctx->child_pid = fork(); + if (ctx->child_pid == 0 && ctx->rename) { + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_dn *dn, *new_dn; + TALLOC_FREE(ctx->test_ctx->ldb); + TALLOC_FREE(ctx->test_ctx->ev); + close(pipes[0]); + ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx); + if (ctx->test_ctx->ev == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ctx->test_ctx->ldb = ldb_init(ctx->test_ctx, + ctx->test_ctx->ev); + if (ctx->test_ctx->ldb == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_connect(ctx->test_ctx->ldb, + ctx->test_ctx->dbpath, 0, NULL); + if (ret != LDB_SUCCESS) { + exit(ret); + } + + tmp_ctx = talloc_new(ctx->test_ctx); + if (tmp_ctx == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + if (ctx->got_cn) { + /* Modify the other one */ + dn = ldb_dn_new_fmt(tmp_ctx, ctx->test_ctx->ldb, + "cn=test_search_2_cn," + "dc=search_test_entry"); + } else { + dn = ldb_dn_new_fmt(tmp_ctx, ctx->test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + } + if (dn == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + new_dn = ldb_dn_new_fmt(tmp_ctx, ctx->test_ctx->ldb, + "cn=test_search_cn_renamed," + "dc=search_test_entry"); + if (new_dn == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_transaction_start(ctx->test_ctx->ldb); + if (ret != 0) { + exit(ret); + } + + if (write(pipes[1], "GO", 2) != 2) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_rename(ctx->test_ctx->ldb, dn, new_dn); + if (ret != 0) { + exit(ret); + } + + ret = ldb_transaction_commit(ctx->test_ctx->ldb); + exit(ret); + + } else if (ctx->child_pid == 0) { + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_message *msg; + struct ldb_message_element *el; + TALLOC_FREE(ctx->test_ctx->ldb); + TALLOC_FREE(ctx->test_ctx->ev); + close(pipes[0]); + ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx); + if (ctx->test_ctx->ev == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ctx->test_ctx->ldb = ldb_init(ctx->test_ctx, + ctx->test_ctx->ev); + if (ctx->test_ctx->ldb == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_connect(ctx->test_ctx->ldb, + ctx->test_ctx->dbpath, 0, NULL); + if (ret != LDB_SUCCESS) { + exit(ret); + } + + tmp_ctx = talloc_new(ctx->test_ctx); + if (tmp_ctx == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + if (ctx->got_cn) { + /* Modify the other one */ + msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb, + "cn=test_search_2_cn," + "dc=search_test_entry"); + } else { + msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + } + if (msg->dn == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_msg_add_string(msg, "filterAttr", "TRUE"); + if (ret != 0) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + el = ldb_msg_find_element(msg, "filterAttr"); + if (el == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + el->flags = LDB_FLAG_MOD_REPLACE; + + ret = ldb_transaction_start(ctx->test_ctx->ldb); + if (ret != 0) { + exit(ret); + } + + if (write(pipes[1], "GO", 2) != 2) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_modify(ctx->test_ctx->ldb, msg); + if (ret != 0) { + exit(ret); + } + + ret = ldb_transaction_commit(ctx->test_ctx->ldb); + exit(ret); + } + + /* + * With TDB 1.3.13 and before "tdb: Remove locking from tdb_traverse_read()" + * we will hang here because the child process can not proceed to + * sending the "GO" as it is blocked at ldb_transaction_start(). + */ + + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + sleep(3); + + return LDB_SUCCESS; +} + +static void test_ldb_modify_during_search(void **state, bool add_index, + bool rename) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + struct modify_during_search_test_ctx + ctx = + { .res_count = 0, + .test_ctx = search_test_ctx->ldb_test_ctx, + .rename = rename + }; + + int ret; + struct ldb_request *req; + pid_t pid; + int wstatus; + + if (add_index) { + struct ldb_message *msg; + struct ldb_dn *indexlist = ldb_dn_new(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "@INDEXLIST"); + assert_non_null(indexlist); + + msg = ldb_msg_new(search_test_ctx); + assert_non_null(msg); + + msg->dn = indexlist; + + ret = ldb_msg_add_string(msg, "@IDXATTR", "cn"); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb, + msg); + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + msg->elements[0].flags = LDB_FLAG_MOD_ADD; + ret = ldb_modify(search_test_ctx->ldb_test_ctx->ldb, + msg); + } + assert_int_equal(ret, LDB_SUCCESS); + } + + tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev); + + ctx.basedn + = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(ctx.basedn); + + + /* + * This search must be over multiple items, and should include + * the new name after a rename, to show that it would match + * both before and after that modify + */ + ret = ldb_build_search_req(&req, + search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + ctx.basedn, + LDB_SCOPE_SUBTREE, + "(&(!(filterAttr=*))" + "(|(cn=test_search_cn_renamed)" + "(cn=test_search_cn)" + "(cn=test_search_2_cn)" + "))", + NULL, + NULL, + &ctx, + test_ldb_modify_during_search_callback1, + NULL); + assert_int_equal(ret, 0); + ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + assert_int_equal(ret, 0); + assert_int_equal(ctx.res_count, 2); + assert_int_equal(ctx.got_cn, true); + assert_int_equal(ctx.got_2_cn, true); + + pid = waitpid(ctx.child_pid, &wstatus, 0); + assert_int_equal(pid, ctx.child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + + +} + +static void test_ldb_modify_during_indexed_search(void **state) +{ + test_ldb_modify_during_search(state, true, false); +} + +static void test_ldb_modify_during_unindexed_search(void **state) +{ + test_ldb_modify_during_search(state, false, false); +} + +static void test_ldb_rename_during_indexed_search(void **state) +{ + test_ldb_modify_during_search(state, true, true); +} + +static void test_ldb_rename_during_unindexed_search(void **state) +{ + test_ldb_modify_during_search(state, false, true); +} + +/* + * This test is also complex. + * + * The purpose is to test if a modify can occur during an ldb_search() + * before the end of the callback + * + * This would be a failure if if in process + * (1) and (2): + * - (1) ldb_search() starts and calls back for a number of entries + * - (2) an entry in the DB is allowed to change before the callback returns + * - (1) the callback can see the modification + * + */ + +/* + * This purpose of this callback is to trigger a write in + * the child process while a search DONE callback is in progress. + * + * In ldb 1.1.31 ldb_search() omitted to take a all-record + * lock for the full duration of the search and callbacks + * + * We assume that if the write will proceed, it will proceed in a 3 + * second window after the function is called. + */ + +static int test_ldb_modify_during_whole_search_callback1(struct ldb_request *req, + struct ldb_reply *ares) +{ + int ret; + int pipes[2]; + char buf[2]; + struct modify_during_search_test_ctx *ctx = req->context; + struct ldb_dn *search_dn; + struct ldb_result *res2; + unsigned res_count; + switch (ares->type) { + case LDB_REPLY_ENTRY: + case LDB_REPLY_REFERRAL: + return LDB_SUCCESS; + + case LDB_REPLY_DONE: + break; + } + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + ctx->child_pid = fork(); + if (ctx->child_pid == 0) { + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_message *msg; + struct ldb_message_element *el; + TALLOC_FREE(ctx->test_ctx->ldb); + TALLOC_FREE(ctx->test_ctx->ev); + close(pipes[0]); + ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx); + if (ctx->test_ctx->ev == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ctx->test_ctx->ldb = ldb_init(ctx->test_ctx, + ctx->test_ctx->ev); + if (ctx->test_ctx->ldb == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_connect(ctx->test_ctx->ldb, + ctx->test_ctx->dbpath, 0, NULL); + if (ret != LDB_SUCCESS) { + exit(ret); + } + + tmp_ctx = talloc_new(ctx->test_ctx); + if (tmp_ctx == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + if (msg->dn == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_msg_add_string(msg, "filterAttr", "TRUE"); + if (ret != 0) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + el = ldb_msg_find_element(msg, "filterAttr"); + if (el == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + el->flags = LDB_FLAG_MOD_REPLACE; + + ret = ldb_transaction_start(ctx->test_ctx->ldb); + if (ret != 0) { + exit(ret); + } + + if (write(pipes[1], "GO", 2) != 2) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_modify(ctx->test_ctx->ldb, msg); + if (ret != 0) { + exit(ret); + } + + ret = ldb_transaction_commit(ctx->test_ctx->ldb); + exit(ret); + } + + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + sleep(3); + + /* + * If writes are not blocked until after this function, we + * will be able to successfully search for this modification + * here + */ + + search_dn = ldb_dn_new_fmt(ares, ctx->test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + + ret = ldb_search(ctx->test_ctx->ldb, ares, + &res2, search_dn, LDB_SCOPE_BASE, NULL, + "filterAttr=TRUE"); + + /* + * We do this in an unusual order, because if we fail an assert before + * ldb_request_done(), we will also fail to clean up as we hold locks. + */ + + res_count = res2->count; + ldb_request_done(req, LDB_SUCCESS); + assert_int_equal(ret, 0); + + /* We should not have got the result */ + assert_int_equal(res_count, 0); + + return ret; +} + +static void test_ldb_modify_during_whole_search(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + struct modify_during_search_test_ctx + ctx = + { + .test_ctx = search_test_ctx->ldb_test_ctx, + }; + + int ret; + struct ldb_request *req; + pid_t pid; + int wstatus; + struct ldb_dn *search_dn; + struct ldb_result *res2; + + tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev); + + ctx.basedn + = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(ctx.basedn); + + + /* + * The search just needs to call DONE, we don't care about the + * contents of the search for this test + */ + ret = ldb_build_search_req(&req, + search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + ctx.basedn, + LDB_SCOPE_SUBTREE, + "(&(!(filterAttr=*))" + "(cn=test_search_cn))", + NULL, + NULL, + &ctx, + test_ldb_modify_during_whole_search_callback1, + NULL); + assert_int_equal(ret, 0); + ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + assert_int_equal(ret, 0); + + pid = waitpid(ctx.child_pid, &wstatus, 0); + assert_int_equal(pid, ctx.child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + + /* + * If writes are blocked until after the search function, we + * will be able to successfully search for this modification + * now + */ + + search_dn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + &res2, search_dn, LDB_SCOPE_BASE, NULL, + "filterAttr=TRUE"); + assert_int_equal(ret, 0); + + /* We got the result */ + assert_int_equal(res2->count, 1); +} + +/* + * This test is also complex. + * + * The purpose is to test if a modify can occur during an ldb_search() + * before the request is destroyed with TALLOC_FREE() + * + * This would be a failure if in process + * (1) and (2): + * - (1) ldb_search() starts and waits + * - (2) an entry in the DB is allowed to change before the ldb_wait() is called + * - (1) the original process can see the modification before the TALLOC_FREE() + * also we check that + * - (1) the original process can see the modification after the TALLOC_FREE() + * + */ + +/* + * This purpose of this callback is to trigger a write in + * the child process before the ldb_wait() is called + * + * In ldb 1.1.31 ldb_search() omitted to take a all-record + * lock for the full duration of the search and callbacks + * + * We assume that if the write will proceed, it will proceed in a 3 + * second window after the function is called. + */ + +static int test_ldb_modify_before_ldb_wait_callback1(struct ldb_request *req, + struct ldb_reply *ares) +{ + switch (ares->type) { + case LDB_REPLY_ENTRY: + case LDB_REPLY_REFERRAL: + return LDB_SUCCESS; + + case LDB_REPLY_DONE: + break; + } + + return ldb_request_done(req, LDB_SUCCESS); +} + +static void test_ldb_modify_before_ldb_wait(void **state) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + int ret; + struct ldb_request *req; + pid_t pid; + int wstatus; + struct ldb_dn *search_dn; + struct ldb_dn *basedn; + struct ldb_result *res2; + int pipes[2]; + char buf[2]; + pid_t child_pid; + unsigned res_count; + + search_dn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + assert_non_null(search_dn); + + basedn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(basedn); + + /* + * The search just needs to call DONE, we don't care about the + * contents of the search for this test + */ + ret = ldb_build_search_req(&req, + search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + basedn, + LDB_SCOPE_SUBTREE, + "(&(!(filterAttr=*))" + "(cn=test_search_cn))", + NULL, + NULL, + NULL, + test_ldb_modify_before_ldb_wait_callback1, + NULL); + assert_int_equal(ret, 0); + ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_message *msg; + struct ldb_message_element *el; + TALLOC_FREE(search_test_ctx->ldb_test_ctx->ldb); + TALLOC_FREE(search_test_ctx->ldb_test_ctx->ev); + close(pipes[0]); + search_test_ctx->ldb_test_ctx->ev = tevent_context_init(search_test_ctx->ldb_test_ctx); + if (search_test_ctx->ldb_test_ctx->ev == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + search_test_ctx->ldb_test_ctx->ldb = ldb_init(search_test_ctx->ldb_test_ctx, + search_test_ctx->ldb_test_ctx->ev); + if (search_test_ctx->ldb_test_ctx->ldb == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_connect(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx->ldb_test_ctx->dbpath, 0, NULL); + if (ret != LDB_SUCCESS) { + exit(ret); + } + + tmp_ctx = talloc_new(search_test_ctx->ldb_test_ctx); + if (tmp_ctx == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + /* + * We must re-create this DN from a string to ensure + * it does not reference the now-gone LDB context of + * the parent + */ + msg->dn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + + if (msg->dn == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_msg_add_string(msg, "filterAttr", "TRUE"); + if (ret != 0) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + el = ldb_msg_find_element(msg, "filterAttr"); + if (el == NULL) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + el->flags = LDB_FLAG_MOD_REPLACE; + + ret = ldb_transaction_start(search_test_ctx->ldb_test_ctx->ldb); + if (ret != 0) { + exit(ret); + } + + if (write(pipes[1], "GO", 2) != 2) { + exit(LDB_ERR_OPERATIONS_ERROR); + } + + ret = ldb_modify(search_test_ctx->ldb_test_ctx->ldb, msg); + if (ret != 0) { + exit(ret); + } + + ret = ldb_transaction_commit(search_test_ctx->ldb_test_ctx->ldb); + exit(ret); + } + close(pipes[1]); + + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + sleep(3); + + /* + * If writes are not blocked until after the (never called) ldb_wait(), we + * will be able to successfully search for this modification + * here + */ + + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, search_test_ctx, + &res2, search_dn, LDB_SCOPE_BASE, NULL, + "filterAttr=TRUE"); + + /* + * We avoid making assertions before TALLOC_FREE()ing the request, + * lest the assert fail and mess with the clean-up because we still + * have locks. + */ + res_count = res2->count; + TALLOC_FREE(req); + + /* We should not have got the result */ + assert_int_equal(res_count, 0); + assert_int_equal(ret, 0); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + + /* + * If writes are blocked until after the search request was freed, we + * will be able to successfully search for this modification + * now + */ + + search_dn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + + ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + &res2, search_dn, LDB_SCOPE_BASE, NULL, + "filterAttr=TRUE"); + assert_int_equal(ret, 0); + + /* We got the result */ + assert_int_equal(res2->count, 1); +} + +/* + * This test is also complex. + * The purpose is to test if a modify can occur during an ldb_search() + * This would be a failure if if in process + * (1) and (2): + * - (1) ltdb_search() starts and calls back for one entry + * - (2) one of the entries to be matched is modified + * - (1) the indexed search tries to return the modified entry, but + * it is no longer found, either: + * - despite it still matching (dn changed) + * - it no longer matching (attrs changed) + * + * We also try un-indexed to show that the behaviour differs on this + * point, which it should not (an index should only impact search + * speed). + */ + +/* + * This purpose of this callback is to trigger a write in the callback + * so as to change in in-memory index code while looping over the + * index result. + */ + +static int test_ldb_callback_modify_during_search_callback1(struct ldb_request *req, + struct ldb_reply *ares) +{ + int ret; + struct modify_during_search_test_ctx *ctx = req->context; + struct ldb_dn *dn = NULL, *new_dn = NULL; + TALLOC_CTX *tmp_ctx = talloc_new(ctx->test_ctx); + struct ldb_message *msg = NULL; + + assert_non_null(tmp_ctx); + + switch (ares->type) { + case LDB_REPLY_ENTRY: + { + const struct ldb_val *cn_val + = ldb_dn_get_component_val(ares->message->dn, 0); + const char *cn = (char *)cn_val->data; + ctx->res_count++; + if (strcmp(cn, "test_search_cn") == 0) { + ctx->got_cn = true; + } else if (strcmp(cn, "test_search_2_cn") == 0) { + ctx->got_2_cn = true; + } + if (ctx->res_count == 2) { + return LDB_SUCCESS; + } + break; + } + case LDB_REPLY_REFERRAL: + return LDB_SUCCESS; + + case LDB_REPLY_DONE: + return ldb_request_done(req, LDB_SUCCESS); + } + + if (ctx->rename) { + if (ctx->got_2_cn) { + /* Modify this one */ + dn = ldb_dn_new_fmt(tmp_ctx, + ctx->test_ctx->ldb, + "cn=test_search_2_cn,%s", + ldb_dn_get_linearized(ctx->basedn)); + } else { + dn = ldb_dn_new_fmt(tmp_ctx, + ctx->test_ctx->ldb, + "cn=test_search_cn,%s", + ldb_dn_get_linearized(ctx->basedn)); + } + assert_non_null(dn); + + new_dn = ldb_dn_new_fmt(tmp_ctx, + ctx->test_ctx->ldb, + "cn=test_search_cn_renamed," + "dc=not_search_test_entry"); + assert_non_null(new_dn); + + ret = ldb_rename(ctx->test_ctx->ldb, dn, new_dn); + assert_int_equal(ret, 0); + + } else { + if (ctx->got_2_cn) { + /* Delete this one */ + dn = ldb_dn_new_fmt(tmp_ctx, + ctx->test_ctx->ldb, + "cn=test_search_2_cn,%s", + ldb_dn_get_linearized(ctx->basedn)); + } else { + dn = ldb_dn_new_fmt(tmp_ctx, + ctx->test_ctx->ldb, + "cn=test_search_cn,%s", + ldb_dn_get_linearized(ctx->basedn)); + } + assert_non_null(dn); + + ret = ldb_delete(ctx->test_ctx->ldb, dn); + assert_int_equal(ret, 0); + } + + /* + * Now fill in the position we just removed from the + * index to ensure we fail the test (otherwise we just read + * past the end of the array and find the value we wanted to + * skip) + */ + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + /* We deliberatly use ou= not cn= here */ + msg->dn = ldb_dn_new_fmt(msg, + ctx->test_ctx->ldb, + "ou=test_search_cn_extra,%s", + ldb_dn_get_linearized(ctx->basedn)); + + ret = ldb_msg_add_string(msg, + "objectUUID", + "0123456789abcde3"); + + ret = ldb_add(ctx->test_ctx->ldb, + msg); + assert_int_equal(ret, LDB_SUCCESS); + + TALLOC_FREE(tmp_ctx); + return LDB_SUCCESS; +} + +static void test_ldb_callback_modify_during_search(void **state, bool add_index, + bool rename) +{ + struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state, + struct search_test_ctx); + struct modify_during_search_test_ctx + ctx = + { .res_count = 0, + .test_ctx = search_test_ctx->ldb_test_ctx, + .rename = rename + }; + + int ret; + struct ldb_request *req; + + ret = ldb_transaction_start(search_test_ctx->ldb_test_ctx->ldb); + assert_int_equal(ret, 0); + + if (add_index) { + struct ldb_message *msg; + struct ldb_dn *indexlist = ldb_dn_new(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "@INDEXLIST"); + assert_non_null(indexlist); + + msg = ldb_msg_new(search_test_ctx); + assert_non_null(msg); + + msg->dn = indexlist; + + ret = ldb_msg_add_string(msg, "@IDXONE", "1"); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_add_string(msg, "@IDXATTR", "cn"); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb, + msg); + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + msg->elements[0].flags = LDB_FLAG_MOD_ADD; + msg->elements[1].flags = LDB_FLAG_MOD_ADD; + ret = ldb_modify(search_test_ctx->ldb_test_ctx->ldb, + msg); + } + assert_int_equal(ret, LDB_SUCCESS); + + /* + * Now bring the IDXONE index into memory by modifying + * it. This exposes an issue in ldb_tdb + */ + msg = ldb_msg_new(search_test_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "cn=test_search_cn_extra,%s", + search_test_ctx->base_dn); + + ret = ldb_msg_add_string(msg, + "objectUUID", + "0123456789abcde2"); + + ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb, + msg); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_delete(search_test_ctx->ldb_test_ctx->ldb, + msg->dn); + assert_int_equal(ret, LDB_SUCCESS); + } + + tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev); + + ctx.basedn + = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "%s", + search_test_ctx->base_dn); + assert_non_null(ctx.basedn); + + + /* + * This search must be over multiple items, and should include + * the new name after a rename, to show that it would match + * both before and after that modify + * + * This needs to be a search that isn't matched by an index so + * that we just use the one-level index. + */ + ret = ldb_build_search_req(&req, + search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + ctx.basedn, + LDB_SCOPE_ONELEVEL, + "(cn=*)", + NULL, + NULL, + &ctx, + test_ldb_callback_modify_during_search_callback1, + NULL); + assert_int_equal(ret, 0); + + ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + assert_int_equal(ret, 0); + + ret = ldb_transaction_commit(search_test_ctx->ldb_test_ctx->ldb); + assert_int_equal(ret, 0); + + assert_int_equal(ctx.res_count, 2); + assert_int_equal(ctx.got_cn, true); + assert_int_equal(ctx.got_2_cn, true); +} + +static void test_ldb_callback_delete_during_indexed_search(void **state) +{ + test_ldb_callback_modify_during_search(state, true, false); +} + +static void test_ldb_callback_delete_during_unindexed_search(void **state) +{ + test_ldb_callback_modify_during_search(state, false, false); +} + +static void test_ldb_callback_rename_during_indexed_search(void **state) +{ + test_ldb_callback_modify_during_search(state, true, true); +} + +static void test_ldb_callback_rename_during_unindexed_search(void **state) +{ + test_ldb_callback_modify_during_search(state, false, true); +} + +static int ldb_case_test_setup(void **state) +{ + int ret; + struct ldb_ldif *ldif; + struct ldbtest_ctx *ldb_test_ctx; + const char *attrs_ldif = \ + "dn: @ATTRIBUTES\n" + "cn: CASE_INSENSITIVE\n" + "\n"; + struct keyval kvs[] = { + { "cn", "CaseInsensitiveValue" }, + { "uid", "CaseSensitiveValue" }, + { "objectUUID", "0123456789abcdef" }, + { NULL, NULL }, + }; + + + ldbtest_setup((void **) &ldb_test_ctx); + + while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &attrs_ldif))) { + ret = ldb_add(ldb_test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + + ldb_test_add_data(ldb_test_ctx, + ldb_test_ctx, + "cn=CaseInsensitiveValue", + kvs); + + *state = ldb_test_ctx; + return 0; +} + +static int ldb_case_test_teardown(void **state) +{ + int ret; + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + + struct ldb_dn *del_dn; + + del_dn = ldb_dn_new_fmt(ldb_test_ctx, + ldb_test_ctx->ldb, + "@ATTRIBUTES"); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + assert_int_equal(ret, LDB_SUCCESS); + + assert_dn_doesnt_exist(ldb_test_ctx, + "@ATTRIBUTES"); + + ldb_test_remove_data(ldb_test_ctx, ldb_test_ctx, + "cn=CaseInsensitiveValue"); + + ldbtest_teardown((void **) &ldb_test_ctx); + return 0; +} + +static void test_ldb_attrs_case_insensitive(void **state) +{ + int cnt; + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + + /* cn matches exact case */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=CaseInsensitiveValue"); + assert_int_equal(cnt, 1); + + /* cn matches lower case */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 1); + + /* uid matches exact case */ + cnt = sub_search_count(ldb_test_ctx, "", "uid=CaseSensitiveValue"); + assert_int_equal(cnt, 1); + + /* uid does not match lower case */ + cnt = sub_search_count(ldb_test_ctx, "", "uid=casesensitivevalue"); + assert_int_equal(cnt, 0); +} + +static struct ldb_schema_attribute cn_attr_1; +static struct ldb_schema_attribute cn_attr_2; +static struct ldb_schema_attribute default_attr; + +/* + override the name to attribute handler function + */ +static const struct ldb_schema_attribute *ldb_test_attribute_handler_override(struct ldb_context *ldb, + void *private_data, + const char *name) +{ + if (private_data != NULL && ldb_attr_cmp(name, "cn") == 0) { + return &cn_attr_1; + } else if (private_data == NULL && ldb_attr_cmp(name, "cn") == 0) { + return &cn_attr_2; + } else if (ldb_attr_cmp(name, "uid") == 0) { + return &cn_attr_2; + } + return &default_attr; +} + +static void test_ldb_attrs_case_handler(void **state) +{ + int cnt; + int ret; + const struct ldb_schema_syntax *syntax; + + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_context *ldb = ldb_test_ctx->ldb; + + /* cn matches lower case */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 1); + + syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING); + assert_non_null(syntax); + + ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb, + "*", 0, + syntax, &default_attr); + assert_int_equal(ret, LDB_SUCCESS); + + syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING); + assert_non_null(syntax); + + ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb, + "cn", 0, + syntax, &cn_attr_1); + assert_int_equal(ret, LDB_SUCCESS); + + /* + * Set an attribute handler, which will fail to match as we + * force case sensitive + */ + ldb_schema_attribute_set_override_handler(ldb, + ldb_test_attribute_handler_override, + (void *)1); + + /* cn does not matche lower case */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 0); + + syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_DIRECTORY_STRING); + assert_non_null(syntax); + + ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb, + "cn", 0, + syntax, &cn_attr_2); + assert_int_equal(ret, LDB_SUCCESS); + + /* + * Set an attribute handler, which will match as we + * force case insensitive + */ + ldb_schema_attribute_set_override_handler(ldb, + ldb_test_attribute_handler_override, + NULL); + + /* cn matches lower case */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 1); + +} + + +static void test_ldb_attrs_index_handler(void **state) +{ + int cnt; + int ret; + const struct ldb_schema_syntax *syntax; + struct ldb_ldif *ldif; + + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXATTR: cn\n" + "\n"; + + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_context *ldb = ldb_test_ctx->ldb; + + /* cn matches lower case */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 1); + + syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING); + assert_non_null(syntax); + + ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb, + "cn", 0, + syntax, &cn_attr_1); + assert_int_equal(ret, LDB_SUCCESS); + + syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_DIRECTORY_STRING); + assert_non_null(syntax); + + ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb, + "cn", LDB_ATTR_FLAG_INDEXED, + syntax, &cn_attr_2); + assert_int_equal(ret, LDB_SUCCESS); + + syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING); + assert_non_null(syntax); + + ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb, + "", 0, + syntax, &default_attr); + assert_int_equal(ret, LDB_SUCCESS); + + /* + * Set an attribute handler + */ + ldb_schema_attribute_set_override_handler(ldb, + ldb_test_attribute_handler_override, + NULL); + + /* cn matches lower case */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 1); + + /* Add the index (actually any modify will do) */ + while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) { + ret = ldb_add(ldb_test_ctx->ldb, ldif->msg); + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + ldif->msg->elements[0].flags = LDB_FLAG_MOD_ADD; + ret = ldb_modify(ldb_test_ctx->ldb, + ldif->msg); + } + assert_int_equal(ret, LDB_SUCCESS); + } + + ldb_schema_set_override_indexlist(ldb, false); + + /* cn does match as there is an index now */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 1); + + /* + * Set an attribute handler, which will later fail to match as we + * didn't re-index the DB + */ + ldb_schema_attribute_set_override_handler(ldb, + ldb_test_attribute_handler_override, + (void *)1); + + /* + * cn does not match as we changed the case sensitivity, but + * didn't re-index + * + * This shows that the override is in control + */ + cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue"); + assert_int_equal(cnt, 0); + +} + +static int ldb_case_attrs_index_test_teardown(void **state) +{ + int ret; + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_dn *del_dn; + + del_dn = ldb_dn_new_fmt(ldb_test_ctx, + ldb_test_ctx->ldb, + "@INDEXLIST"); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + assert_int_equal(ret, LDB_SUCCESS); + } + + assert_dn_doesnt_exist(ldb_test_ctx, + "@INDEXLIST"); + + ldb_case_test_teardown(state); + return 0; +} + + +struct rename_test_ctx { + struct ldbtest_ctx *ldb_test_ctx; + + struct ldb_dn *basedn; + const char *str_basedn; + + const char *teardown_dn; +}; + +static int ldb_rename_test_setup(void **state) +{ + struct ldbtest_ctx *ldb_test_ctx; + struct rename_test_ctx *rename_test_ctx; + const char *strdn = "dc=rename_test_entry_from"; + + ldbtest_setup((void **) &ldb_test_ctx); + + rename_test_ctx = talloc(ldb_test_ctx, struct rename_test_ctx); + assert_non_null(rename_test_ctx); + rename_test_ctx->ldb_test_ctx = ldb_test_ctx; + assert_non_null(rename_test_ctx->ldb_test_ctx); + + rename_test_ctx->basedn = ldb_dn_new_fmt(rename_test_ctx, + rename_test_ctx->ldb_test_ctx->ldb, + "%s", strdn); + assert_non_null(rename_test_ctx->basedn); + + rename_test_ctx->str_basedn = strdn; + rename_test_ctx->teardown_dn = strdn; + + add_dn_with_cn(ldb_test_ctx, + rename_test_ctx->basedn, + "test_rename_cn_val", + "0123456789abcde0"); + + *state = rename_test_ctx; + return 0; +} + +static int ldb_rename_test_teardown(void **state) +{ + int ret; + struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort(*state, + struct rename_test_ctx); + struct ldbtest_ctx *ldb_test_ctx; + struct ldb_dn *del_dn; + + ldb_test_ctx = rename_test_ctx->ldb_test_ctx; + + del_dn = ldb_dn_new_fmt(rename_test_ctx, + rename_test_ctx->ldb_test_ctx->ldb, + "%s", rename_test_ctx->teardown_dn); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + assert_int_equal(ret, LDB_SUCCESS); + + assert_dn_doesnt_exist(ldb_test_ctx, + rename_test_ctx->teardown_dn); + + ldbtest_teardown((void **) &ldb_test_ctx); + return 0; +} + +static void test_ldb_rename(void **state) +{ + struct rename_test_ctx *rename_test_ctx = + talloc_get_type_abort(*state, struct rename_test_ctx); + int ret; + const char *str_new_dn = "dc=rename_test_entry_to"; + struct ldb_dn *new_dn; + + new_dn = ldb_dn_new_fmt(rename_test_ctx, + rename_test_ctx->ldb_test_ctx->ldb, + "%s", str_new_dn); + assert_non_null(new_dn); + + ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb, + rename_test_ctx->basedn, + new_dn); + assert_int_equal(ret, LDB_SUCCESS); + + assert_dn_exists(rename_test_ctx->ldb_test_ctx, str_new_dn); + assert_dn_doesnt_exist(rename_test_ctx->ldb_test_ctx, + rename_test_ctx->str_basedn); + rename_test_ctx->teardown_dn = str_new_dn; + + /* FIXME - test the values which didn't change */ +} + +static void test_ldb_rename_from_doesnt_exist(void **state) +{ + struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort( + *state, + struct rename_test_ctx); + int ret; + const char *str_new_dn = "dc=rename_test_entry_to"; + const char *str_bad_old_dn = "dc=rename_test_no_such_entry"; + struct ldb_dn *new_dn; + struct ldb_dn *bad_old_dn; + + new_dn = ldb_dn_new_fmt(rename_test_ctx, + rename_test_ctx->ldb_test_ctx->ldb, + "%s", str_new_dn); + assert_non_null(new_dn); + + bad_old_dn = ldb_dn_new_fmt(rename_test_ctx, + rename_test_ctx->ldb_test_ctx->ldb, + "%s", str_bad_old_dn); + assert_non_null(bad_old_dn); + + assert_dn_doesnt_exist(rename_test_ctx->ldb_test_ctx, + str_bad_old_dn); + + ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb, + bad_old_dn, new_dn); + assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT); + + assert_dn_doesnt_exist(rename_test_ctx->ldb_test_ctx, + str_new_dn); +} + +static void test_ldb_rename_to_exists(void **state) +{ + struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort( + *state, + struct rename_test_ctx); + int ret; + const char *str_new_dn = "dc=rename_test_already_exists"; + struct ldb_dn *new_dn; + + new_dn = ldb_dn_new_fmt(rename_test_ctx, + rename_test_ctx->ldb_test_ctx->ldb, + "%s", str_new_dn); + assert_non_null(new_dn); + + add_dn_with_cn(rename_test_ctx->ldb_test_ctx, + new_dn, + "test_rename_cn_val", + "0123456789abcde1"); + + ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb, + rename_test_ctx->basedn, + new_dn); + assert_int_equal(ret, LDB_ERR_ENTRY_ALREADY_EXISTS); + + /* Old object must still exist */ + assert_dn_exists(rename_test_ctx->ldb_test_ctx, + rename_test_ctx->str_basedn); + + ret = ldb_delete(rename_test_ctx->ldb_test_ctx->ldb, + new_dn); + assert_int_equal(ret, LDB_SUCCESS); + + assert_dn_exists(rename_test_ctx->ldb_test_ctx, + rename_test_ctx->teardown_dn); +} + +static void test_ldb_rename_self(void **state) +{ + struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort( + *state, + struct rename_test_ctx); + int ret; + + /* Oddly enough, this is a success in ldb.. */ + ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb, + rename_test_ctx->basedn, + rename_test_ctx->basedn); + assert_int_equal(ret, LDB_SUCCESS); + + /* Old object must still exist */ + assert_dn_exists(rename_test_ctx->ldb_test_ctx, + rename_test_ctx->str_basedn); +} + +static void test_ldb_rename_dn_case_change(void **state) +{ + struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort( + *state, + struct rename_test_ctx); + int ret; + char *str_new_dn; + struct ldb_dn *new_dn; + unsigned i; + + str_new_dn = talloc_strdup(rename_test_ctx, rename_test_ctx->str_basedn); + assert_non_null(str_new_dn); + for (i = 0; str_new_dn[i]; i++) { + str_new_dn[i] = toupper(str_new_dn[i]); + } + + new_dn = ldb_dn_new_fmt(rename_test_ctx, + rename_test_ctx->ldb_test_ctx->ldb, + "%s", str_new_dn); + assert_non_null(new_dn); + + ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb, + rename_test_ctx->basedn, + new_dn); + assert_int_equal(ret, LDB_SUCCESS); + + /* DNs are case insensitive, so both searches will match */ + assert_dn_exists(rename_test_ctx->ldb_test_ctx, str_new_dn); + assert_dn_exists(rename_test_ctx->ldb_test_ctx, + rename_test_ctx->str_basedn); + /* FIXME - test the values didn't change */ +} + +static int ldb_read_only_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + ldbtest_setup((void **) &test_ctx); + + *state = test_ctx; + return 0; +} + +static int ldb_read_only_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + ldbtest_teardown((void **) &test_ctx); + return 0; +} + +static void test_read_only(void **state) +{ + struct ldb_context *ro_ldb = NULL; + struct ldb_context *rw_ldb = NULL; + int ret; + TALLOC_CTX *tmp_ctx = NULL; + + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + /* + * Close the ldb context freeing it this will ensure it exists on + * disk and can be opened in read only mode + */ + TALLOC_FREE(test_ctx->ldb); + + /* + * Open the database in read only and read write mode, + * ensure it's opend in read only mode first + */ + ro_ldb = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ro_ldb, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + rw_ldb = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(rw_ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + + /* + * Set up a context for the temporary variables + */ + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + /* + * Ensure that we can search the read write database + */ + { + struct ldb_result *result = NULL; + struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, rw_ldb, + "dc=test"); + assert_non_null(dn); + + ret = ldb_search(rw_ldb, tmp_ctx, &result, dn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, LDB_SUCCESS); + TALLOC_FREE(result); + TALLOC_FREE(dn); + } + + /* + * Ensure that we can search the read only database + */ + { + struct ldb_result *result = NULL; + struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, ro_ldb, + "dc=test"); + assert_non_null(dn); + + ret = ldb_search(ro_ldb, tmp_ctx, &result, dn, + LDB_SCOPE_BASE, NULL, NULL); + assert_int_equal(ret, LDB_SUCCESS); + TALLOC_FREE(result); + TALLOC_FREE(dn); + } + /* + * Ensure that a write to the read only database fails + */ + { + struct ldb_message *msg = NULL; + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, ro_ldb, "dc=test"); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", + "0123456789abcde1"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(ro_ldb, msg); + assert_int_equal(ret, LDB_ERR_UNWILLING_TO_PERFORM); + TALLOC_FREE(msg); + } + + /* + * Ensure that a write to the read write database succeeds + */ + { + struct ldb_message *msg = NULL; + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, rw_ldb, "dc=test"); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_cn_val"); + assert_int_equal(ret, 0); + + ret = ldb_msg_add_string(msg, "objectUUID", + "0123456789abcde2"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(rw_ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + TALLOC_FREE(msg); + } + + /* + * Ensure that a delete from a read only database fails + */ + { + struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, ro_ldb, "dc=test"); + assert_non_null(dn); + + ret = ldb_delete(ro_ldb, dn); + assert_int_equal(ret, LDB_ERR_UNWILLING_TO_PERFORM); + TALLOC_FREE(dn); + } + + + /* + * Ensure that a delete from a read write succeeds + */ + { + struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, rw_ldb, "dc=test"); + assert_non_null(dn); + + ret = ldb_delete(rw_ldb, dn); + assert_int_equal(ret, LDB_SUCCESS); + TALLOC_FREE(dn); + } + TALLOC_FREE(tmp_ctx); +} + +static bool unique_values = false; + +static int unique_index_test_module_add( + struct ldb_module *module, + struct ldb_request *req) +{ + if (unique_values) { + struct ldb_message *msg = discard_const(req->op.add.message); + struct ldb_message_element *el = NULL; + el = ldb_msg_find_element(msg, "cn"); + if (el != NULL) { + el->flags |= LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX; + } + } + + return ldb_next_request(module, req); +} + +static int unique_index_test_module_init(struct ldb_module *module) +{ + return ldb_next_init(module); +} + +static const struct ldb_module_ops ldb_unique_index_test_module_ops = { + .name = "unique_index_test", + .init_context = unique_index_test_module_init, + .add = unique_index_test_module_add, +}; + +static int ldb_unique_index_test_setup(void **state) +{ + int ret; + struct ldb_ldif *ldif; + struct ldbtest_ctx *ldb_test_ctx; + const char *attrs_ldif = \ + "dn: @ATTRIBUTES\n" + "cn: UNIQUE_INDEX\n" + "\n"; + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXATTR: cn\n" +#ifdef GUID_IDX + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" +#endif + "\n"; + const char *options[] = {"modules:unique_index_test", NULL}; + + + ret = ldb_register_module(&ldb_unique_index_test_module_ops); + assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_ENTRY_ALREADY_EXISTS); + ldbtest_noconn_setup((void **) &ldb_test_ctx); + + + ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, options); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &attrs_ldif))) { + ret = ldb_add(ldb_test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + + while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) { + ret = ldb_add(ldb_test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + + unique_values = true; + + *state = ldb_test_ctx; + return 0; +} + +static int ldb_unique_index_test_teardown(void **state) +{ + int ret; + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_dn *del_dn; + + del_dn = ldb_dn_new_fmt(ldb_test_ctx, + ldb_test_ctx->ldb, + "@INDEXLIST"); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + assert_int_equal(ret, LDB_SUCCESS); + } + + assert_dn_doesnt_exist(ldb_test_ctx, + "@INDEXLIST"); + + TALLOC_FREE(del_dn); + + del_dn = ldb_dn_new_fmt(ldb_test_ctx, + ldb_test_ctx->ldb, + "@ATTRIBUTES"); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + assert_int_equal(ret, LDB_SUCCESS); + } + + assert_dn_doesnt_exist(ldb_test_ctx, + "@ATTRIBUTES"); + + ldbtest_teardown((void **) &ldb_test_ctx); + return 0; +} + + +static void test_ldb_add_unique_value_to_unique_index(void **state) +{ + int ret; + struct ldb_message *msg; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg = ldb_msg_new(tmp_ctx); + assert_non_null(msg); + + msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=test"); + assert_non_null(msg->dn); + + ret = ldb_msg_add_string(msg, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg, "objectUUID", + "0123456789abcde1"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(test_ctx->ldb, msg); + assert_int_equal(ret, LDB_SUCCESS); + + talloc_free(tmp_ctx); +} + +static int ldb_non_unique_index_test_setup(void **state) +{ + int ret; + struct ldb_ldif *ldif; + struct ldbtest_ctx *ldb_test_ctx; + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXATTR: cn\n" +#ifdef GUID_IDX + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" +#endif + "\n"; + const char *options[] = {"modules:unique_index_test", NULL}; + + + ret = ldb_register_module(&ldb_unique_index_test_module_ops); + assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_ENTRY_ALREADY_EXISTS); + ldbtest_noconn_setup((void **) &ldb_test_ctx); + + + ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, options); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) { + ret = ldb_add(ldb_test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + + unique_values = true; + + *state = ldb_test_ctx; + return 0; +} + +static int ldb_non_unique_index_test_teardown(void **state) +{ + int ret; + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_dn *del_dn; + + del_dn = ldb_dn_new_fmt(ldb_test_ctx, + ldb_test_ctx->ldb, + "@INDEXLIST"); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + assert_int_equal(ret, LDB_SUCCESS); + } + + assert_dn_doesnt_exist(ldb_test_ctx, + "@INDEXLIST"); + + TALLOC_FREE(del_dn); + + ldbtest_teardown((void **) &ldb_test_ctx); + return 0; +} + +static void test_ldb_add_duplicate_value_to_unique_index(void **state) +{ + int ret; + struct ldb_message *msg01; + struct ldb_message *msg02; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg01 = ldb_msg_new(tmp_ctx); + assert_non_null(msg01); + + msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01"); + assert_non_null(msg01->dn); + + ret = ldb_msg_add_string(msg01, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg01, "objectUUID", + "0123456789abcde1"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(test_ctx->ldb, msg01); + assert_int_equal(ret, LDB_SUCCESS); + + msg02 = ldb_msg_new(tmp_ctx); + assert_non_null(msg02); + + msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02"); + assert_non_null(msg02->dn); + + ret = ldb_msg_add_string(msg02, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg02, "objectUUID", + "0123456789abcde2"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(test_ctx->ldb, msg02); + assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION); + talloc_free(tmp_ctx); +} + +static void test_ldb_add_to_index_duplicates_allowed(void **state) +{ + int ret; + struct ldb_message *msg01; + struct ldb_message *msg02; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + + unique_values = false; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + + msg01 = ldb_msg_new(tmp_ctx); + assert_non_null(msg01); + + msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01"); + assert_non_null(msg01->dn); + + ret = ldb_msg_add_string(msg01, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg01, "objectUUID", + "0123456789abcde1"); + + ret = ldb_add(test_ctx->ldb, msg01); + assert_int_equal(ret, LDB_SUCCESS); + + msg02 = ldb_msg_new(tmp_ctx); + assert_non_null(msg02); + + msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02"); + assert_non_null(msg02->dn); + + ret = ldb_msg_add_string(msg02, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg02, "objectUUID", + "0123456789abcde2"); + + ret = ldb_add(test_ctx->ldb, msg02); + assert_int_equal(ret, LDB_SUCCESS); + talloc_free(tmp_ctx); +} + +static void test_ldb_add_to_index_unique_values_required(void **state) +{ + int ret; + struct ldb_message *msg01; + struct ldb_message *msg02; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + + unique_values = true; + + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + + msg01 = ldb_msg_new(tmp_ctx); + assert_non_null(msg01); + + msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01"); + assert_non_null(msg01->dn); + + ret = ldb_msg_add_string(msg01, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg01, "objectUUID", + "0123456789abcde1"); + + ret = ldb_add(test_ctx->ldb, msg01); + assert_int_equal(ret, LDB_SUCCESS); + + msg02 = ldb_msg_new(tmp_ctx); + assert_non_null(msg02); + + msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02"); + assert_non_null(msg02->dn); + + ret = ldb_msg_add_string(msg02, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg02, "objectUUID", + "0123456789abcde2"); + + ret = ldb_add(test_ctx->ldb, msg02); + assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION); + talloc_free(tmp_ctx); +} + +static void ldb_debug_string(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) +{ + + if (level <= LDB_DEBUG_WARNING) { + *((char **)context) = talloc_vasprintf(NULL, fmt, ap); + } +} + +static void test_ldb_unique_index_duplicate_logging(void **state) +{ + int ret; + struct ldb_message *msg01; + struct ldb_message *msg02; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + char *debug_string = NULL; + char *p = NULL; + + /* The GUID mode is not compatible with this test */ +#ifdef GUID_IDX + return; +#endif + + ldb_set_debug(test_ctx->ldb, ldb_debug_string, &debug_string); + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg01 = ldb_msg_new(tmp_ctx); + assert_non_null(msg01); + + msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01"); + assert_non_null(msg01->dn); + + ret = ldb_msg_add_string(msg01, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg01, "objectUUID", + "0123456789abcde1"); + + ret = ldb_add(test_ctx->ldb, msg01); + assert_int_equal(ret, LDB_SUCCESS); + + msg02 = ldb_msg_new(tmp_ctx); + assert_non_null(msg02); + + msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02"); + assert_non_null(msg02->dn); + + ret = ldb_msg_add_string(msg02, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg02, "objectUUID", + "0123456789abcde2"); + + ret = ldb_add(test_ctx->ldb, msg02); + assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION); + + assert_non_null(debug_string); + p = strstr( + debug_string, + "unique index violation on cn " + "in dc=test02, conflicts with dc=test01 in " + "@INDEX:CN:test_unique_index"); + assert_non_null(p); + TALLOC_FREE(debug_string); + talloc_free(tmp_ctx); +} + +static void test_ldb_duplicate_dn_logging(void **state) +{ + int ret; + struct ldb_message *msg01; + struct ldb_message *msg02; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + char *debug_string = NULL; + + /* The GUID mode is not compatible with this test */ +#ifdef GUID_IDX + return; +#endif + + ldb_set_debug(test_ctx->ldb, ldb_debug_string, &debug_string); + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg01 = ldb_msg_new(tmp_ctx); + assert_non_null(msg01); + + msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01"); + assert_non_null(msg01->dn); + + ret = ldb_msg_add_string(msg01, "cn", "test_unique_index01"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg01, "objectUUID", + "0123456789abcde1"); + + ret = ldb_add(test_ctx->ldb, msg01); + assert_int_equal(ret, LDB_SUCCESS); + + msg02 = ldb_msg_new(tmp_ctx); + assert_non_null(msg02); + + msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test01"); + assert_non_null(msg02->dn); + + ret = ldb_msg_add_string(msg02, "cn", "test_unique_index02"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg02, "objectUUID", + "0123456789abcde2"); + + ret = ldb_add(test_ctx->ldb, msg02); + assert_int_equal(ret, LDB_ERR_ENTRY_ALREADY_EXISTS); + + assert_null(debug_string); + talloc_free(tmp_ctx); +} + +static int ldb_guid_index_test_setup(void **state) +{ + int ret; + struct ldb_ldif *ldif; + struct ldbtest_ctx *ldb_test_ctx; + const char *attrs_ldif = \ + "dn: @ATTRIBUTES\n" + "cn: UNIQUE_INDEX\n" + "\n"; + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXATTR: cn\n" + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" + "\n"; + + ldbtest_noconn_setup((void **) &ldb_test_ctx); + + + ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &attrs_ldif))) { + ret = ldb_add(ldb_test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + + while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) { + ret = ldb_add(ldb_test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + + *state = ldb_test_ctx; + return 0; +} + +static int ldb_guid_index_test_teardown(void **state) +{ + int ret; + struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + struct ldb_dn *del_dn; + + del_dn = ldb_dn_new_fmt(ldb_test_ctx, + ldb_test_ctx->ldb, + "@INDEXLIST"); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + assert_int_equal(ret, LDB_SUCCESS); + } + + assert_dn_doesnt_exist(ldb_test_ctx, + "@INDEXLIST"); + + TALLOC_FREE(del_dn); + + del_dn = ldb_dn_new_fmt(ldb_test_ctx, + ldb_test_ctx->ldb, + "@ATTRIBUTES"); + assert_non_null(del_dn); + + ret = ldb_delete(ldb_test_ctx->ldb, del_dn); + if (ret != LDB_ERR_NO_SUCH_OBJECT) { + assert_int_equal(ret, LDB_SUCCESS); + } + + assert_dn_doesnt_exist(ldb_test_ctx, + "@ATTRIBUTES"); + + ldbtest_teardown((void **) &ldb_test_ctx); + return 0; +} + + +static void test_ldb_unique_index_duplicate_with_guid(void **state) +{ + int ret; + struct ldb_message *msg01; + struct ldb_message *msg02; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + char *debug_string = NULL; + char *p = NULL; + + ldb_set_debug(test_ctx->ldb, ldb_debug_string, &debug_string); + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg01 = ldb_msg_new(tmp_ctx); + assert_non_null(msg01); + + msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01"); + assert_non_null(msg01->dn); + + ret = ldb_msg_add_string(msg01, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg01, "objectUUID", "0123456789abcdef"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(test_ctx->ldb, msg01); + assert_int_equal(ret, LDB_SUCCESS); + + msg02 = ldb_msg_new(tmp_ctx); + assert_non_null(msg02); + + msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02"); + assert_non_null(msg02->dn); + + ret = ldb_msg_add_string(msg02, "cn", "test_unique_index"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg02, "objectUUID", "0123456789abcde0"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(test_ctx->ldb, msg02); + assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION); + + assert_non_null(debug_string); + p = strstr( + debug_string, + "unique index violation on cn in dc=test02, conflicts with " + "objectUUID 0123456789abcdef in @INDEX:CN:test_unique_index"); + assert_non_null(p); + TALLOC_FREE(debug_string); + talloc_free(tmp_ctx); + ldb_set_debug(test_ctx->ldb, NULL, NULL); +} + +static void test_ldb_guid_index_duplicate_dn_logging(void **state) +{ + int ret; + struct ldb_message *msg01; + struct ldb_message *msg02; + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + TALLOC_CTX *tmp_ctx; + char *debug_string = NULL; + + ldb_set_debug(test_ctx->ldb, ldb_debug_string, &debug_string); + tmp_ctx = talloc_new(test_ctx); + assert_non_null(tmp_ctx); + + msg01 = ldb_msg_new(tmp_ctx); + assert_non_null(msg01); + + msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01"); + assert_non_null(msg01->dn); + + ret = ldb_msg_add_string(msg01, "cn", "test_unique_index01"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg01, "objectUUID", "0123456789abcdef"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(test_ctx->ldb, msg01); + assert_int_equal(ret, LDB_SUCCESS); + + msg02 = ldb_msg_new(tmp_ctx); + assert_non_null(msg02); + + msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test01"); + assert_non_null(msg02->dn); + + ret = ldb_msg_add_string(msg02, "cn", "test_unique_index02"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_add_string(msg02, "objectUUID", "0123456789abcde1"); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_add(test_ctx->ldb, msg02); + assert_int_equal(ret, LDB_ERR_ENTRY_ALREADY_EXISTS); + + assert_null(debug_string); + talloc_free(tmp_ctx); + ldb_set_debug(test_ctx->ldb, NULL, NULL); +} + +static void test_ldb_talloc_destructor_transaction_cleanup(void **state) +{ + struct ldbtest_ctx *test_ctx = NULL; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + assert_non_null(test_ctx); + + ldb_transaction_start(test_ctx->ldb); + + /* + * Trigger the destructor + */ + TALLOC_FREE(test_ctx->ldb); + + /* + * Now ensure that a new connection can be opened + */ + { + TALLOC_CTX *tctx = talloc_new(test_ctx); + struct ldbtest_ctx *ctx = talloc_zero(tctx, struct ldbtest_ctx); + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + int ret; + + ldbtest_setup((void *)&ctx); + + basedn = ldb_dn_new_fmt(tctx, ctx->ldb, "dc=test"); + assert_non_null(basedn); + + ret = ldb_search(ctx->ldb, + tctx, + &result, + basedn, + LDB_SCOPE_BASE, + NULL, + NULL); + assert_int_equal(ret, 0); + assert_non_null(result); + assert_int_equal(result->count, 0); + + ldbtest_teardown((void *)&ctx); + } +} + +#ifdef TEST_LMDB +static int test_ldb_multiple_connections_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + int ret; + int pipes[2]; + char buf[2]; + int pid, child_pid; + int wstatus; + + switch (ares->type) { + case LDB_REPLY_ENTRY: + break; + + case LDB_REPLY_REFERRAL: + return LDB_SUCCESS; + + case LDB_REPLY_DONE: + return ldb_request_done(req, LDB_SUCCESS); + } + + { + /* + * We open a new ldb on an ldb that is already open and + * then close it. + * + * If the multiple connection wrapping is correct the + * underlying MDB_env will be left open and we should see + * an active reader in the child we fork next + */ + struct ldb_context *ldb = NULL; + struct tevent_context *ev = NULL; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + ev = tevent_context_init(mem_ctx); + assert_non_null(ev); + + ldb = ldb_init(mem_ctx, ev); + assert_non_null(ldb); + + ret = ldb_connect(ldb, TEST_BE"://apitest.ldb" , 0, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + TALLOC_FREE(ldb); + TALLOC_FREE(mem_ctx); + } + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + struct MDB_env *env = NULL; + struct MDB_envinfo stat; + close(pipes[0]); + + /* + * Check that there are exactly two readers on the MDB file + * backing the ldb. + * + */ + ret = mdb_env_create(&env); + if (ret != 0) { + print_error(__location__ + " mdb_env_create returned (%d)", + ret); + exit(ret); + } + + ret = mdb_env_open(env, + "apitest.ldb", + MDB_NOSUBDIR | MDB_NOTLS, + 0644); + if (ret != 0) { + print_error(__location__ + " mdb_env_open returned (%d)", + ret); + exit(ret); + } + + ret = mdb_env_info(env, &stat); + if (ret != 0) { + print_error(__location__ + " mdb_env_info returned (%d)", + ret); + exit(ret); + } + if (stat.me_numreaders != 2) { + print_error(__location__ + " Incorrect number of readers (%d)", + stat.me_numreaders); + exit(LDB_ERR_CONSTRAINT_VIOLATION); + } + + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + return LDB_SUCCESS; + +} + +static void test_ldb_close_with_multiple_connections(void **state) +{ + struct search_test_ctx *search_test_ctx = NULL; + struct ldb_dn *search_dn = NULL; + struct ldb_request *req = NULL; + int ret = 0; + + search_test_ctx = talloc_get_type_abort(*state, struct search_test_ctx); + assert_non_null(search_test_ctx); + + search_dn = ldb_dn_new_fmt(search_test_ctx, + search_test_ctx->ldb_test_ctx->ldb, + "cn=test_search_cn," + "dc=search_test_entry"); + assert_non_null(search_dn); + + /* + * The search just needs to call DONE, we don't care about the + * contents of the search for this test + */ + ret = ldb_build_search_req(&req, + search_test_ctx->ldb_test_ctx->ldb, + search_test_ctx, + search_dn, + LDB_SCOPE_SUBTREE, + "(&(!(filterAttr=*))" + "(cn=test_search_cn))", + NULL, + NULL, + NULL, + test_ldb_multiple_connections_callback, + NULL); + assert_int_equal(ret, 0); + + ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req); + assert_int_equal(ret, 0); + + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + assert_int_equal(ret, 0); +} + +#endif + +static void test_transaction_start_across_fork(void **state) +{ + struct ldb_context *ldb1 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + int pipes[2]; + char buf[2]; + int wstatus; + pid_t pid, child_pid; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + close(pipes[0]); + ret = ldb_transaction_start(ldb1); + if (ret != LDB_ERR_PROTOCOL_ERROR) { + print_error(__location__": ldb_transaction_start " + "returned (%d) %s\n", + ret, + ldb1->err_string); + exit(LDB_ERR_OTHER); + } + + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); +} + +static void test_transaction_commit_across_fork(void **state) +{ + struct ldb_context *ldb1 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + int pipes[2]; + char buf[2]; + int wstatus; + pid_t pid, child_pid; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + ret = ldb_transaction_start(ldb1); + assert_int_equal(ret, 0); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + close(pipes[0]); + ret = ldb_transaction_commit(ldb1); + + if (ret != LDB_ERR_PROTOCOL_ERROR) { + print_error(__location__": ldb_transaction_commit " + "returned (%d) %s\n", + ret, + ldb1->err_string); + exit(LDB_ERR_OTHER); + } + + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); +} + +static void test_lock_read_across_fork(void **state) +{ + struct ldb_context *ldb1 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + int pipes[2]; + char buf[2]; + int wstatus; + pid_t pid, child_pid; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + + close(pipes[0]); + + basedn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "dc=test"); + assert_non_null(basedn); + + ret = ldb_search(test_ctx->ldb, + test_ctx, + &result, + basedn, + LDB_SCOPE_BASE, + NULL, + NULL); + if (ret != LDB_ERR_PROTOCOL_ERROR) { + print_error(__location__": ldb_search " + "returned (%d) %s\n", + ret, + ldb1->err_string); + exit(LDB_ERR_OTHER); + } + + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); + + { + /* + * Ensure that the search actually succeeds on the opening + * pid + */ + struct ldb_dn *basedn; + struct ldb_result *result = NULL; + + close(pipes[0]); + + basedn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "dc=test"); + assert_non_null(basedn); + + ret = ldb_search(test_ctx->ldb, + test_ctx, + &result, + basedn, + LDB_SCOPE_BASE, + NULL, + NULL); + assert_int_equal(0, ret); + } +} + +static void test_multiple_opens_across_fork(void **state) +{ + struct ldb_context *ldb1 = NULL; + struct ldb_context *ldb2 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + int pipes[2]; + char buf[2]; + int wstatus; + pid_t pid, child_pid; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database again + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb2 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb2, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + struct ldb_context *ldb3 = NULL; + + close(pipes[0]); + ldb3 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb3, test_ctx->dbpath, 0, NULL); + if (ret != 0) { + print_error(__location__": ldb_connect returned (%d)\n", + ret); + exit(ret); + } + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_connect, + ldbtest_noconn_setup, + ldbtest_noconn_teardown), + cmocka_unit_test_setup_teardown(test_ldif_message, + ldbtest_noconn_setup, + ldbtest_noconn_teardown), + cmocka_unit_test_setup_teardown(test_ldif_message_redacted, + ldbtest_noconn_setup, + ldbtest_noconn_teardown), + cmocka_unit_test_setup_teardown(test_ldb_add, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_ldb_search, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_ldb_del, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_ldb_del_noexist, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_ldb_handle, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_ldb_build_search_req, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_transactions, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_nested_transactions, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_add_key, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_extend_key, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_add_key_noval, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_replace_key, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_replace_noexist_key, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_replace_zero_vals, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_replace_noexist_key_zero_vals, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_del_key, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_del_keyval, + ldb_modify_test_setup, + ldb_modify_test_teardown), + cmocka_unit_test_setup_teardown(test_search_match_none, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_search_match_one, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_search_match_filter, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_search_match_both, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_search_match_basedn, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_search_against_transaction, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_during_unindexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_during_indexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_rename_during_unindexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_rename_during_indexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_callback_rename_during_unindexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_callback_rename_during_indexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_callback_delete_during_unindexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_callback_delete_during_indexed_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_during_whole_search, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_modify_before_ldb_wait, + ldb_search_test_setup, + ldb_search_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_attrs_case_insensitive, + ldb_case_test_setup, + ldb_case_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_attrs_case_handler, + ldb_case_test_setup, + ldb_case_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_attrs_index_handler, + ldb_case_test_setup, + ldb_case_attrs_index_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_rename, + ldb_rename_test_setup, + ldb_rename_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_rename_from_doesnt_exist, + ldb_rename_test_setup, + ldb_rename_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_rename_to_exists, + ldb_rename_test_setup, + ldb_rename_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_rename_self, + ldb_rename_test_setup, + ldb_rename_test_teardown), + cmocka_unit_test_setup_teardown(test_ldb_rename_dn_case_change, + ldb_rename_test_setup, + ldb_rename_test_teardown), + cmocka_unit_test_setup_teardown(test_read_only, + ldb_read_only_setup, + ldb_read_only_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_unique_value_to_unique_index, + ldb_unique_index_test_setup, + ldb_unique_index_test_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_duplicate_value_to_unique_index, + ldb_unique_index_test_setup, + ldb_unique_index_test_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_to_index_duplicates_allowed, + ldb_non_unique_index_test_setup, + ldb_non_unique_index_test_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_add_to_index_unique_values_required, + ldb_non_unique_index_test_setup, + ldb_non_unique_index_test_teardown), + /* These tests are not compatible with mdb */ + cmocka_unit_test_setup_teardown( + test_ldb_unique_index_duplicate_logging, + ldb_unique_index_test_setup, + ldb_unique_index_test_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_duplicate_dn_logging, + ldb_unique_index_test_setup, + ldb_unique_index_test_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_guid_index_duplicate_dn_logging, + ldb_guid_index_test_setup, + ldb_guid_index_test_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_unique_index_duplicate_with_guid, + ldb_guid_index_test_setup, + ldb_guid_index_test_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_talloc_destructor_transaction_cleanup, + ldbtest_setup, + ldbtest_teardown), +#ifdef TEST_LMDB + cmocka_unit_test_setup_teardown( + test_ldb_close_with_multiple_connections, + ldb_search_test_setup, + ldb_search_test_teardown), +#endif + cmocka_unit_test_setup_teardown( + test_transaction_start_across_fork, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_transaction_commit_across_fork, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_lock_read_across_fork, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_multiple_opens_across_fork, + ldbtest_setup, + ldbtest_teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_msg.c b/ldb-2.0.8/tests/ldb_msg.c new file mode 100644 index 0000000..31786a9 --- /dev/null +++ b/ldb-2.0.8/tests/ldb_msg.c @@ -0,0 +1,380 @@ +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +struct test_ctx { + struct ldb_message *msg; +}; + +static int ldb_msg_setup(void **state) +{ + struct test_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct test_ctx); + assert_non_null(test_ctx); + + test_ctx->msg = ldb_msg_new(test_ctx); + + *state = test_ctx; + return 0; +} + +static int ldb_msg_teardown(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + + talloc_free(test_ctx); + return 0; +} + + +static void add_uint_value(struct test_ctx *test_ctx, + struct ldb_message *msg, + const char *attr, + unsigned int x) +{ + int ret; + struct ldb_val v, v_dup; + char s[5]; + snprintf(s, sizeof(s), "%04x", x); + v.data = (uint8_t *)s; + v.length = 4; + v_dup = ldb_val_dup(test_ctx, &v); + assert_non_null(v_dup.data); + assert_ptr_not_equal(v_dup.data, v.data); + assert_int_equal(v_dup.length, 4); + + ret = ldb_msg_add_value(msg, attr, &v_dup, NULL); + assert_int_equal(ret, LDB_SUCCESS); +} + + +static void test_ldb_msg_find_duplicate_val(void **state) +{ + int ret; + unsigned int i; + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + struct ldb_message *msg = test_ctx->msg; + struct ldb_message_element *el; + struct ldb_val dummy; + struct ldb_val *dupe = &dummy; /* so we can tell it was modified to NULL, not left as NULL */ + + ret = ldb_msg_add_empty(msg, "el1", 0, &el); + assert_int_equal(ret, LDB_SUCCESS); + + /* An empty message contains no duplicates */ + ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0); + assert_int_equal(ret, LDB_SUCCESS); + assert_null(dupe); + + for (i = 0; i < 5; i++) { + add_uint_value(test_ctx, msg, "el1", i); + } + /* at this point there are no duplicates, and the check uses the naive + quadratic path */ + ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0); + assert_int_equal(ret, LDB_SUCCESS); + assert_null(dupe); + + /* add a duplicate, still using quadratric path */ + add_uint_value(test_ctx, msg, "el1", 3); + ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(dupe); + assert_int_equal(dupe->length, 4); + assert_memory_equal(dupe->data, "0003", 4); + + /* add some more, triggering algorithmic jump */ + for (i = 2; i < 11; i++) { + add_uint_value(test_ctx, msg, "el1", i); + } + ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(dupe); + assert_int_equal(dupe->length, 4); + /*XXX not really guaranteed by the API */ + assert_memory_equal(dupe->data, "0002", 4); + + /* start a new element without duplicates, for the clever algorithm */ + ldb_msg_add_empty(msg, "el2", 0, &el); + for (i = 0; i < 12; i++) { + add_uint_value(test_ctx, msg, "el2", i); + } + ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0); + assert_int_equal(ret, LDB_SUCCESS); + assert_null(dupe); +} + + +static struct ldb_message_element *new_msg_element(TALLOC_CTX *mem_ctx, + const char *name, + unsigned int value_offset, + unsigned int num_values) +{ + unsigned int i, x; + struct ldb_message_element *el = talloc_zero(mem_ctx, + struct ldb_message_element); + + el->values = talloc_array(el, struct ldb_val, num_values); + for (i = 0; i < num_values; i++) { + struct ldb_val v; + char s[50]; + v.data = (uint8_t *)s; + /* % 3 is to ensure the values list is unsorted */ + x = i + value_offset; + v.length = snprintf(s, sizeof(s), "%u %u", x % 3, x); + el->values[i] = ldb_val_dup(mem_ctx, &v); + } + el->name = name; + el->num_values = num_values; + return el; +} + +static void _assert_element_equal(struct ldb_message_element *a, + struct ldb_message_element *b, + const char * const file, + const int line) +{ + unsigned int i; + _assert_int_equal(a->num_values, b->num_values, file, line); + _assert_int_equal(a->flags, b->flags, file, line); + _assert_string_equal(a->name, b->name, file, line); + for (i = 0; i < a->num_values; i++) { + struct ldb_val *v1 = &a->values[i]; + struct ldb_val *v2 = &b->values[i]; + _assert_int_equal(v1->length, v2->length, file, line); + _assert_memory_equal(v1->data, v2->data, v1->length, + file, line); + } +} + +#define assert_element_equal(a, b) \ + _assert_element_equal((a), (b), \ + __FILE__, __LINE__) + + +static void test_ldb_msg_find_common_values(void **state) +{ + /* we only use the state as a talloc context */ + struct ldb_message_element *el, *el2, *el3, *el4, *el2b, *empty; + struct ldb_message_element *orig, *orig2, *orig3, *orig4; + int ret; + const uint32_t remove_dupes = LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES; + el = new_msg_element(*state, "test", 0, 4); + el2 = new_msg_element(*state, "test", 4, 4); + el3 = new_msg_element(*state, "test", 6, 4); + empty = new_msg_element(*state, "test", 0, 0); + orig = new_msg_element(*state, "test", 0, 4); + orig2 = new_msg_element(*state, "test", 4, 4); + orig3 = new_msg_element(*state, "test", 6, 4); + + /* first round is with short value arrays, using quadratic method */ + /* we expect no collisions here */ + ret = ldb_msg_find_common_values(NULL, *state, el, el2, 0); + assert_int_equal(ret, LDB_SUCCESS); + + /*or here */ + ret = ldb_msg_find_common_values(NULL, *state, el, el3, 0); + assert_int_equal(ret, LDB_SUCCESS); + + /* the same elements in reverse order */ + ret = ldb_msg_find_common_values(NULL, *state, el2, el, 0); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_find_common_values(NULL, *state, el3, el, 0); + assert_int_equal(ret, LDB_SUCCESS); + + /* 6, 7 collide */ + ret = ldb_msg_find_common_values(NULL, *state, el2, el3, 0); + assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS); + + /* and again */ + ret = ldb_msg_find_common_values(NULL, *state, el3, el2, 0); + assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS); + + /* make sure the arrays haven't changed */ + assert_element_equal(el, orig); + assert_element_equal(el2, orig2); + assert_element_equal(el3, orig3); + + /* now with the control permisive flag, the first element should be + modified to remove the overlap.*/ + + /* 6, 7 collide, so el2 will only have 4 and 5 */ + ret = ldb_msg_find_common_values(NULL, *state, el2, el3, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + + assert_element_equal(el3, orig3); + assert_int_not_equal(el2->num_values, orig2->num_values); + assert_int_equal(el2->num_values, 2); + el2b = new_msg_element(*state, "test", 4, 2); + assert_element_equal(el2, el2b); + + /* now try the same things with a long and a short value list. + this should still trigger the quadratic path. + */ + el2 = new_msg_element(*state, "test", 4, 10); + orig2 = new_msg_element(*state, "test", 4, 10); + + /* no collisions */ + ret = ldb_msg_find_common_values(NULL, *state, el, el2, 0); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, el2, el, 0); + assert_int_equal(ret, LDB_SUCCESS); + + /*collisions */ + ret = ldb_msg_find_common_values(NULL, *state, el3, el2, 0); + assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS); + + assert_element_equal(el, orig); + assert_element_equal(el2, orig2); + assert_element_equal(el3, orig3); + + /*collisions with permissive flag*/ + ret = ldb_msg_find_common_values(NULL, *state, el3, el2, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + assert_element_equal(el2, orig2); + assert_int_equal(el3->num_values, 0); + + /* permutations involving empty elements. + everything should succeed. */ + ret = ldb_msg_find_common_values(NULL, *state, el3, el2, 0); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, el3, el, 0); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, el2, el3, 0); + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(el2->num_values, orig2->num_values); + ret = ldb_msg_find_common_values(NULL, *state, el3, el2, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(el2->num_values, orig2->num_values); + assert_int_equal(el3->num_values, 0); /* el3 is now empty */ + ret = ldb_msg_find_common_values(NULL, *state, el2, el3, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, el3, empty, 0); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, empty, empty, 0); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, empty, el3, 0); + assert_int_equal(ret, LDB_SUCCESS); + + assert_element_equal(el2, orig2); + assert_element_equal(el, orig); + assert_int_equal(el3->num_values, 0); + + /* now with two large value lists */ + el = new_msg_element(*state, "test", 0, 12); + orig = new_msg_element(*state, "test", 0, 12); + el4 = new_msg_element(*state, "test", 12, 12); + orig4 = new_msg_element(*state, "test", 12, 12); + + /* no collisions */ + ret = ldb_msg_find_common_values(NULL, *state, el, el4, 0); + assert_int_equal(ret, LDB_SUCCESS); + + ret = ldb_msg_find_common_values(NULL, *state, el4, el, 0); + assert_int_equal(ret, LDB_SUCCESS); + + /* collisions */ + ret = ldb_msg_find_common_values(NULL, *state, el4, el2, 0); + assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS); + ret = ldb_msg_find_common_values(NULL, *state, el2, el4, 0); + assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS); + ret = ldb_msg_find_common_values(NULL, *state, el2, el, 0); + assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS); + + assert_element_equal(el, orig); + assert_element_equal(el2, orig2); + assert_element_equal(el4, orig4); + + /* with permissive control, but no collisions */ + ret = ldb_msg_find_common_values(NULL, *state, el, el4, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, el4, el, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + + assert_element_equal(el, orig); + assert_element_equal(el4, orig4); + + /* now with collisions, thus modifications. + At this stage: + el is 0-11 (inclusive) + e2 is 4-13 + el3 is empty + el4 is 12-23 + */ + ret = ldb_msg_find_common_values(NULL, *state, el4, el2, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + assert_element_equal(el2, orig2); + assert_int_not_equal(el4->num_values, orig4->num_values); + /* 4 should start at 14 */ + orig4 = new_msg_element(*state, "test", 14, 10); + assert_element_equal(el4, orig4); + + ret = ldb_msg_find_common_values(NULL, *state, el2, el, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + assert_element_equal(el, orig); + assert_int_not_equal(el2->num_values, orig2->num_values); + orig2 = new_msg_element(*state, "test", 12, 2); + assert_element_equal(el2, orig2); + + /* test the empty el against the full elements */ + ret = ldb_msg_find_common_values(NULL, *state, el, empty, 0); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, empty, el, 0); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, el, empty, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + ret = ldb_msg_find_common_values(NULL, *state, empty, el, remove_dupes); + assert_int_equal(ret, LDB_SUCCESS); + assert_element_equal(el, orig); + assert_element_equal(empty, el3); + + /* make sure an identical element with a different name is rejected */ + el2 = new_msg_element(*state, "fish", 12, 2); + ret = ldb_msg_find_common_values(NULL, *state, el2, el, remove_dupes); + assert_int_equal(ret, LDB_ERR_INAPPROPRIATE_MATCHING); +} + + + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_ldb_msg_find_duplicate_val, + ldb_msg_setup, + ldb_msg_teardown), + cmocka_unit_test_setup_teardown( + test_ldb_msg_find_common_values, + ldb_msg_setup, + ldb_msg_teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_no_lmdb_test.c b/ldb-2.0.8/tests/ldb_no_lmdb_test.c new file mode 100644 index 0000000..8e5a6ee --- /dev/null +++ b/ldb-2.0.8/tests/ldb_no_lmdb_test.c @@ -0,0 +1,158 @@ +/* + * Ensure lmdb backend is disabled + * + * Copyright (C) Mathieu Parent 2019 + * + * 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 . + * + */ + +/* + * Ensure lmdb backend is disabled + * + * Setup and tear down code copied from ldb_lmdb_test.c + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define TEST_BE "mdb" + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; + + const char *dbfile; + const char *lockfile; /* lockfile is separate */ + + const char *dbpath; +}; + +static void unlink_old_db(struct ldbtest_ctx *test_ctx) +{ + int ret; + + errno = 0; + ret = unlink(test_ctx->lockfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } + + errno = 0; + ret = unlink(test_ctx->dbfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } +} + +static int ldbtest_noconn_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb"); + assert_non_null(test_ctx->dbfile); + + test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock", + test_ctx->dbfile); + assert_non_null(test_ctx->lockfile); + + test_ctx->dbpath = talloc_asprintf(test_ctx, + TEST_BE"://%s", test_ctx->dbfile); + assert_non_null(test_ctx->dbpath); + + unlink_old_db(test_ctx); + *state = test_ctx; + return 0; +} + +static int ldbtest_noconn_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + + unlink_old_db(test_ctx); + talloc_free(test_ctx); + return 0; +} + +static int ldbtest_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + int ret; + + ldbtest_noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, LDB_ERR_OTHER); + + *state = test_ctx; + return 0; +} + +static int ldbtest_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + ldbtest_noconn_teardown((void **) &test_ctx); + return 0; +} + +static void test_ldb_lmdb_not_found(void **state) +{ + // Actual test in ldbtest_setup + assert_int_equal(0, 0); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_ldb_lmdb_not_found, + ldbtest_setup, + ldbtest_teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_parse_test.c b/ldb-2.0.8/tests/ldb_parse_test.c new file mode 100644 index 0000000..a739d77 --- /dev/null +++ b/ldb-2.0.8/tests/ldb_parse_test.c @@ -0,0 +1,93 @@ +/* + * Tests exercising the ldb parse operations. + * + * Copyright (C) Catalyst.NET Ltd 2017 + * Copyright (C) Michael Hanselmann 2019 + * + * 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 . + * + */ + +#include +#include +#include +#include +#include + +#include "../include/ldb.h" + +struct test_ctx +{ +}; + +static int setup(void **state) +{ + struct test_ctx *ctx; + + ctx = talloc_zero(NULL, struct test_ctx); + assert_non_null(ctx); + + *state = ctx; + + return 0; +} + +static int teardown(void **state) +{ + struct test_ctx *ctx = + talloc_get_type_abort(*state, struct test_ctx); + + talloc_free(ctx); + + return 0; +} + +static void test_roundtrip(TALLOC_CTX *mem_ctx, const char *filter, const char *expected) +{ + struct ldb_parse_tree *tree; + char *serialized; + + assert_non_null(filter); + assert_non_null(expected); + + tree = ldb_parse_tree(mem_ctx, filter); + assert_non_null(tree); + + serialized = ldb_filter_from_tree(mem_ctx, tree); + assert_non_null(serialized); + + assert_string_equal(serialized, expected); +} + +static void test_parse_filtertype(void **state) +{ + struct test_ctx *ctx = + talloc_get_type_abort(*state, struct test_ctx); + + test_roundtrip(ctx, "", "(|(objectClass=*)(distinguishedName=*))"); + test_roundtrip(ctx, "a=value", "(a=value)"); + test_roundtrip(ctx, "(|(foo=bar)(baz=hello))", "(|(foo=bar)(baz=hello))"); + test_roundtrip(ctx, " ", "(|(objectClass=*)(distinguishedName=*))"); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_parse_filtertype, setup, teardown), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/ldb_tdb_test.c b/ldb-2.0.8/tests/ldb_tdb_test.c new file mode 100644 index 0000000..ef91ba5 --- /dev/null +++ b/ldb-2.0.8/tests/ldb_tdb_test.c @@ -0,0 +1,389 @@ +/* + * lmdb backend specific tests for ldb + * + * Copyright (C) Andrew Bartlett 2018 + * + * 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 . + * + */ + +/* + * lmdb backend specific tests for ldb + * + * Setup and tear down code copied from ldb_mod_op_test.c + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../ldb_tdb/ldb_tdb.h" +#include "../ldb_key_value/ldb_kv.h" + +#define TEST_BE "tdb" + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; + + const char *dbfile; + + const char *dbpath; +}; + +static void unlink_old_db(struct ldbtest_ctx *test_ctx) +{ + int ret; + + errno = 0; + ret = unlink(test_ctx->dbfile); + if (ret == -1 && errno != ENOENT) { + fail(); + } +} + +static int ldbtest_noconn_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb"); + assert_non_null(test_ctx->dbfile); + + test_ctx->dbpath = talloc_asprintf(test_ctx, + TEST_BE"://%s", test_ctx->dbfile); + assert_non_null(test_ctx->dbpath); + + unlink_old_db(test_ctx); + *state = test_ctx; + return 0; +} + +static int ldbtest_noconn_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + + unlink_old_db(test_ctx); + talloc_free(test_ctx); + return 0; +} + +static int ldbtest_setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + int ret; + struct ldb_ldif *ldif; + const char *index_ldif = \ + "dn: @INDEXLIST\n" + "@IDXGUID: objectUUID\n" + "@IDX_DN_GUID: GUID\n" + "\n"; + + ldbtest_noconn_setup((void **) &test_ctx); + + ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + + while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) { + ret = ldb_add(test_ctx->ldb, ldif->msg); + assert_int_equal(ret, LDB_SUCCESS); + } + *state = test_ctx; + return 0; +} + +static int ldbtest_teardown(void **state) +{ + struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, + struct ldbtest_ctx); + ldbtest_noconn_teardown((void **) &test_ctx); + return 0; +} + + +static TDB_CONTEXT *get_tdb_context(struct ldb_context *ldb) +{ + void *data = NULL; + struct ldb_kv_private *ldb_kv = NULL; + TDB_CONTEXT *tdb = NULL; + + data = ldb_module_get_private(ldb->modules); + assert_non_null(data); + + ldb_kv = talloc_get_type(data, struct ldb_kv_private); + assert_non_null(ldb_kv); + + tdb = ldb_kv->tdb; + assert_non_null(tdb); + + return tdb; +} + +static void test_multiple_opens(void **state) +{ + struct ldb_context *ldb1 = NULL; + struct ldb_context *ldb2 = NULL; + struct ldb_context *ldb3 = NULL; + TDB_CONTEXT *tdb1 = NULL; + TDB_CONTEXT *tdb2 = NULL; + TDB_CONTEXT *tdb3 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database again + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb2 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb2, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb3 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb3, test_ctx->dbpath, 0, NULL); + assert_int_equal(ret, 0); + /* + * We now have 3 ldb's open pointing to the same on disk database + * they should all share the same MDB_env + */ + tdb1 = get_tdb_context(ldb1); + tdb2 = get_tdb_context(ldb2); + tdb3 = get_tdb_context(ldb3); + + assert_ptr_equal(tdb1, tdb2); + assert_ptr_equal(tdb1, tdb3); +} + +static void test_multiple_opens_across_fork(void **state) +{ + struct ldb_context *ldb1 = NULL; + struct ldb_context *ldb2 = NULL; + TDB_CONTEXT *tdb1 = NULL; + TDB_CONTEXT *tdb2 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + int pipes[2]; + char buf[2]; + int wstatus; + pid_t pid, child_pid; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database again + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb2 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb2, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + tdb1 = get_tdb_context(ldb1); + tdb2 = get_tdb_context(ldb2); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + struct ldb_context *ldb3 = NULL; + TDB_CONTEXT *tdb3 = NULL; + + close(pipes[0]); + ldb3 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb3, test_ctx->dbpath, 0, NULL); + if (ret != 0) { + print_error(__location__": ldb_connect returned (%d)\n", + ret); + exit(ret); + } + tdb3 = get_tdb_context(ldb3); + if (tdb1 != tdb2) { + print_error(__location__": tdb1 != tdb2\n"); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if (tdb1 != tdb3) { + print_error(__location__": tdb1 != tdb3\n"); + exit(LDB_ERR_OPERATIONS_ERROR); + } + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); +} + +static void test_multiple_opens_across_fork_triggers_reopen(void **state) +{ + struct ldb_context *ldb1 = NULL; + struct ldb_context *ldb2 = NULL; + TDB_CONTEXT *tdb1 = NULL; + TDB_CONTEXT *tdb2 = NULL; + int ret; + struct ldbtest_ctx *test_ctx = NULL; + int pipes[2]; + char buf[2]; + int wstatus; + pid_t pid, child_pid; + + test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); + + /* + * Open the database again + */ + ldb1 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb1, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + ldb2 = ldb_init(test_ctx, test_ctx->ev); + ret = ldb_connect(ldb2, test_ctx->dbpath, LDB_FLG_RDONLY, NULL); + assert_int_equal(ret, 0); + + tdb1 = get_tdb_context(ldb1); + tdb2 = get_tdb_context(ldb2); + assert_ptr_equal(tdb1, tdb2); + + /* + * Break the internal tdb_reopen() by making a + * transaction + * + * This shows that the tdb_reopen() is called, which is + * essential if the host OS does not have pread() + */ + ret = tdb_transaction_start(tdb1); + assert_int_equal(ret, 0); + + ret = pipe(pipes); + assert_int_equal(ret, 0); + + child_pid = fork(); + if (child_pid == 0) { + struct ldb_context *ldb3 = NULL; + + close(pipes[0]); + ldb3 = ldb_init(test_ctx, test_ctx->ev); + + /* + * This should fail as we have taken out a lock + * against the raw TDB above, and tdb_reopen() + * will fail in that state. + * + * This check matters as tdb_reopen() is important + * if the host does not have pread() + */ + ret = ldb_connect(ldb3, test_ctx->dbpath, 0, NULL); + if (ret == 0) { + print_error(__location__": ldb_connect expected " + "LDB_ERR_OPERATIONS_ERROR " + "returned (%d)\n", + ret); + exit(5000); + } + ret = write(pipes[1], "GO", 2); + if (ret != 2) { + print_error(__location__ + " write returned (%d)", + ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + exit(LDB_SUCCESS); + } + close(pipes[1]); + ret = read(pipes[0], buf, 2); + assert_int_equal(ret, 2); + + pid = waitpid(child_pid, &wstatus, 0); + assert_int_equal(pid, child_pid); + + assert_true(WIFEXITED(wstatus)); + + assert_int_equal(WEXITSTATUS(wstatus), 0); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_multiple_opens, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_multiple_opens_across_fork, + ldbtest_setup, + ldbtest_teardown), + cmocka_unit_test_setup_teardown( + test_multiple_opens_across_fork_triggers_reopen, + ldbtest_setup, + ldbtest_teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/photo.ldif b/ldb-2.0.8/tests/photo.ldif new file mode 100644 index 0000000..95ab065 --- /dev/null +++ b/ldb-2.0.8/tests/photo.ldif @@ -0,0 +1,5 @@ +dn: cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST +changetype: modify +add: jpegPhoto +jpegPhoto:< file://tests/samba4.png + diff --git a/ldb-2.0.8/tests/python/api.py b/ldb-2.0.8/tests/python/api.py new file mode 100755 index 0000000..4d55566 --- /dev/null +++ b/ldb-2.0.8/tests/python/api.py @@ -0,0 +1,3326 @@ +#!/usr/bin/env python3 +# Simple tests for the ldb python bindings. +# Copyright (C) 2007 Jelmer Vernooij + +import os +from unittest import TestCase +import sys +import gc +import time +import ldb +import shutil + +PY3 = sys.version_info > (3, 0) + +TDB_PREFIX = "tdb://" +MDB_PREFIX = "mdb://" + +MDB_INDEX_OBJ = { + "dn": "@INDEXLIST", + "@IDXONE": [b"1"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"] +} + + +def tempdir(): + import tempfile + try: + dir_prefix = os.path.join(os.environ["SELFTEST_PREFIX"], "tmp") + except KeyError: + dir_prefix = None + return tempfile.mkdtemp(dir=dir_prefix) + + +class NoContextTests(TestCase): + + def test_valid_attr_name(self): + self.assertTrue(ldb.valid_attr_name("foo")) + self.assertFalse(ldb.valid_attr_name("24foo")) + + def test_timestring(self): + self.assertEqual("19700101000000.0Z", ldb.timestring(0)) + self.assertEqual("20071119191012.0Z", ldb.timestring(1195499412)) + + def test_string_to_time(self): + self.assertEqual(0, ldb.string_to_time("19700101000000.0Z")) + self.assertEqual(1195499412, ldb.string_to_time("20071119191012.0Z")) + + def test_binary_encode(self): + encoded = ldb.binary_encode(b'test\\x') + decoded = ldb.binary_decode(encoded) + self.assertEqual(decoded, b'test\\x') + + encoded2 = ldb.binary_encode('test\\x') + self.assertEqual(encoded2, encoded) + + +class LdbBaseTest(TestCase): + def setUp(self): + super(LdbBaseTest, self).setUp() + try: + if self.prefix is None: + self.prefix = TDB_PREFIX + except AttributeError: + self.prefix = TDB_PREFIX + + def tearDown(self): + super(LdbBaseTest, self).tearDown() + + def url(self): + return self.prefix + self.filename + + def flags(self): + if self.prefix == MDB_PREFIX: + return ldb.FLG_NOSYNC + else: + return 0 + + +class SimpleLdb(LdbBaseTest): + + def setUp(self): + super(SimpleLdb, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "test.ldb") + self.ldb = ldb.Ldb(self.url(), flags=self.flags()) + try: + self.ldb.add(self.index) + except AttributeError: + pass + + def tearDown(self): + shutil.rmtree(self.testdir) + super(SimpleLdb, self).tearDown() + # Ensure the LDB is closed now, so we close the FD + del(self.ldb) + + def test_connect(self): + ldb.Ldb(self.url(), flags=self.flags()) + + def test_connect_none(self): + ldb.Ldb() + + def test_connect_later(self): + x = ldb.Ldb() + x.connect(self.url(), flags=self.flags()) + + def test_repr(self): + x = ldb.Ldb() + self.assertTrue(repr(x).startswith("]", repr(x.modules())) + + def test_firstmodule_none(self): + x = ldb.Ldb() + self.assertEqual(x.firstmodule, None) + + def test_firstmodule_tdb(self): + x = ldb.Ldb(self.url(), flags=self.flags()) + mod = x.firstmodule + self.assertEqual(repr(mod), "") + + def test_search(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(len(l.search()), 0) + + def test_search_controls(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(len(l.search(controls=["paged_results:0:5"])), 0) + + def test_utf8_ldb_Dn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + dn = ldb.Dn(l, (b'a=' + b'\xc4\x85\xc4\x87\xc4\x99\xc5\x82\xc5\x84\xc3\xb3\xc5\x9b\xc5\xba\xc5\xbc').decode('utf8')) + + def test_utf8_encoded_ldb_Dn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + dn_encoded_utf8 = b'a=' + b'\xc4\x85\xc4\x87\xc4\x99\xc5\x82\xc5\x84\xc3\xb3\xc5\x9b\xc5\xba\xc5\xbc' + try: + dn = ldb.Dn(l, dn_encoded_utf8) + except UnicodeDecodeError as e: + raise + except TypeError as te: + if PY3: + p3errors = ["argument 2 must be str, not bytes", + "Can't convert 'bytes' object to str implicitly"] + self.assertIn(str(te), p3errors) + else: + raise + + def test_search_attrs(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(len(l.search(ldb.Dn(l, ""), ldb.SCOPE_SUBTREE, "(dc=*)", ["dc"])), 0) + + def test_search_string_dn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(len(l.search("", ldb.SCOPE_SUBTREE, "(dc=*)", ["dc"])), 0) + + def test_search_attr_string(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertRaises(TypeError, l.search, attrs="dc") + self.assertRaises(TypeError, l.search, attrs=b"dc") + + def test_opaque(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + l.set_opaque("my_opaque", l) + self.assertTrue(l.get_opaque("my_opaque") is not None) + self.assertEqual(None, l.get_opaque("unknown")) + + def test_search_scope_base_empty_db(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(len(l.search(ldb.Dn(l, "dc=foo1"), + ldb.SCOPE_BASE)), 0) + + def test_search_scope_onelevel_empty_db(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(len(l.search(ldb.Dn(l, "dc=foo1"), + ldb.SCOPE_ONELEVEL)), 0) + + def test_delete(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertRaises(ldb.LdbError, lambda: l.delete(ldb.Dn(l, "dc=foo2"))) + + def test_delete_w_unhandled_ctrl(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo1") + m["b"] = [b"a"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + self.assertRaises(ldb.LdbError, lambda: l.delete(m.dn, ["search_options:1:2"])) + l.delete(m.dn) + + def test_contains(self): + name = self.url() + l = ldb.Ldb(name, flags=self.flags()) + self.assertFalse(ldb.Dn(l, "dc=foo3") in l) + l = ldb.Ldb(name, flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo3") + m["b"] = ["a"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + try: + self.assertTrue(ldb.Dn(l, "dc=foo3") in l) + self.assertFalse(ldb.Dn(l, "dc=foo4") in l) + finally: + l.delete(m.dn) + + def test_get_config_basedn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(None, l.get_config_basedn()) + + def test_get_root_basedn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(None, l.get_root_basedn()) + + def test_get_schema_basedn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(None, l.get_schema_basedn()) + + def test_get_default_basedn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(None, l.get_default_basedn()) + + def test_add(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo4") + m["bla"] = b"bla" + m["objectUUID"] = b"0123456789abcdef" + self.assertEqual(len(l.search()), 0) + l.add(m) + try: + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=foo4")) + + def test_search_iterator(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + s = l.search_iterator() + s.abandon() + try: + for me in s: + self.fail() + self.fail() + except RuntimeError as re: + pass + try: + s.abandon() + self.fail() + except RuntimeError as re: + pass + try: + s.result() + self.fail() + except RuntimeError as re: + pass + + s = l.search_iterator() + count = 0 + for me in s: + self.assertTrue(isinstance(me, ldb.Message)) + count += 1 + r = s.result() + self.assertEqual(len(r), 0) + self.assertEqual(count, 0) + + m1 = ldb.Message() + m1.dn = ldb.Dn(l, "dc=foo4") + m1["bla"] = b"bla" + m1["objectUUID"] = b"0123456789abcdef" + l.add(m1) + try: + s = l.search_iterator() + msgs = [] + for me in s: + self.assertTrue(isinstance(me, ldb.Message)) + count += 1 + msgs.append(me) + r = s.result() + self.assertEqual(len(r), 0) + self.assertEqual(len(msgs), 1) + self.assertEqual(msgs[0].dn, m1.dn) + + m2 = ldb.Message() + m2.dn = ldb.Dn(l, "dc=foo5") + m2["bla"] = b"bla" + m2["objectUUID"] = b"0123456789abcdee" + l.add(m2) + + s = l.search_iterator() + msgs = [] + for me in s: + self.assertTrue(isinstance(me, ldb.Message)) + count += 1 + msgs.append(me) + r = s.result() + self.assertEqual(len(r), 0) + self.assertEqual(len(msgs), 2) + if msgs[0].dn == m1.dn: + self.assertEqual(msgs[0].dn, m1.dn) + self.assertEqual(msgs[1].dn, m2.dn) + else: + self.assertEqual(msgs[0].dn, m2.dn) + self.assertEqual(msgs[1].dn, m1.dn) + + s = l.search_iterator() + msgs = [] + for me in s: + self.assertTrue(isinstance(me, ldb.Message)) + count += 1 + msgs.append(me) + break + try: + s.result() + self.fail() + except RuntimeError as re: + pass + for me in s: + self.assertTrue(isinstance(me, ldb.Message)) + count += 1 + msgs.append(me) + break + for me in s: + self.fail() + + r = s.result() + self.assertEqual(len(r), 0) + self.assertEqual(len(msgs), 2) + if msgs[0].dn == m1.dn: + self.assertEqual(msgs[0].dn, m1.dn) + self.assertEqual(msgs[1].dn, m2.dn) + else: + self.assertEqual(msgs[0].dn, m2.dn) + self.assertEqual(msgs[1].dn, m1.dn) + finally: + l.delete(ldb.Dn(l, "dc=foo4")) + l.delete(ldb.Dn(l, "dc=foo5")) + + def test_add_text(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo4") + m["bla"] = "bla" + m["objectUUID"] = b"0123456789abcdef" + self.assertEqual(len(l.search()), 0) + l.add(m) + try: + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=foo4")) + + def test_add_w_unhandled_ctrl(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo4") + m["bla"] = b"bla" + self.assertEqual(len(l.search()), 0) + self.assertRaises(ldb.LdbError, lambda: l.add(m, ["search_options:1:2"])) + + def test_add_dict(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = {"dn": ldb.Dn(l, "dc=foo5"), + "bla": b"bla", + "objectUUID": b"0123456789abcdef"} + self.assertEqual(len(l.search()), 0) + l.add(m) + try: + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=foo5")) + + def test_add_dict_text(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = {"dn": ldb.Dn(l, "dc=foo5"), + "bla": "bla", + "objectUUID": b"0123456789abcdef"} + self.assertEqual(len(l.search()), 0) + l.add(m) + try: + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=foo5")) + + def test_add_dict_string_dn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = {"dn": "dc=foo6", "bla": b"bla", + "objectUUID": b"0123456789abcdef"} + self.assertEqual(len(l.search()), 0) + l.add(m) + try: + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=foo6")) + + def test_add_dict_bytes_dn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = {"dn": b"dc=foo6", "bla": b"bla", + "objectUUID": b"0123456789abcdef"} + self.assertEqual(len(l.search()), 0) + l.add(m) + try: + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=foo6")) + + def test_rename(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo7") + m["bla"] = b"bla" + m["objectUUID"] = b"0123456789abcdef" + self.assertEqual(len(l.search()), 0) + l.add(m) + try: + l.rename(ldb.Dn(l, "dc=foo7"), ldb.Dn(l, "dc=bar")) + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=bar")) + + def test_rename_string_dns(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo8") + m["bla"] = b"bla" + m["objectUUID"] = b"0123456789abcdef" + self.assertEqual(len(l.search()), 0) + l.add(m) + self.assertEqual(len(l.search()), 1) + try: + l.rename("dc=foo8", "dc=bar") + self.assertEqual(len(l.search()), 1) + finally: + l.delete(ldb.Dn(l, "dc=bar")) + + def test_rename_bad_string_dns(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo8") + m["bla"] = b"bla" + m["objectUUID"] = b"0123456789abcdef" + self.assertEqual(len(l.search()), 0) + l.add(m) + self.assertEqual(len(l.search()), 1) + self.assertRaises(ldb.LdbError,lambda: l.rename("dcXfoo8", "dc=bar")) + self.assertRaises(ldb.LdbError,lambda: l.rename("dc=foo8", "dcXbar")) + l.delete(ldb.Dn(l, "dc=foo8")) + + def test_empty_dn(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertEqual(0, len(l.search())) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=empty") + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + rm = l.search() + self.assertEqual(1, len(rm)) + self.assertEqual(set(["dn", "distinguishedName", "objectUUID"]), + set(rm[0].keys())) + + rm = l.search(m.dn) + self.assertEqual(1, len(rm)) + self.assertEqual(set(["dn", "distinguishedName", "objectUUID"]), + set(rm[0].keys())) + rm = l.search(m.dn, attrs=["blah"]) + self.assertEqual(1, len(rm)) + self.assertEqual(0, len(rm[0])) + + def test_modify_delete(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modifydelete") + m["bla"] = [b"1234"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + rm = l.search(m.dn)[0] + self.assertEqual([b"1234"], list(rm["bla"])) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modifydelete") + m["bla"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "bla") + self.assertEqual(ldb.FLAG_MOD_DELETE, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn) + self.assertEqual(1, len(rm)) + self.assertEqual(set(["dn", "distinguishedName", "objectUUID"]), + set(rm[0].keys())) + rm = l.search(m.dn, attrs=["bla"]) + self.assertEqual(1, len(rm)) + self.assertEqual(0, len(rm[0])) + finally: + l.delete(ldb.Dn(l, "dc=modifydelete")) + + def test_modify_delete_text(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modifydelete") + m.text["bla"] = ["1234"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + rm = l.search(m.dn)[0] + self.assertEqual(["1234"], list(rm.text["bla"])) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modifydelete") + m["bla"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "bla") + self.assertEqual(ldb.FLAG_MOD_DELETE, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn) + self.assertEqual(1, len(rm)) + self.assertEqual(set(["dn", "distinguishedName", "objectUUID"]), + set(rm[0].keys())) + rm = l.search(m.dn, attrs=["bla"]) + self.assertEqual(1, len(rm)) + self.assertEqual(0, len(rm[0])) + finally: + l.delete(ldb.Dn(l, "dc=modifydelete")) + + def test_modify_add(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m["bla"] = [b"1234"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m["bla"] = ldb.MessageElement([b"456"], ldb.FLAG_MOD_ADD, "bla") + self.assertEqual(ldb.FLAG_MOD_ADD, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEqual(3, len(rm)) + self.assertEqual([b"1234", b"456"], list(rm["bla"])) + finally: + l.delete(ldb.Dn(l, "dc=add")) + + def test_modify_add_text(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m.text["bla"] = ["1234"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla") + self.assertEqual(ldb.FLAG_MOD_ADD, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEqual(3, len(rm)) + self.assertEqual(["1234", "456"], list(rm.text["bla"])) + finally: + l.delete(ldb.Dn(l, "dc=add")) + + def test_modify_replace(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify2") + m["bla"] = [b"1234", b"456"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify2") + m["bla"] = ldb.MessageElement([b"789"], ldb.FLAG_MOD_REPLACE, "bla") + self.assertEqual(ldb.FLAG_MOD_REPLACE, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEqual(3, len(rm)) + self.assertEqual([b"789"], list(rm["bla"])) + rm = l.search(m.dn, attrs=["bla"])[0] + self.assertEqual(1, len(rm)) + finally: + l.delete(ldb.Dn(l, "dc=modify2")) + + def test_modify_replace_text(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify2") + m.text["bla"] = ["1234", "456"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify2") + m["bla"] = ldb.MessageElement(["789"], ldb.FLAG_MOD_REPLACE, "bla") + self.assertEqual(ldb.FLAG_MOD_REPLACE, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEqual(3, len(rm)) + self.assertEqual(["789"], list(rm.text["bla"])) + rm = l.search(m.dn, attrs=["bla"])[0] + self.assertEqual(1, len(rm)) + finally: + l.delete(ldb.Dn(l, "dc=modify2")) + + def test_modify_flags_change(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m["bla"] = [b"1234"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m["bla"] = ldb.MessageElement([b"456"], ldb.FLAG_MOD_ADD, "bla") + self.assertEqual(ldb.FLAG_MOD_ADD, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEqual(3, len(rm)) + self.assertEqual([b"1234", b"456"], list(rm["bla"])) + + # Now create another modify, but switch the flags before we do it + m["bla"] = ldb.MessageElement([b"456"], ldb.FLAG_MOD_ADD, "bla") + m["bla"].set_flags(ldb.FLAG_MOD_DELETE) + l.modify(m) + rm = l.search(m.dn, attrs=["bla"])[0] + self.assertEqual(1, len(rm)) + self.assertEqual([b"1234"], list(rm["bla"])) + finally: + l.delete(ldb.Dn(l, "dc=add")) + + def test_modify_flags_change_text(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m.text["bla"] = ["1234"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=add") + m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla") + self.assertEqual(ldb.FLAG_MOD_ADD, m["bla"].flags()) + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEqual(3, len(rm)) + self.assertEqual(["1234", "456"], list(rm.text["bla"])) + + # Now create another modify, but switch the flags before we do it + m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla") + m["bla"].set_flags(ldb.FLAG_MOD_DELETE) + l.modify(m) + rm = l.search(m.dn, attrs=["bla"])[0] + self.assertEqual(1, len(rm)) + self.assertEqual(["1234"], list(rm.text["bla"])) + finally: + l.delete(ldb.Dn(l, "dc=add")) + + def test_transaction_commit(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + l.transaction_start() + m = ldb.Message(ldb.Dn(l, "dc=foo9")) + m["foo"] = [b"bar"] + m["objectUUID"] = b"0123456789abcdef" + l.add(m) + l.transaction_commit() + l.delete(m.dn) + + def test_transaction_cancel(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + l.transaction_start() + m = ldb.Message(ldb.Dn(l, "dc=foo10")) + m["foo"] = [b"bar"] + m["objectUUID"] = b"0123456789abcdee" + l.add(m) + l.transaction_cancel() + self.assertEqual(0, len(l.search(ldb.Dn(l, "dc=foo10")))) + + def test_set_debug(self): + def my_report_fn(level, text): + pass + l = ldb.Ldb(self.url(), flags=self.flags()) + l.set_debug(my_report_fn) + + def test_zero_byte_string(self): + """Testing we do not get trapped in the \0 byte in a property string.""" + l = ldb.Ldb(self.url(), flags=self.flags()) + l.add({ + "dn": b"dc=somedn", + "objectclass": b"user", + "cN": b"LDAPtestUSER", + "givenname": b"ldap", + "displayname": b"foo\0bar", + "objectUUID": b"0123456789abcdef" + }) + res = l.search(expression="(dn=dc=somedn)") + self.assertEqual(b"foo\0bar", res[0]["displayname"][0]) + + def test_no_crash_broken_expr(self): + l = ldb.Ldb(self.url(), flags=self.flags()) + self.assertRaises(ldb.LdbError, lambda: l.search("", ldb.SCOPE_SUBTREE, "&(dc=*)(dn=*)", ["dc"])) + +# Run the SimpleLdb tests against an lmdb backend + + +class SimpleLdbLmdb(SimpleLdb): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + self.index = MDB_INDEX_OBJ + super(SimpleLdbLmdb, self).setUp() + + def tearDown(self): + super(SimpleLdbLmdb, self).tearDown() + + +class SimpleLdbNoLmdb(LdbBaseTest): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') != '0': + self.skipTest("lmdb backend enabled") + self.prefix = MDB_PREFIX + self.index = MDB_INDEX_OBJ + super(SimpleLdbNoLmdb, self).setUp() + + def tearDown(self): + super(SimpleLdbNoLmdb, self).tearDown() + + def test_lmdb_disabled(self): + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "test.ldb") + try: + self.ldb = ldb.Ldb(self.url(), flags=self.flags()) + self.fail("Should have failed on missing LMDB") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_OTHER) + + +class SearchTests(LdbBaseTest): + def tearDown(self): + shutil.rmtree(self.testdir) + super(SearchTests, self).tearDown() + + # Ensure the LDB is closed now, so we close the FD + del(self.l) + + def setUp(self): + super(SearchTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "search_test.ldb") + options = ["modules:rdn_name"] + if hasattr(self, 'IDXCHECK'): + options.append("disable_full_db_scan_for_self_test:1") + self.l = ldb.Ldb(self.url(), + flags=self.flags(), + options=options) + try: + self.l.add(self.index) + except AttributeError: + pass + + self.l.add({"dn": "@ATTRIBUTES", + "DC": "CASE_INSENSITIVE"}) + + # Note that we can't use the name objectGUID here, as we + # want to stay clear of the objectGUID handler in LDB and + # instead use just the 16 bytes raw, which we just keep + # to printable chars here for ease of handling. + + self.l.add({"dn": "DC=SAMBA,DC=ORG", + "name": b"samba.org", + "objectUUID": b"0123456789abcdef"}) + self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + self.l.add({"dn": "OU=USERS,DC=SAMBA,DC=ORG", + "name": b"Users", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + self.l.add({"dn": "OU=OU1,DC=SAMBA,DC=ORG", + "name": b"OU #1", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde3"}) + self.l.add({"dn": "OU=OU2,DC=SAMBA,DC=ORG", + "name": b"OU #2", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde4"}) + self.l.add({"dn": "OU=OU3,DC=SAMBA,DC=ORG", + "name": b"OU #3", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde5"}) + self.l.add({"dn": "OU=OU4,DC=SAMBA,DC=ORG", + "name": b"OU #4", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde6"}) + self.l.add({"dn": "OU=OU5,DC=SAMBA,DC=ORG", + "name": b"OU #5", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde7"}) + self.l.add({"dn": "OU=OU6,DC=SAMBA,DC=ORG", + "name": b"OU #6", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde8"}) + self.l.add({"dn": "OU=OU7,DC=SAMBA,DC=ORG", + "name": b"OU #7", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde9"}) + self.l.add({"dn": "OU=OU8,DC=SAMBA,DC=ORG", + "name": b"OU #8", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcde0"}) + self.l.add({"dn": "OU=OU9,DC=SAMBA,DC=ORG", + "name": b"OU #9", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcdea"}) + self.l.add({"dn": "OU=OU10,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcdeb"}) + self.l.add({"dn": "OU=OU11,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "y", "y": "a", + "objectUUID": b"0123456789abcdec"}) + self.l.add({"dn": "OU=OU12,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "y", "y": "b", + "objectUUID": b"0123456789abcded"}) + self.l.add({"dn": "OU=OU13,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcdee"}) + self.l.add({"dn": "OU=OU14,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcd01"}) + self.l.add({"dn": "OU=OU15,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcd02"}) + self.l.add({"dn": "OU=OU16,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcd03"}) + self.l.add({"dn": "OU=OU17,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcd04"}) + self.l.add({"dn": "OU=OU18,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcd05"}) + self.l.add({"dn": "OU=OU19,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcd06"}) + self.l.add({"dn": "OU=OU20,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "b", + "objectUUID": b"0123456789abcd07"}) + self.l.add({"dn": "OU=OU21,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "c", + "objectUUID": b"0123456789abcd08"}) + self.l.add({"dn": "OU=OU22,DC=SAMBA,DC=ORG", + "name": b"OU #10", + "x": "x", "y": "c", + "objectUUID": b"0123456789abcd09"}) + + def test_base(self): + """Testing a search""" + + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res11), 1) + + def test_base_lower(self): + """Testing a search""" + + res11 = self.l.search(base="OU=OU11,DC=samba,DC=org", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res11), 1) + + def test_base_or(self): + """Testing a search""" + + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(|(ou=ou11)(ou=ou12))") + self.assertEqual(len(res11), 1) + + def test_base_or2(self): + """Testing a search""" + + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(|(x=y)(y=b))") + self.assertEqual(len(res11), 1) + + def test_base_and(self): + """Testing a search""" + + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(&(ou=ou11)(ou=ou12))") + self.assertEqual(len(res11), 0) + + def test_base_and2(self): + """Testing a search""" + + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(&(x=y)(y=a))") + self.assertEqual(len(res11), 1) + + def test_base_false(self): + """Testing a search""" + + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(|(ou=ou13)(ou=ou12))") + self.assertEqual(len(res11), 0) + + def test_check_base_false(self): + """Testing a search""" + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(|(ou=ou13)(ou=ou12))") + self.assertEqual(len(res11), 0) + + def test_check_base_error(self): + """Testing a search""" + checkbaseonsearch = {"dn": "@OPTIONS", + "checkBaseOnSearch": b"TRUE"} + try: + self.l.add(checkbaseonsearch) + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + m = ldb.Message.from_dict(self.l, + checkbaseonsearch) + self.l.modify(m) + + try: + res11 = self.l.search(base="OU=OU11x,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(|(ou=ou13)(ou=ou12))") + self.fail("Should have failed on missing base") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_NO_SUCH_OBJECT) + + def test_subtree_and(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(ou=ou11)(ou=ou12))") + self.assertEqual(len(res11), 0) + + def test_subtree_and2(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(x=y)(|(y=b)(y=c)))") + self.assertEqual(len(res11), 1) + + def test_subtree_and2_lower(self): + """Testing a search""" + + res11 = self.l.search(base="DC=samba,DC=org", + scope=ldb.SCOPE_SUBTREE, + expression="(&(x=y)(|(y=b)(y=c)))") + self.assertEqual(len(res11), 1) + + def test_subtree_or(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(|(ou=ou11)(ou=ou12))") + self.assertEqual(len(res11), 2) + + def test_subtree_or2(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(|(x=y)(y=b))") + self.assertEqual(len(res11), 20) + + def test_subtree_or3(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(|(x=y)(y=b)(y=c))") + self.assertEqual(len(res11), 22) + + def test_one_and(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(&(ou=ou11)(ou=ou12))") + self.assertEqual(len(res11), 0) + + def test_one_and2(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(&(x=y)(y=b))") + self.assertEqual(len(res11), 1) + + def test_one_or(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(|(ou=ou11)(ou=ou12))") + self.assertEqual(len(res11), 2) + + def test_one_or2(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(|(x=y)(y=b))") + self.assertEqual(len(res11), 20) + + def test_one_or2_lower(self): + """Testing a search""" + + res11 = self.l.search(base="DC=samba,DC=org", + scope=ldb.SCOPE_ONELEVEL, + expression="(|(x=y)(y=b))") + self.assertEqual(len(res11), 20) + + def test_one_unindexable(self): + """Testing a search""" + + try: + res11 = self.l.search(base="DC=samba,DC=org", + scope=ldb.SCOPE_ONELEVEL, + expression="(y=b*)") + if hasattr(self, 'IDX') and \ + not hasattr(self, 'IDXONE') and \ + hasattr(self, 'IDXCHECK'): + self.fail("Should have failed as un-indexed search") + + self.assertEqual(len(res11), 9) + + except ldb.LdbError as err: + enum = err.args[0] + estr = err.args[1] + self.assertEqual(enum, ldb.ERR_INAPPROPRIATE_MATCHING) + self.assertIn(estr, "ldb FULL SEARCH disabled") + + def test_one_unindexable_presence(self): + """Testing a search""" + + try: + res11 = self.l.search(base="DC=samba,DC=org", + scope=ldb.SCOPE_ONELEVEL, + expression="(y=*)") + if hasattr(self, 'IDX') and \ + not hasattr(self, 'IDXONE') and \ + hasattr(self, 'IDXCHECK'): + self.fail("Should have failed as un-indexed search") + + self.assertEqual(len(res11), 24) + + except ldb.LdbError as err: + enum = err.args[0] + estr = err.args[1] + self.assertEqual(enum, ldb.ERR_INAPPROPRIATE_MATCHING) + self.assertIn(estr, "ldb FULL SEARCH disabled") + + def test_subtree_and_or(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(|(x=z)(y=b))(x=x)(y=c))") + self.assertEqual(len(res11), 0) + + def test_subtree_and_or2(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(x=x)(y=c)(|(x=z)(y=b)))") + self.assertEqual(len(res11), 0) + + def test_subtree_and_or3(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(|(ou=ou11)(ou=ou10))(|(x=y)(y=b)(y=c)))") + self.assertEqual(len(res11), 2) + + def test_subtree_and_or4(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(|(x=y)(y=b)(y=c))(|(ou=ou11)(ou=ou10)))") + self.assertEqual(len(res11), 2) + + def test_subtree_and_or5(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(|(x=y)(y=b)(y=c))(ou=ou11))") + self.assertEqual(len(res11), 1) + + def test_subtree_or_and(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(|(x=x)(y=c)(&(x=z)(y=b)))") + self.assertEqual(len(res11), 10) + + def test_subtree_large_and_unique(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(ou=ou10)(y=a))") + self.assertEqual(len(res11), 1) + + def test_subtree_and_none(self): + """Testing a search""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(&(ou=ouX)(y=a))") + self.assertEqual(len(res11), 0) + + def test_subtree_and_idx_record(self): + """Testing a search against the index record""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(@IDXDN=DC=SAMBA,DC=ORG)") + self.assertEqual(len(res11), 0) + + def test_subtree_and_idxone_record(self): + """Testing a search against the index record""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(@IDXONE=DC=SAMBA,DC=ORG)") + self.assertEqual(len(res11), 0) + + def test_subtree_unindexable(self): + """Testing a search""" + + try: + res11 = self.l.search(base="DC=samba,DC=org", + scope=ldb.SCOPE_SUBTREE, + expression="(y=b*)") + if hasattr(self, 'IDX') and \ + hasattr(self, 'IDXCHECK'): + self.fail("Should have failed as un-indexed search") + + self.assertEqual(len(res11), 9) + + except ldb.LdbError as err: + enum = err.args[0] + estr = err.args[1] + self.assertEqual(enum, ldb.ERR_INAPPROPRIATE_MATCHING) + self.assertIn(estr, "ldb FULL SEARCH disabled") + + def test_subtree_unindexable_presence(self): + """Testing a search""" + + try: + res11 = self.l.search(base="DC=samba,DC=org", + scope=ldb.SCOPE_SUBTREE, + expression="(y=*)") + if hasattr(self, 'IDX') and \ + hasattr(self, 'IDXCHECK'): + self.fail("Should have failed as un-indexed search") + + self.assertEqual(len(res11), 24) + + except ldb.LdbError as err: + enum = err.args[0] + estr = err.args[1] + self.assertEqual(enum, ldb.ERR_INAPPROPRIATE_MATCHING) + self.assertIn(estr, "ldb FULL SEARCH disabled") + + def test_dn_filter_one(self): + """Testing that a dn= filter succeeds + (or fails with disallowDNFilter + set and IDXGUID or (IDX and not IDXONE) mode) + when the scope is SCOPE_ONELEVEL. + + This should be made more consistent, but for now lock in + the behaviour + + """ + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(dn=OU=OU1,DC=SAMBA,DC=ORG)") + if hasattr(self, 'disallowDNFilter') and \ + hasattr(self, 'IDX') and \ + (hasattr(self, 'IDXGUID') or + ((hasattr(self, 'IDXONE') == False and hasattr(self, 'IDX')))): + self.assertEqual(len(res11), 0) + else: + self.assertEqual(len(res11), 1) + + def test_dn_filter_subtree(self): + """Testing that a dn= filter succeeds + (or fails with disallowDNFilter set) + when the scope is SCOPE_SUBTREE""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(dn=OU=OU1,DC=SAMBA,DC=ORG)") + if hasattr(self, 'disallowDNFilter') \ + and hasattr(self, 'IDX'): + self.assertEqual(len(res11), 0) + else: + self.assertEqual(len(res11), 1) + + def test_dn_filter_base(self): + """Testing that (incorrectly) a dn= filter works + when the scope is SCOPE_BASE""" + + res11 = self.l.search(base="OU=OU1,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(dn=OU=OU1,DC=SAMBA,DC=ORG)") + + # At some point we should fix this, but it isn't trivial + self.assertEqual(len(res11), 1) + + def test_distinguishedName_filter_one(self): + """Testing that a distinguishedName= filter succeeds + when the scope is SCOPE_ONELEVEL. + + This should be made more consistent, but for now lock in + the behaviour + + """ + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(distinguishedName=OU=OU1,DC=SAMBA,DC=ORG)") + self.assertEqual(len(res11), 1) + + def test_distinguishedName_filter_subtree(self): + """Testing that a distinguishedName= filter succeeds + when the scope is SCOPE_SUBTREE""" + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(distinguishedName=OU=OU1,DC=SAMBA,DC=ORG)") + self.assertEqual(len(res11), 1) + + def test_distinguishedName_filter_base(self): + """Testing that (incorrectly) a distinguishedName= filter works + when the scope is SCOPE_BASE""" + + res11 = self.l.search(base="OU=OU1,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(distinguishedName=OU=OU1,DC=SAMBA,DC=ORG)") + + # At some point we should fix this, but it isn't trivial + self.assertEqual(len(res11), 1) + + def test_bad_dn_filter_base(self): + """Testing that a dn= filter on an invalid DN works + when the scope is SCOPE_BASE but + returns zero results""" + + res11 = self.l.search(base="OU=OU1,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(dn=OU=OU1,DC=SAMBA,DCXXXX)") + + # At some point we should fix this, but it isn't trivial + self.assertEqual(len(res11), 0) + + + def test_bad_dn_filter_one(self): + """Testing that a dn= filter succeeds but returns zero + results when the DN is not valid on a SCOPE_ONELEVEL search + + """ + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(dn=OU=OU1,DC=SAMBA,DCXXXX)") + self.assertEqual(len(res11), 0) + + def test_bad_dn_filter_subtree(self): + """Testing that a dn= filter succeeds but returns zero + results when the DN is not valid on a SCOPE_SUBTREE search + + """ + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(dn=OU=OU1,DC=SAMBA,DCXXXX)") + self.assertEqual(len(res11), 0) + + def test_bad_distinguishedName_filter_base(self): + """Testing that a distinguishedName= filter on an invalid DN works + when the scope is SCOPE_BASE but + returns zero results""" + + res11 = self.l.search(base="OU=OU1,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE, + expression="(distinguishedName=OU=OU1,DC=SAMBA,DCXXXX)") + + # At some point we should fix this, but it isn't trivial + self.assertEqual(len(res11), 0) + + + def test_bad_distinguishedName_filter_one(self): + """Testing that a distinguishedName= filter succeeds but returns zero + results when the DN is not valid on a SCOPE_ONELEVEL search + + """ + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression="(distinguishedName=OU=OU1,DC=SAMBA,DCXXXX)") + self.assertEqual(len(res11), 0) + + def test_bad_distinguishedName_filter_subtree(self): + """Testing that a distinguishedName= filter succeeds but returns zero + results when the DN is not valid on a SCOPE_SUBTREE search + + """ + + res11 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(distinguishedName=OU=OU1,DC=SAMBA,DCXXXX)") + self.assertEqual(len(res11), 0) + + def test_bad_dn_search_base(self): + """Testing with a bad base DN (SCOPE_BASE)""" + + try: + res11 = self.l.search(base="OU=OU1,DC=SAMBA,DCXXX", + scope=ldb.SCOPE_BASE) + self.fail("Should have failed with ERR_INVALID_DN_SYNTAX") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_INVALID_DN_SYNTAX) + + + def test_bad_dn_search_one(self): + """Testing with a bad base DN (SCOPE_ONELEVEL)""" + + try: + res11 = self.l.search(base="DC=SAMBA,DCXXXX", + scope=ldb.SCOPE_ONELEVEL) + self.fail("Should have failed with ERR_INVALID_DN_SYNTAX") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_INVALID_DN_SYNTAX) + + def test_bad_dn_search_subtree(self): + """Testing with a bad base DN (SCOPE_SUBTREE)""" + + try: + res11 = self.l.search(base="DC=SAMBA,DCXXXX", + scope=ldb.SCOPE_SUBTREE) + self.fail("Should have failed with ERR_INVALID_DN_SYNTAX") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_INVALID_DN_SYNTAX) + + + +# Run the search tests against an lmdb backend +class SearchTestsLmdb(SearchTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + self.index = MDB_INDEX_OBJ + super(SearchTestsLmdb, self).setUp() + + def tearDown(self): + super(SearchTestsLmdb, self).tearDown() + + +class IndexedSearchTests(SearchTests): + """Test searches using the index, to ensure the index doesn't + break things""" + + def setUp(self): + super(IndexedSearchTests, self).setUp() + self.l.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"]}) + self.IDX = True + + +class IndexedCheckSearchTests(IndexedSearchTests): + """Test searches using the index, to ensure the index doesn't + break things (full scan disabled)""" + + def setUp(self): + self.IDXCHECK = True + super(IndexedCheckSearchTests, self).setUp() + + +class IndexedSearchDnFilterTests(SearchTests): + """Test searches using the index, to ensure the index doesn't + break things""" + + def setUp(self): + super(IndexedSearchDnFilterTests, self).setUp() + self.l.add({"dn": "@OPTIONS", + "disallowDNFilter": "TRUE"}) + self.disallowDNFilter = True + + self.l.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"]}) + self.IDX = True + + +class IndexedAndOneLevelSearchTests(SearchTests): + """Test searches using the index including @IDXONE, to ensure + the index doesn't break things""" + + def setUp(self): + super(IndexedAndOneLevelSearchTests, self).setUp() + self.l.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXONE": [b"1"]}) + self.IDX = True + self.IDXONE = True + + +class IndexedCheckedAndOneLevelSearchTests(IndexedAndOneLevelSearchTests): + """Test searches using the index including @IDXONE, to ensure + the index doesn't break things (full scan disabled)""" + + def setUp(self): + self.IDXCHECK = True + super(IndexedCheckedAndOneLevelSearchTests, self).setUp() + + +class IndexedAndOneLevelDNFilterSearchTests(SearchTests): + """Test searches using the index including @IDXONE, to ensure + the index doesn't break things""" + + def setUp(self): + super(IndexedAndOneLevelDNFilterSearchTests, self).setUp() + self.l.add({"dn": "@OPTIONS", + "disallowDNFilter": "TRUE", + "checkBaseOnSearch": "TRUE"}) + self.disallowDNFilter = True + self.checkBaseOnSearch = True + + self.l.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXONE": [b"1"]}) + self.IDX = True + self.IDXONE = True + + +class GUIDIndexedSearchTests(SearchTests): + """Test searches using the index, to ensure the index doesn't + break things""" + + def setUp(self): + self.index = {"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]} + super(GUIDIndexedSearchTests, self).setUp() + + self.IDXGUID = True + self.IDXONE = True + + +class GUIDIndexedDNFilterSearchTests(SearchTests): + """Test searches using the index, to ensure the index doesn't + break things""" + + def setUp(self): + self.index = {"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]} + super(GUIDIndexedDNFilterSearchTests, self).setUp() + self.l.add({"dn": "@OPTIONS", + "disallowDNFilter": "TRUE", + "checkBaseOnSearch": "TRUE"}) + self.disallowDNFilter = True + self.checkBaseOnSearch = True + self.IDX = True + self.IDXGUID = True + + +class GUIDAndOneLevelIndexedSearchTests(SearchTests): + """Test searches using the index including @IDXONE, to ensure + the index doesn't break things""" + + def setUp(self): + self.index = {"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]} + super(GUIDAndOneLevelIndexedSearchTests, self).setUp() + self.l.add({"dn": "@OPTIONS", + "disallowDNFilter": "TRUE", + "checkBaseOnSearch": "TRUE"}) + self.disallowDNFilter = True + self.checkBaseOnSearch = True + self.IDX = True + self.IDXGUID = True + self.IDXONE = True + + +class GUIDIndexedSearchTestsLmdb(GUIDIndexedSearchTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(GUIDIndexedSearchTestsLmdb, self).setUp() + + def tearDown(self): + super(GUIDIndexedSearchTestsLmdb, self).tearDown() + + +class GUIDIndexedDNFilterSearchTestsLmdb(GUIDIndexedDNFilterSearchTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(GUIDIndexedDNFilterSearchTestsLmdb, self).setUp() + + def tearDown(self): + super(GUIDIndexedDNFilterSearchTestsLmdb, self).tearDown() + + +class GUIDAndOneLevelIndexedSearchTestsLmdb(GUIDAndOneLevelIndexedSearchTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(GUIDAndOneLevelIndexedSearchTestsLmdb, self).setUp() + + def tearDown(self): + super(GUIDAndOneLevelIndexedSearchTestsLmdb, self).tearDown() + + +class AddModifyTests(LdbBaseTest): + def tearDown(self): + shutil.rmtree(self.testdir) + super(AddModifyTests, self).tearDown() + + # Ensure the LDB is closed now, so we close the FD + del(self.l) + + def setUp(self): + super(AddModifyTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "add_test.ldb") + self.l = ldb.Ldb(self.url(), + flags=self.flags(), + options=["modules:rdn_name"]) + try: + self.l.add(self.index) + except AttributeError: + pass + + self.l.add({"dn": "DC=SAMBA,DC=ORG", + "name": b"samba.org", + "objectUUID": b"0123456789abcdef"}) + self.l.add({"dn": "@ATTRIBUTES", + "objectUUID": "UNIQUE_INDEX"}) + + def test_add_dup(self): + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + try: + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + self.fail("Should have failed adding dupliate entry") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + def test_add_bad(self): + try: + self.l.add({"dn": "BAD,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + self.fail("Should have failed adding entry with invalid DN") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_INVALID_DN_SYNTAX) + + def test_add_del_add(self): + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + self.l.delete("OU=DUP,DC=SAMBA,DC=ORG") + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + + def test_add_move_add(self): + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + self.l.rename("OU=DUP,DC=SAMBA,DC=ORG", + "OU=DUP2,DC=SAMBA,DC=ORG") + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + + def test_add_move_fail_move_move(self): + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + + res2 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(objectUUID=0123456789abcde1)") + self.assertEqual(len(res2), 1) + self.assertEqual(str(res2[0].dn), "OU=DUP,DC=SAMBA,DC=ORG") + + res3 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(objectUUID=0123456789abcde2)") + self.assertEqual(len(res3), 1) + self.assertEqual(str(res3[0].dn), "OU=DUP2,DC=SAMBA,DC=ORG") + + try: + self.l.rename("OU=DUP,DC=SAMBA,DC=ORG", + "OU=DUP2,DC=SAMBA,DC=ORG") + self.fail("Should have failed on duplicate DN") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + self.l.rename("OU=DUP2,DC=SAMBA,DC=ORG", + "OU=DUP3,DC=SAMBA,DC=ORG") + + self.l.rename("OU=DUP,DC=SAMBA,DC=ORG", + "OU=DUP2,DC=SAMBA,DC=ORG") + + res2 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(objectUUID=0123456789abcde1)") + self.assertEqual(len(res2), 1) + self.assertEqual(str(res2[0].dn), "OU=DUP2,DC=SAMBA,DC=ORG") + + res3 = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(objectUUID=0123456789abcde2)") + self.assertEqual(len(res3), 1) + self.assertEqual(str(res3[0].dn), "OU=DUP3,DC=SAMBA,DC=ORG") + + def test_move_missing(self): + try: + self.l.rename("OU=DUP,DC=SAMBA,DC=ORG", + "OU=DUP2,DC=SAMBA,DC=ORG") + self.fail("Should have failed on missing") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_NO_SUCH_OBJECT) + + def test_move_missing2(self): + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + + try: + self.l.rename("OU=DUP,DC=SAMBA,DC=ORG", + "OU=DUP2,DC=SAMBA,DC=ORG") + self.fail("Should have failed on missing") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_NO_SUCH_OBJECT) + + def test_move_bad(self): + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + + try: + self.l.rename("OUXDUP,DC=SAMBA,DC=ORG", + "OU=DUP2,DC=SAMBA,DC=ORG") + self.fail("Should have failed on invalid DN") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_INVALID_DN_SYNTAX) + + def test_move_bad2(self): + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + + try: + self.l.rename("OU=DUP,DC=SAMBA,DC=ORG", + "OUXDUP2,DC=SAMBA,DC=ORG") + self.fail("Should have failed on missing") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_INVALID_DN_SYNTAX) + + def test_move_fail_move_add(self): + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + try: + self.l.rename("OU=DUP,DC=SAMBA,DC=ORG", + "OU=DUP2,DC=SAMBA,DC=ORG") + self.fail("Should have failed on duplicate DN") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + self.l.rename("OU=DUP2,DC=SAMBA,DC=ORG", + "OU=DUP3,DC=SAMBA,DC=ORG") + + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde3"}) + + +class AddModifyTestsLmdb(AddModifyTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + self.index = MDB_INDEX_OBJ + super(AddModifyTestsLmdb, self).setUp() + + def tearDown(self): + super(AddModifyTestsLmdb, self).tearDown() + + +class IndexedAddModifyTests(AddModifyTests): + """Test searches using the index, to ensure the index doesn't + break things""" + + def setUp(self): + if not hasattr(self, 'index'): + self.index = {"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou", b"objectUUID", b"z"], + "@IDXONE": [b"1"]} + super(IndexedAddModifyTests, self).setUp() + + def test_duplicate_GUID(self): + try: + self.l.add({"dn": "OU=DUPGUID,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcdef"}) + self.fail("Should have failed adding dupliate GUID") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_CONSTRAINT_VIOLATION) + + def test_duplicate_name_dup_GUID(self): + self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"a123456789abcdef"}) + try: + self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"a123456789abcdef"}) + self.fail("Should have failed adding dupliate GUID") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + def test_duplicate_name_dup_GUID2(self): + self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"abc3456789abcdef"}) + try: + self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"aaa3456789abcdef"}) + self.fail("Should have failed adding dupliate DN") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + # Checking the GUID didn't stick in the index + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"aaa3456789abcdef"}) + + def test_add_dup_guid_add(self): + self.l.add({"dn": "OU=DUP,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + try: + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde1"}) + self.fail("Should have failed on duplicate GUID") + + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_CONSTRAINT_VIOLATION) + + self.l.add({"dn": "OU=DUP2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "x": "z", "y": "a", + "objectUUID": b"0123456789abcde2"}) + + def test_duplicate_index_values(self): + self.l.add({"dn": "OU=DIV1,DC=SAMBA,DC=ORG", + "name": b"Admins", + "z": "1", + "objectUUID": b"0123456789abcdff"}) + self.l.add({"dn": "OU=DIV2,DC=SAMBA,DC=ORG", + "name": b"Admins", + "z": "1", + "objectUUID": b"0123456789abcdfd"}) + + +class GUIDIndexedAddModifyTests(IndexedAddModifyTests): + """Test searches using the index, to ensure the index doesn't + break things""" + + def setUp(self): + self.index = {"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXONE": [b"1"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]} + super(GUIDIndexedAddModifyTests, self).setUp() + + +class GUIDTransIndexedAddModifyTests(GUIDIndexedAddModifyTests): + """Test GUID index behaviour insdie the transaction""" + + def setUp(self): + super(GUIDTransIndexedAddModifyTests, self).setUp() + self.l.transaction_start() + + def tearDown(self): + self.l.transaction_commit() + super(GUIDTransIndexedAddModifyTests, self).tearDown() + + +class TransIndexedAddModifyTests(IndexedAddModifyTests): + """Test index behaviour insdie the transaction""" + + def setUp(self): + super(TransIndexedAddModifyTests, self).setUp() + self.l.transaction_start() + + def tearDown(self): + self.l.transaction_commit() + super(TransIndexedAddModifyTests, self).tearDown() + + +class GuidIndexedAddModifyTestsLmdb(GUIDIndexedAddModifyTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(GuidIndexedAddModifyTestsLmdb, self).setUp() + + def tearDown(self): + super(GuidIndexedAddModifyTestsLmdb, self).tearDown() + + +class GuidTransIndexedAddModifyTestsLmdb(GUIDTransIndexedAddModifyTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(GuidTransIndexedAddModifyTestsLmdb, self).setUp() + + def tearDown(self): + super(GuidTransIndexedAddModifyTestsLmdb, self).tearDown() + + +class BadIndexTests(LdbBaseTest): + def setUp(self): + super(BadIndexTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "test.ldb") + self.ldb = ldb.Ldb(self.url(), flags=self.flags()) + if hasattr(self, 'IDXGUID'): + self.ldb.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]}) + else: + self.ldb.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"]}) + + super(BadIndexTests, self).setUp() + + def test_unique(self): + self.ldb.add({"dn": "x=x,dc=samba,dc=org", + "objectUUID": b"0123456789abcde1", + "y": "1"}) + self.ldb.add({"dn": "x=y,dc=samba,dc=org", + "objectUUID": b"0123456789abcde2", + "y": "1"}) + self.ldb.add({"dn": "x=z,dc=samba,dc=org", + "objectUUID": b"0123456789abcde3", + "y": "1"}) + + res = self.ldb.search(expression="(y=1)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 3) + + # Now set this to unique index, but forget to check the result + try: + self.ldb.add({"dn": "@ATTRIBUTES", + "y": "UNIQUE_INDEX"}) + self.fail() + except ldb.LdbError: + pass + + # We must still have a working index + res = self.ldb.search(expression="(y=1)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 3) + + def test_unique_transaction(self): + self.ldb.add({"dn": "x=x,dc=samba,dc=org", + "objectUUID": b"0123456789abcde1", + "y": "1"}) + self.ldb.add({"dn": "x=y,dc=samba,dc=org", + "objectUUID": b"0123456789abcde2", + "y": "1"}) + self.ldb.add({"dn": "x=z,dc=samba,dc=org", + "objectUUID": b"0123456789abcde3", + "y": "1"}) + + res = self.ldb.search(expression="(y=1)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 3) + + self.ldb.transaction_start() + + # Now set this to unique index, but forget to check the result + try: + self.ldb.add({"dn": "@ATTRIBUTES", + "y": "UNIQUE_INDEX"}) + except ldb.LdbError: + pass + + try: + self.ldb.transaction_commit() + self.fail() + + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_OPERATIONS_ERROR) + + # We must still have a working index + res = self.ldb.search(expression="(y=1)", + base="dc=samba,dc=org") + + self.assertEqual(len(res), 3) + + def test_casefold(self): + self.ldb.add({"dn": "x=x,dc=samba,dc=org", + "objectUUID": b"0123456789abcde1", + "y": "a"}) + self.ldb.add({"dn": "x=y,dc=samba,dc=org", + "objectUUID": b"0123456789abcde2", + "y": "A"}) + self.ldb.add({"dn": "x=z,dc=samba,dc=org", + "objectUUID": b"0123456789abcde3", + "y": ["a", "A"]}) + + res = self.ldb.search(expression="(y=a)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 2) + + self.ldb.add({"dn": "@ATTRIBUTES", + "y": "CASE_INSENSITIVE"}) + + # We must still have a working index + res = self.ldb.search(expression="(y=a)", + base="dc=samba,dc=org") + + if hasattr(self, 'IDXGUID'): + self.assertEqual(len(res), 3) + else: + # We should not return this entry twice, but sadly + # we have not yet fixed + # https://bugzilla.samba.org/show_bug.cgi?id=13361 + self.assertEqual(len(res), 4) + + def test_casefold_transaction(self): + self.ldb.add({"dn": "x=x,dc=samba,dc=org", + "objectUUID": b"0123456789abcde1", + "y": "a"}) + self.ldb.add({"dn": "x=y,dc=samba,dc=org", + "objectUUID": b"0123456789abcde2", + "y": "A"}) + self.ldb.add({"dn": "x=z,dc=samba,dc=org", + "objectUUID": b"0123456789abcde3", + "y": ["a", "A"]}) + + res = self.ldb.search(expression="(y=a)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 2) + + self.ldb.transaction_start() + + self.ldb.add({"dn": "@ATTRIBUTES", + "y": "CASE_INSENSITIVE"}) + + self.ldb.transaction_commit() + + # We must still have a working index + res = self.ldb.search(expression="(y=a)", + base="dc=samba,dc=org") + + if hasattr(self, 'IDXGUID'): + self.assertEqual(len(res), 3) + else: + # We should not return this entry twice, but sadly + # we have not yet fixed + # https://bugzilla.samba.org/show_bug.cgi?id=13361 + self.assertEqual(len(res), 4) + + def test_modify_transaction(self): + self.ldb.add({"dn": "x=y,dc=samba,dc=org", + "objectUUID": b"0123456789abcde1", + "y": "2", + "z": "2"}) + + res = self.ldb.search(expression="(y=2)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + + self.ldb.add({"dn": "@ATTRIBUTES", + "y": "UNIQUE_INDEX"}) + + self.ldb.transaction_start() + + m = ldb.Message() + m.dn = ldb.Dn(self.ldb, "x=y,dc=samba,dc=org") + m["0"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "y") + m["1"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "not-here") + + try: + self.ldb.modify(m) + self.fail() + + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_NO_SUCH_ATTRIBUTE) + + try: + self.ldb.transaction_commit() + # We should fail here, but we want to be sure + # we fail below + + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_OPERATIONS_ERROR) + + # The index should still be pointing to x=y + res = self.ldb.search(expression="(y=2)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + + try: + self.ldb.add({"dn": "x=y2,dc=samba,dc=org", + "objectUUID": b"0123456789abcde2", + "y": "2"}) + self.fail("Added unique attribute twice") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_CONSTRAINT_VIOLATION) + + res = self.ldb.search(expression="(y=2)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), "x=y,dc=samba,dc=org") + + def tearDown(self): + super(BadIndexTests, self).tearDown() + + +class GUIDBadIndexTests(BadIndexTests): + """Test Bad index things with GUID index mode""" + + def setUp(self): + self.IDXGUID = True + + super(GUIDBadIndexTests, self).setUp() + + +class GUIDBadIndexTestsLmdb(BadIndexTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + self.index = MDB_INDEX_OBJ + self.IDXGUID = True + super(GUIDBadIndexTestsLmdb, self).setUp() + + def tearDown(self): + super(GUIDBadIndexTestsLmdb, self).tearDown() + + +class BatchModeTests(LdbBaseTest): + + def setUp(self): + super(BatchModeTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "test.ldb") + self.ldb = ldb.Ldb(self.url(), + flags=self.flags(), + options=["batch_mode:1"]) + if hasattr(self, 'IDXGUID'): + self.ldb.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]}) + else: + self.ldb.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"]}) + + def test_modify_transaction(self): + self.ldb.add({"dn": "x=y,dc=samba,dc=org", + "objectUUID": b"0123456789abcde1", + "y": "2", + "z": "2"}) + + res = self.ldb.search(expression="(y=2)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + + self.ldb.add({"dn": "@ATTRIBUTES", + "y": "UNIQUE_INDEX"}) + + self.ldb.transaction_start() + + m = ldb.Message() + m.dn = ldb.Dn(self.ldb, "x=y,dc=samba,dc=org") + m["0"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "y") + m["1"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "not-here") + + try: + self.ldb.modify(m) + self.fail() + + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_NO_SUCH_ATTRIBUTE) + + try: + self.ldb.transaction_commit() + self.fail("Commit should have failed as we were in batch mode") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_OPERATIONS_ERROR) + + def tearDown(self): + super(BatchModeTests, self).tearDown() + + +class DnTests(TestCase): + + def setUp(self): + super(DnTests, self).setUp() + self.ldb = ldb.Ldb() + + def tearDown(self): + super(DnTests, self).tearDown() + del(self.ldb) + + def test_set_dn_invalid(self): + x = ldb.Message() + + def assign(): + x.dn = "astring" + self.assertRaises(TypeError, assign) + + def test_eq(self): + x = ldb.Dn(self.ldb, "dc=foo11,bar=bloe") + y = ldb.Dn(self.ldb, "dc=foo11,bar=bloe") + self.assertEqual(x, y) + y = ldb.Dn(self.ldb, "dc=foo11,bar=blie") + self.assertNotEqual(x, y) + + def test_str(self): + x = ldb.Dn(self.ldb, "dc=foo12,bar=bloe") + self.assertEqual(x.__str__(), "dc=foo12,bar=bloe") + + def test_repr(self): + x = ldb.Dn(self.ldb, "dc=foo13,bla=blie") + self.assertEqual(x.__repr__(), "Dn('dc=foo13,bla=blie')") + + def test_get_casefold_2(self): + x = ldb.Dn(self.ldb, "dc=foo14,bar=bloe") + self.assertEqual(x.get_casefold(), "DC=FOO14,BAR=bloe") + + def test_validate(self): + x = ldb.Dn(self.ldb, "dc=foo15,bar=bloe") + self.assertTrue(x.validate()) + + def test_parent(self): + x = ldb.Dn(self.ldb, "dc=foo16,bar=bloe") + self.assertEqual("bar=bloe", x.parent().__str__()) + + def test_parent_nonexistent(self): + x = ldb.Dn(self.ldb, "@BLA") + self.assertEqual(None, x.parent()) + + def test_is_valid(self): + x = ldb.Dn(self.ldb, "dc=foo18,dc=bloe") + self.assertTrue(x.is_valid()) + x = ldb.Dn(self.ldb, "") + self.assertTrue(x.is_valid()) + + def test_is_special(self): + x = ldb.Dn(self.ldb, "dc=foo19,bar=bloe") + self.assertFalse(x.is_special()) + x = ldb.Dn(self.ldb, "@FOOBAR") + self.assertTrue(x.is_special()) + + def test_check_special(self): + x = ldb.Dn(self.ldb, "dc=foo20,bar=bloe") + self.assertFalse(x.check_special("FOOBAR")) + x = ldb.Dn(self.ldb, "@FOOBAR") + self.assertTrue(x.check_special("@FOOBAR")) + + def test_len(self): + x = ldb.Dn(self.ldb, "dc=foo21,bar=bloe") + self.assertEqual(2, len(x)) + x = ldb.Dn(self.ldb, "dc=foo21") + self.assertEqual(1, len(x)) + + def test_add_child(self): + x = ldb.Dn(self.ldb, "dc=foo22,bar=bloe") + self.assertTrue(x.add_child(ldb.Dn(self.ldb, "bla=bloe"))) + self.assertEqual("bla=bloe,dc=foo22,bar=bloe", x.__str__()) + + def test_add_base(self): + x = ldb.Dn(self.ldb, "dc=foo23,bar=bloe") + base = ldb.Dn(self.ldb, "bla=bloe") + self.assertTrue(x.add_base(base)) + self.assertEqual("dc=foo23,bar=bloe,bla=bloe", x.__str__()) + + def test_add_child_str(self): + x = ldb.Dn(self.ldb, "dc=foo22,bar=bloe") + self.assertTrue(x.add_child("bla=bloe")) + self.assertEqual("bla=bloe,dc=foo22,bar=bloe", x.__str__()) + + def test_add_base_str(self): + x = ldb.Dn(self.ldb, "dc=foo23,bar=bloe") + base = "bla=bloe" + self.assertTrue(x.add_base(base)) + self.assertEqual("dc=foo23,bar=bloe,bla=bloe", x.__str__()) + + def test_add(self): + x = ldb.Dn(self.ldb, "dc=foo24") + y = ldb.Dn(self.ldb, "bar=bla") + self.assertEqual("dc=foo24,bar=bla", str(x + y)) + + def test_remove_base_components(self): + x = ldb.Dn(self.ldb, "dc=foo24,dc=samba,dc=org") + x.remove_base_components(len(x) - 1) + self.assertEqual("dc=foo24", str(x)) + + def test_parse_ldif(self): + msgs = self.ldb.parse_ldif("dn: foo=bar\n") + msg = next(msgs) + self.assertEqual("foo=bar", str(msg[1].dn)) + self.assertTrue(isinstance(msg[1], ldb.Message)) + ldif = self.ldb.write_ldif(msg[1], ldb.CHANGETYPE_NONE) + self.assertEqual("dn: foo=bar\n\n", ldif) + + def test_parse_ldif_more(self): + msgs = self.ldb.parse_ldif("dn: foo=bar\n\n\ndn: bar=bar") + msg = next(msgs) + self.assertEqual("foo=bar", str(msg[1].dn)) + msg = next(msgs) + self.assertEqual("bar=bar", str(msg[1].dn)) + + def test_print_ldif(self): + ldif = '''dn: dc=foo27 +foo: foo + +''' + self.msg = ldb.Message(ldb.Dn(self.ldb, "dc=foo27")) + self.msg["foo"] = [b"foo"] + self.assertEqual(ldif, + self.ldb.write_ldif(self.msg, + ldb.CHANGETYPE_NONE)) + + def test_print_ldif_binary(self): + # this also confirms that ldb flags are set even without a URL) + self.ldb = ldb.Ldb(flags=ldb.FLG_SHOW_BINARY) + ldif = '''dn: dc=foo27 +foo: f +öö + +''' + self.msg = ldb.Message(ldb.Dn(self.ldb, "dc=foo27")) + self.msg["foo"] = ["f\nöö"] + self.assertEqual(ldif, + self.ldb.write_ldif(self.msg, + ldb.CHANGETYPE_NONE)) + + + def test_print_ldif_no_base64_bad(self): + ldif = '''dn: dc=foo27 +foo: f +öö + +''' + self.msg = ldb.Message(ldb.Dn(self.ldb, "dc=foo27")) + self.msg["foo"] = ["f\nöö"] + self.msg["foo"].set_flags(ldb.FLAG_FORCE_NO_BASE64_LDIF) + self.assertEqual(ldif, + self.ldb.write_ldif(self.msg, + ldb.CHANGETYPE_NONE)) + + def test_print_ldif_no_base64_good(self): + ldif = '''dn: dc=foo27 +foo: föö + +''' + self.msg = ldb.Message(ldb.Dn(self.ldb, "dc=foo27")) + self.msg["foo"] = ["föö"] + self.msg["foo"].set_flags(ldb.FLAG_FORCE_NO_BASE64_LDIF) + self.assertEqual(ldif, + self.ldb.write_ldif(self.msg, + ldb.CHANGETYPE_NONE)) + + def test_canonical_string(self): + x = ldb.Dn(self.ldb, "dc=foo25,bar=bloe") + self.assertEqual("/bloe/foo25", x.canonical_str()) + + def test_canonical_ex_string(self): + x = ldb.Dn(self.ldb, "dc=foo26,bar=bloe") + self.assertEqual("/bloe\nfoo26", x.canonical_ex_str()) + + def test_ldb_is_child_of(self): + """Testing ldb_dn_compare_dn""" + dn1 = ldb.Dn(self.ldb, "dc=base") + dn2 = ldb.Dn(self.ldb, "cn=foo,dc=base") + dn3 = ldb.Dn(self.ldb, "cn=bar,dc=base") + dn4 = ldb.Dn(self.ldb, "cn=baz,cn=bar,dc=base") + + self.assertTrue(dn1.is_child_of(dn1)) + self.assertTrue(dn2.is_child_of(dn1)) + self.assertTrue(dn4.is_child_of(dn1)) + self.assertTrue(dn4.is_child_of(dn3)) + self.assertTrue(dn4.is_child_of(dn4)) + self.assertFalse(dn3.is_child_of(dn2)) + self.assertFalse(dn1.is_child_of(dn4)) + + def test_ldb_is_child_of_str(self): + """Testing ldb_dn_compare_dn""" + dn1_str = "dc=base" + dn2_str = "cn=foo,dc=base" + dn3_str = "cn=bar,dc=base" + dn4_str = "cn=baz,cn=bar,dc=base" + + dn1 = ldb.Dn(self.ldb, dn1_str) + dn2 = ldb.Dn(self.ldb, dn2_str) + dn3 = ldb.Dn(self.ldb, dn3_str) + dn4 = ldb.Dn(self.ldb, dn4_str) + + self.assertTrue(dn1.is_child_of(dn1_str)) + self.assertTrue(dn2.is_child_of(dn1_str)) + self.assertTrue(dn4.is_child_of(dn1_str)) + self.assertTrue(dn4.is_child_of(dn3_str)) + self.assertTrue(dn4.is_child_of(dn4_str)) + self.assertFalse(dn3.is_child_of(dn2_str)) + self.assertFalse(dn1.is_child_of(dn4_str)) + + def test_get_component_name(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + self.assertEqual(dn.get_component_name(0), 'cn') + self.assertEqual(dn.get_component_name(1), 'dc') + self.assertEqual(dn.get_component_name(2), None) + self.assertEqual(dn.get_component_name(-1), None) + + def test_get_component_value(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + self.assertEqual(dn.get_component_value(0), 'foo') + self.assertEqual(dn.get_component_value(1), 'base') + self.assertEqual(dn.get_component_name(2), None) + self.assertEqual(dn.get_component_name(-1), None) + + def test_set_component(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + dn.set_component(0, 'cn', 'bar') + self.assertEqual(str(dn), "cn=bar,dc=base") + dn.set_component(1, 'o', 'asep') + self.assertEqual(str(dn), "cn=bar,o=asep") + self.assertRaises(TypeError, dn.set_component, 2, 'dc', 'base') + self.assertEqual(str(dn), "cn=bar,o=asep") + dn.set_component(1, 'o', 'a,b+c') + self.assertEqual(str(dn), r"cn=bar,o=a\,b\+c") + + def test_set_component_bytes(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + dn.set_component(0, 'cn', b'bar') + self.assertEqual(str(dn), "cn=bar,dc=base") + dn.set_component(1, 'o', b'asep') + self.assertEqual(str(dn), "cn=bar,o=asep") + + def test_set_component_none(self): + dn = ldb.Dn(self.ldb, "cn=foo,cn=bar,dc=base") + self.assertRaises(TypeError, dn.set_component, 1, 'cn', None) + + def test_get_extended_component_null(self): + dn = ldb.Dn(self.ldb, "cn=foo,cn=bar,dc=base") + self.assertEqual(dn.get_extended_component("TEST"), None) + + def test_get_extended_component(self): + self.ldb._register_test_extensions() + dn = ldb.Dn(self.ldb, ";cn=bar,dc=base") + self.assertEqual(dn.get_extended_component("TEST"), b"foo") + + def test_set_extended_component(self): + self.ldb._register_test_extensions() + dn = ldb.Dn(self.ldb, "dc=base") + dn.set_extended_component("TEST", "foo") + self.assertEqual(dn.get_extended_component("TEST"), b"foo") + dn.set_extended_component("TEST", b"bar") + self.assertEqual(dn.get_extended_component("TEST"), b"bar") + + def test_extended_str(self): + self.ldb._register_test_extensions() + dn = ldb.Dn(self.ldb, ";cn=bar,dc=base") + self.assertEqual(dn.extended_str(), ";cn=bar,dc=base") + + def test_get_rdn_name(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + self.assertEqual(dn.get_rdn_name(), 'cn') + + def test_get_rdn_value(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + self.assertEqual(dn.get_rdn_value(), 'foo') + + def test_get_casefold(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + self.assertEqual(dn.get_casefold(), 'CN=FOO,DC=BASE') + + def test_get_linearized(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + self.assertEqual(dn.get_linearized(), 'cn=foo,dc=base') + + def test_is_null(self): + dn = ldb.Dn(self.ldb, "cn=foo,dc=base") + self.assertFalse(dn.is_null()) + + dn = ldb.Dn(self.ldb, '') + self.assertTrue(dn.is_null()) + + +class LdbMsgTests(TestCase): + + def setUp(self): + super(LdbMsgTests, self).setUp() + self.msg = ldb.Message() + + def test_init_dn(self): + self.msg = ldb.Message(ldb.Dn(ldb.Ldb(), "dc=foo27")) + self.assertEqual("dc=foo27", str(self.msg.dn)) + + def test_iter_items(self): + self.assertEqual(0, len(self.msg.items())) + self.msg.dn = ldb.Dn(ldb.Ldb(), "dc=foo28") + self.assertEqual(1, len(self.msg.items())) + + def test_repr(self): + self.msg.dn = ldb.Dn(ldb.Ldb(), "dc=foo29") + self.msg["dc"] = b"foo" + if PY3: + self.assertIn(repr(self.msg), [ + "Message({'dn': Dn('dc=foo29'), 'dc': MessageElement([b'foo'])})", + "Message({'dc': MessageElement([b'foo']), 'dn': Dn('dc=foo29')})", + ]) + self.assertIn(repr(self.msg.text), [ + "Message({'dn': Dn('dc=foo29'), 'dc': MessageElement([b'foo'])}).text", + "Message({'dc': MessageElement([b'foo']), 'dn': Dn('dc=foo29')}).text", + ]) + else: + self.assertIn(repr(self.msg), [ + "Message({'dn': Dn('dc=foo29'), 'dc': MessageElement(['foo'])})", + "Message({'dc': MessageElement(['foo']), 'dn': Dn('dc=foo29')})", + ]) + self.assertIn(repr(self.msg.text), [ + "Message({'dn': Dn('dc=foo29'), 'dc': MessageElement(['foo'])}).text", + "Message({'dc': MessageElement(['foo']), 'dn': Dn('dc=foo29')}).text", + ]) + + def test_len(self): + self.assertEqual(0, len(self.msg)) + + def test_notpresent(self): + self.assertRaises(KeyError, lambda: self.msg["foo"]) + + def test_del(self): + del self.msg["foo"] + + def test_add(self): + self.msg.add(ldb.MessageElement([b"456"], ldb.FLAG_MOD_ADD, "bla")) + + def test_add_text(self): + self.msg.add(ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")) + + def test_elements_empty(self): + self.assertEqual([], self.msg.elements()) + + def test_elements(self): + el = ldb.MessageElement([b"456"], ldb.FLAG_MOD_ADD, "bla") + self.msg.add(el) + self.assertEqual([el], self.msg.elements()) + self.assertEqual([el.text], self.msg.text.elements()) + + def test_add_value(self): + self.assertEqual(0, len(self.msg)) + self.msg["foo"] = [b"foo"] + self.assertEqual(1, len(self.msg)) + + def test_add_value_text(self): + self.assertEqual(0, len(self.msg)) + self.msg["foo"] = ["foo"] + self.assertEqual(1, len(self.msg)) + + def test_add_value_multiple(self): + self.assertEqual(0, len(self.msg)) + self.msg["foo"] = [b"foo", b"bla"] + self.assertEqual(1, len(self.msg)) + self.assertEqual([b"foo", b"bla"], list(self.msg["foo"])) + + def test_add_value_multiple_text(self): + self.assertEqual(0, len(self.msg)) + self.msg["foo"] = ["foo", "bla"] + self.assertEqual(1, len(self.msg)) + self.assertEqual(["foo", "bla"], list(self.msg.text["foo"])) + + def test_set_value(self): + self.msg["foo"] = [b"fool"] + self.assertEqual([b"fool"], list(self.msg["foo"])) + self.msg["foo"] = [b"bar"] + self.assertEqual([b"bar"], list(self.msg["foo"])) + + def test_set_value_text(self): + self.msg["foo"] = ["fool"] + self.assertEqual(["fool"], list(self.msg.text["foo"])) + self.msg["foo"] = ["bar"] + self.assertEqual(["bar"], list(self.msg.text["foo"])) + + def test_keys(self): + self.msg.dn = ldb.Dn(ldb.Ldb(), "@BASEINFO") + self.msg["foo"] = [b"bla"] + self.msg["bar"] = [b"bla"] + self.assertEqual(["dn", "foo", "bar"], list(self.msg.keys())) + + def test_keys_text(self): + self.msg.dn = ldb.Dn(ldb.Ldb(), "@BASEINFO") + self.msg["foo"] = ["bla"] + self.msg["bar"] = ["bla"] + self.assertEqual(["dn", "foo", "bar"], list(self.msg.text.keys())) + + def test_dn(self): + self.msg.dn = ldb.Dn(ldb.Ldb(), "@BASEINFO") + self.assertEqual("@BASEINFO", self.msg.dn.__str__()) + + def test_get_dn(self): + self.msg.dn = ldb.Dn(ldb.Ldb(), "@BASEINFO") + self.assertEqual("@BASEINFO", self.msg.get("dn").__str__()) + + def test_dn_text(self): + self.msg.text.dn = ldb.Dn(ldb.Ldb(), "@BASEINFO") + self.assertEqual("@BASEINFO", str(self.msg.dn)) + self.assertEqual("@BASEINFO", str(self.msg.text.dn)) + + def test_get_dn_text(self): + self.msg.dn = ldb.Dn(ldb.Ldb(), "@BASEINFO") + self.assertEqual("@BASEINFO", str(self.msg.get("dn"))) + self.assertEqual("@BASEINFO", str(self.msg.text.get("dn"))) + + def test_get_invalid(self): + self.msg.dn = ldb.Dn(ldb.Ldb(), "@BASEINFO") + self.assertRaises(TypeError, self.msg.get, 42) + + def test_get_other(self): + self.msg["foo"] = [b"bar"] + self.assertEqual(b"bar", self.msg.get("foo")[0]) + self.assertEqual(b"bar", self.msg.get("foo", idx=0)) + self.assertEqual(None, self.msg.get("foo", idx=1)) + self.assertEqual("", self.msg.get("foo", default='', idx=1)) + + def test_get_other_text(self): + self.msg["foo"] = ["bar"] + self.assertEqual(["bar"], list(self.msg.text.get("foo"))) + self.assertEqual("bar", self.msg.text.get("foo")[0]) + self.assertEqual("bar", self.msg.text.get("foo", idx=0)) + self.assertEqual(None, self.msg.get("foo", idx=1)) + self.assertEqual("", self.msg.get("foo", default='', idx=1)) + + def test_get_default(self): + self.assertEqual(None, self.msg.get("tatayoyo", idx=0)) + self.assertEqual("anniecordie", self.msg.get("tatayoyo", "anniecordie")) + + def test_get_default_text(self): + self.assertEqual(None, self.msg.text.get("tatayoyo", idx=0)) + self.assertEqual("anniecordie", self.msg.text.get("tatayoyo", "anniecordie")) + + def test_get_unknown(self): + self.assertEqual(None, self.msg.get("lalalala")) + + def test_get_unknown_text(self): + self.assertEqual(None, self.msg.text.get("lalalala")) + + def test_msg_diff(self): + l = ldb.Ldb() + msgs = l.parse_ldif("dn: foo=bar\nfoo: bar\nbaz: do\n\ndn: foo=bar\nfoo: bar\nbaz: dont\n") + msg1 = next(msgs)[1] + msg2 = next(msgs)[1] + msgdiff = l.msg_diff(msg1, msg2) + self.assertEqual("foo=bar", msgdiff.get("dn").__str__()) + self.assertRaises(KeyError, lambda: msgdiff["foo"]) + self.assertEqual(1, len(msgdiff)) + + def test_equal_empty(self): + msg1 = ldb.Message() + msg2 = ldb.Message() + self.assertEqual(msg1, msg2) + + def test_equal_simplel(self): + db = ldb.Ldb() + msg1 = ldb.Message() + msg1.dn = ldb.Dn(db, "foo=bar") + msg2 = ldb.Message() + msg2.dn = ldb.Dn(db, "foo=bar") + self.assertEqual(msg1, msg2) + msg1['foo'] = b'bar' + msg2['foo'] = b'bar' + self.assertEqual(msg1, msg2) + msg2['foo'] = b'blie' + self.assertNotEqual(msg1, msg2) + msg2['foo'] = b'blie' + + def test_from_dict(self): + rec = {"dn": "dc=fromdict", + "a1": [b"a1-val1", b"a1-val1"]} + l = ldb.Ldb() + # check different types of input Flags + for flags in [ldb.FLAG_MOD_ADD, ldb.FLAG_MOD_REPLACE, ldb.FLAG_MOD_DELETE]: + m = ldb.Message.from_dict(l, rec, flags) + self.assertEqual(rec["a1"], list(m["a1"])) + self.assertEqual(flags, m["a1"].flags()) + # check input params + self.assertRaises(TypeError, ldb.Message.from_dict, dict(), rec, ldb.FLAG_MOD_REPLACE) + self.assertRaises(TypeError, ldb.Message.from_dict, l, list(), ldb.FLAG_MOD_REPLACE) + self.assertRaises(ValueError, ldb.Message.from_dict, l, rec, 0) + # Message.from_dict expects dictionary with 'dn' + err_rec = {"a1": [b"a1-val1", b"a1-val1"]} + self.assertRaises(TypeError, ldb.Message.from_dict, l, err_rec, ldb.FLAG_MOD_REPLACE) + + def test_from_dict_text(self): + rec = {"dn": "dc=fromdict", + "a1": ["a1-val1", "a1-val1"]} + l = ldb.Ldb() + # check different types of input Flags + for flags in [ldb.FLAG_MOD_ADD, ldb.FLAG_MOD_REPLACE, ldb.FLAG_MOD_DELETE]: + m = ldb.Message.from_dict(l, rec, flags) + self.assertEqual(rec["a1"], list(m.text["a1"])) + self.assertEqual(flags, m.text["a1"].flags()) + # check input params + self.assertRaises(TypeError, ldb.Message.from_dict, dict(), rec, ldb.FLAG_MOD_REPLACE) + self.assertRaises(TypeError, ldb.Message.from_dict, l, list(), ldb.FLAG_MOD_REPLACE) + self.assertRaises(ValueError, ldb.Message.from_dict, l, rec, 0) + # Message.from_dict expects dictionary with 'dn' + err_rec = {"a1": ["a1-val1", "a1-val1"]} + self.assertRaises(TypeError, ldb.Message.from_dict, l, err_rec, ldb.FLAG_MOD_REPLACE) + + def test_copy_add_message_element(self): + m = ldb.Message() + m["1"] = ldb.MessageElement([b"val 111"], ldb.FLAG_MOD_ADD, "1") + m["2"] = ldb.MessageElement([b"val 222"], ldb.FLAG_MOD_ADD, "2") + mto = ldb.Message() + mto["1"] = m["1"] + mto["2"] = m["2"] + self.assertEqual(mto["1"], m["1"]) + self.assertEqual(mto["2"], m["2"]) + mto = ldb.Message() + mto.add(m["1"]) + mto.add(m["2"]) + self.assertEqual(mto["1"], m["1"]) + self.assertEqual(mto["2"], m["2"]) + + def test_copy_add_message_element_text(self): + m = ldb.Message() + m["1"] = ldb.MessageElement(["val 111"], ldb.FLAG_MOD_ADD, "1") + m["2"] = ldb.MessageElement(["val 222"], ldb.FLAG_MOD_ADD, "2") + mto = ldb.Message() + mto["1"] = m["1"] + mto["2"] = m["2"] + self.assertEqual(mto["1"], m.text["1"]) + self.assertEqual(mto["2"], m.text["2"]) + mto = ldb.Message() + mto.add(m["1"]) + mto.add(m["2"]) + self.assertEqual(mto.text["1"], m.text["1"]) + self.assertEqual(mto.text["2"], m.text["2"]) + self.assertEqual(mto["1"], m["1"]) + self.assertEqual(mto["2"], m["2"]) + + +class MessageElementTests(TestCase): + + def test_cmp_element(self): + x = ldb.MessageElement([b"foo"]) + y = ldb.MessageElement([b"foo"]) + z = ldb.MessageElement([b"bzr"]) + self.assertEqual(x, y) + self.assertNotEqual(x, z) + + def test_cmp_element_text(self): + x = ldb.MessageElement([b"foo"]) + y = ldb.MessageElement(["foo"]) + self.assertEqual(x, y) + + def test_create_iterable(self): + x = ldb.MessageElement([b"foo"]) + self.assertEqual([b"foo"], list(x)) + self.assertEqual(["foo"], list(x.text)) + + def test_repr(self): + x = ldb.MessageElement([b"foo"]) + if PY3: + self.assertEqual("MessageElement([b'foo'])", repr(x)) + self.assertEqual("MessageElement([b'foo']).text", repr(x.text)) + else: + self.assertEqual("MessageElement(['foo'])", repr(x)) + self.assertEqual("MessageElement(['foo']).text", repr(x.text)) + x = ldb.MessageElement([b"foo", b"bla"]) + self.assertEqual(2, len(x)) + if PY3: + self.assertEqual("MessageElement([b'foo',b'bla'])", repr(x)) + self.assertEqual("MessageElement([b'foo',b'bla']).text", repr(x.text)) + else: + self.assertEqual("MessageElement(['foo','bla'])", repr(x)) + self.assertEqual("MessageElement(['foo','bla']).text", repr(x.text)) + + def test_get_item(self): + x = ldb.MessageElement([b"foo", b"bar"]) + self.assertEqual(b"foo", x[0]) + self.assertEqual(b"bar", x[1]) + self.assertEqual(b"bar", x[-1]) + self.assertRaises(IndexError, lambda: x[45]) + + def test_get_item_text(self): + x = ldb.MessageElement(["foo", "bar"]) + self.assertEqual("foo", x.text[0]) + self.assertEqual("bar", x.text[1]) + self.assertEqual("bar", x.text[-1]) + self.assertRaises(IndexError, lambda: x[45]) + + def test_len(self): + x = ldb.MessageElement([b"foo", b"bar"]) + self.assertEqual(2, len(x)) + + def test_eq(self): + x = ldb.MessageElement([b"foo", b"bar"]) + y = ldb.MessageElement([b"foo", b"bar"]) + self.assertEqual(y, x) + x = ldb.MessageElement([b"foo"]) + self.assertNotEqual(y, x) + y = ldb.MessageElement([b"foo"]) + self.assertEqual(y, x) + + def test_extended(self): + el = ldb.MessageElement([b"456"], ldb.FLAG_MOD_ADD, "bla") + if PY3: + self.assertEqual("MessageElement([b'456'])", repr(el)) + self.assertEqual("MessageElement([b'456']).text", repr(el.text)) + else: + self.assertEqual("MessageElement(['456'])", repr(el)) + self.assertEqual("MessageElement(['456']).text", repr(el.text)) + + def test_bad_text(self): + el = ldb.MessageElement(b'\xba\xdd') + self.assertRaises(UnicodeDecodeError, el.text.__getitem__, 0) + + +class ModuleTests(TestCase): + + def setUp(self): + super(ModuleTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "test.ldb") + self.ldb = ldb.Ldb(self.filename) + + def tearDown(self): + shutil.rmtree(self.testdir) + super(ModuleTests, self).setUp() + + def test_register_module(self): + class ExampleModule: + name = "example" + ldb.register_module(ExampleModule) + + def test_use_module(self): + ops = [] + + class ExampleModule: + name = "bla" + + def __init__(self, ldb, next): + ops.append("init") + self.next = next + + def search(self, *args, **kwargs): + return self.next.search(*args, **kwargs) + + def request(self, *args, **kwargs): + pass + + ldb.register_module(ExampleModule) + l = ldb.Ldb(self.filename) + l.add({"dn": "@MODULES", "@LIST": "bla"}) + self.assertEqual([], ops) + l = ldb.Ldb(self.filename) + self.assertEqual(["init"], ops) + + +class LdbResultTests(LdbBaseTest): + + def setUp(self): + super(LdbResultTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "test.ldb") + self.l = ldb.Ldb(self.url(), flags=self.flags()) + try: + self.l.add(self.index) + except AttributeError: + pass + self.l.add({"dn": "DC=SAMBA,DC=ORG", "name": b"samba.org", + "objectUUID": b"0123456789abcde0"}) + self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", "name": b"Admins", + "objectUUID": b"0123456789abcde1"}) + self.l.add({"dn": "OU=USERS,DC=SAMBA,DC=ORG", "name": b"Users", + "objectUUID": b"0123456789abcde2"}) + self.l.add({"dn": "OU=OU1,DC=SAMBA,DC=ORG", "name": b"OU #1", + "objectUUID": b"0123456789abcde3"}) + self.l.add({"dn": "OU=OU2,DC=SAMBA,DC=ORG", "name": b"OU #2", + "objectUUID": b"0123456789abcde4"}) + self.l.add({"dn": "OU=OU3,DC=SAMBA,DC=ORG", "name": b"OU #3", + "objectUUID": b"0123456789abcde5"}) + self.l.add({"dn": "OU=OU4,DC=SAMBA,DC=ORG", "name": b"OU #4", + "objectUUID": b"0123456789abcde6"}) + self.l.add({"dn": "OU=OU5,DC=SAMBA,DC=ORG", "name": b"OU #5", + "objectUUID": b"0123456789abcde7"}) + self.l.add({"dn": "OU=OU6,DC=SAMBA,DC=ORG", "name": b"OU #6", + "objectUUID": b"0123456789abcde8"}) + self.l.add({"dn": "OU=OU7,DC=SAMBA,DC=ORG", "name": b"OU #7", + "objectUUID": b"0123456789abcde9"}) + self.l.add({"dn": "OU=OU8,DC=SAMBA,DC=ORG", "name": b"OU #8", + "objectUUID": b"0123456789abcdea"}) + self.l.add({"dn": "OU=OU9,DC=SAMBA,DC=ORG", "name": b"OU #9", + "objectUUID": b"0123456789abcdeb"}) + self.l.add({"dn": "OU=OU10,DC=SAMBA,DC=ORG", "name": b"OU #10", + "objectUUID": b"0123456789abcdec"}) + + def tearDown(self): + shutil.rmtree(self.testdir) + super(LdbResultTests, self).tearDown() + # Ensure the LDB is closed now, so we close the FD + del(self.l) + + def test_return_type(self): + res = self.l.search() + self.assertEqual(str(res), "") + + def test_get_msgs(self): + res = self.l.search() + list = res.msgs + + def test_get_controls(self): + res = self.l.search() + list = res.controls + + def test_get_referals(self): + res = self.l.search() + list = res.referals + + def test_iter_msgs(self): + found = False + for l in self.l.search().msgs: + if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": + found = True + self.assertTrue(found) + + def test_iter_msgs_count(self): + self.assertTrue(self.l.search().count > 0) + # 13 objects has been added to the DC=SAMBA, DC=ORG + self.assertEqual(self.l.search(base="DC=SAMBA,DC=ORG").count, 13) + + def test_iter_controls(self): + res = self.l.search().controls + it = iter(res) + + def test_create_control(self): + self.assertRaises(ValueError, ldb.Control, self.l, "tatayoyo:0") + c = ldb.Control(self.l, "relax:1") + self.assertEqual(c.critical, True) + self.assertEqual(c.oid, "1.3.6.1.4.1.4203.666.5.12") + + def test_iter_refs(self): + res = self.l.search().referals + it = iter(res) + + def test_search_sequence_msgs(self): + found = False + res = self.l.search().msgs + + for i in range(0, len(res)): + l = res[i] + if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": + found = True + self.assertTrue(found) + + def test_search_as_iter(self): + found = False + res = self.l.search() + + for l in res: + if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": + found = True + self.assertTrue(found) + + def test_search_iter(self): + found = False + res = self.l.search_iterator() + + for l in res: + if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": + found = True + self.assertTrue(found) + + # Show that search results can't see into a transaction + + def test_search_against_trans(self): + found11 = False + + (r1, w1) = os.pipe() + + (r2, w2) = os.pipe() + + # For the first element, fork a child that will + # write to the DB + pid = os.fork() + if pid == 0: + # In the child, re-open + del(self.l) + gc.collect() + + child_ldb = ldb.Ldb(self.url(), flags=self.flags()) + # start a transaction + child_ldb.transaction_start() + + # write to it + child_ldb.add({"dn": "OU=OU11,DC=SAMBA,DC=ORG", + "name": b"samba.org", + "objectUUID": b"o123456789acbdef"}) + + os.write(w1, b"added") + + # Now wait for the search to be done + os.read(r2, 6) + + # and commit + try: + child_ldb.transaction_commit() + except ldb.LdbError as err: + # We print this here to see what went wrong in the child + print(err) + os._exit(1) + + os.write(w1, b"transaction") + os._exit(0) + + self.assertEqual(os.read(r1, 5), b"added") + + # This should not turn up until the transaction is concluded + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res11), 0) + + os.write(w2, b"search") + + # Now wait for the transaction to be done. This should + # deadlock, but the search doesn't hold a read lock for the + # iterator lifetime currently. + self.assertEqual(os.read(r1, 11), b"transaction") + + # This should now turn up, as the transaction is over + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res11), 1) + + self.assertFalse(found11) + + (got_pid, status) = os.waitpid(pid, 0) + self.assertEqual(got_pid, pid) + + def test_search_iter_against_trans(self): + found = False + found11 = False + + # We need to hold this iterator open to hold the all-record + # lock + res = self.l.search_iterator() + + (r1, w1) = os.pipe() + + (r2, w2) = os.pipe() + + # For the first element, with the sequence open (which + # means with ldb locks held), fork a child that will + # write to the DB + pid = os.fork() + if pid == 0: + # In the child, re-open + del(res) + del(self.l) + gc.collect() + + child_ldb = ldb.Ldb(self.url(), flags=self.flags()) + # start a transaction + child_ldb.transaction_start() + + # write to it + child_ldb.add({"dn": "OU=OU11,DC=SAMBA,DC=ORG", + "name": b"samba.org", + "objectUUID": b"o123456789acbdef"}) + + os.write(w1, b"added") + + # Now wait for the search to be done + os.read(r2, 6) + + # and commit + try: + child_ldb.transaction_commit() + except ldb.LdbError as err: + # We print this here to see what went wrong in the child + print(err) + os._exit(1) + + os.write(w1, b"transaction") + os._exit(0) + + self.assertEqual(os.read(r1, 5), b"added") + + # This should not turn up until the transaction is concluded + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res11), 0) + + os.write(w2, b"search") + + # allow the transaction to start + time.sleep(1) + + # This should not turn up until the search finishes and + # removed the read lock, but for ldb_tdb that happened as soon + # as we called the first res.next() + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res11), 0) + + # These results are all collected at the first next(res) call + for l in res: + if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": + found = True + if str(l.dn) == "OU=OU11,DC=SAMBA,DC=ORG": + found11 = True + + # Now wait for the transaction to be done. + self.assertEqual(os.read(r1, 11), b"transaction") + + # This should now turn up, as the transaction is over and all + # read locks are gone + res11 = self.l.search(base="OU=OU11,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res11), 1) + + self.assertTrue(found) + self.assertFalse(found11) + + (got_pid, status) = os.waitpid(pid, 0) + self.assertEqual(got_pid, pid) + + +class LdbResultTestsLmdb(LdbResultTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + self.index = MDB_INDEX_OBJ + super(LdbResultTestsLmdb, self).setUp() + + def tearDown(self): + super(LdbResultTestsLmdb, self).tearDown() + + +class BadTypeTests(TestCase): + def test_control(self): + l = ldb.Ldb() + self.assertRaises(TypeError, ldb.Control, '', 'relax:1') + self.assertRaises(TypeError, ldb.Control, ldb, 1234) + + def test_modify(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + m = ldb.Message(dn) + self.assertRaises(TypeError, l.modify, '') + self.assertRaises(TypeError, l.modify, m, '') + + def test_add(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + m = ldb.Message(dn) + self.assertRaises(TypeError, l.add, '') + self.assertRaises(TypeError, l.add, m, '') + + def test_delete(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + self.assertRaises(TypeError, l.add, '') + self.assertRaises(TypeError, l.add, dn, '') + + def test_rename(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + self.assertRaises(TypeError, l.add, '', dn) + self.assertRaises(TypeError, l.add, dn, '') + self.assertRaises(TypeError, l.add, dn, dn, '') + + def test_search(self): + l = ldb.Ldb() + self.assertRaises(TypeError, l.search, base=1234) + self.assertRaises(TypeError, l.search, scope='') + self.assertRaises(TypeError, l.search, expression=1234) + self.assertRaises(TypeError, l.search, attrs='') + self.assertRaises(TypeError, l.search, controls='') + + +class VersionTests(TestCase): + + def test_version(self): + self.assertTrue(isinstance(ldb.__version__, str)) + +class NestedTransactionTests(LdbBaseTest): + def setUp(self): + super(NestedTransactionTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "test.ldb") + self.ldb = ldb.Ldb(self.url(), flags=self.flags()) + self.ldb.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"x", b"y", b"ou"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]}) + + super(NestedTransactionTests, self).setUp() + + # + # This test documents that currently ldb does not support true nested + # transactions. + # + # Note: The test is written so that it treats failure as pass. + # It is done this way as standalone ldb builds do not use the samba + # known fail mechanism + # + def test_nested_transactions(self): + + self.ldb.transaction_start() + + self.ldb.add({"dn": "x=x1,dc=samba,dc=org", + "objectUUID": b"0123456789abcde1"}) + res = self.ldb.search(expression="(objectUUID=0123456789abcde1)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + + self.ldb.add({"dn": "x=x2,dc=samba,dc=org", + "objectUUID": b"0123456789abcde2"}) + res = self.ldb.search(expression="(objectUUID=0123456789abcde2)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + + self.ldb.transaction_start() + self.ldb.add({"dn": "x=x3,dc=samba,dc=org", + "objectUUID": b"0123456789abcde3"}) + res = self.ldb.search(expression="(objectUUID=0123456789abcde3)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + self.ldb.transaction_cancel() + # + # Check that we can not see the record added by the cancelled + # transaction. + # Currently this fails as ldb does not support true nested + # transactions, and only the outer commits and cancels have an effect + # + res = self.ldb.search(expression="(objectUUID=0123456789abcde3)", + base="dc=samba,dc=org") + # + # FIXME this test currently passes on a failure, i.e. if nested + # transaction support worked correctly the correct test would + # be. + # self.assertEqual(len(res), 0) + # as the add of objectUUID=0123456789abcde3 would reverted when + # the sub transaction it was nested in was rolled back. + # + # Currently this is not the case so the record is still present. + self.assertEqual(len(res), 1) + + + # Commit the outer transaction + # + self.ldb.transaction_commit() + # + # Now check we can still see the records added in the outer + # transaction. + # + res = self.ldb.search(expression="(objectUUID=0123456789abcde1)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + res = self.ldb.search(expression="(objectUUID=0123456789abcde2)", + base="dc=samba,dc=org") + self.assertEqual(len(res), 1) + # + # And that we can't see the records added by the nested transaction. + # + res = self.ldb.search(expression="(objectUUID=0123456789abcde3)", + base="dc=samba,dc=org") + # FIXME again if nested transactions worked correctly we would not + # see this record. The test should be. + # self.assertEqual(len(res), 0) + self.assertEqual(len(res), 1) + + def tearDown(self): + super(NestedTransactionTests, self).tearDown() + + +class LmdbNestedTransactionTests(NestedTransactionTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + self.index = MDB_INDEX_OBJ + super(LmdbNestedTransactionTests, self).setUp() + + def tearDown(self): + super(LmdbNestedTransactionTests, self).tearDown() + + +if __name__ == '__main__': + import unittest + unittest.TestProgram() diff --git a/ldb-2.0.8/tests/python/index.py b/ldb-2.0.8/tests/python/index.py new file mode 100755 index 0000000..f957087 --- /dev/null +++ b/ldb-2.0.8/tests/python/index.py @@ -0,0 +1,1455 @@ +#!/usr/bin/env python3 +# +# Tests for truncated index keys +# +# Copyright (C) Andrew Bartlett 2018 +# +# 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 . +# +"""Tests for truncated index keys + +Databases such as lmdb have a maximum key length, these tests ensure that +ldb behaves correctly in those circumstances. + +""" + +import os +from unittest import TestCase +import sys +import ldb +import shutil + +PY3 = sys.version_info > (3, 0) + +TDB_PREFIX = "tdb://" +MDB_PREFIX = "mdb://" + + +def tempdir(): + import tempfile + try: + dir_prefix = os.path.join(os.environ["SELFTEST_PREFIX"], "tmp") + except KeyError: + dir_prefix = None + return tempfile.mkdtemp(dir=dir_prefix) + + +def contains(result, dn): + if result is None: + return False + + for r in result: + if str(r["dn"]) == dn: + return True + return False + + +class LdbBaseTest(TestCase): + def setUp(self): + super(LdbBaseTest, self).setUp() + try: + if self.prefix is None: + self.prefix = TDB_PREFIX + except AttributeError: + self.prefix = TDB_PREFIX + + def tearDown(self): + super(LdbBaseTest, self).tearDown() + + def url(self): + return self.prefix + self.filename + + def flags(self): + if self.prefix == MDB_PREFIX: + return ldb.FLG_NOSYNC + else: + return 0 + + +class MaxIndexKeyLengthTests(LdbBaseTest): + def checkGuids(self, key, guids): + # + # This check relies on the current implementation where the indexes + # are in the same database as the data. + # + # It checks that the index record exists, unless guids is None then + # the record must not exist. And the it contains the expected guid + # entries. + # + # The caller needs to provide the GUID's in the expected order + # + res = self.l.search( + base=key, + scope=ldb.SCOPE_BASE) + if guids is None: + self.assertEqual(len(res), 0) + return + self.assertEqual(len(res), 1) + + # The GUID index format has only one value + index = res[0]["@IDX"][0] + self.assertEqual(len(guids), len(index)) + self.assertEqual(guids, index) + + def tearDown(self): + shutil.rmtree(self.testdir) + super(MaxIndexKeyLengthTests, self).tearDown() + + # Ensure the LDB is closed now, so we close the FD + del(self.l) + + def setUp(self): + super(MaxIndexKeyLengthTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "key_len_test.ldb") + # Note that the maximum key length is set to 54 + # This accounts for the 4 bytes added by the dn formatting + # a leading dn=, and a trailing zero terminator + # + self.l = ldb.Ldb(self.url(), + options=[ + "modules:rdn_name", + "max_key_len_for_self_test:54"]) + self.l.add({"dn": "@ATTRIBUTES", + "uniqueThing": "UNIQUE_INDEX"}) + self.l.add({"dn": "@INDEXLIST", + "@IDXATTR": [ + b"uniqueThing", + b"notUnique", + b"base64____lt", + b"base64_____eq", + b"base64______gt"], + "@IDXONE": [b"1"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]}) + + # Add a value to a unique index that exceeds the maximum key length + # This should be rejected. + def test_add_long_unique_add(self): + try: + self.l.add({"dn": "OU=UNIQUE_MAX_LEN,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcdef", + "uniqueThing": "01234567890123456789012345678901"}) + # index key will be + # "@INDEX:UNIQUETHING:01234567890123456789012345678901" + self.fail("Should have failed on long index key") + + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_CONSTRAINT_VIOLATION) + + # Test that DN's longer the maximum key length can be added + # and that duplicate DN's are rejected correctly + def test_add_long_dn_add(self): + # + # For all entries the DN index key gets truncated to + # @INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA + # + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcdef"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM", + "objectUUID": b"0123456789abcde0"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde0" + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde0" + b"0123456789abcde1" + b"0123456789abcdef") + + # Key is equal to max length does not get inserted into the truncated + # key namespace + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde5"}) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + # This key should not get truncated, as it's one character less than + # max, and will not be in the truncate name space + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde7"}) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde7") + + try: + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcde2"}) + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + try: + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM", + "objectUUID": b"0123456789abcde3"}) + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + try: + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + "objectUUID": b"0123456789abcde4"}) + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + try: + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde6"}) + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + try: + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde8"}) + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + def test_rename_truncated_dn_keys(self): + # For all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcdef"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM", + "objectUUID": b"0123456789abcde0"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde0" + b"0123456789abcdef") + + # Non conflicting rename, should succeed + self.l.rename("OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + # Index should be unchanged. + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde0" + b"0123456789abcdef") + + # Conflicting rename should fail + try: + self.l.rename("OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM", + "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_ENTRY_ALREADY_EXISTS) + + def test_delete_truncated_dn_keys(self): + # + # For all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA + # + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcdef"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde1" + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde5"}) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + # Try to delete a non existent DN with a truncated key + try: + self.l.delete("OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM") + except ldb.LdbError as err: + enum = err.args[0] + self.assertEqual(enum, ldb.ERR_NO_SUCH_OBJECT) + # Ensure that non of the other truncated DN's got deleted + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG") + self.assertEqual(len(res), 1) + + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + self.assertEqual(len(res), 1) + + # Ensure that the non truncated DN did not get deleted + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA") + self.assertEqual(len(res), 1) + + # Check the indexes are correct + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde1" + b"0123456789abcdef") + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + # delete an existing entry + self.l.delete("OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG") + + # Ensure it got deleted + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG") + self.assertEqual(len(res), 0) + + # Ensure that non of the other truncated DN's got deleted + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + self.assertEqual(len(res), 1) + + # Ensure the non truncated entry did not get deleted. + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA") + self.assertEqual(len(res), 1) + + # Check the indexes are correct + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde1") + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + # delete an existing entry + self.l.delete("OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + + # Ensure it got deleted + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXX,DC=SAMBA,DC=GOV") + self.assertEqual(len(res), 0) + + # Ensure that non of the non truncated DN's got deleted + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA") + self.assertEqual(len(res), 1) + # Check the indexes are correct + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + None) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + # delete an existing entry + self.l.delete("OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA") + + # Ensure it got deleted + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBAxxx") + self.assertEqual(len(res), 0) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + None) + + def test_search_truncated_dn_keys(self): + # + # For all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA + # + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcdef"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde1" + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde5"}) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG") + self.assertEqual(len(res), 1) + + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + self.assertEqual(len(res), 1) + + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA") + self.assertEqual(len(res), 1) + + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM") + self.assertEqual(len(res), 0) + + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + self.assertEqual(len(res), 0) + + # Non existent, key one less than truncation limit + res = self.l.search(base="OU=A_LONG_DNXXXXXXXXXXXXXX,DC=SAMBA") + self.assertEqual(len(res), 0) + + def test_search_dn_filter_truncated_dn_keys(self): + # + # For all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA + # + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcdef"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde1" + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde5"}) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + res = self.l.search( + expression="dn=OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG") + self.assertEqual(len(res), 1) + + res = self.l.search( + expression="dn=OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + self.assertEqual(len(res), 1) + + res = self.l.search( + expression="dn=OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA") + self.assertEqual(len(res), 1) + + res = self.l.search( + expression="dn=OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM") + self.assertEqual(len(res), 0) + + res = self.l.search( + expression="dn=OU=A_LONG_DNXXXXXXXXXXXX,DC=SAMBA,DC=GOV") + self.assertEqual(len(res), 0) + + # Non existent, key one less than truncation limit + res = self.l.search( + expression="dn=OU=A_LONG_DNXXXXXXXXXXXXXX,DC=SAMBA") + self.assertEqual(len(res), 0) + + def test_search_one_level_truncated_dn_keys(self): + # + # Except for the base DN's + # all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=??,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA + # The base DN-s truncate to + # @INDEX:@IDXDN:OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR + # + self.l.add({"dn": "OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcdef"}) + self.l.add({"dn": "OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcd1f"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR", + b"0123456789abcd1f" + b"0123456789abcdef") + + self.l.add({"dn": "OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcde1"}) + self.l.add({"dn": "OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcd11"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA", + b"0123456789abcd11" + b"0123456789abcde1") + + self.l.add({"dn": "OU=02,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcde2"}) + self.l.add({"dn": "OU=02,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcdf2"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=02,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA", + b"0123456789abcde2" + b"0123456789abcdf2") + + self.l.add({"dn": "OU=03,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcde3"}) + self.l.add({"dn": "OU=03,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcd13"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=03,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA", + b"0123456789abcd13" + b"0123456789abcde3") + + # This key is not truncated as it's the max_key_len + self.l.add({"dn": "OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA", + "objectUUID": b"0123456789abcde7"}) + self.checkGuids( + "@INDEX:@IDXDN:OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA", + b"0123456789abcde7") + + res = self.l.search(base="OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1", + scope=ldb.SCOPE_ONELEVEL) + self.assertEqual(len(res), 3) + self.assertTrue( + contains(res, "OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1")) + self.assertTrue( + contains(res, "OU=02,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1")) + self.assertTrue( + contains(res, "OU=03,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR1")) + + res = self.l.search(base="OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2", + scope=ldb.SCOPE_ONELEVEL) + self.assertEqual(len(res), 3) + self.assertTrue( + contains(res, "OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2")) + self.assertTrue( + contains(res, "OU=02,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2")) + self.assertTrue( + contains(res, "OU=03,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA,DC=OR2")) + + res = self.l.search(base="OU=A_LONG_DN_ONE_LVLX,DC=SAMBA", + scope=ldb.SCOPE_ONELEVEL) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=01,OU=A_LONG_DN_ONE_LVLX,DC=SAMBA")) + + def test_search_sub_tree_truncated_dn_keys(self): + # + # Except for the base DN's + # all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=??,OU=A_LONG_DN_SUB_TREE,DC=SAMBA + # The base DN-s truncate to + # @INDEX:@IDXDN:OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR + # + self.l.add({"dn": "OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcdef"}) + self.l.add({"dn": "OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcde4"}) + self.l.add({"dn": "OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR3", + "objectUUID": b"0123456789abcde8"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR", + b"0123456789abcde4" + b"0123456789abcde8" + b"0123456789abcdef") + + self.l.add({"dn": "OU=01,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcde1"}) + self.l.add({"dn": "OU=01,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcde5"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=01,OU=A_LONG_DN_SUB_TREE,DC=SAMBA", + b"0123456789abcde1" + b"0123456789abcde5") + + self.l.add({"dn": "OU=02,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcde2"}) + self.l.add({"dn": "OU=02,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcde6"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=02,OU=A_LONG_DN_SUB_TREE,DC=SAMBA", + b"0123456789abcde2" + b"0123456789abcde6") + + self.l.add({"dn": "OU=03,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcde3"}) + + self.l.add({"dn": "OU=03,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcde7"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=03,OU=A_LONG_DN_SUB_TREE,DC=SAMBA", + b"0123456789abcde3" + b"0123456789abcde7") + + self.l.add({"dn": "OU=04,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR4", + "objectUUID": b"0123456789abcde9"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=04,OU=A_LONG_DN_SUB_TREE,DC=SAMBA", + b"0123456789abcde9") + + res = self.l.search(base="OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1", + scope=ldb.SCOPE_SUBTREE) + self.assertEqual(len(res), 4) + self.assertTrue( + contains(res, "OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1")) + self.assertTrue( + contains(res, "OU=01,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1")) + self.assertTrue( + contains(res, "OU=02,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1")) + self.assertTrue( + contains(res, "OU=03,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR1")) + + res = self.l.search(base="OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2", + scope=ldb.SCOPE_SUBTREE) + self.assertEqual(len(res), 4) + self.assertTrue( + contains(res, "OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2")) + self.assertTrue( + contains(res, "OU=01,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2")) + self.assertTrue( + contains(res, "OU=02,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2")) + self.assertTrue( + contains(res, "OU=03,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR2")) + + res = self.l.search(base="OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR3", + scope=ldb.SCOPE_SUBTREE) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR3")) + + res = self.l.search(base="OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR4", + scope=ldb.SCOPE_SUBTREE) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=04,OU=A_LONG_DN_SUB_TREE,DC=SAMBA,DC=OR4")) + + def test_search_base_truncated_dn_keys(self): + # + # For all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA + # + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + "objectUUID": b"0123456789abcdef"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde1" + b"0123456789abcdef") + + self.l.add({"dn": "OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + "objectUUID": b"0123456789abcde5"}) + self.checkGuids( + "@INDEX:@IDXDN:OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + b"0123456789abcde5") + + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res), 1) + + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res), 1) + + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res), 1) + + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXXX,DC=SAMBA,DC=COM", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res), 0) + + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXX,DC=SAMBA,DC=GOV", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res), 0) + + # Non existent, key one less than truncation limit + res = self.l.search( + base="OU=A_LONG_DNXXXXXXXXXXXXXX,DC=SAMBA", + scope=ldb.SCOPE_BASE) + self.assertEqual(len(res), 0) + + # + # Test non unique index searched with truncated keys + # + def test_index_truncated_keys(self): + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + eq_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + lt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + # > than max length and differs in values that will be truncated + gt_max_b = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" + + # Add two entries with the same value, key length = max so no + # truncation. + self.l.add({"dn": "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": eq_max, + "objectUUID": b"0123456789abcde0"}) + self.checkGuids( + "@INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0") + + self.l.add({"dn": "OU=02,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": eq_max, + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + b"0123456789abcde1") + + # + # An entry outside the tree + # + self.l.add({"dn": "OU=10,OU=SEARCH_NON_UNIQUE01,DC=SAMBA,DC=ORG", + "notUnique": eq_max, + "objectUUID": b"0123456789abcd11"}) + self.checkGuids( + "@INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcd11" + b"0123456789abcde0" + b"0123456789abcde1") + + # Key longer than max so should get truncated to same key as + # the previous two entries + self.l.add({"dn": "OU=03,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": gt_max, + "objectUUID": b"0123456789abcde2"}) + # But in the truncated key space + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde2") + + # Key longer than max so should get truncated to same key as + # the previous entries but differs in the chars after max length + self.l.add({"dn": "OU=23,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": gt_max_b, + "objectUUID": b"0123456789abcd22"}) + # But in the truncated key space + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcd22" + b"0123456789abcde2") + # + # An entry outside the tree + # + self.l.add({"dn": "OU=11,OU=SEARCH_NON_UNIQUE01,DC=SAMBA,DC=ORG", + "notUnique": gt_max, + "objectUUID": b"0123456789abcd12"}) + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcd12" + b"0123456789abcd22" + b"0123456789abcde2") + + # Key shorter than max + # + self.l.add({"dn": "OU=04,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": lt_max, + "objectUUID": b"0123456789abcde3"}) + self.checkGuids( + "@INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde3") + # + # An entry outside the tree + # + self.l.add({"dn": "OU=12,OU=SEARCH_NON_UNIQUE01,DC=SAMBA,DC=ORG", + "notUnique": lt_max, + "objectUUID": b"0123456789abcd13"}) + self.checkGuids( + "@INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcd13" + b"0123456789abcde3") + + # + # search for target is max value not truncated + # should return ou's 01, 02 + # + expression = "(notUnique=" + eq_max.decode('ascii') + ")" + res = self.l.search(base="OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 2) + self.assertTrue( + contains(res, "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + self.assertTrue( + contains(res, "OU=02,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + # + # search for target is max value not truncated + # search one level up the tree, scope is ONE_LEVEL + # So should get no matches + # + expression = "(notUnique=" + eq_max.decode('ascii') + ")" + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 0) + # + # search for target is max value not truncated + # search one level up the tree, scope is SUBTREE + # So should get 3 matches + # + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression=expression) + self.assertEqual(len(res), 3) + self.assertTrue( + contains(res, "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + self.assertTrue( + contains(res, "OU=02,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + self.assertTrue( + contains(res, "OU=10,OU=SEARCH_NON_UNIQUE01,DC=SAMBA,DC=ORG")) + # + # search for target is max value + 1 so truncated + # should return ou 23 as it's gt_max_b being searched for + # + expression = "(notUnique=" + gt_max_b.decode('ascii') + ")" + res = self.l.search(base="OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=23,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + # + # search for target is max value + 1 so truncated + # should return ou 03 as it's gt_max being searched for + # + expression = "(notUnique=" + gt_max.decode('ascii') + ")" + res = self.l.search(base="OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=03,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + # + # scope one level and one level up one level up should get no matches + # + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 0) + # + # scope sub tree and one level up one level up should get 2 matches + # + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression=expression) + self.assertEqual(len(res), 2) + self.assertTrue( + contains(res, "OU=03,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + self.assertTrue( + contains(res, "OU=11,OU=SEARCH_NON_UNIQUE01,DC=SAMBA,DC=ORG")) + + # + # search for target is max value - 1 so not truncated + # should return ou 04 + # + expression = "(notUnique=" + lt_max.decode('ascii') + ")" + res = self.l.search(base="OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=04,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + # + # scope one level and one level up one level up should get no matches + # + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 0) + + # + # scope sub tree and one level up one level up should get 2 matches + # + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression=expression) + self.assertEqual(len(res), 2) + self.assertTrue( + contains(res, "OU=04,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + self.assertTrue( + contains(res, "OU=12,OU=SEARCH_NON_UNIQUE01,DC=SAMBA,DC=ORG")) + + # + # Test index key truncation for base64 encoded values + # + def test_index_truncated_base64_encoded_keys(self): + value = b"aaaaaaaaaaaaaaaaaaaa\x02" + # base64 encodes to "YWFhYWFhYWFhYWFhYWFhYWFhYWEC" + + # One less than max key length + self.l.add({"dn": "OU=01,OU=BASE64,DC=SAMBA,DC=ORG", + "base64____lt": value, + "objectUUID": b"0123456789abcde0"}) + self.checkGuids( + "@INDEX:BASE64____LT::YWFhYWFhYWFhYWFhYWFhYWFhYWEC", + b"0123456789abcde0") + + # Equal max key length + self.l.add({"dn": "OU=02,OU=BASE64,DC=SAMBA,DC=ORG", + "base64_____eq": value, + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX:BASE64_____EQ::YWFhYWFhYWFhYWFhYWFhYWFhYWEC", + b"0123456789abcde1") + + # One greater than max key length + self.l.add({"dn": "OU=03,OU=BASE64,DC=SAMBA,DC=ORG", + "base64______gt": value, + "objectUUID": b"0123456789abcde2"}) + self.checkGuids( + "@INDEX#BASE64______GT##YWFhYWFhYWFhYWFhYWFhYWFhYWE", + b"0123456789abcde2") + # + # Test adding to non unique index with identical multivalued index + # attributes + # + + def test_index_multi_valued_identical_keys(self): + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + as_eq_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + bs_eq_max = b"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + + try: + self.l.add({"dn": "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": [bs_eq_max, as_eq_max, as_eq_max], + "objectUUID": b"0123456789abcde0"}) + self.fail("Exception not thrown") + except ldb.LdbError as e: + code = e.args[0] + self.assertEqual(ldb.ERR_ATTRIBUTE_OR_VALUE_EXISTS, code) + + # + # Test non unique index with multivalued index attributes + # searched with non truncated keys + # + def test_search_index_multi_valued_truncated_keys(self): + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aa_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ab_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" + bb_gt_max = b"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + + self.l.add({"dn": "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": [aa_gt_max, ab_gt_max, bb_gt_max], + "objectUUID": b"0123456789abcde0"}) + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + + expression = "(notUnique=" + aa_gt_max.decode('ascii') + ")" + res = self.l.search(base="OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + expression = "(notUnique=" + ab_gt_max.decode('ascii') + ")" + res = self.l.search(base="OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + expression = "(notUnique=" + bb_gt_max.decode('ascii') + ")" + res = self.l.search(base="OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_ONELEVEL, + expression=expression) + self.assertEqual(len(res), 1) + self.assertTrue( + contains(res, "OU=01,OU=SEARCH_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + # + # Test deletion of records with non unique index with multivalued index + # attributes + # replicate this to test modify with modify flags i.e. DELETE, REPLACE + # + def test_delete_index_multi_valued_truncated_keys(self): + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aa_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ab_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" + bb_gt_max = b"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + cc_gt_max = b"cccccccccccccccccccccccccccccccccc" + + self.l.add({"dn": "OU=01,OU=DELETE_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": [aa_gt_max, ab_gt_max, bb_gt_max], + "objectUUID": b"0123456789abcde0"}) + self.l.add({"dn": "OU=02,OU=DELETE_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": [aa_gt_max, ab_gt_max, cc_gt_max], + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + b"0123456789abcde0" + + b"0123456789abcde1" + b"0123456789abcde1") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + b"0123456789abcde1") + + res = self.l.search( + base="DC=SAMBA,DC=ORG", + expression="(notUnique=" + aa_gt_max.decode("ascii") + ")") + self.assertEqual(2, len(res)) + self.assertTrue( + contains(res, "OU=01,OU=DELETE_NON_UNIQUE,DC=SAMBA,DC=ORG")) + self.assertTrue( + contains(res, "OU=02,OU=DELETE_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + self.l.delete("OU=02,OU=DELETE_NON_UNIQUE,DC=SAMBA,DC=ORG") + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + None) + + self.l.delete("OU=01,OU=DELETE_NON_UNIQUE,DC=SAMBA,DC=ORG") + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + None) + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + None) + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + None) + + # + # Test modification of records with non unique index with multivalued index + # attributes + # + def test_modify_index_multi_valued_truncated_keys(self): + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aa_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ab_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" + bb_gt_max = b"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + cc_gt_max = b"cccccccccccccccccccccccccccccccccc" + + self.l.add({"dn": "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": [aa_gt_max, ab_gt_max, bb_gt_max], + "objectUUID": b"0123456789abcde0"}) + self.l.add({"dn": "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG", + "notUnique": [aa_gt_max, ab_gt_max, cc_gt_max], + "objectUUID": b"0123456789abcde1"}) + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + b"0123456789abcde0" + + b"0123456789abcde1" + b"0123456789abcde1") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + b"0123456789abcde1") + + res = self.l.search( + base="DC=SAMBA,DC=ORG", + expression="(notUnique=" + aa_gt_max.decode("ascii") + ")") + self.assertEqual(2, len(res)) + self.assertTrue( + contains(res, "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG")) + self.assertTrue( + contains(res, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG")) + + # + # Modify that does not change the indexed attribute + # + msg = ldb.Message() + msg.dn = ldb.Dn(self.l, "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") + msg["notUnique"] = ldb.MessageElement( + [aa_gt_max, ab_gt_max, bb_gt_max], + ldb.FLAG_MOD_REPLACE, + "notUnique") + self.l.modify(msg) + # + # As the modify is replacing the attribute with the same contents + # there should be no changes to the indexes. + # + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + b"0123456789abcde0" + + b"0123456789abcde1" + b"0123456789abcde1") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + b"0123456789abcde1") + + # + # Modify that removes a value from the indexed attribute + # + msg = ldb.Message() + msg.dn = ldb.Dn(self.l, "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") + msg["notUnique"] = ldb.MessageElement( + [aa_gt_max, bb_gt_max], + ldb.FLAG_MOD_REPLACE, + "notUnique") + self.l.modify(msg) + + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + + b"0123456789abcde1" + b"0123456789abcde1") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + b"0123456789abcde1") + + # + # Modify that does a constrained delete the indexed attribute + # + msg = ldb.Message() + msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") + msg["notUnique"] = ldb.MessageElement( + [ab_gt_max], + ldb.FLAG_MOD_DELETE, + "notUnique") + self.l.modify(msg) + + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + b"0123456789abcde1") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + b"0123456789abcde1") + + # + # Modify that does an unconstrained delete the indexed attribute + # + msg = ldb.Message() + msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") + msg["notUnique"] = ldb.MessageElement( + [], + ldb.FLAG_MOD_DELETE, + "notUnique") + self.l.modify(msg) + + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + None) + + # + # Modify that adds a value to the indexed attribute + # + msg = ldb.Message() + msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") + msg["notUnique"] = ldb.MessageElement( + [cc_gt_max], + ldb.FLAG_MOD_ADD, + "notUnique") + self.l.modify(msg) + + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + b"0123456789abcde1") + + # + # Modify that adds a values to the indexed attribute + # + msg = ldb.Message() + msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") + msg["notUnique"] = ldb.MessageElement( + [aa_gt_max, ab_gt_max], + ldb.FLAG_MOD_ADD, + "notUnique") + self.l.modify(msg) + + self.checkGuids( + "@INDEX#NOTUNIQUE#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + b"0123456789abcde0" + + b"0123456789abcde1" + b"0123456789abcde1") + self.checkGuids( + "@INDEX#NOTUNIQUE#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + b"0123456789abcde0") + self.checkGuids( + "@INDEX#NOTUNIQUE#ccccccccccccccccccccccccccccccccc", + b"0123456789abcde1") + + # + # Test Sub tree searches when checkBaseOnSearch is enabled and the + # DN indexes are truncated and collide. + # + def test_check_base_on_search_truncated_dn_keys(self): + # + # Except for the base DN's + # all entries the DN index key gets truncated to + # 0 1 2 3 4 5 + # 12345678901234567890123456789012345678901234567890 + # @INDEX:@IDXDN:OU=??,OU=CHECK_BASE_DN_XXXX,DC=SAMBA + # The base DN-s truncate to + # @INDEX:@IDXDN:OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR + # + checkbaseonsearch = {"dn": "@OPTIONS", + "checkBaseOnSearch": b"TRUE"} + self.l.add(checkbaseonsearch) + + self.l.add({"dn": "OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcdef"}) + self.l.add({"dn": "OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcdee"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR", + b"0123456789abcdee" + b"0123456789abcdef") + + self.l.add({"dn": "OU=01,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcdec"}) + self.l.add({"dn": "OU=01,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcdeb"}) + self.l.add({"dn": "OU=01,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR3", + "objectUUID": b"0123456789abcded"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=01,OU=CHECK_BASE_DN_XXXX,DC=SAMBA", + b"0123456789abcdeb" + b"0123456789abcdec" + b"0123456789abcded") + + self.l.add({"dn": "OU=02,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR1", + "objectUUID": b"0123456789abcde0"}) + self.l.add({"dn": "OU=02,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR2", + "objectUUID": b"0123456789abcde1"}) + self.l.add({"dn": "OU=02,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR3", + "objectUUID": b"0123456789abcde2"}) + self.checkGuids( + "@INDEX#@IDXDN#OU=02,OU=CHECK_BASE_DN_XXXX,DC=SAMBA", + b"0123456789abcde0" + b"0123456789abcde1" + b"0123456789abcde2") + + res = self.l.search(base="OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR1", + scope=ldb.SCOPE_SUBTREE) + self.assertEqual(len(res), 3) + self.assertTrue( + contains(res, "OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR1")) + self.assertTrue( + contains(res, "OU=01,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR1")) + self.assertTrue( + contains(res, "OU=02,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR1")) + + res = self.l.search(base="OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR2", + scope=ldb.SCOPE_SUBTREE) + self.assertEqual(len(res), 3) + self.assertTrue( + contains(res, "OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR2")) + self.assertTrue( + contains(res, "OU=01,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR2")) + self.assertTrue( + contains(res, "OU=02,OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR2")) + + try: + res = self.l.search(base="OU=CHECK_BASE_DN_XXXX,DC=SAMBA,DC=OR3", + scope=ldb.SCOPE_SUBTREE) + self.fail("Expected exception no thrown") + except ldb.LdbError as e: + code = e.args[0] + self.assertEqual(ldb.ERR_NO_SUCH_OBJECT, code) + + +# Run the index truncation tests against an lmdb backend +class MaxIndexKeyLengthTestsLmdb(MaxIndexKeyLengthTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(MaxIndexKeyLengthTestsLmdb, self).setUp() + + def tearDown(self): + super(MaxIndexKeyLengthTestsLmdb, self).tearDown() + + +class OrderedIntegerRangeTests(LdbBaseTest): + + def tearDown(self): + shutil.rmtree(self.testdir) + super(OrderedIntegerRangeTests, self).tearDown() + + # Ensure the LDB is closed now, so we close the FD + del(self.l) + + def setUp(self): + super(OrderedIntegerRangeTests, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, "ordered_integer_test.ldb") + + self.l = ldb.Ldb(self.url(), + options=self.options()) + self.l.add({"dn": "@ATTRIBUTES", + "int64attr": "ORDERED_INTEGER"}) + self.l.add({"dn": "@INDEXLIST", + "@IDXATTR": [b"int64attr"], + "@IDXONE": [b"1"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]}) + + def options(self): + if self.prefix == MDB_PREFIX: + return ['modules:rdn_name', + 'disable_full_db_scan_for_self_test:1'] + else: + return ['modules:rdn_name'] + + def test_comparison_expression(self): + int64_max = 2**63-1 + int64_min = -2**63 + test_nums = list(range(-5, 5)) + test_nums += list(range(int64_max-5, int64_max+1)) + test_nums += list(range(int64_min, int64_min+5)) + test_nums = sorted(test_nums) + + for (i, num) in enumerate(test_nums): + ouuid = 0x0123456789abcdef + i + ouuid_s = bytes(('0' + hex(ouuid)[2:]).encode()) + self.l.add({"dn": "OU=COMPTESTOU{},DC=SAMBA,DC=ORG".format(i), + "objectUUID": ouuid_s, + "int64attr": str(num)}) + + def assert_int64_expr(expr, py_expr=None): + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(int64attr%s)" % (expr)) + + if not py_expr: + py_expr = expr + expect = [n for n in test_nums if eval(str(n) + py_expr)] + vals = sorted([int(r.get("int64attr")[0]) for r in res]) + self.assertEqual(len(res), len(expect)) + self.assertEqual(set(vals), set(expect)) + self.assertEqual(expect, vals) + + assert_int64_expr(">=-2") + assert_int64_expr("<=2") + assert_int64_expr(">=" + str(int64_min)) + assert_int64_expr("<=" + str(int64_min)) + assert_int64_expr("<=" + str(int64_min+1)) + assert_int64_expr("<=" + str(int64_max)) + assert_int64_expr(">=" + str(int64_max)) + assert_int64_expr(">=" + str(int64_max-1)) + assert_int64_expr("=10", "==10") + + def test_comparison_expression_duplicates(self): + int64_max = 2**63-1 + int64_min = -2**63 + test_nums = list(range(-5, 5)) * 3 + test_nums += list(range(-20, 20, 5)) * 2 + test_nums += list(range(-50, 50, 15)) + test_nums = sorted(test_nums) + + for (i, num) in enumerate(test_nums): + ouuid = 0x0123456789abcdef + i + ouuid_s = bytes(('0' + hex(ouuid)[2:]).encode()) + self.l.add({"dn": "OU=COMPTESTOU{},DC=SAMBA,DC=ORG".format(i), + "objectUUID": ouuid_s, + "int64attr": str(num)}) + + def assert_int64_expr(expr, py_expr=None): + res = self.l.search(base="DC=SAMBA,DC=ORG", + scope=ldb.SCOPE_SUBTREE, + expression="(int64attr%s)" % (expr)) + + if not py_expr: + py_expr = expr + expect = [n for n in test_nums if eval(str(n) + py_expr)] + vals = sorted([int(r.get("int64attr")[0]) for r in res]) + self.assertEqual(len(res), len(expect)) + self.assertEqual(set(vals), set(expect)) + self.assertEqual(expect, vals) + + assert_int64_expr(">=-2") + assert_int64_expr("<=2") + assert_int64_expr(">=" + str(int64_min)) + assert_int64_expr("<=" + str(int64_min)) + assert_int64_expr("<=" + str(int64_min+1)) + assert_int64_expr("<=" + str(int64_max)) + assert_int64_expr(">=" + str(int64_max)) + assert_int64_expr(">=" + str(int64_max-1)) + assert_int64_expr("=-5", "==-5") + assert_int64_expr("=5", "==5") + + +# Run the ordered integer range tests against an lmdb backend +class OrderedIntegerRangeTestsLmdb(OrderedIntegerRangeTests): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(OrderedIntegerRangeTestsLmdb, self).setUp() + + def tearDown(self): + super(OrderedIntegerRangeTestsLmdb, self).tearDown() + + +# Run the index truncation tests against an lmdb backend +class RejectSubDBIndex(LdbBaseTest): + + def setUp(self): + if os.environ.get('HAVE_LMDB', '1') == '0': + self.skipTest("No lmdb backend") + self.prefix = MDB_PREFIX + super(RejectSubDBIndex, self).setUp() + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, + "reject_subidx_test.ldb") + self.l = ldb.Ldb(self.url(), + options=[ + "modules:rdn_name"]) + + def tearDown(self): + super(RejectSubDBIndex, self).tearDown() + + def test_try_subdb_index(self): + try: + self.l.add({"dn": "@INDEXLIST", + "@IDX_LMDB_SUBDB": [b"1"], + "@IDXONE": [b"1"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"], + }) + except ldb.LdbError as e: + code = e.args[0] + string = e.args[1] + self.assertEqual(ldb.ERR_OPERATIONS_ERROR, code) + self.assertIn("sub-database index", string) + + +if __name__ == '__main__': + import unittest + unittest.TestProgram() diff --git a/ldb-2.0.8/tests/python/repack.py b/ldb-2.0.8/tests/python/repack.py new file mode 100644 index 0000000..0844cd2 --- /dev/null +++ b/ldb-2.0.8/tests/python/repack.py @@ -0,0 +1,204 @@ +import os +from unittest import TestCase +import shutil +from subprocess import check_output +import ldb + +TDB_PREFIX = "tdb://" +MDB_PREFIX = "mdb://" + +def tempdir(): + import tempfile + try: + dir_prefix = os.path.join(os.environ["SELFTEST_PREFIX"], "tmp") + except KeyError: + dir_prefix = None + return tempfile.mkdtemp(dir=dir_prefix) + + +# Check enabling and disabling GUID indexing works and that the database is +# repacked at version 2 if GUID indexing is enabled, or version 1 if disabled. +class GUIDIndexAndPackFormatTests(TestCase): + prefix = TDB_PREFIX + + def setup_newdb(self): + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, + "guidpackformattest.ldb") + url = self.prefix + self.filename + self.l = ldb.Ldb(url, options=["modules:"]) + + self.num_recs_added = 0 + + #guidindexpackv1.ldb is a pre-made database packed with version 1 format + #but with GUID indexing enabled, which is not allowed, so Samba should + #repack the database on the first transaction. + def setup_premade_v1_db(self): + db_name = "guidindexpackv1.ldb" + this_file_dir = os.path.dirname(os.path.abspath(__file__)) + db_path = os.path.join(this_file_dir, "../", db_name) + self.testdir = tempdir() + self.filename = os.path.join(self.testdir, db_name) + + shutil.copy(db_path, self.filename) + + url = self.prefix + self.filename + self.l = ldb.Ldb(url, options=["modules:"]) + self.num_recs_added = 10 + + def tearDown(self): + if hasattr(self, 'testdir'): + shutil.rmtree(self.testdir) + + def add_one_rec(self): + ouuid = 0x0123456789abcdef + self.num_recs_added + ouuid_s = '0' + hex(ouuid)[2:] + dn = "OU=GUIDPFTEST{},DC=SAMBA,DC=ORG".format(self.num_recs_added) + rec = {"dn": dn, "objectUUID": ouuid_s, "distinguishedName": dn} + self.l.add(rec) + self.num_recs_added += 1 + + # Turn GUID back into a str for easier comparisons + return rec + + def set_guid_indexing(self, enable=True): + modmsg = ldb.Message() + modmsg.dn = ldb.Dn(self.l, '@INDEXLIST') + + attrs = {"@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]} + for attr, val in attrs.items(): + replace = ldb.FLAG_MOD_REPLACE + el = val if enable else [] + el = ldb.MessageElement(elements=el, flags=replace, name=attr) + modmsg.add(el) + + self.l.modify(modmsg) + + # Parse out the comments above each record that ldbdump produces + # containing pack format version and KV level key for each record. + # Return all GUID index keys and the set of all unique pack formats. + def ldbdump_guid_keys_pack_formats(self): + dump = check_output(["bin/ldbdump", "-i", self.filename]) + dump = dump.decode("utf-8") + dump = dump.split("\n") + + comments = [s for s in dump if s.startswith("#")] + + guid_key_tag = "# key: GUID=" + guid_keys = {c[len(guid_key_tag):] for c in comments + if c.startswith(guid_key_tag)} + + pack_format_tag = "# pack format: " + pack_formats = {c[len(pack_format_tag):] for c in comments + if c.startswith(pack_format_tag)} + pack_formats = [int(s, 16) for s in pack_formats] + + return guid_keys, pack_formats + + # Put the whole database in a dict so we can easily check the database + # hasn't changed + def get_database(self): + recs = self.l.search(base="", scope=ldb.SCOPE_SUBTREE, expression="") + db = dict() + for r in recs: + dn = str(r.dn) + self.assertNotIn(dn, db) + db[dn] = dict() + for k in r.keys(): + k = str(k) + db[dn][k] = str(r.get(k)) + return db + + # Toggle GUID indexing on and off a few times, and check that when GUID + # indexing is enabled, the database is repacked to pack format V2, and + # when GUID indexing is disabled again, the database is repacked with + # pack format V1. + def toggle_guidindex_check_pack(self): + expect_db = self.get_database() + + for enable in [False, False, True, False, True, True, False]: + pf = ldb.PACKING_FORMAT_V2 if enable else ldb.PACKING_FORMAT + + self.set_guid_indexing(enable=enable) + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + num_guid_keys = self.num_recs_added if enable else 0 + self.assertEqual(len(guid_keys), num_guid_keys) + self.assertEqual(pack_formats, [pf]) + self.assertEqual(self.get_database(), expect_db) + + rec = self.add_one_rec() + expect_db[rec['dn']] = rec + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + num_guid_keys = self.num_recs_added if enable else 0 + self.assertEqual(len(guid_keys), num_guid_keys) + self.assertEqual(pack_formats, [pf]) + self.assertEqual(self.get_database(), expect_db) + + # Check a newly created database is initially packed at V1, then is + # repacked at V2 when GUID indexing is enabled. + def test_repack(self): + self.setup_newdb() + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + self.assertEqual(len(guid_keys), 0) + self.assertEqual(pack_formats, [ldb.PACKING_FORMAT]) + self.assertEqual(self.get_database(), {}) + + self.l.add({"dn": "@ATTRIBUTES"}) + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + self.assertEqual(len(guid_keys), 0) + self.assertEqual(pack_formats, [ldb.PACKING_FORMAT]) + self.assertEqual(self.get_database(), {}) + + self.l.add({"dn": "@INDEXLIST", + "@IDXONE": [b"1"], + "@IDXGUID": [b"objectUUID"], + "@IDX_DN_GUID": [b"GUID"]}) + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + self.assertEqual(len(guid_keys), 0) + self.assertEqual(pack_formats, [ldb.PACKING_FORMAT_V2]) + self.assertEqual(self.get_database(), {}) + + rec = self.add_one_rec() + expect_db = {rec["dn"]: rec} + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + self.assertEqual(len(guid_keys), 1) + self.assertEqual(pack_formats, [ldb.PACKING_FORMAT_V2]) + self.assertEqual(self.get_database(), expect_db) + + self.toggle_guidindex_check_pack() + + # Check a database with V1 format with GUID indexing enabled is repacked + # with version 2 format. + def test_guid_indexed_v1_db(self): + self.setup_premade_v1_db() + + expect_db = self.get_database() + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + self.assertEqual(len(guid_keys), self.num_recs_added) + self.assertEqual(pack_formats, [ldb.PACKING_FORMAT]) + self.assertEqual(self.get_database(), expect_db) + + rec = self.add_one_rec() + expect_db[rec['dn']] = rec + + guid_keys, pack_formats = self.ldbdump_guid_keys_pack_formats() + self.assertEqual(len(guid_keys), self.num_recs_added) + self.assertEqual(pack_formats, [ldb.PACKING_FORMAT_V2]) + self.assertEqual(self.get_database(), expect_db) + + self.toggle_guidindex_check_pack() + + +if __name__ == '__main__': + import unittest + + + unittest.TestProgram() diff --git a/ldb-2.0.8/tests/samba4.png b/ldb-2.0.8/tests/samba4.png new file mode 100644 index 0000000..c809688 Binary files /dev/null and b/ldb-2.0.8/tests/samba4.png differ diff --git a/ldb-2.0.8/tests/sample_module.c b/ldb-2.0.8/tests/sample_module.c new file mode 100644 index 0000000..6ba9ed2 --- /dev/null +++ b/ldb-2.0.8/tests/sample_module.c @@ -0,0 +1,122 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij 2007 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "ldb_module.h" + +static int sample_add_callback(struct ldb_request *down_req, + struct ldb_reply *ares) +{ + struct ldb_request *req = + talloc_get_type_abort(down_req->context, + struct ldb_request); + + if (ares == NULL) { + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + if (ares->type == LDB_REPLY_REFERRAL) { + return ldb_module_send_referral(req, ares->referral); + } + + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(req, ares->controls, + ares->response, ares->error); + } + + if (ares->type != LDB_REPLY_DONE) { + return ldb_module_done(req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + return ldb_module_done(req, ares->controls, + ares->response, LDB_SUCCESS); +} + +static int sample_add(struct ldb_module *mod, struct ldb_request *req) +{ + struct ldb_context *ldb = ldb_module_get_ctx(mod); + struct ldb_control *control = NULL; + struct ldb_message *msg = NULL; + struct ldb_request *down_req = NULL; + int ret; + + /* check if there's a relax control */ + control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID); + if (control != NULL) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + msg = ldb_msg_copy_shallow(req, req->op.add.message); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_msg_add_fmt(msg, "touchedBy", "sample"); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_add_req(&down_req, ldb, req, + msg, + req->controls, + req, sample_add_callback, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(down_req, msg); + + /* go on with the call chain */ + return ldb_next_request(mod, down_req); +} + +static int sample_modify(struct ldb_module *mod, struct ldb_request *req) +{ + struct ldb_control *control; + + /* check if there's a relax control */ + control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID); + if (control != NULL) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + /* not found go on */ + return ldb_next_request(mod, req); +} + + +static struct ldb_module_ops ldb_sample_module_ops = { + .name = "sample", + .add = sample_add, + .del = sample_modify, + .modify = sample_modify, +}; + +int ldb_sample_init(const char *version) +{ + LDB_MODULE_CHECK_VERSION(version); + return ldb_register_module(&ldb_sample_module_ops); +} diff --git a/ldb-2.0.8/tests/schema-tests/schema-add-test.ldif b/ldb-2.0.8/tests/schema-tests/schema-add-test.ldif new file mode 100644 index 0000000..472ab48 --- /dev/null +++ b/ldb-2.0.8/tests/schema-tests/schema-add-test.ldif @@ -0,0 +1,66 @@ +dn: CN=Users,DC=schema,DC=test +objectClass: top +objectClass: container +cn: Users +description: Default container for upgraded user accounts +instanceType: 4 +whenCreated: 20050116175504.0Z +whenChanged: 20050116175504.0Z +uSNCreated: 1 +uSNChanged: 1 +showInAdvancedViewOnly: FALSE +name: Users +objectGUID: b847056a-9934-d87b-8a1a-99fabe0863c8 +systemFlags: 0x8c000000 +objectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +isCriticalSystemObject: TRUE +nTSecurityDescriptor: foo + +dn: CN=Administrator,CN=Users,DC=schema,DC=test +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: user +cn: Administrator +description: Built-in account for administering the computer/domain +instanceType: 4 +whenCreated: 20050116175504.0Z +whenChanged: 20050116175504.0Z +uSNCreated: 1 +memberOf: CN=Group Policy Creator Owners,CN=Users,DC=schema,DC=test +memberOf: CN=Domain Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Enterprise Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Schema Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Administrators,CN=Builtin,DC=schema,DC=test +uSNChanged: 1 +name: Administrator +objectGUID: 6c02f98c-46c6-aa38-5f13-a510cac04e6c +userAccountControl: 0x10200 +badPwdCount: 0 +codePage: 0 +countryCode: 0 +badPasswordTime: 0 +lastLogoff: 0 +lastLogon: 0 +pwdLastSet: 0 +primaryGroupID: 513 +objectSid: S-1-5-21-43662522-77495566-38969261-500 +adminCount: 1 +accountExpires: 9223372036854775807 +logonCount: 0 +sAMAccountName: Administrator +sAMAccountType: 0x30000000 +objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +isCriticalSystemObject: TRUE +unicodePwd: samba +nTSecurityDescriptor: foo + +dn: CN=Test,CN=Users,DC=schema,DC=test +objectClass: top +objectClass: test +cn: Test +description: This is a test +objectCategory: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +nTSecurityDescriptor: foo +instanceType: 4 + diff --git a/ldb-2.0.8/tests/schema-tests/schema-mod-test-1.ldif b/ldb-2.0.8/tests/schema-tests/schema-mod-test-1.ldif new file mode 100644 index 0000000..b976724 --- /dev/null +++ b/ldb-2.0.8/tests/schema-tests/schema-mod-test-1.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +replace: description +description: this test must not fail + diff --git a/ldb-2.0.8/tests/schema-tests/schema-mod-test-2.ldif b/ldb-2.0.8/tests/schema-tests/schema-mod-test-2.ldif new file mode 100644 index 0000000..fa193af --- /dev/null +++ b/ldb-2.0.8/tests/schema-tests/schema-mod-test-2.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +delete: description +# this test must not fail + diff --git a/ldb-2.0.8/tests/schema-tests/schema-mod-test-3.ldif b/ldb-2.0.8/tests/schema-tests/schema-mod-test-3.ldif new file mode 100644 index 0000000..8ab7798 --- /dev/null +++ b/ldb-2.0.8/tests/schema-tests/schema-mod-test-3.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +add: description +description: this test must not fail + diff --git a/ldb-2.0.8/tests/schema-tests/schema-mod-test-4.ldif b/ldb-2.0.8/tests/schema-tests/schema-mod-test-4.ldif new file mode 100644 index 0000000..cbf0e60 --- /dev/null +++ b/ldb-2.0.8/tests/schema-tests/schema-mod-test-4.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +add: foo +foo: this test must fail + diff --git a/ldb-2.0.8/tests/schema-tests/schema-mod-test-5.ldif b/ldb-2.0.8/tests/schema-tests/schema-mod-test-5.ldif new file mode 100644 index 0000000..bc64e9e --- /dev/null +++ b/ldb-2.0.8/tests/schema-tests/schema-mod-test-5.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +delete: nTSecurityDescriptor +# this test must fail + diff --git a/ldb-2.0.8/tests/schema-tests/schema.ldif b/ldb-2.0.8/tests/schema-tests/schema.ldif new file mode 100644 index 0000000..4ab1932 --- /dev/null +++ b/ldb-2.0.8/tests/schema-tests/schema.ldif @@ -0,0 +1,100 @@ +dn: @INDEXLIST +@IDXATTR: name +@IDXATTR: sAMAccountName +@IDXATTR: objectSid +@IDXATTR: objectClass +@IDXATTR: member +@IDXATTR: uidNumber +@IDXATTR: gidNumber +@IDXATTR: unixName +@IDXATTR: privilege +@IDXATTR: lDAPDisplayName + +dn: @ATTRIBUTES +realm: CASE_INSENSITIVE +userPrincipalName: CASE_INSENSITIVE +servicePrincipalName: CASE_INSENSITIVE +name: CASE_INSENSITIVE +dn: CASE_INSENSITIVE +sAMAccountName: CASE_INSENSITIVE +objectClass: CASE_INSENSITIVE +unicodePwd: HIDDEN +ntPwdHash: HIDDEN +ntPwdHistory: HIDDEN +lmPwdHash: HIDDEN +lmPwdHistory: HIDDEN +createTimestamp: HIDDEN +modifyTimestamp: HIDDEN + +dn: @MODULES +@LIST: timestamps,schema + +dn: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +lDAPDisplayName: top +cn: Top +uSNCreated: 1 +uSNChanged: 1 +subClassOf: top +systemMustContain: objectClass +systemMayContain: structuralObjectClass +systemMayContain: createTimeStamp +systemMayContain: modifyTimeStamp +systemMayContain: creatorsName +systemMayContain: modifiersName +systemMayContain: hasSubordinates +systemMayContain: subschemaSubentry +systemMayContain: collectiveSubentry +systemMayContain: entryUUID +systemMayContain: entryCSN +systemMayContain: namingCSN +systemMayContain: superiorUUID +systemMayContain: contextCSN +systemMayContain: whenCreated +systemMayContain: whenChanged +systemMayContain: uSNCreated +systemMayContain: uSNChanged +systemMayContain: distinguishedName +systemMayContain: name +systemMayContain: cn +systemMayContain: userPassword +systemMayContain: labeledURI + +dn: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +lDAPDisplayName: classSchema +cn: Class-Schema +uSNCreated: 2 +uSNChanged: 2 +lDAPDisplayName: classSchema +subClassOf: top +systemMustContain: cn +systemMustContain: subClassOf +systemMayContain: systemPossSuperiors +systemMayContain: systemOnly +systemMayContain: systemMustContain +systemMayContain: systemMayContain +systemMayContain: systemAuxiliaryClass +systemMayContain: possSuperiors +systemMayContain: mustContain +systemMayContain: mayContain +systemMayContain: lDAPDisplayName +systemMayContain: auxiliaryClass + +dn: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Attribute-Schema +uSNCreated: 3 +uSNChanged: 3 +lDAPDisplayName: attributeSchema +subClassOf: top +systemMustContain: oMSyntax +systemMustContain: lDAPDisplayName +systemMustContain: isSingleValued +systemMustContain: cn +systemMustContain: attributeSyntax +systemMustContain: attributeID + diff --git a/ldb-2.0.8/tests/slapd.conf b/ldb-2.0.8/tests/slapd.conf new file mode 100644 index 0000000..fa2789d --- /dev/null +++ b/ldb-2.0.8/tests/slapd.conf @@ -0,0 +1,26 @@ +loglevel 0 + +include tests/schema/core.schema +include tests/schema/cosine.schema +include tests/schema/inetorgperson.schema +include tests/schema/openldap.schema +include tests/schema/nis.schema + + +pidfile tests/tmp/slapd.pid +argsfile tests/tmp/slapd.args + +access to * by * write + +allow update_anon bind_anon_dn + +include tests/tmp/modules.conf + +defaultsearchbase "o=University of Michigan,c=TEST" + +backend bdb +database bdb +suffix "o=University of Michigan,c=TEST" +directory tests/tmp/db +index objectClass eq +index uid eq diff --git a/ldb-2.0.8/tests/start_slapd.sh b/ldb-2.0.8/tests/start_slapd.sh new file mode 100755 index 0000000..11679d4 --- /dev/null +++ b/ldb-2.0.8/tests/start_slapd.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +if [ -z "$LDBDIR" ]; then + LDBDIR=`dirname $0`/.. + export LDBDIR +fi + +mkdir -p $LDBDIR/tests/tmp/db + +# running slapd in the background (with &) means it stays in the same process group, so it can be +# killed by timelimit +slapd -d0 -f $LDBDIR/tests/slapd.conf -h "`$LDBDIR/tests/ldapi_url.sh`" $* & + +sleep 2 diff --git a/ldb-2.0.8/tests/test-attribs.ldif b/ldb-2.0.8/tests/test-attribs.ldif new file mode 100644 index 0000000..79508c4 --- /dev/null +++ b/ldb-2.0.8/tests/test-attribs.ldif @@ -0,0 +1,6 @@ +dn: @ATTRIBUTES +uid: CASE_INSENSITIVE +cn: CASE_INSENSITIVE +ou: CASE_INSENSITIVE +dn: CASE_INSENSITIVE + diff --git a/ldb-2.0.8/tests/test-config.ldif b/ldb-2.0.8/tests/test-config.ldif new file mode 100644 index 0000000..7926a9e --- /dev/null +++ b/ldb-2.0.8/tests/test-config.ldif @@ -0,0 +1,67 @@ +############################## +# global configuration options +dn: cn=Global,cn=Config,cn=Samba +objectclass: globalconfig +LocalConfigCn: cn=%U,cn=Config,cn=Samba +LocalConfigCn;1: cn=%U,cn=Config,cn=Samba +LocalConfigCn;2: cn=%I,cn=Config,cn=Samba +LocalConfigCn;3: cn=%M,cn=Config,cn=Samba + +############# +dn: cn=Protocol,cn=Global,cn=Config,cn=Samba +maxXmit: 7000 + +################################ +dn: cn=Volker,cn=Config,cn=Samba +Workgroup: VNET3 +UnixCharset: UTF8 +Security: user +Interfaces: vmnet* eth* +NetbiosName: blu +GuestAccount: tridge + +################################# +dn: cn=Volker,cn=Config,cn=Samba +Workgroup: VNET3 +UnixCharset: UTF8 +Security: user +Interfaces: vmnet* eth* +NetbiosName: blu +GuestAccount: tridge +Include: cn=%U,cn=MyConfig,cn=Config,cn=Samba + +#### ((objectClass=fileshare)(cn=test)) +############################## +# [test] share +dn: cn=test,cn=Shares,cn=Config,cn=Samba +objectclass: fileshare +cn: test +Comment: a test share +Path: /home/tridge/samba4/prefix/test +ReadOnly: no + +##################################### +# [msdn] a remote proxy share, stored +# on \\msdn\test +dn: cn=msdn,cn=Shares,cn=Config,cn=Samba +objectclass: fileshare +cn: msdn +NtvfsHandler: cifs +ReadOnly: no +_CifsServer: msdn +_CifsUser: administrator +_CifsPassword: penguin +_CifsDomain: winxp +_CifsShare: test + + +############################## +# [VisualC] share +dn: cn=visualc,cn=Shares,cn=Config,cn=Samba +objectclass: fileshare +cn: VisualC +Comment: VisualC development +Path: /home/tridge/VisualC +ReadOnly: no +NtvfsHandler: simple + diff --git a/ldb-2.0.8/tests/test-controls.sh b/ldb-2.0.8/tests/test-controls.sh new file mode 100755 index 0000000..328ed29 --- /dev/null +++ b/ldb-2.0.8/tests/test-controls.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +if [ -n "$TEST_DATA_PREFIX" ]; then + LDB_URL="$TEST_DATA_PREFIX/tdbtest.ldb" +else + LDB_URL="tdbtest.ldb" +fi +export LDB_URL + +PATH=bin:$PATH +export PATH + +rm -f $LDB_URL* + +echo "LDB_URL: $LDB_URL" +cat </dev/null 2>&1 && exit 1 +dn: dc=foobar +dc: foobar +someThing: someThingElse +EOF + +cat </dev/null 2>&1 && exit 1 +dn: dc=bar +changetype: modify +replace someThing +someThing: someThingElseBetter +EOF + +$VALGRIND ldbsearch --controls "bypassoperational:0" >/dev/null 2>&1 || exit 1 diff --git a/ldb-2.0.8/tests/test-default-config.ldif b/ldb-2.0.8/tests/test-default-config.ldif new file mode 100644 index 0000000..87b7bcd --- /dev/null +++ b/ldb-2.0.8/tests/test-default-config.ldif @@ -0,0 +1,17 @@ +############################## +# global configuration options +dn: cn=Global,cn=DefaultConfig,cn=Samba +objectclass: globalconfig +Workgroup: WORKGROUP +UnixCharset: UTF8 +Security: user +NetbiosName: blu +GuestAccount: nobody + +############################## +# [_default_] share +dn: cn=_default_,cn=Shares,cn=DefaultConfig,cn=Samba +objectclass: fileshare +cn: _default_ +Path: /tmp +ReadOnly: yes diff --git a/ldb-2.0.8/tests/test-dup-2.ldif b/ldb-2.0.8/tests/test-dup-2.ldif new file mode 100644 index 0000000..a426101 --- /dev/null +++ b/ldb-2.0.8/tests/test-dup-2.ldif @@ -0,0 +1,6 @@ +dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST +objectclass: OpenLDAPperson +cn: Sentinel +sn: USER +uid: USER, Sentinel + diff --git a/ldb-2.0.8/tests/test-dup.ldif b/ldb-2.0.8/tests/test-dup.ldif new file mode 100644 index 0000000..b35420b --- /dev/null +++ b/ldb-2.0.8/tests/test-dup.ldif @@ -0,0 +1,13 @@ +dn: cn=Fred Bassett,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST +objectclass: OpenLDAPperson +cn: Fred Bassett +sn: Bassett +uid: Bassett, Fred + +dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST +objectclass: OpenLDAPperson +cn: Sentinel +sn: USER +uid: USER, Sentinel + + diff --git a/ldb-2.0.8/tests/test-extended.sh b/ldb-2.0.8/tests/test-extended.sh new file mode 100755 index 0000000..0599757 --- /dev/null +++ b/ldb-2.0.8/tests/test-extended.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +echo "Running extended search tests" + +mv $LDB_URL $LDB_URL.1 + +cat < /dev/null && { + echo "Should have failed to add again - gave $?" + exit 1 +} + +echo "Adding LDIF with one already-existing user again - should fail" +$VALGRIND ldbadd $LDBDIR/tests/test-dup.ldif 2> /dev/null && { + echo "Should have failed to add again - gave $?" + exit 1 +} + +echo "Adding again - should succeed (as previous failed)" +$VALGRIND ldbadd $LDBDIR/tests/test-dup-2.ldif || exit 1 + +echo "Modifying elements" +$VALGRIND ldbmodify $LDBDIR/tests/test-modify.ldif || exit 1 + +echo "Modify LDIF with one un-met constraint - should fail" +$VALGRIND ldbadd $LDBDIR/tests/test-modify-unmet.ldif 2> /dev/null && { + echo "Should have failed to modify - gave $?" + exit 1 +} + +echo "Modify LDIF with after failure of un-met constraint - should also fail" +$VALGRIND ldbadd $LDBDIR/tests/test-modify-unmet-2.ldif 2> /dev/null && { + echo "Should have failed to modify - gave $?" + exit 1 +} + +echo "Showing modified record" +$VALGRIND ldbsearch '(uid=uham)' || exit 1 + +echo "Rename entry with ldbmodify - modrdn" +$VALGRIND ldbmodify $LDBDIR/tests/test-modify-modrdn.ldif || exit 1 + +echo "Rename entry with ldbrename" +OLDDN="cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST" +NEWDN="cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST" +$VALGRIND ldbrename "$OLDDN" "$NEWDN" || exit 1 + +echo "Showing renamed record" +$VALGRIND ldbsearch '(uid=uham)' || exit 1 + +echo "Starting ldbtest" +$VALGRIND ldbtest --num-records 100 --num-searches 10 || exit 1 + +if [ $LDB_SPECIALS = 1 ]; then + echo "Adding index" + $VALGRIND ldbadd $LDBDIR/tests/test-index.ldif || exit 1 +fi + +echo "Adding bad attributes - should fail" +$VALGRIND ldbadd $LDBDIR/tests/test-wrong_attributes.ldif && { + echo "Should fhave failed - gave $?" + exit 1 +} + +echo "Testing indexed search" +$VALGRIND ldbsearch '(uid=uham)' || exit 1 +$VALGRIND ldbsearch '(&(objectclass=person)(objectclass=person)(objectclass=top))' || exit 1 +$VALGRIND ldbsearch '(&(uid=uham)(uid=uham))' || exit 1 +$VALGRIND ldbsearch '(|(uid=uham)(uid=uham))' || exit 1 +$VALGRIND ldbsearch '(|(uid=uham)(uid=uham)(objectclass=OpenLDAPperson))' || exit 1 +$VALGRIND ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 +$VALGRIND ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \* \+ dn || exit 1 +$VALGRIND ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 + +echo "Testing invalid search expression" +$VALGRIND ldbsearch '(&(uid=uham)(title=foo\blah))' uid && exit 1 + +# note that the "((" is treated as an attribute not an expression +# this matches the openldap ldapsearch behaviour of looking for a '=' +# to see if the first argument is an expression or not +$VALGRIND ldbsearch '((' uid || exit 1 +$VALGRIND ldbsearch '(objectclass=)' uid || exit 1 +$VALGRIND ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' -s base "" sn || exit 1 + +echo "Test wildcard match" +$VALGRIND ldbadd $LDBDIR/tests/test-wildcard.ldif || exit 1 +$VALGRIND ldbsearch '(cn=test*multi)' || exit 1 +$VALGRIND ldbsearch '(cn=*test*multi*)' || exit 1 +$VALGRIND ldbsearch '(cn=*test_multi)' || exit 1 +$VALGRIND ldbsearch '(cn=test_multi*)' || exit 1 +$VALGRIND ldbsearch '(cn=test*multi*test*multi)' || exit 1 +$VALGRIND ldbsearch '(cn=test*multi*test*multi*multi_*)' || exit 1 + +echo "Starting ldbtest indexed" +$VALGRIND ldbtest --num-records 100 --num-searches 500 || exit 1 + +echo "Testing one level search" +count=`$VALGRIND ldbsearch -b 'ou=Groups,o=University of Michigan,c=TEST' -s one 'objectclass=*' none |grep '^dn' | wc -l` +if [ $count != 3 ]; then + echo returned $count records - expected 3 + exit 1 +fi + +echo "Testing binary file attribute value" +$VALGRIND ldbmodify $LDBDIR/tests/photo.ldif || exit 1 +count=`$VALGRIND ldbsearch '(cn=Hampster Ursula)' jpegPhoto | grep '^dn' | wc -l` +if [ $count != 1 ]; then + echo returned $count records - expected 1 + exit 1 +fi + +echo "*TODO* Testing UTF8 upper lower case searches !!" + +echo "Testing compare" +count=`$VALGRIND ldbsearch '(cn>=t)' cn | grep '^dn' | wc -l` +if [ $count != 1 ]; then + # only "cn: test_multi_test_multi_test_multi" (comes after "t") + # upper-cased words come before "t" - hence excluded + echo returned $count records - expected 1 + exit 1 +fi +$VALGRIND ldbsearch '(cn>t)' cn && exit 1 # strictly greater should not work + +count=`$VALGRIND ldbsearch '(cn<=t)' cn | grep '^dn' | wc -l` +if [ $count != 18 ]; then + # everything except "cn: test_multi_test_multi_test_multi" (comes after "t") + # upper-cased letters come before "t" - hence included + echo returned $count records - expected 18 + exit 1 +fi +$VALGRIND ldbsearch '(cn + * + * 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 . + */ + +#include +#include +#include +#include + +#include +#include "ldb_private.h" + +static void test_ldb_dn_add_child_fmt(void **state) +{ + struct ldb_context *ldb = ldb_init(NULL, NULL); + + struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org"); + + assert_true(ldb_dn_add_child_fmt(dn, + "DC=X")); + + assert_string_equal("DC=X,dc=samba,dc=org", + ldb_dn_get_linearized(dn)); + + assert_string_equal("DC=X,DC=SAMBA,DC=ORG", + ldb_dn_get_casefold(dn)); + +} + +static void test_ldb_dn_add_child_fmt2(void **state) +{ + struct ldb_context *ldb = ldb_init(NULL, NULL); + + struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org"); + + assert_true(ldb_dn_add_child_fmt(dn, + "DC=X,DC=Y")); + + assert_string_equal("DC=X,DC=Y,dc=samba,dc=org", + ldb_dn_get_linearized(dn)); + + assert_string_equal("DC=X,DC=Y,DC=SAMBA,DC=ORG", + ldb_dn_get_casefold(dn)); + + assert_int_equal(4, + ldb_dn_get_comp_num(dn)); + +} + +static void test_ldb_dn_add_child_val(void **state) +{ + struct ldb_context *ldb = ldb_init(NULL, NULL); + + struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org"); + struct ldb_val name = {.data = discard_const("X"), + .length = 1 + }; + + assert_true(ldb_dn_add_child_val(dn, + "DC", name)); + + assert_string_equal("DC=X,dc=samba,dc=org", + ldb_dn_get_linearized(dn)); + + assert_string_equal("DC=X,DC=SAMBA,DC=ORG", + ldb_dn_get_casefold(dn)); + +} + +static void test_ldb_dn_add_child_val2(void **state) +{ + struct ldb_context *ldb = ldb_init(NULL, NULL); + + struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org"); + + struct ldb_val name = {.data = discard_const("X,DC=Y"), + .length = 6 + }; + + assert_true(ldb_dn_add_child_val(dn, + "DC", name)); + + assert_string_equal("DC=X\\,DC\\3DY,dc=samba,dc=org", + ldb_dn_get_linearized(dn)); + + assert_string_equal("DC=X\\,DC\\3DY,DC=SAMBA,DC=ORG", + ldb_dn_get_casefold(dn)); + + assert_int_equal(3, + ldb_dn_get_comp_num(dn)); + +} + +struct explode_test { + const char *strdn; + int comp_num; + int ext_comp_num; + bool special; + bool invalid; + const char *linearized; + const char *ext_linearized_1; + bool explode_result; +}; + +static int extended_dn_read_ID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + + /* Allow to check we can cope with validity checks */ + if (in->length != 4) { + return -1; + } + + *out = *in; + out->data = talloc_memdup(mem_ctx, in->data, in->length); + if (out->data == NULL) { + return -1; + } + + return 0; +} + +/* write out (resued for both HEX and clear for now) */ +static int extended_dn_write_ID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + *out = *in; + + out->data = talloc_memdup(mem_ctx, in->data, in->length); + if (out->data == NULL) { + return -1; + } + return 0; +} + + +static void test_ldb_dn_explode(void **state) +{ + size_t i; + struct ldb_context *ldb = ldb_init(NULL, NULL); + struct explode_test tests[] = { + {"A=B", 1, 0, false, false, "A=B", "A=B", true}, + {"", 0, 0, false, false, "", "", true}, + {" ", -1, -1, false, false, " ", " ", false}, + {"<>", 0, 0, false, false, "", NULL, true}, + {"<", 0, 0, false, false, "", NULL, true}, + {"<><", 0, 0, false, false, "", NULL, true}, + {"<><>", 0, 0, false, false, "", NULL, true}, + {"A=B,C=D", 2, 0, false, false, "A=B,C=D", "A=B,C=D", true}, + {"A=B,C=D", -1, -1, false, false, "", NULL, false}, + {";A=B,C=D", -1, -1, false, false, "A=B,C=D", NULL, false}, + {";A=B,C=D", -1, -1, false, true, "A=B,C=D", NULL, false}, + {";A=B,C=D", 2, 1, false, false, "A=B,C=D", ";A=B,C=D", true}, + {"x=🔥", 1, 0, false, false, "x=🔥", "x=🔥", true}, + {"@FOO", 0, 0, true, false, "@FOO", "@FOO", true}, + }; + + struct ldb_dn_extended_syntax syntax = { + .name = "ID", + .read_fn = extended_dn_read_ID, + .write_clear_fn = extended_dn_write_ID, + .write_hex_fn = extended_dn_write_ID + }; + + ldb_dn_extended_add_syntax(ldb, 0, &syntax); + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + bool result; + const char *linear; + const char *ext_linear; + struct ldb_dn *dn = ldb_dn_new(ldb, ldb, tests[i].strdn); + + /* + * special, invalid, linear, and ext_linear are set before + * explode + */ + fprintf(stderr, "%zu «%s»: ", i, tests[i].strdn); + linear = ldb_dn_get_linearized(dn); + assert_true((linear == NULL) == (tests[i].linearized == NULL)); + assert_string_equal(linear, + tests[i].linearized); + + ext_linear = ldb_dn_get_extended_linearized(ldb, dn, 1); + assert_true((ext_linear == NULL) == + (tests[i].ext_linearized_1 == NULL)); + + if (tests[i].ext_linearized_1 != NULL) { + assert_string_equal(ext_linear, + tests[i].ext_linearized_1); + } + assert_true(ldb_dn_is_special(dn) == tests[i].special); + assert_true(ldb_dn_is_valid(dn) != tests[i].invalid); + + /* comp nums are set by explode */ + result = ldb_dn_validate(dn); + fprintf(stderr, "res %i lin «%s» ext «%s»\n", + result, linear, ext_linear); + + assert_true(result == tests[i].explode_result); + assert_int_equal(ldb_dn_get_comp_num(dn), + tests[i].comp_num); + assert_int_equal(ldb_dn_get_extended_comp_num(dn), + tests[i].ext_comp_num); + } +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_ldb_dn_add_child_fmt), + cmocka_unit_test(test_ldb_dn_add_child_fmt2), + cmocka_unit_test(test_ldb_dn_add_child_val), + cmocka_unit_test(test_ldb_dn_add_child_val2), + cmocka_unit_test(test_ldb_dn_explode), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/test_ldb_qsort.c b/ldb-2.0.8/tests/test_ldb_qsort.c new file mode 100644 index 0000000..663cf0e --- /dev/null +++ b/ldb-2.0.8/tests/test_ldb_qsort.c @@ -0,0 +1,65 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2018 Andreas Schneider + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#include + +static int cmp_integer(int *a, int *b, void *opaque) +{ + if (a == NULL || b == NULL) { + return 0; + } + + if (*a > *b) { + return 1; + } + + if (*a < *b) { + return -1; + } + + return 0; +} + +static void test_ldb_qsort(void **state) +{ + int a[6] = { 6, 3, 2, 7, 9, 4 }; + + ldb_qsort(a, 6, sizeof(int), NULL, (ldb_qsort_cmp_fn_t)cmp_integer); + + assert_int_equal(a[0], 2); + assert_int_equal(a[1], 3); + assert_int_equal(a[2], 4); + assert_int_equal(a[3], 6); + assert_int_equal(a[4], 7); + assert_int_equal(a[5], 9); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_ldb_qsort), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/ldb-2.0.8/tests/testdata.txt b/ldb-2.0.8/tests/testdata.txt new file mode 100644 index 0000000..dadb9f0 --- /dev/null +++ b/ldb-2.0.8/tests/testdata.txt @@ -0,0 +1,8 @@ +foo=bar5 +(&(|(a=b)(c=d))(e=f)) +(&(|(a=b)(c=d)(g=h))(e=f)) +name=firstname lastname +(&(sid=S-1-2-3)(name = fred bloggs)) +(&(|(a=b)(c=d))(g=f)) +(&(sid=S-1-2-3)(!(name = fred bloggs))) +(&(!(|(a=b)(c=d))(g=f))) diff --git a/ldb-2.0.8/tests/testsearch.txt b/ldb-2.0.8/tests/testsearch.txt new file mode 100644 index 0000000..c573863 --- /dev/null +++ b/ldb-2.0.8/tests/testsearch.txt @@ -0,0 +1,5 @@ +(blah=foo) +(objectclass=person) +(dn=*) +(&(objectclass=person)(objectclass=person)) +(&(objectclass=person)(objectclass=personx)) diff --git a/ldb-2.0.8/third_party/cmocka/cmocka.c b/ldb-2.0.8/third_party/cmocka/cmocka.c new file mode 100644 index 0000000..b21fe15 --- /dev/null +++ b/ldb-2.0.8/third_party/cmocka/cmocka.c @@ -0,0 +1,3431 @@ +/* + * Copyright 2008 Google Inc. + * Copyright 2014-2018 Andreas Schneider + * Copyright 2015 Jakub Hrozek + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_MALLOC_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This allows to add a platform specific header file. Some embedded platforms + * sometimes miss certain types and definitions. + * + * Example: + * + * typedef unsigned long int uintptr_t + * #define _UINTPTR_T 1 + * #define _UINTPTR_T_DEFINED 1 + */ +#ifdef CMOCKA_PLATFORM_INCLUDE +# include "cmocka_platform.h" +#endif /* CMOCKA_PLATFORM_INCLUDE */ + +#include +#include + +/* Size of guard bytes around dynamically allocated blocks. */ +#define MALLOC_GUARD_SIZE 16 +/* Pattern used to initialize guard blocks. */ +#define MALLOC_GUARD_PATTERN 0xEF +/* Pattern used to initialize memory allocated with test_malloc(). */ +#define MALLOC_ALLOC_PATTERN 0xBA +#define MALLOC_FREE_PATTERN 0xCD +/* Alignment of allocated blocks. NOTE: This must be base2. */ +#define MALLOC_ALIGNMENT sizeof(size_t) + +/* Printf formatting for source code locations. */ +#define SOURCE_LOCATION_FORMAT "%s:%u" + +#if defined(HAVE_GCC_THREAD_LOCAL_STORAGE) +# define CMOCKA_THREAD __thread +#elif defined(HAVE_MSVC_THREAD_LOCAL_STORAGE) +# define CMOCKA_THREAD __declspec(thread) +#else +# define CMOCKA_THREAD +#endif + +#ifdef HAVE_CLOCK_REALTIME +#define CMOCKA_CLOCK_GETTIME(clock_id, ts) clock_gettime((clock_id), (ts)) +#else +#define CMOCKA_CLOCK_GETTIME(clock_id, ts) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) < (b) ? (b) : (a)) +#endif + +/** + * POSIX has sigsetjmp/siglongjmp, while Windows only has setjmp/longjmp. + */ +#ifdef HAVE_SIGLONGJMP +# define cm_jmp_buf sigjmp_buf +# define cm_setjmp(env) sigsetjmp(env, 1) +# define cm_longjmp(env, val) siglongjmp(env, val) +#else +# define cm_jmp_buf jmp_buf +# define cm_setjmp(env) setjmp(env) +# define cm_longjmp(env, val) longjmp(env, val) +#endif + + +/* + * Declare and initialize the pointer member of ValuePointer variable name + * with ptr. + */ +#define declare_initialize_value_pointer_pointer(name, ptr) \ + ValuePointer name ; \ + name.value = 0; \ + name.x.pointer = (void*)(ptr) + +/* + * Declare and initialize the value member of ValuePointer variable name + * with val. + */ +#define declare_initialize_value_pointer_value(name, val) \ + ValuePointer name ; \ + name.value = val + +/* Cast a LargestIntegralType to pointer_type via a ValuePointer. */ +#define cast_largest_integral_type_to_pointer( \ + pointer_type, largest_integral_type) \ + ((pointer_type)((ValuePointer*)&(largest_integral_type))->x.pointer) + +/* Used to cast LargetIntegralType to void* and vice versa. */ +typedef union ValuePointer { + LargestIntegralType value; + struct { +#if defined(WORDS_BIGENDIAN) && (WORDS_SIZEOF_VOID_P == 4) + unsigned int padding; +#endif + void *pointer; + } x; +} ValuePointer; + +/* Doubly linked list node. */ +typedef struct ListNode { + const void *value; + int refcount; + struct ListNode *next; + struct ListNode *prev; +} ListNode; + +/* Debug information for malloc(). */ +struct MallocBlockInfoData { + void* block; /* Address of the block returned by malloc(). */ + size_t allocated_size; /* Total size of the allocated block. */ + size_t size; /* Request block size. */ + SourceLocation location; /* Where the block was allocated. */ + ListNode node; /* Node within list of all allocated blocks. */ +}; + +typedef union { + struct MallocBlockInfoData *data; + char *ptr; +} MallocBlockInfo; + +/* State of each test. */ +typedef struct TestState { + const ListNode *check_point; /* Check point of the test if there's a */ + /* setup function. */ + void *state; /* State associated with the test. */ +} TestState; + +/* Determines whether two values are the same. */ +typedef int (*EqualityFunction)(const void *left, const void *right); + +/* Value of a symbol and the place it was declared. */ +typedef struct SymbolValue { + SourceLocation location; + LargestIntegralType value; +} SymbolValue; + +/* + * Contains a list of values for a symbol. + * NOTE: Each structure referenced by symbol_values_list_head must have a + * SourceLocation as its' first member. + */ +typedef struct SymbolMapValue { + const char *symbol_name; + ListNode symbol_values_list_head; +} SymbolMapValue; + +/* Where a particular ordering was located and its symbol name */ +typedef struct FuncOrderingValue { + SourceLocation location; + const char * function; +} FuncOrderingValue; + +/* Used by list_free() to deallocate values referenced by list nodes. */ +typedef void (*CleanupListValue)(const void *value, void *cleanup_value_data); + +/* Structure used to check the range of integer types.a */ +typedef struct CheckIntegerRange { + CheckParameterEvent event; + LargestIntegralType minimum; + LargestIntegralType maximum; +} CheckIntegerRange; + +/* Structure used to check whether an integer value is in a set. */ +typedef struct CheckIntegerSet { + CheckParameterEvent event; + const LargestIntegralType *set; + size_t size_of_set; +} CheckIntegerSet; + +/* Used to check whether a parameter matches the area of memory referenced by + * this structure. */ +typedef struct CheckMemoryData { + CheckParameterEvent event; + const void *memory; + size_t size; +} CheckMemoryData; + +static ListNode* list_initialize(ListNode * const node); +static ListNode* list_add(ListNode * const head, ListNode *new_node); +static ListNode* list_add_value(ListNode * const head, const void *value, + const int count); +static ListNode* list_remove( + ListNode * const node, const CleanupListValue cleanup_value, + void * const cleanup_value_data); +static void list_remove_free( + ListNode * const node, const CleanupListValue cleanup_value, + void * const cleanup_value_data); +static int list_empty(const ListNode * const head); +static int list_find( + ListNode * const head, const void *value, + const EqualityFunction equal_func, ListNode **output); +static int list_first(ListNode * const head, ListNode **output); +static ListNode* list_free( + ListNode * const head, const CleanupListValue cleanup_value, + void * const cleanup_value_data); + +static void add_symbol_value( + ListNode * const symbol_map_head, const char * const symbol_names[], + const size_t number_of_symbol_names, const void* value, const int count); +static int get_symbol_value( + ListNode * const symbol_map_head, const char * const symbol_names[], + const size_t number_of_symbol_names, void **output); +static void free_value(const void *value, void *cleanup_value_data); +static void free_symbol_map_value( + const void *value, void *cleanup_value_data); +static void remove_always_return_values(ListNode * const map_head, + const size_t number_of_symbol_names); + +static size_t check_for_leftover_values_list(const ListNode * head, + const char * const error_message); + +static size_t check_for_leftover_values( + const ListNode * const map_head, const char * const error_message, + const size_t number_of_symbol_names); + +static void remove_always_return_values_from_list(ListNode * const map_head); + +/* + * This must be called at the beginning of a test to initialize some data + * structures. + */ +static void initialize_testing(const char *test_name); + +/* This must be called at the end of a test to free() allocated structures. */ +static void teardown_testing(const char *test_name); + +static enum cm_message_output cm_get_output(void); + +static int cm_error_message_enabled = 1; +static CMOCKA_THREAD char *cm_error_message; + +void cm_print_error(const char * const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2); + +/* + * Keeps track of the calling context returned by setenv() so that the fail() + * method can jump out of a test. + */ +static CMOCKA_THREAD cm_jmp_buf global_run_test_env; +static CMOCKA_THREAD int global_running_test = 0; + +/* Keeps track of the calling context returned by setenv() so that */ +/* mock_assert() can optionally jump back to expect_assert_failure(). */ +jmp_buf global_expect_assert_env; +int global_expecting_assert = 0; +const char *global_last_failed_assert = NULL; +static int global_skip_test; + +/* Keeps a map of the values that functions will have to return to provide */ +/* mocked interfaces. */ +static CMOCKA_THREAD ListNode global_function_result_map_head; +/* Location of the last mock value returned was declared. */ +static CMOCKA_THREAD SourceLocation global_last_mock_value_location; + +/* Keeps a map of the values that functions expect as parameters to their + * mocked interfaces. */ +static CMOCKA_THREAD ListNode global_function_parameter_map_head; +/* Location of last parameter value checked was declared. */ +static CMOCKA_THREAD SourceLocation global_last_parameter_location; + +/* List (acting as FIFO) of call ordering. */ +static CMOCKA_THREAD ListNode global_call_ordering_head; +/* Location of last call ordering that was declared. */ +static CMOCKA_THREAD SourceLocation global_last_call_ordering_location; + +/* List of all currently allocated blocks. */ +static CMOCKA_THREAD ListNode global_allocated_blocks; + +static enum cm_message_output global_msg_output = CM_OUTPUT_STDOUT; + +static const char *global_test_filter_pattern; + +#ifndef _WIN32 +/* Signals caught by exception_handler(). */ +static const int exception_signals[] = { + SIGFPE, + SIGILL, + SIGSEGV, +#ifdef SIGBUS + SIGBUS, +#endif +#ifdef SIGSYS + SIGSYS, +#endif +}; + +/* Default signal functions that should be restored after a test is complete. */ +typedef void (*SignalFunction)(int signal); +static SignalFunction default_signal_functions[ + ARRAY_SIZE(exception_signals)]; + +#else /* _WIN32 */ + +/* The default exception filter. */ +static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter; + +/* Fatal exceptions. */ +typedef struct ExceptionCodeInfo { + DWORD code; + const char* description; +} ExceptionCodeInfo; + +#define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code} + +static const ExceptionCodeInfo exception_codes[] = { + EXCEPTION_CODE_INFO(EXCEPTION_ACCESS_VIOLATION), + EXCEPTION_CODE_INFO(EXCEPTION_ARRAY_BOUNDS_EXCEEDED), + EXCEPTION_CODE_INFO(EXCEPTION_DATATYPE_MISALIGNMENT), + EXCEPTION_CODE_INFO(EXCEPTION_FLT_DENORMAL_OPERAND), + EXCEPTION_CODE_INFO(EXCEPTION_FLT_DIVIDE_BY_ZERO), + EXCEPTION_CODE_INFO(EXCEPTION_FLT_INEXACT_RESULT), + EXCEPTION_CODE_INFO(EXCEPTION_FLT_INVALID_OPERATION), + EXCEPTION_CODE_INFO(EXCEPTION_FLT_OVERFLOW), + EXCEPTION_CODE_INFO(EXCEPTION_FLT_STACK_CHECK), + EXCEPTION_CODE_INFO(EXCEPTION_FLT_UNDERFLOW), + EXCEPTION_CODE_INFO(EXCEPTION_GUARD_PAGE), + EXCEPTION_CODE_INFO(EXCEPTION_ILLEGAL_INSTRUCTION), + EXCEPTION_CODE_INFO(EXCEPTION_INT_DIVIDE_BY_ZERO), + EXCEPTION_CODE_INFO(EXCEPTION_INT_OVERFLOW), + EXCEPTION_CODE_INFO(EXCEPTION_INVALID_DISPOSITION), + EXCEPTION_CODE_INFO(EXCEPTION_INVALID_HANDLE), + EXCEPTION_CODE_INFO(EXCEPTION_IN_PAGE_ERROR), + EXCEPTION_CODE_INFO(EXCEPTION_NONCONTINUABLE_EXCEPTION), + EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION), + EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW), +}; +#endif /* !_WIN32 */ + +enum CMUnitTestStatus { + CM_TEST_NOT_STARTED, + CM_TEST_PASSED, + CM_TEST_FAILED, + CM_TEST_ERROR, + CM_TEST_SKIPPED, +}; + +struct CMUnitTestState { + const ListNode *check_point; /* Check point of the test if there's a setup function. */ + const struct CMUnitTest *test; /* Point to array element in the tests we get passed */ + void *state; /* State associated with the test */ + const char *error_message; /* The error messages by the test */ + enum CMUnitTestStatus status; /* PASSED, FAILED, ABORT ... */ + double runtime; /* Time calculations */ +}; + +/* Exit the currently executing test. */ +static void exit_test(const int quit_application) +{ + const char *env = getenv("CMOCKA_TEST_ABORT"); + int abort_test = 0; + + if (env != NULL && strlen(env) == 1) { + abort_test = (env[0] == '1'); + } + + if (global_skip_test == 0 && + abort_test == 1) { + print_error("%s", cm_error_message); + abort(); + } else if (global_running_test) { + cm_longjmp(global_run_test_env, 1); + } else if (quit_application) { + exit(-1); + } +} + +void _skip(const char * const file, const int line) +{ + cm_print_error(SOURCE_LOCATION_FORMAT ": Skipped!\n", file, line); + global_skip_test = 1; + exit_test(1); +} + +/* Initialize a SourceLocation structure. */ +static void initialize_source_location(SourceLocation * const location) { + assert_non_null(location); + location->file = NULL; + location->line = 0; +} + + +/* Determine whether a source location is currently set. */ +static int source_location_is_set(const SourceLocation * const location) { + assert_non_null(location); + return location->file && location->line; +} + + +/* Set a source location. */ +static void set_source_location( + SourceLocation * const location, const char * const file, + const int line) { + assert_non_null(location); + location->file = file; + location->line = line; +} + + +static int c_strreplace(char *src, + size_t src_len, + const char *pattern, + const char *repl, + int *str_replaced) +{ + char *p = NULL; + + p = strstr(src, pattern); + if (p == NULL) { + return -1; + } + + do { + size_t of = p - src; + size_t l = strlen(src); + size_t pl = strlen(pattern); + size_t rl = strlen(repl); + + /* overflow check */ + if (src_len <= l + MAX(pl, rl) + 1) { + return -1; + } + + if (rl != pl) { + memmove(src + of + rl, src + of + pl, l - of - pl + 1); + } + + memcpy(src + of, repl, rl); + + if (str_replaced != NULL) { + *str_replaced = 1; + } + p = strstr(src, pattern); + } while (p != NULL); + + return 0; +} + +static int c_strmatch(const char *str, const char *pattern) +{ + int ok; + + if (str == NULL || pattern == NULL) { + return 0; + } + + for (;;) { + /* Check if pattern is done */ + if (*pattern == '\0') { + /* If string is at the end, we're good */ + if (*str == '\0') { + return 1; + } + + return 0; + } + + if (*pattern == '*') { + /* Move on */ + pattern++; + + /* If we are at the end, everything is fine */ + if (*pattern == '\0') { + return 1; + } + + /* Try to match each position */ + for (; *str != '\0'; str++) { + ok = c_strmatch(str, pattern); + if (ok) { + return 1; + } + } + + /* No match */ + return 0; + } + + /* If we are at the end, leave */ + if (*str == '\0') { + return 0; + } + + /* Check if we have a single wildcard or matching char */ + if (*pattern != '?' && *str != *pattern) { + return 0; + } + + /* Move string and pattern */ + str++; + pattern++; + } + + return 0; +} + +/* Create function results and expected parameter lists. */ +void initialize_testing(const char *test_name) { + (void)test_name; + list_initialize(&global_function_result_map_head); + initialize_source_location(&global_last_mock_value_location); + list_initialize(&global_function_parameter_map_head); + initialize_source_location(&global_last_parameter_location); + list_initialize(&global_call_ordering_head); + initialize_source_location(&global_last_parameter_location); +} + + +static void fail_if_leftover_values(const char *test_name) { + int error_occurred = 0; + (void)test_name; + remove_always_return_values(&global_function_result_map_head, 1); + if (check_for_leftover_values( + &global_function_result_map_head, + "%s() has remaining non-returned values.\n", 1)) { + error_occurred = 1; + } + + remove_always_return_values(&global_function_parameter_map_head, 2); + if (check_for_leftover_values( + &global_function_parameter_map_head, + "'%s' parameter still has values that haven't been checked.\n", + 2)) { + error_occurred = 1; + } + + remove_always_return_values_from_list(&global_call_ordering_head); + if (check_for_leftover_values_list(&global_call_ordering_head, + "%s function was expected to be called but was not not.\n")) { + error_occurred = 1; + } + if (error_occurred) { + exit_test(1); + } +} + + +static void teardown_testing(const char *test_name) { + (void)test_name; + list_free(&global_function_result_map_head, free_symbol_map_value, + (void*)0); + initialize_source_location(&global_last_mock_value_location); + list_free(&global_function_parameter_map_head, free_symbol_map_value, + (void*)1); + initialize_source_location(&global_last_parameter_location); + list_free(&global_call_ordering_head, free_value, + (void*)0); + initialize_source_location(&global_last_call_ordering_location); +} + +/* Initialize a list node. */ +static ListNode* list_initialize(ListNode * const node) { + node->value = NULL; + node->next = node; + node->prev = node; + node->refcount = 1; + return node; +} + + +/* + * Adds a value at the tail of a given list. + * The node referencing the value is allocated from the heap. + */ +static ListNode* list_add_value(ListNode * const head, const void *value, + const int refcount) { + ListNode * const new_node = (ListNode*)malloc(sizeof(ListNode)); + assert_non_null(head); + assert_non_null(value); + new_node->value = value; + new_node->refcount = refcount; + return list_add(head, new_node); +} + + +/* Add new_node to the end of the list. */ +static ListNode* list_add(ListNode * const head, ListNode *new_node) { + assert_non_null(head); + assert_non_null(new_node); + new_node->next = head; + new_node->prev = head->prev; + head->prev->next = new_node; + head->prev = new_node; + return new_node; +} + + +/* Remove a node from a list. */ +static ListNode* list_remove( + ListNode * const node, const CleanupListValue cleanup_value, + void * const cleanup_value_data) { + assert_non_null(node); + node->prev->next = node->next; + node->next->prev = node->prev; + if (cleanup_value) { + cleanup_value(node->value, cleanup_value_data); + } + return node; +} + + +/* Remove a list node from a list and free the node. */ +static void list_remove_free( + ListNode * const node, const CleanupListValue cleanup_value, + void * const cleanup_value_data) { + assert_non_null(node); + free(list_remove(node, cleanup_value, cleanup_value_data)); +} + + +/* + * Frees memory kept by a linked list The cleanup_value function is called for + * every "value" field of nodes in the list, except for the head. In addition + * to each list value, cleanup_value_data is passed to each call to + * cleanup_value. The head of the list is not deallocated. + */ +static ListNode* list_free( + ListNode * const head, const CleanupListValue cleanup_value, + void * const cleanup_value_data) { + assert_non_null(head); + while (!list_empty(head)) { + list_remove_free(head->next, cleanup_value, cleanup_value_data); + } + return head; +} + + +/* Determine whether a list is empty. */ +static int list_empty(const ListNode * const head) { + assert_non_null(head); + return head->next == head; +} + + +/* + * Find a value in the list using the equal_func to compare each node with the + * value. + */ +static int list_find(ListNode * const head, const void *value, + const EqualityFunction equal_func, ListNode **output) { + ListNode *current; + assert_non_null(head); + for (current = head->next; current != head; current = current->next) { + if (equal_func(current->value, value)) { + *output = current; + return 1; + } + } + return 0; +} + +/* Returns the first node of a list */ +static int list_first(ListNode * const head, ListNode **output) { + ListNode *target_node = NULL; + assert_non_null(head); + if (list_empty(head)) { + return 0; + } + target_node = head->next; + *output = target_node; + return 1; +} + + +/* Deallocate a value referenced by a list. */ +static void free_value(const void *value, void *cleanup_value_data) { + (void)cleanup_value_data; + assert_non_null(value); + free((void*)value); +} + + +/* Releases memory associated to a symbol_map_value. */ +static void free_symbol_map_value(const void *value, + void *cleanup_value_data) { + SymbolMapValue * const map_value = (SymbolMapValue*)value; + const LargestIntegralType children = cast_ptr_to_largest_integral_type(cleanup_value_data); + assert_non_null(value); + list_free(&map_value->symbol_values_list_head, + children ? free_symbol_map_value : free_value, + (void *) ((uintptr_t)children - 1)); + free(map_value); +} + + +/* + * Determine whether a symbol name referenced by a symbol_map_value matches the + * specified function name. + */ +static int symbol_names_match(const void *map_value, const void *symbol) { + return !strcmp(((SymbolMapValue*)map_value)->symbol_name, + (const char*)symbol); +} + +/* + * Adds a value to the queue of values associated with the given hierarchy of + * symbols. It's assumed value is allocated from the heap. + */ +static void add_symbol_value(ListNode * const symbol_map_head, + const char * const symbol_names[], + const size_t number_of_symbol_names, + const void* value, const int refcount) { + const char* symbol_name; + ListNode *target_node; + SymbolMapValue *target_map_value; + assert_non_null(symbol_map_head); + assert_non_null(symbol_names); + assert_true(number_of_symbol_names); + symbol_name = symbol_names[0]; + + if (!list_find(symbol_map_head, symbol_name, symbol_names_match, + &target_node)) { + SymbolMapValue * const new_symbol_map_value = + (SymbolMapValue*)malloc(sizeof(*new_symbol_map_value)); + new_symbol_map_value->symbol_name = symbol_name; + list_initialize(&new_symbol_map_value->symbol_values_list_head); + target_node = list_add_value(symbol_map_head, new_symbol_map_value, + 1); + } + + target_map_value = (SymbolMapValue*)target_node->value; + if (number_of_symbol_names == 1) { + list_add_value(&target_map_value->symbol_values_list_head, + value, refcount); + } else { + add_symbol_value(&target_map_value->symbol_values_list_head, + &symbol_names[1], number_of_symbol_names - 1, value, + refcount); + } +} + + +/* + * Gets the next value associated with the given hierarchy of symbols. + * The value is returned as an output parameter with the function returning the + * node's old refcount value if a value is found, 0 otherwise. This means that + * a return value of 1 indicates the node was just removed from the list. + */ +static int get_symbol_value( + ListNode * const head, const char * const symbol_names[], + const size_t number_of_symbol_names, void **output) { + const char* symbol_name = NULL; + ListNode *target_node = NULL; + assert_non_null(head); + assert_non_null(symbol_names); + assert_true(number_of_symbol_names); + assert_non_null(output); + symbol_name = symbol_names[0]; + + if (list_find(head, symbol_name, symbol_names_match, &target_node)) { + SymbolMapValue *map_value = NULL; + ListNode *child_list = NULL; + int return_value = 0; + assert_non_null(target_node); + assert_non_null(target_node->value); + + map_value = (SymbolMapValue*)target_node->value; + child_list = &map_value->symbol_values_list_head; + + if (number_of_symbol_names == 1) { + ListNode *value_node = NULL; + return_value = list_first(child_list, &value_node); + assert_true(return_value); + /* Add a check to silence clang analyzer */ + if (return_value == 0) { + goto out; + } + *output = (void*) value_node->value; + return_value = value_node->refcount; + if (value_node->refcount - 1 == 0) { + list_remove_free(value_node, NULL, NULL); + } else if (value_node->refcount > WILL_RETURN_ONCE) { + --value_node->refcount; + } + } else { + return_value = get_symbol_value( + child_list, &symbol_names[1], number_of_symbol_names - 1, + output); + } + if (list_empty(child_list)) { + list_remove_free(target_node, free_symbol_map_value, (void*)0); + } + return return_value; + } +out: + cm_print_error("No entries for symbol %s.\n", symbol_name); + return 0; +} + +/** + * Taverse a list of nodes and remove first symbol value in list that has a + * refcount < -1 (i.e. should always be returned and has been returned at + * least once). + */ + +static void remove_always_return_values_from_list(ListNode * const map_head) +{ + ListNode * current = NULL; + ListNode * next = NULL; + assert_non_null(map_head); + + for (current = map_head->next, next = current->next; + current != map_head; + current = next, next = current->next) { + if (current->refcount < -1) { + list_remove_free(current, free_value, NULL); + } + } +} + +/* + * Traverse down a tree of symbol values and remove the first symbol value + * in each branch that has a refcount < -1 (i.e should always be returned + * and has been returned at least once). + */ +static void remove_always_return_values(ListNode * const map_head, + const size_t number_of_symbol_names) { + ListNode *current; + assert_non_null(map_head); + assert_true(number_of_symbol_names); + current = map_head->next; + while (current != map_head) { + SymbolMapValue * const value = (SymbolMapValue*)current->value; + ListNode * const next = current->next; + ListNode *child_list; + assert_non_null(value); + child_list = &value->symbol_values_list_head; + + if (!list_empty(child_list)) { + if (number_of_symbol_names == 1) { + ListNode * const child_node = child_list->next; + /* If this item has been returned more than once, free it. */ + if (child_node->refcount < -1) { + list_remove_free(child_node, free_value, NULL); + } + } else { + remove_always_return_values(child_list, + number_of_symbol_names - 1); + } + } + + if (list_empty(child_list)) { + list_remove_free(current, free_value, NULL); + } + current = next; + } +} + +static size_t check_for_leftover_values_list(const ListNode * head, + const char * const error_message) +{ + ListNode *child_node; + size_t leftover_count = 0; + if (!list_empty(head)) + { + for (child_node = head->next; child_node != head; + child_node = child_node->next, ++leftover_count) { + const FuncOrderingValue *const o = + (const FuncOrderingValue*) child_node->value; + cm_print_error(error_message, o->function); + cm_print_error(SOURCE_LOCATION_FORMAT + ": note: remaining item was declared here\n", + o->location.file, o->location.line); + } + } + return leftover_count; +} + +/* + * Checks if there are any leftover values set up by the test that were never + * retrieved through execution, and fail the test if that is the case. + */ +static size_t check_for_leftover_values( + const ListNode * const map_head, const char * const error_message, + const size_t number_of_symbol_names) { + const ListNode *current; + size_t symbols_with_leftover_values = 0; + assert_non_null(map_head); + assert_true(number_of_symbol_names); + + for (current = map_head->next; current != map_head; + current = current->next) { + const SymbolMapValue * const value = + (SymbolMapValue*)current->value; + const ListNode *child_list; + assert_non_null(value); + child_list = &value->symbol_values_list_head; + + if (!list_empty(child_list)) { + if (number_of_symbol_names == 1) { + const ListNode *child_node; + cm_print_error(error_message, value->symbol_name); + + for (child_node = child_list->next; child_node != child_list; + child_node = child_node->next) { + const SourceLocation * const location = + (const SourceLocation*)child_node->value; + cm_print_error(SOURCE_LOCATION_FORMAT + ": note: remaining item was declared here\n", + location->file, location->line); + } + } else { + cm_print_error("%s: ", value->symbol_name); + check_for_leftover_values(child_list, error_message, + number_of_symbol_names - 1); + } + symbols_with_leftover_values ++; + } + } + return symbols_with_leftover_values; +} + + +/* Get the next return value for the specified mock function. */ +LargestIntegralType _mock(const char * const function, const char* const file, + const int line) { + void *result; + const int rc = get_symbol_value(&global_function_result_map_head, + &function, 1, &result); + if (rc) { + SymbolValue * const symbol = (SymbolValue*)result; + const LargestIntegralType value = symbol->value; + global_last_mock_value_location = symbol->location; + if (rc == 1) { + free(symbol); + } + return value; + } else { + cm_print_error(SOURCE_LOCATION_FORMAT ": error: Could not get value " + "to mock function %s\n", file, line, function); + if (source_location_is_set(&global_last_mock_value_location)) { + cm_print_error(SOURCE_LOCATION_FORMAT + ": note: Previously returned mock value was declared here\n", + global_last_mock_value_location.file, + global_last_mock_value_location.line); + } else { + cm_print_error("There were no previously returned mock values for " + "this test.\n"); + } + exit_test(1); + } + return 0; +} + +/* Ensure that function is being called in proper order */ +void _function_called(const char *const function, + const char *const file, + const int line) +{ + ListNode *first_value_node = NULL; + ListNode *value_node = NULL; + int rc; + + rc = list_first(&global_call_ordering_head, &value_node); + first_value_node = value_node; + if (rc) { + FuncOrderingValue *expected_call; + int cmp; + + expected_call = (FuncOrderingValue *)value_node->value; + + cmp = strcmp(expected_call->function, function); + if (value_node->refcount < -1) { + /* + * Search through value nodes until either function is found or + * encounter a non-zero refcount greater than -2 + */ + if (cmp != 0) { + value_node = value_node->next; + expected_call = (FuncOrderingValue *)value_node->value; + + cmp = strcmp(expected_call->function, function); + while (value_node->refcount < -1 && + cmp != 0 && + value_node != first_value_node->prev) { + value_node = value_node->next; + if (value_node == NULL) { + break; + } + expected_call = (FuncOrderingValue *)value_node->value; + if (expected_call == NULL) { + continue; + } + cmp = strcmp(expected_call->function, function); + } + + if (expected_call == NULL || value_node == first_value_node->prev) { + cm_print_error(SOURCE_LOCATION_FORMAT + ": error: No expected mock calls matching " + "called() invocation in %s", + file, line, + function); + exit_test(1); + } + } + } + + if (cmp == 0) { + if (value_node->refcount > -2 && --value_node->refcount == 0) { + list_remove_free(value_node, free_value, NULL); + } + } else { + cm_print_error(SOURCE_LOCATION_FORMAT + ": error: Expected call to %s but received called() " + "in %s\n", + file, line, + expected_call->function, + function); + exit_test(1); + } + } else { + cm_print_error(SOURCE_LOCATION_FORMAT + ": error: No mock calls expected but called() was " + "invoked in %s\n", + file, line, + function); + exit_test(1); + } +} + +/* Add a return value for the specified mock function name. */ +void _will_return(const char * const function_name, const char * const file, + const int line, const LargestIntegralType value, + const int count) { + SymbolValue * const return_value = + (SymbolValue*)malloc(sizeof(*return_value)); + assert_true(count != 0); + return_value->value = value; + set_source_location(&return_value->location, file, line); + add_symbol_value(&global_function_result_map_head, &function_name, 1, + return_value, count); +} + + +/* + * Add a custom parameter checking function. If the event parameter is NULL + * the event structure is allocated internally by this function. If event + * parameter is provided it must be allocated on the heap and doesn't need to + * be deallocated by the caller. + */ +void _expect_check( + const char* const function, const char* const parameter, + const char* const file, const int line, + const CheckParameterValue check_function, + const LargestIntegralType check_data, + CheckParameterEvent * const event, const int count) { + CheckParameterEvent * const check = + event ? event : (CheckParameterEvent*)malloc(sizeof(*check)); + const char* symbols[] = {function, parameter}; + check->parameter_name = parameter; + check->check_value = check_function; + check->check_value_data = check_data; + set_source_location(&check->location, file, line); + add_symbol_value(&global_function_parameter_map_head, symbols, 2, check, + count); +} + +/* + * Add an call expectations that a particular function is called correctly. + * This is used for code under test that makes calls to several functions + * in depended upon components (mocks). + */ + +void _expect_function_call( + const char * const function_name, + const char * const file, + const int line, + const int count) +{ + FuncOrderingValue *ordering; + + assert_non_null(function_name); + assert_non_null(file); + assert_true(count != 0); + + ordering = (FuncOrderingValue *)malloc(sizeof(*ordering)); + + set_source_location(&ordering->location, file, line); + ordering->function = function_name; + + list_add_value(&global_call_ordering_head, ordering, count); +} + +/* Returns 1 if the specified values are equal. If the values are not equal + * an error is displayed and 0 is returned. */ +static int values_equal_display_error(const LargestIntegralType left, + const LargestIntegralType right) { + const int equal = left == right; + if (!equal) { + cm_print_error(LargestIntegralTypePrintfFormat " != " + LargestIntegralTypePrintfFormat "\n", left, right); + } + return equal; +} + +/* + * Returns 1 if the specified values are not equal. If the values are equal + * an error is displayed and 0 is returned. */ +static int values_not_equal_display_error(const LargestIntegralType left, + const LargestIntegralType right) { + const int not_equal = left != right; + if (!not_equal) { + cm_print_error(LargestIntegralTypePrintfFormat " == " + LargestIntegralTypePrintfFormat "\n", left, right); + } + return not_equal; +} + + +/* + * Determine whether value is contained within check_integer_set. + * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is + * returned and an error is displayed. If invert is 1 and the value is not + * in the set 1 is returned, otherwise 0 is returned and an error is + * displayed. + */ +static int value_in_set_display_error( + const LargestIntegralType value, + const CheckIntegerSet * const check_integer_set, const int invert) { + int succeeded = invert; + assert_non_null(check_integer_set); + { + const LargestIntegralType * const set = check_integer_set->set; + const size_t size_of_set = check_integer_set->size_of_set; + size_t i; + for (i = 0; i < size_of_set; i++) { + if (set[i] == value) { + /* If invert = 0 and item is found, succeeded = 1. */ + /* If invert = 1 and item is found, succeeded = 0. */ + succeeded = !succeeded; + break; + } + } + if (succeeded) { + return 1; + } + cm_print_error(LargestIntegralTypePrintfFormatDecimal + " is %sin the set (", + value, invert ? "" : "not "); + for (i = 0; i < size_of_set; i++) { + cm_print_error(LargestIntegralTypePrintfFormat ", ", set[i]); + } + cm_print_error(")\n"); + } + return 0; +} + + +/* + * Determine whether a value is within the specified range. If the value is + * within the specified range 1 is returned. If the value isn't within the + * specified range an error is displayed and 0 is returned. + */ +static int integer_in_range_display_error( + const LargestIntegralType value, const LargestIntegralType range_min, + const LargestIntegralType range_max) { + if (value >= range_min && value <= range_max) { + return 1; + } + cm_print_error(LargestIntegralTypePrintfFormatDecimal + " is not within the range " + LargestIntegralTypePrintfFormatDecimal "-" + LargestIntegralTypePrintfFormatDecimal "\n", + value, range_min, range_max); + return 0; +} + + +/* + * Determine whether a value is within the specified range. If the value + * is not within the range 1 is returned. If the value is within the + * specified range an error is displayed and zero is returned. + */ +static int integer_not_in_range_display_error( + const LargestIntegralType value, const LargestIntegralType range_min, + const LargestIntegralType range_max) { + if (value < range_min || value > range_max) { + return 1; + } + cm_print_error(LargestIntegralTypePrintfFormatDecimal + " is within the range " + LargestIntegralTypePrintfFormatDecimal "-" + LargestIntegralTypePrintfFormatDecimal "\n", + value, range_min, range_max); + return 0; +} + + +/* + * Determine whether the specified strings are equal. If the strings are equal + * 1 is returned. If they're not equal an error is displayed and 0 is + * returned. + */ +static int string_equal_display_error( + const char * const left, const char * const right) { + if (strcmp(left, right) == 0) { + return 1; + } + cm_print_error("\"%s\" != \"%s\"\n", left, right); + return 0; +} + + +/* + * Determine whether the specified strings are equal. If the strings are not + * equal 1 is returned. If they're not equal an error is displayed and 0 is + * returned + */ +static int string_not_equal_display_error( + const char * const left, const char * const right) { + if (strcmp(left, right) != 0) { + return 1; + } + cm_print_error("\"%s\" == \"%s\"\n", left, right); + return 0; +} + + +/* + * Determine whether the specified areas of memory are equal. If they're equal + * 1 is returned otherwise an error is displayed and 0 is returned. + */ +static int memory_equal_display_error(const char* const a, const char* const b, + const size_t size) { + size_t differences = 0; + size_t i; + for (i = 0; i < size; i++) { + const char l = a[i]; + const char r = b[i]; + if (l != r) { + if (differences < 16) { + cm_print_error("difference at offset %" PRIdS " 0x%02x 0x%02x\n", + i, l, r); + } + differences ++; + } + } + if (differences > 0) { + if (differences >= 16) { + cm_print_error("...\n"); + } + cm_print_error("%"PRIdS " bytes of %p and %p differ\n", + differences, (void *)a, (void *)b); + return 0; + } + return 1; +} + + +/* + * Determine whether the specified areas of memory are not equal. If they're + * not equal 1 is returned otherwise an error is displayed and 0 is + * returned. + */ +static int memory_not_equal_display_error( + const char* const a, const char* const b, const size_t size) { + size_t same = 0; + size_t i; + for (i = 0; i < size; i++) { + const char l = a[i]; + const char r = b[i]; + if (l == r) { + same ++; + } + } + if (same == size) { + cm_print_error("%"PRIdS "bytes of %p and %p the same\n", + same, (void *)a, (void *)b); + return 0; + } + return 1; +} + + +/* CheckParameterValue callback to check whether a value is within a set. */ +static int check_in_set(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + return value_in_set_display_error(value, + cast_largest_integral_type_to_pointer(CheckIntegerSet*, + check_value_data), 0); +} + + +/* CheckParameterValue callback to check whether a value isn't within a set. */ +static int check_not_in_set(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + return value_in_set_display_error(value, + cast_largest_integral_type_to_pointer(CheckIntegerSet*, + check_value_data), 1); +} + + +/* Create the callback data for check_in_set() or check_not_in_set() and + * register a check event. */ +static void expect_set( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType values[], const size_t number_of_values, + const CheckParameterValue check_function, const int count) { + CheckIntegerSet * const check_integer_set = + (CheckIntegerSet*)malloc(sizeof(*check_integer_set) + + (sizeof(values[0]) * number_of_values)); + LargestIntegralType * const set = (LargestIntegralType*)( + check_integer_set + 1); + declare_initialize_value_pointer_pointer(check_data, check_integer_set); + assert_non_null(values); + assert_true(number_of_values); + memcpy(set, values, number_of_values * sizeof(values[0])); + check_integer_set->set = set; + check_integer_set->size_of_set = number_of_values; + _expect_check( + function, parameter, file, line, check_function, + check_data.value, &check_integer_set->event, count); +} + + +/* Add an event to check whether a value is in a set. */ +void _expect_in_set( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType values[], const size_t number_of_values, + const int count) { + expect_set(function, parameter, file, line, values, number_of_values, + check_in_set, count); +} + + +/* Add an event to check whether a value isn't in a set. */ +void _expect_not_in_set( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType values[], const size_t number_of_values, + const int count) { + expect_set(function, parameter, file, line, values, number_of_values, + check_not_in_set, count); +} + + +/* CheckParameterValue callback to check whether a value is within a range. */ +static int check_in_range(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + CheckIntegerRange * const check_integer_range = + cast_largest_integral_type_to_pointer(CheckIntegerRange*, + check_value_data); + assert_non_null(check_integer_range); + return integer_in_range_display_error(value, check_integer_range->minimum, + check_integer_range->maximum); +} + + +/* CheckParameterValue callback to check whether a value is not within a range. */ +static int check_not_in_range(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + CheckIntegerRange * const check_integer_range = + cast_largest_integral_type_to_pointer(CheckIntegerRange*, + check_value_data); + assert_non_null(check_integer_range); + return integer_not_in_range_display_error( + value, check_integer_range->minimum, check_integer_range->maximum); +} + + +/* Create the callback data for check_in_range() or check_not_in_range() and + * register a check event. */ +static void expect_range( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType minimum, const LargestIntegralType maximum, + const CheckParameterValue check_function, const int count) { + CheckIntegerRange * const check_integer_range = + (CheckIntegerRange*)malloc(sizeof(*check_integer_range)); + declare_initialize_value_pointer_pointer(check_data, check_integer_range); + check_integer_range->minimum = minimum; + check_integer_range->maximum = maximum; + _expect_check(function, parameter, file, line, check_function, + check_data.value, &check_integer_range->event, count); +} + + +/* Add an event to determine whether a parameter is within a range. */ +void _expect_in_range( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType minimum, const LargestIntegralType maximum, + const int count) { + expect_range(function, parameter, file, line, minimum, maximum, + check_in_range, count); +} + + +/* Add an event to determine whether a parameter is not within a range. */ +void _expect_not_in_range( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType minimum, const LargestIntegralType maximum, + const int count) { + expect_range(function, parameter, file, line, minimum, maximum, + check_not_in_range, count); +} + + +/* CheckParameterValue callback to check whether a value is equal to an + * expected value. */ +static int check_value(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + return values_equal_display_error(value, check_value_data); +} + + +/* Add an event to check a parameter equals an expected value. */ +void _expect_value( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType value, const int count) { + _expect_check(function, parameter, file, line, check_value, value, NULL, + count); +} + + +/* CheckParameterValue callback to check whether a value is not equal to an + * expected value. */ +static int check_not_value(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + return values_not_equal_display_error(value, check_value_data); +} + + +/* Add an event to check a parameter is not equal to an expected value. */ +void _expect_not_value( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType value, const int count) { + _expect_check(function, parameter, file, line, check_not_value, value, + NULL, count); +} + + +/* CheckParameterValue callback to check whether a parameter equals a string. */ +static int check_string(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + return string_equal_display_error( + cast_largest_integral_type_to_pointer(char*, value), + cast_largest_integral_type_to_pointer(char*, check_value_data)); +} + + +/* Add an event to check whether a parameter is equal to a string. */ +void _expect_string( + const char* const function, const char* const parameter, + const char* const file, const int line, const char* string, + const int count) { + declare_initialize_value_pointer_pointer(string_pointer, + discard_const(string)); + _expect_check(function, parameter, file, line, check_string, + string_pointer.value, NULL, count); +} + + +/* CheckParameterValue callback to check whether a parameter is not equals to + * a string. */ +static int check_not_string(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + return string_not_equal_display_error( + cast_largest_integral_type_to_pointer(char*, value), + cast_largest_integral_type_to_pointer(char*, check_value_data)); +} + + +/* Add an event to check whether a parameter is not equal to a string. */ +void _expect_not_string( + const char* const function, const char* const parameter, + const char* const file, const int line, const char* string, + const int count) { + declare_initialize_value_pointer_pointer(string_pointer, + discard_const(string)); + _expect_check(function, parameter, file, line, check_not_string, + string_pointer.value, NULL, count); +} + +/* CheckParameterValue callback to check whether a parameter equals an area of + * memory. */ +static int check_memory(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + CheckMemoryData * const check = cast_largest_integral_type_to_pointer( + CheckMemoryData*, check_value_data); + assert_non_null(check); + return memory_equal_display_error( + cast_largest_integral_type_to_pointer(const char*, value), + (const char*)check->memory, check->size); +} + + +/* Create the callback data for check_memory() or check_not_memory() and + * register a check event. */ +static void expect_memory_setup( + const char* const function, const char* const parameter, + const char* const file, const int line, + const void * const memory, const size_t size, + const CheckParameterValue check_function, const int count) { + CheckMemoryData * const check_data = + (CheckMemoryData*)malloc(sizeof(*check_data) + size); + void * const mem = (void*)(check_data + 1); + declare_initialize_value_pointer_pointer(check_data_pointer, check_data); + assert_non_null(memory); + assert_true(size); + memcpy(mem, memory, size); + check_data->memory = mem; + check_data->size = size; + _expect_check(function, parameter, file, line, check_function, + check_data_pointer.value, &check_data->event, count); +} + + +/* Add an event to check whether a parameter matches an area of memory. */ +void _expect_memory( + const char* const function, const char* const parameter, + const char* const file, const int line, const void* const memory, + const size_t size, const int count) { + expect_memory_setup(function, parameter, file, line, memory, size, + check_memory, count); +} + + +/* CheckParameterValue callback to check whether a parameter is not equal to + * an area of memory. */ +static int check_not_memory(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + CheckMemoryData * const check = cast_largest_integral_type_to_pointer( + CheckMemoryData*, check_value_data); + assert_non_null(check); + return memory_not_equal_display_error( + cast_largest_integral_type_to_pointer(const char*, value), + (const char*)check->memory, + check->size); +} + + +/* Add an event to check whether a parameter doesn't match an area of memory. */ +void _expect_not_memory( + const char* const function, const char* const parameter, + const char* const file, const int line, const void* const memory, + const size_t size, const int count) { + expect_memory_setup(function, parameter, file, line, memory, size, + check_not_memory, count); +} + + +/* CheckParameterValue callback that always returns 1. */ +static int check_any(const LargestIntegralType value, + const LargestIntegralType check_value_data) { + (void)value; + (void)check_value_data; + return 1; +} + + +/* Add an event to allow any value for a parameter. */ +void _expect_any( + const char* const function, const char* const parameter, + const char* const file, const int line, const int count) { + _expect_check(function, parameter, file, line, check_any, 0, NULL, + count); +} + + +void _check_expected( + const char * const function_name, const char * const parameter_name, + const char* file, const int line, const LargestIntegralType value) { + void *result = NULL; + const char* symbols[] = {function_name, parameter_name}; + const int rc = get_symbol_value(&global_function_parameter_map_head, + symbols, 2, &result); + if (rc) { + CheckParameterEvent * const check = (CheckParameterEvent*)result; + int check_succeeded; + global_last_parameter_location = check->location; + check_succeeded = check->check_value(value, check->check_value_data); + if (rc == 1) { + free(check); + } + if (!check_succeeded) { + cm_print_error(SOURCE_LOCATION_FORMAT + ": error: Check of parameter %s, function %s failed\n" + SOURCE_LOCATION_FORMAT + ": note: Expected parameter declared here\n", + file, line, + parameter_name, function_name, + global_last_parameter_location.file, + global_last_parameter_location.line); + _fail(file, line); + } + } else { + cm_print_error(SOURCE_LOCATION_FORMAT ": error: Could not get value " + "to check parameter %s of function %s\n", file, line, + parameter_name, function_name); + if (source_location_is_set(&global_last_parameter_location)) { + cm_print_error(SOURCE_LOCATION_FORMAT + ": note: Previously declared parameter value was declared here\n", + global_last_parameter_location.file, + global_last_parameter_location.line); + } else { + cm_print_error("There were no previously declared parameter values " + "for this test.\n"); + } + exit_test(1); + } +} + + +/* Replacement for assert. */ +void mock_assert(const int result, const char* const expression, + const char* const file, const int line) { + if (!result) { + if (global_expecting_assert) { + global_last_failed_assert = expression; + longjmp(global_expect_assert_env, result); + } else { + cm_print_error("ASSERT: %s\n", expression); + _fail(file, line); + } + } +} + + +void _assert_true(const LargestIntegralType result, + const char * const expression, + const char * const file, const int line) { + if (!result) { + cm_print_error("%s\n", expression); + _fail(file, line); + } +} + +void _assert_return_code(const LargestIntegralType result, + size_t rlen, + const LargestIntegralType error, + const char * const expression, + const char * const file, + const int line) +{ + LargestIntegralType valmax; + + + switch (rlen) { + case 1: + valmax = 255; + break; + case 2: + valmax = 32767; + break; + case 4: + valmax = 2147483647; + break; + case 8: + default: + if (rlen > sizeof(valmax)) { + valmax = 2147483647; + } else { + valmax = 9223372036854775807L; + } + break; + } + + if (result > valmax - 1) { + if (error > 0) { + cm_print_error("%s < 0, errno(" + LargestIntegralTypePrintfFormatDecimal "): %s\n", + expression, error, strerror((int)error)); + } else { + cm_print_error("%s < 0\n", expression); + } + _fail(file, line); + } +} + +void _assert_int_equal( + const LargestIntegralType a, const LargestIntegralType b, + const char * const file, const int line) { + if (!values_equal_display_error(a, b)) { + _fail(file, line); + } +} + + +void _assert_int_not_equal( + const LargestIntegralType a, const LargestIntegralType b, + const char * const file, const int line) { + if (!values_not_equal_display_error(a, b)) { + _fail(file, line); + } +} + + +void _assert_string_equal(const char * const a, const char * const b, + const char * const file, const int line) { + if (!string_equal_display_error(a, b)) { + _fail(file, line); + } +} + + +void _assert_string_not_equal(const char * const a, const char * const b, + const char *file, const int line) { + if (!string_not_equal_display_error(a, b)) { + _fail(file, line); + } +} + + +void _assert_memory_equal(const void * const a, const void * const b, + const size_t size, const char* const file, + const int line) { + if (!memory_equal_display_error((const char*)a, (const char*)b, size)) { + _fail(file, line); + } +} + + +void _assert_memory_not_equal(const void * const a, const void * const b, + const size_t size, const char* const file, + const int line) { + if (!memory_not_equal_display_error((const char*)a, (const char*)b, + size)) { + _fail(file, line); + } +} + + +void _assert_in_range( + const LargestIntegralType value, const LargestIntegralType minimum, + const LargestIntegralType maximum, const char* const file, + const int line) { + if (!integer_in_range_display_error(value, minimum, maximum)) { + _fail(file, line); + } +} + +void _assert_not_in_range( + const LargestIntegralType value, const LargestIntegralType minimum, + const LargestIntegralType maximum, const char* const file, + const int line) { + if (!integer_not_in_range_display_error(value, minimum, maximum)) { + _fail(file, line); + } +} + +void _assert_in_set(const LargestIntegralType value, + const LargestIntegralType values[], + const size_t number_of_values, const char* const file, + const int line) { + CheckIntegerSet check_integer_set; + check_integer_set.set = values; + check_integer_set.size_of_set = number_of_values; + if (!value_in_set_display_error(value, &check_integer_set, 0)) { + _fail(file, line); + } +} + +void _assert_not_in_set(const LargestIntegralType value, + const LargestIntegralType values[], + const size_t number_of_values, const char* const file, + const int line) { + CheckIntegerSet check_integer_set; + check_integer_set.set = values; + check_integer_set.size_of_set = number_of_values; + if (!value_in_set_display_error(value, &check_integer_set, 1)) { + _fail(file, line); + } +} + + +/* Get the list of allocated blocks. */ +static ListNode* get_allocated_blocks_list(void) { + /* If it initialized, initialize the list of allocated blocks. */ + if (!global_allocated_blocks.value) { + list_initialize(&global_allocated_blocks); + global_allocated_blocks.value = (void*)1; + } + return &global_allocated_blocks; +} + +static void *libc_malloc(size_t size) +{ +#undef malloc + return malloc(size); +#define malloc test_malloc +} + +static void libc_free(void *ptr) +{ +#undef free + free(ptr); +#define free test_free +} + +static void *libc_realloc(void *ptr, size_t size) +{ +#undef realloc + return realloc(ptr, size); +#define realloc test_realloc +} + +static void vcm_print_error(const char* const format, + va_list args) CMOCKA_PRINTF_ATTRIBUTE(1, 0); + +/* It's important to use the libc malloc and free here otherwise + * the automatic free of leaked blocks can reap the error messages + */ +static void vcm_print_error(const char* const format, va_list args) +{ + char buffer[1024]; + size_t msg_len = 0; + va_list ap; + int len; + va_copy(ap, args); + + len = vsnprintf(buffer, sizeof(buffer), format, args); + if (len < 0) { + /* TODO */ + goto end; + } + + if (cm_error_message == NULL) { + /* CREATE MESSAGE */ + + cm_error_message = libc_malloc(len + 1); + if (cm_error_message == NULL) { + /* TODO */ + goto end; + } + } else { + /* APPEND MESSAGE */ + char *tmp; + + msg_len = strlen(cm_error_message); + tmp = libc_realloc(cm_error_message, msg_len + len + 1); + if (tmp == NULL) { + goto end; + } + cm_error_message = tmp; + } + + if (((size_t)len) < sizeof(buffer)) { + /* Use len + 1 to also copy '\0' */ + memcpy(cm_error_message + msg_len, buffer, len + 1); + } else { + vsnprintf(cm_error_message + msg_len, len, format, ap); + } +end: + va_end(ap); + +} + +static void vcm_free_error(char *err_msg) +{ + libc_free(err_msg); +} + +/* Use the real malloc in this function. */ +#undef malloc +void* _test_malloc(const size_t size, const char* file, const int line) { + char *ptr = NULL; + MallocBlockInfo block_info; + ListNode * const block_list = get_allocated_blocks_list(); + size_t allocate_size; + char *block = NULL; + + allocate_size = size + (MALLOC_GUARD_SIZE * 2) + + sizeof(struct MallocBlockInfoData) + MALLOC_ALIGNMENT; + assert_true(allocate_size > size); + + block = (char *)malloc(allocate_size); + assert_non_null(block); + + /* Calculate the returned address. */ + ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE + + sizeof(struct MallocBlockInfoData) + + MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1)); + + /* Initialize the guard blocks. */ + memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE); + memset(ptr + size, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE); + memset(ptr, MALLOC_ALLOC_PATTERN, size); + + block_info.ptr = ptr - (MALLOC_GUARD_SIZE + + sizeof(struct MallocBlockInfoData)); + set_source_location(&block_info.data->location, file, line); + block_info.data->allocated_size = allocate_size; + block_info.data->size = size; + block_info.data->block = block; + block_info.data->node.value = block_info.ptr; + list_add(block_list, &block_info.data->node); + return ptr; +} +#define malloc test_malloc + + +void* _test_calloc(const size_t number_of_elements, const size_t size, + const char* file, const int line) { + void* const ptr = _test_malloc(number_of_elements * size, file, line); + if (ptr) { + memset(ptr, 0, number_of_elements * size); + } + return ptr; +} + + +/* Use the real free in this function. */ +#undef free +void _test_free(void* const ptr, const char* file, const int line) { + unsigned int i; + char *block = discard_const_p(char, ptr); + MallocBlockInfo block_info; + + if (ptr == NULL) { + return; + } + + _assert_true(cast_ptr_to_largest_integral_type(ptr), "ptr", file, line); + block_info.ptr = block - (MALLOC_GUARD_SIZE + + sizeof(struct MallocBlockInfoData)); + /* Check the guard blocks. */ + { + char *guards[2] = {block - MALLOC_GUARD_SIZE, + block + block_info.data->size}; + for (i = 0; i < ARRAY_SIZE(guards); i++) { + unsigned int j; + char * const guard = guards[i]; + for (j = 0; j < MALLOC_GUARD_SIZE; j++) { + const char diff = guard[j] - MALLOC_GUARD_PATTERN; + if (diff) { + cm_print_error(SOURCE_LOCATION_FORMAT + ": error: Guard block of %p size=%lu is corrupt\n" + SOURCE_LOCATION_FORMAT ": note: allocated here at %p\n", + file, + line, + ptr, + (unsigned long)block_info.data->size, + block_info.data->location.file, + block_info.data->location.line, + (void *)&guard[j]); + _fail(file, line); + } + } + } + } + list_remove(&block_info.data->node, NULL, NULL); + + block = discard_const_p(char, block_info.data->block); + memset(block, MALLOC_FREE_PATTERN, block_info.data->allocated_size); + free(block); +} +#define free test_free + +#undef realloc +void *_test_realloc(void *ptr, + const size_t size, + const char *file, + const int line) +{ + MallocBlockInfo block_info; + char *block = ptr; + size_t block_size = size; + void *new_block; + + if (ptr == NULL) { + return _test_malloc(size, file, line); + } + + if (size == 0) { + _test_free(ptr, file, line); + return NULL; + } + + block_info.ptr = block - (MALLOC_GUARD_SIZE + + sizeof(struct MallocBlockInfoData)); + + new_block = _test_malloc(size, file, line); + if (new_block == NULL) { + return NULL; + } + + if (block_info.data->size < size) { + block_size = block_info.data->size; + } + + memcpy(new_block, ptr, block_size); + + /* Free previous memory */ + _test_free(ptr, file, line); + + return new_block; +} +#define realloc test_realloc + +/* Crudely checkpoint the current heap state. */ +static const ListNode* check_point_allocated_blocks(void) { + return get_allocated_blocks_list()->prev; +} + + +/* Display the blocks allocated after the specified check point. This + * function returns the number of blocks displayed. */ +static size_t display_allocated_blocks(const ListNode * const check_point) { + const ListNode * const head = get_allocated_blocks_list(); + const ListNode *node; + size_t allocated_blocks = 0; + assert_non_null(check_point); + assert_non_null(check_point->next); + + for (node = check_point->next; node != head; node = node->next) { + const MallocBlockInfo block_info = { + .ptr = discard_const(node->value), + }; + assert_non_null(block_info.ptr); + + if (allocated_blocks == 0) { + cm_print_error("Blocks allocated...\n"); + } + cm_print_error(SOURCE_LOCATION_FORMAT ": note: block %p allocated here\n", + block_info.data->location.file, + block_info.data->location.line, + block_info.data->block); + allocated_blocks++; + } + return allocated_blocks; +} + + +/* Free all blocks allocated after the specified check point. */ +static void free_allocated_blocks(const ListNode * const check_point) { + const ListNode * const head = get_allocated_blocks_list(); + const ListNode *node; + assert_non_null(check_point); + + node = check_point->next; + assert_non_null(node); + + while (node != head) { + const MallocBlockInfo block_info = { + .ptr = discard_const(node->value), + }; + node = node->next; + free(discard_const_p(char, block_info.data) + + sizeof(struct MallocBlockInfoData) + + MALLOC_GUARD_SIZE); + } +} + + +/* Fail if any any blocks are allocated after the specified check point. */ +static void fail_if_blocks_allocated(const ListNode * const check_point, + const char * const test_name) { + const size_t allocated_blocks = display_allocated_blocks(check_point); + if (allocated_blocks > 0) { + free_allocated_blocks(check_point); + cm_print_error("ERROR: %s leaked %zu block(s)\n", test_name, + allocated_blocks); + exit_test(1); + } +} + + +void _fail(const char * const file, const int line) { + enum cm_message_output output = cm_get_output(); + + switch(output) { + case CM_OUTPUT_STDOUT: + cm_print_error("[ LINE ] --- " SOURCE_LOCATION_FORMAT ": error: Failure!", file, line); + break; + default: + cm_print_error(SOURCE_LOCATION_FORMAT ": error: Failure!", file, line); + break; + } + exit_test(1); +} + + +#ifndef _WIN32 +static void exception_handler(int sig) { + const char *sig_strerror = ""; + +#ifdef HAVE_STRSIGNAL + sig_strerror = strsignal(sig); +#endif + + cm_print_error("Test failed with exception: %s(%d)", + sig_strerror, sig); + exit_test(1); +} + +#else /* _WIN32 */ + +static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) { + EXCEPTION_RECORD * const exception_record = + exception_pointers->ExceptionRecord; + const DWORD code = exception_record->ExceptionCode; + unsigned int i; + for (i = 0; i < ARRAY_SIZE(exception_codes); i++) { + const ExceptionCodeInfo * const code_info = &exception_codes[i]; + if (code == code_info->code) { + static int shown_debug_message = 0; + fflush(stdout); + cm_print_error("%s occurred at %p.\n", code_info->description, + exception_record->ExceptionAddress); + if (!shown_debug_message) { + cm_print_error( + "\n" + "To debug in Visual Studio...\n" + "1. Select menu item File->Open Project\n" + "2. Change 'Files of type' to 'Executable Files'\n" + "3. Open this executable.\n" + "4. Select menu item Debug->Start\n" + "\n" + "Alternatively, set the environment variable \n" + "UNIT_TESTING_DEBUG to 1 and rebuild this executable, \n" + "then click 'Debug' in the popup dialog box.\n" + "\n"); + shown_debug_message = 1; + } + exit_test(0); + return EXCEPTION_EXECUTE_HANDLER; + } + } + return EXCEPTION_CONTINUE_SEARCH; +} +#endif /* !_WIN32 */ + +void cm_print_error(const char * const format, ...) +{ + va_list args; + va_start(args, format); + if (cm_error_message_enabled) { + vcm_print_error(format, args); + } else { + vprint_error(format, args); + } + va_end(args); +} + +/* Standard output and error print methods. */ +void vprint_message(const char* const format, va_list args) { + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), format, args); + printf("%s", buffer); + fflush(stdout); +#ifdef _WIN32 + OutputDebugString(buffer); +#endif /* _WIN32 */ +} + + +void vprint_error(const char* const format, va_list args) { + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), format, args); + fprintf(stderr, "%s", buffer); + fflush(stderr); +#ifdef _WIN32 + OutputDebugString(buffer); +#endif /* _WIN32 */ +} + + +void print_message(const char* const format, ...) { + va_list args; + va_start(args, format); + vprint_message(format, args); + va_end(args); +} + + +void print_error(const char* const format, ...) { + va_list args; + va_start(args, format); + vprint_error(format, args); + va_end(args); +} + +/* New formatter */ +static enum cm_message_output cm_get_output(void) +{ + enum cm_message_output output = global_msg_output; + char *env; + + env = getenv("CMOCKA_MESSAGE_OUTPUT"); + if (env != NULL) { + if (strcasecmp(env, "STDOUT") == 0) { + output = CM_OUTPUT_STDOUT; + } else if (strcasecmp(env, "SUBUNIT") == 0) { + output = CM_OUTPUT_SUBUNIT; + } else if (strcasecmp(env, "TAP") == 0) { + output = CM_OUTPUT_TAP; + } else if (strcasecmp(env, "XML") == 0) { + output = CM_OUTPUT_XML; + } + } + + return output; +} + +enum cm_printf_type { + PRINTF_TEST_START, + PRINTF_TEST_SUCCESS, + PRINTF_TEST_FAILURE, + PRINTF_TEST_ERROR, + PRINTF_TEST_SKIPPED, +}; + +static int xml_printed; +static int file_append; + +static void cmprintf_group_finish_xml(const char *group_name, + size_t total_executed, + size_t total_failed, + size_t total_errors, + size_t total_skipped, + double total_runtime, + struct CMUnitTestState *cm_tests) +{ + FILE *fp = stdout; + int file_opened = 0; + int multiple_files = 0; + char *env; + size_t i; + + env = getenv("CMOCKA_XML_FILE"); + if (env != NULL) { + char buf[1024]; + int rc; + + snprintf(buf, sizeof(buf), "%s", env); + + rc = c_strreplace(buf, sizeof(buf), "%g", group_name, &multiple_files); + if (rc < 0) { + snprintf(buf, sizeof(buf), "%s", env); + } + + fp = fopen(buf, "r"); + if (fp == NULL) { + fp = fopen(buf, "w"); + if (fp != NULL) { + file_append = 1; + file_opened = 1; + } else { + fp = stderr; + } + } else { + fclose(fp); + if (file_append) { + fp = fopen(buf, "a"); + if (fp != NULL) { + file_opened = 1; + xml_printed = 1; + } else { + fp = stderr; + } + } else { + fp = stderr; + } + } + } + + if (!xml_printed || (file_opened && !file_append)) { + fprintf(fp, "\n"); + if (!file_opened) { + xml_printed = 1; + } + } + + fprintf(fp, "\n"); + fprintf(fp, " \n", + group_name, + total_runtime, /* seconds */ + (unsigned)total_executed, + (unsigned)total_failed, + (unsigned)total_errors, + (unsigned)total_skipped); + + for (i = 0; i < total_executed; i++) { + struct CMUnitTestState *cmtest = &cm_tests[i]; + + fprintf(fp, " \n", + cmtest->test->name, cmtest->runtime); + + switch (cmtest->status) { + case CM_TEST_ERROR: + case CM_TEST_FAILED: + if (cmtest->error_message != NULL) { + fprintf(fp, " \n", + cmtest->error_message); + } else { + fprintf(fp, " \n"); + } + break; + case CM_TEST_SKIPPED: + fprintf(fp, " \n"); + break; + + case CM_TEST_PASSED: + case CM_TEST_NOT_STARTED: + break; + } + + fprintf(fp, " \n"); + } + + fprintf(fp, " \n"); + fprintf(fp, "\n"); + + if (file_opened) { + fclose(fp); + } +} + +static void cmprintf_group_start_standard(const size_t num_tests) +{ + print_message("[==========] Running %u test(s).\n", + (unsigned)num_tests); +} + +static void cmprintf_group_finish_standard(size_t total_executed, + size_t total_passed, + size_t total_failed, + size_t total_errors, + size_t total_skipped, + struct CMUnitTestState *cm_tests) +{ + size_t i; + + print_message("[==========] %u test(s) run.\n", (unsigned)total_executed); + print_error("[ PASSED ] %u test(s).\n", + (unsigned)(total_passed)); + + if (total_skipped) { + print_error("[ SKIPPED ] %"PRIdS " test(s), listed below:\n", total_skipped); + for (i = 0; i < total_executed; i++) { + struct CMUnitTestState *cmtest = &cm_tests[i]; + + if (cmtest->status == CM_TEST_SKIPPED) { + print_error("[ SKIPPED ] %s\n", cmtest->test->name); + } + } + print_error("\n %u SKIPPED TEST(S)\n", (unsigned)(total_skipped)); + } + + if (total_failed) { + print_error("[ FAILED ] %"PRIdS " test(s), listed below:\n", total_failed); + for (i = 0; i < total_executed; i++) { + struct CMUnitTestState *cmtest = &cm_tests[i]; + + if (cmtest->status == CM_TEST_FAILED) { + print_error("[ FAILED ] %s\n", cmtest->test->name); + } + } + print_error("\n %u FAILED TEST(S)\n", + (unsigned)(total_failed + total_errors)); + } +} + +static void cmprintf_standard(enum cm_printf_type type, + const char *test_name, + const char *error_message) +{ + switch (type) { + case PRINTF_TEST_START: + print_message("[ RUN ] %s\n", test_name); + break; + case PRINTF_TEST_SUCCESS: + print_message("[ OK ] %s\n", test_name); + break; + case PRINTF_TEST_FAILURE: + if (error_message != NULL) { + print_error("[ ERROR ] --- %s\n", error_message); + } + print_message("[ FAILED ] %s\n", test_name); + break; + case PRINTF_TEST_SKIPPED: + print_message("[ SKIPPED ] %s\n", test_name); + break; + case PRINTF_TEST_ERROR: + if (error_message != NULL) { + print_error("%s\n", error_message); + } + print_error("[ ERROR ] %s\n", test_name); + break; + } +} + +static void cmprintf_group_start_tap(const size_t num_tests) +{ + print_message("1..%u\n", (unsigned)num_tests); +} + +static void cmprintf_group_finish_tap(const char *group_name, + size_t total_executed, + size_t total_passed, + size_t total_skipped) +{ + const char *status = "not ok"; + if (total_passed + total_skipped == total_executed) { + status = "ok"; + } + print_message("# %s - %s\n", status, group_name); +} + +static void cmprintf_tap(enum cm_printf_type type, + uint32_t test_number, + const char *test_name, + const char *error_message) +{ + switch (type) { + case PRINTF_TEST_START: + break; + case PRINTF_TEST_SUCCESS: + print_message("ok %u - %s\n", (unsigned)test_number, test_name); + break; + case PRINTF_TEST_FAILURE: + print_message("not ok %u - %s\n", (unsigned)test_number, test_name); + if (error_message != NULL) { + char *msg; + char *p; + + msg = strdup(error_message); + if (msg == NULL) { + return; + } + p = msg; + + while (p[0] != '\0') { + char *q = p; + + p = strchr(q, '\n'); + if (p != NULL) { + p[0] = '\0'; + } + + print_message("# %s\n", q); + + if (p == NULL) { + break; + } + p++; + } + libc_free(msg); + } + break; + case PRINTF_TEST_SKIPPED: + print_message("not ok %u # SKIP %s\n", (unsigned)test_number, test_name); + break; + case PRINTF_TEST_ERROR: + print_message("not ok %u - %s %s\n", + (unsigned)test_number, test_name, error_message); + break; + } +} + +static void cmprintf_subunit(enum cm_printf_type type, + const char *test_name, + const char *error_message) +{ + switch (type) { + case PRINTF_TEST_START: + print_message("test: %s\n", test_name); + break; + case PRINTF_TEST_SUCCESS: + print_message("success: %s\n", test_name); + break; + case PRINTF_TEST_FAILURE: + print_message("failure: %s", test_name); + if (error_message != NULL) { + print_message(" [\n%s\n]\n", error_message); + } + break; + case PRINTF_TEST_SKIPPED: + print_message("skip: %s\n", test_name); + break; + case PRINTF_TEST_ERROR: + print_message("error: %s [ %s ]\n", test_name, error_message); + break; + } +} + +static void cmprintf_group_start(const size_t num_tests) +{ + enum cm_message_output output; + + output = cm_get_output(); + + switch (output) { + case CM_OUTPUT_STDOUT: + cmprintf_group_start_standard(num_tests); + break; + case CM_OUTPUT_SUBUNIT: + break; + case CM_OUTPUT_TAP: + cmprintf_group_start_tap(num_tests); + break; + case CM_OUTPUT_XML: + break; + } +} + +static void cmprintf_group_finish(const char *group_name, + size_t total_executed, + size_t total_passed, + size_t total_failed, + size_t total_errors, + size_t total_skipped, + double total_runtime, + struct CMUnitTestState *cm_tests) +{ + enum cm_message_output output; + + output = cm_get_output(); + + switch (output) { + case CM_OUTPUT_STDOUT: + cmprintf_group_finish_standard(total_executed, + total_passed, + total_failed, + total_errors, + total_skipped, + cm_tests); + break; + case CM_OUTPUT_SUBUNIT: + break; + case CM_OUTPUT_TAP: + cmprintf_group_finish_tap(group_name, total_executed, total_passed, total_skipped); + break; + case CM_OUTPUT_XML: + cmprintf_group_finish_xml(group_name, + total_executed, + total_failed, + total_errors, + total_skipped, + total_runtime, + cm_tests); + break; + } +} + +static void cmprintf(enum cm_printf_type type, + size_t test_number, + const char *test_name, + const char *error_message) +{ + enum cm_message_output output; + + output = cm_get_output(); + + switch (output) { + case CM_OUTPUT_STDOUT: + cmprintf_standard(type, test_name, error_message); + break; + case CM_OUTPUT_SUBUNIT: + cmprintf_subunit(type, test_name, error_message); + break; + case CM_OUTPUT_TAP: + cmprintf_tap(type, test_number, test_name, error_message); + break; + case CM_OUTPUT_XML: + break; + } +} + +void cmocka_set_message_output(enum cm_message_output output) +{ + global_msg_output = output; +} + +void cmocka_set_test_filter(const char *pattern) +{ + global_test_filter_pattern = pattern; +} + +/**************************************************************************** + * TIME CALCULATIONS + ****************************************************************************/ + +#ifdef HAVE_STRUCT_TIMESPEC +static struct timespec cm_tspecdiff(struct timespec time1, + struct timespec time0) +{ + struct timespec ret; + int xsec = 0; + int sign = 1; + + if (time0.tv_nsec > time1.tv_nsec) { + xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1)); + time0.tv_nsec -= (long int) (1E9 * xsec); + time0.tv_sec += xsec; + } + + if ((time1.tv_nsec - time0.tv_nsec) > 1E9) { + xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9); + time0.tv_nsec += (long int) (1E9 * xsec); + time0.tv_sec -= xsec; + } + + ret.tv_sec = time1.tv_sec - time0.tv_sec; + ret.tv_nsec = time1.tv_nsec - time0.tv_nsec; + + if (time1.tv_sec < time0.tv_sec) { + sign = -1; + } + + ret.tv_sec = ret.tv_sec * sign; + + return ret; +} + +static double cm_secdiff(struct timespec clock1, struct timespec clock0) +{ + double ret; + struct timespec diff; + + diff = cm_tspecdiff(clock1, clock0); + + ret = diff.tv_sec; + ret += (double) diff.tv_nsec / (double) 1E9; + + return ret; +} +#endif /* HAVE_STRUCT_TIMESPEC */ + +/**************************************************************************** + * CMOCKA TEST RUNNER + ****************************************************************************/ +static int cmocka_run_one_test_or_fixture(const char *function_name, + CMUnitTestFunction test_func, + CMFixtureFunction setup_func, + CMFixtureFunction teardown_func, + void ** const volatile state, + const void *const heap_check_point) +{ + const ListNode * const volatile check_point = (const ListNode*) + (heap_check_point != NULL ? + heap_check_point : check_point_allocated_blocks()); + int handle_exceptions = 1; + void *current_state = NULL; + int rc = 0; + + /* FIXME check only one test or fixture is set */ + + /* Detect if we should handle exceptions */ +#ifdef _WIN32 + handle_exceptions = !IsDebuggerPresent(); +#endif /* _WIN32 */ +#ifdef UNIT_TESTING_DEBUG + handle_exceptions = 0; +#endif /* UNIT_TESTING_DEBUG */ + + + if (handle_exceptions) { +#ifndef _WIN32 + unsigned int i; + for (i = 0; i < ARRAY_SIZE(exception_signals); i++) { + default_signal_functions[i] = signal( + exception_signals[i], exception_handler); + } +#else /* _WIN32 */ + previous_exception_filter = SetUnhandledExceptionFilter( + exception_filter); +#endif /* !_WIN32 */ + } + + /* Init the test structure */ + initialize_testing(function_name); + + global_running_test = 1; + + if (cm_setjmp(global_run_test_env) == 0) { + if (test_func != NULL) { + test_func(state != NULL ? state : ¤t_state); + + fail_if_blocks_allocated(check_point, function_name); + rc = 0; + } else if (setup_func != NULL) { + rc = setup_func(state != NULL ? state : ¤t_state); + + /* + * For setup we can ignore any allocated blocks. We just need to + * ensure they're deallocated on tear down. + */ + } else if (teardown_func != NULL) { + rc = teardown_func(state != NULL ? state : ¤t_state); + + fail_if_blocks_allocated(check_point, function_name); + } else { + /* ERROR */ + } + fail_if_leftover_values(function_name); + global_running_test = 0; + } else { + /* TEST FAILED */ + global_running_test = 0; + rc = -1; + } + teardown_testing(function_name); + + if (handle_exceptions) { +#ifndef _WIN32 + unsigned int i; + for (i = 0; i < ARRAY_SIZE(exception_signals); i++) { + signal(exception_signals[i], default_signal_functions[i]); + } +#else /* _WIN32 */ + if (previous_exception_filter) { + SetUnhandledExceptionFilter(previous_exception_filter); + previous_exception_filter = NULL; + } +#endif /* !_WIN32 */ + } + + return rc; +} + +static int cmocka_run_group_fixture(const char *function_name, + CMFixtureFunction setup_func, + CMFixtureFunction teardown_func, + void **state, + const void *const heap_check_point) +{ + int rc; + + if (setup_func != NULL) { + rc = cmocka_run_one_test_or_fixture(function_name, + NULL, + setup_func, + NULL, + state, + heap_check_point); + } else { + rc = cmocka_run_one_test_or_fixture(function_name, + NULL, + NULL, + teardown_func, + state, + heap_check_point); + } + + return rc; +} + +static int cmocka_run_one_tests(struct CMUnitTestState *test_state) +{ +#ifdef HAVE_STRUCT_TIMESPEC + struct timespec start = { + .tv_sec = 0, + .tv_nsec = 0, + }; + struct timespec finish = { + .tv_sec = 0, + .tv_nsec = 0, + }; +#endif + int rc = 0; + + /* Run setup */ + if (test_state->test->setup_func != NULL) { + /* Setup the memory check point, it will be evaluated on teardown */ + test_state->check_point = check_point_allocated_blocks(); + + rc = cmocka_run_one_test_or_fixture(test_state->test->name, + NULL, + test_state->test->setup_func, + NULL, + &test_state->state, + test_state->check_point); + if (rc != 0) { + test_state->status = CM_TEST_ERROR; + cm_print_error("Test setup failed"); + } + } + + /* Run test */ +#ifdef HAVE_STRUCT_TIMESPEC + CMOCKA_CLOCK_GETTIME(CLOCK_REALTIME, &start); +#endif + + if (rc == 0) { + rc = cmocka_run_one_test_or_fixture(test_state->test->name, + test_state->test->test_func, + NULL, + NULL, + &test_state->state, + NULL); + if (rc == 0) { + test_state->status = CM_TEST_PASSED; + } else { + if (global_skip_test) { + test_state->status = CM_TEST_SKIPPED; + global_skip_test = 0; /* Do not skip the next test */ + } else { + test_state->status = CM_TEST_FAILED; + } + } + rc = 0; + } + + test_state->runtime = 0.0; + +#ifdef HAVE_STRUCT_TIMESPEC + CMOCKA_CLOCK_GETTIME(CLOCK_REALTIME, &finish); + test_state->runtime = cm_secdiff(finish, start); +#endif + + /* Run teardown */ + if (rc == 0 && test_state->test->teardown_func != NULL) { + rc = cmocka_run_one_test_or_fixture(test_state->test->name, + NULL, + NULL, + test_state->test->teardown_func, + &test_state->state, + test_state->check_point); + if (rc != 0) { + test_state->status = CM_TEST_ERROR; + cm_print_error("Test teardown failed"); + } + } + + test_state->error_message = cm_error_message; + cm_error_message = NULL; + + return rc; +} + +int _cmocka_run_group_tests(const char *group_name, + const struct CMUnitTest * const tests, + const size_t num_tests, + CMFixtureFunction group_setup, + CMFixtureFunction group_teardown) +{ + struct CMUnitTestState *cm_tests; + const ListNode *group_check_point = check_point_allocated_blocks(); + void *group_state = NULL; + size_t total_tests = 0; + size_t total_failed = 0; + size_t total_passed = 0; + size_t total_executed = 0; + size_t total_errors = 0; + size_t total_skipped = 0; + double total_runtime = 0; + size_t i; + int rc; + + /* Make sure LargestIntegralType is at least the size of a pointer. */ + assert_true(sizeof(LargestIntegralType) >= sizeof(void*)); + + cm_tests = (struct CMUnitTestState *)libc_malloc(sizeof(struct CMUnitTestState) * num_tests); + if (cm_tests == NULL) { + return -1; + } + + /* Setup cmocka test array */ + for (i = 0; i < num_tests; i++) { + if (tests[i].name != NULL && + (tests[i].test_func != NULL + || tests[i].setup_func != NULL + || tests[i].teardown_func != NULL)) { + if (global_test_filter_pattern != NULL) { + int ok; + + ok = c_strmatch(tests[i].name, global_test_filter_pattern); + if (!ok) { + continue; + } + } + cm_tests[total_tests] = (struct CMUnitTestState) { + .test = &tests[i], + .status = CM_TEST_NOT_STARTED, + .state = NULL, + }; + total_tests++; + } + } + + cmprintf_group_start(total_tests); + + rc = 0; + + /* Run group setup */ + if (group_setup != NULL) { + rc = cmocka_run_group_fixture("cmocka_group_setup", + group_setup, + NULL, + &group_state, + group_check_point); + } + + if (rc == 0) { + /* Execute tests */ + for (i = 0; i < total_tests; i++) { + struct CMUnitTestState *cmtest = &cm_tests[i]; + size_t test_number = i + 1; + + cmprintf(PRINTF_TEST_START, test_number, cmtest->test->name, NULL); + + if (group_state != NULL) { + cmtest->state = group_state; + } else if (cmtest->test->initial_state != NULL) { + cmtest->state = cmtest->test->initial_state; + } + + rc = cmocka_run_one_tests(cmtest); + total_executed++; + total_runtime += cmtest->runtime; + if (rc == 0) { + switch (cmtest->status) { + case CM_TEST_PASSED: + cmprintf(PRINTF_TEST_SUCCESS, + test_number, + cmtest->test->name, + cmtest->error_message); + total_passed++; + break; + case CM_TEST_SKIPPED: + cmprintf(PRINTF_TEST_SKIPPED, + test_number, + cmtest->test->name, + cmtest->error_message); + total_skipped++; + break; + case CM_TEST_FAILED: + cmprintf(PRINTF_TEST_FAILURE, + test_number, + cmtest->test->name, + cmtest->error_message); + total_failed++; + break; + default: + cmprintf(PRINTF_TEST_ERROR, + test_number, + cmtest->test->name, + "Internal cmocka error"); + total_errors++; + break; + } + } else { + char err_msg[2048] = {0}; + + snprintf(err_msg, sizeof(err_msg), + "Could not run test: %s", + cmtest->error_message); + + cmprintf(PRINTF_TEST_ERROR, + test_number, + cmtest->test->name, + err_msg); + total_errors++; + } + } + } else { + if (cm_error_message != NULL) { + print_error("[ ERROR ] --- %s\n", cm_error_message); + vcm_free_error(cm_error_message); + cm_error_message = NULL; + } + cmprintf(PRINTF_TEST_ERROR, 0, + group_name, "[ FAILED ] GROUP SETUP"); + total_errors++; + } + + /* Run group teardown */ + if (group_teardown != NULL) { + rc = cmocka_run_group_fixture("cmocka_group_teardown", + NULL, + group_teardown, + &group_state, + group_check_point); + if (rc != 0) { + if (cm_error_message != NULL) { + print_error("[ ERROR ] --- %s\n", cm_error_message); + vcm_free_error(cm_error_message); + cm_error_message = NULL; + } + cmprintf(PRINTF_TEST_ERROR, 0, + group_name, "[ FAILED ] GROUP TEARDOWN"); + } + } + + cmprintf_group_finish(group_name, + total_executed, + total_passed, + total_failed, + total_errors, + total_skipped, + total_runtime, + cm_tests); + + for (i = 0; i < total_tests; i++) { + vcm_free_error(discard_const_p(char, cm_tests[i].error_message)); + } + libc_free(cm_tests); + fail_if_blocks_allocated(group_check_point, "cmocka_group_tests"); + + return total_failed + total_errors; +} + +/**************************************************************************** + * DEPRECATED TEST RUNNER + ****************************************************************************/ + +int _run_test( + const char * const function_name, const UnitTestFunction Function, + void ** const volatile state, const UnitTestFunctionType function_type, + const void* const heap_check_point) { + const ListNode * const volatile check_point = (const ListNode*) + (heap_check_point ? + heap_check_point : check_point_allocated_blocks()); + void *current_state = NULL; + volatile int rc = 1; + int handle_exceptions = 1; +#ifdef _WIN32 + handle_exceptions = !IsDebuggerPresent(); +#endif /* _WIN32 */ +#ifdef UNIT_TESTING_DEBUG + handle_exceptions = 0; +#endif /* UNIT_TESTING_DEBUG */ + + cm_error_message_enabled = 0; + + if (handle_exceptions) { +#ifndef _WIN32 + unsigned int i; + for (i = 0; i < ARRAY_SIZE(exception_signals); i++) { + default_signal_functions[i] = signal( + exception_signals[i], exception_handler); + } +#else /* _WIN32 */ + previous_exception_filter = SetUnhandledExceptionFilter( + exception_filter); +#endif /* !_WIN32 */ + } + + if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) { + print_message("[ RUN ] %s\n", function_name); + } + initialize_testing(function_name); + global_running_test = 1; + if (cm_setjmp(global_run_test_env) == 0) { + Function(state ? state : ¤t_state); + fail_if_leftover_values(function_name); + + /* If this is a setup function then ignore any allocated blocks + * only ensure they're deallocated on tear down. */ + if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) { + fail_if_blocks_allocated(check_point, function_name); + } + + global_running_test = 0; + + if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) { + print_message("[ OK ] %s\n", function_name); + } + rc = 0; + } else { + global_running_test = 0; + print_message("[ FAILED ] %s\n", function_name); + } + teardown_testing(function_name); + + if (handle_exceptions) { +#ifndef _WIN32 + unsigned int i; + for (i = 0; i < ARRAY_SIZE(exception_signals); i++) { + signal(exception_signals[i], default_signal_functions[i]); + } +#else /* _WIN32 */ + if (previous_exception_filter) { + SetUnhandledExceptionFilter(previous_exception_filter); + previous_exception_filter = NULL; + } +#endif /* !_WIN32 */ + } + + return rc; +} + + +int _run_tests(const UnitTest * const tests, const size_t number_of_tests) { + /* Whether to execute the next test. */ + int run_next_test = 1; + /* Whether the previous test failed. */ + int previous_test_failed = 0; + /* Whether the previous setup failed. */ + int previous_setup_failed = 0; + /* Check point of the heap state. */ + const ListNode * const check_point = check_point_allocated_blocks(); + /* Current test being executed. */ + size_t current_test = 0; + /* Number of tests executed. */ + size_t tests_executed = 0; + /* Number of failed tests. */ + size_t total_failed = 0; + /* Number of setup functions. */ + size_t setups = 0; + /* Number of teardown functions. */ + size_t teardowns = 0; + size_t i; + /* + * A stack of test states. A state is pushed on the stack + * when a test setup occurs and popped on tear down. + */ + TestState* test_states = + (TestState*)malloc(number_of_tests * sizeof(*test_states)); + /* The number of test states which should be 0 at the end */ + long number_of_test_states = 0; + /* Names of the tests that failed. */ + const char** failed_names = (const char**)malloc(number_of_tests * + sizeof(*failed_names)); + void **current_state = NULL; + + /* Count setup and teardown functions */ + for (i = 0; i < number_of_tests; i++) { + const UnitTest * const test = &tests[i]; + + if (test->function_type == UNIT_TEST_FUNCTION_TYPE_SETUP) { + setups++; + } + + if (test->function_type == UNIT_TEST_FUNCTION_TYPE_TEARDOWN) { + teardowns++; + } + } + + print_message("[==========] Running %"PRIdS " test(s).\n", + number_of_tests - setups - teardowns); + + /* Make sure LargestIntegralType is at least the size of a pointer. */ + assert_true(sizeof(LargestIntegralType) >= sizeof(void*)); + + while (current_test < number_of_tests) { + const ListNode *test_check_point = NULL; + TestState *current_TestState; + const UnitTest * const test = &tests[current_test++]; + if (!test->function) { + continue; + } + + switch (test->function_type) { + case UNIT_TEST_FUNCTION_TYPE_TEST: + if (! previous_setup_failed) { + run_next_test = 1; + } + break; + case UNIT_TEST_FUNCTION_TYPE_SETUP: { + /* Checkpoint the heap before the setup. */ + current_TestState = &test_states[number_of_test_states++]; + current_TestState->check_point = check_point_allocated_blocks(); + test_check_point = current_TestState->check_point; + current_state = ¤t_TestState->state; + *current_state = NULL; + run_next_test = 1; + break; + } + case UNIT_TEST_FUNCTION_TYPE_TEARDOWN: + /* Check the heap based on the last setup checkpoint. */ + assert_true(number_of_test_states); + current_TestState = &test_states[--number_of_test_states]; + test_check_point = current_TestState->check_point; + current_state = ¤t_TestState->state; + break; + default: + print_error("Invalid unit test function type %d\n", + test->function_type); + exit_test(1); + break; + } + + if (run_next_test) { + int failed = _run_test(test->name, test->function, current_state, + test->function_type, test_check_point); + if (failed) { + failed_names[total_failed] = test->name; + } + + switch (test->function_type) { + case UNIT_TEST_FUNCTION_TYPE_TEST: + previous_test_failed = failed; + total_failed += failed; + tests_executed ++; + break; + + case UNIT_TEST_FUNCTION_TYPE_SETUP: + if (failed) { + total_failed ++; + tests_executed ++; + /* Skip forward until the next test or setup function. */ + run_next_test = 0; + previous_setup_failed = 1; + } + previous_test_failed = 0; + break; + + case UNIT_TEST_FUNCTION_TYPE_TEARDOWN: + /* If this test failed. */ + if (failed && !previous_test_failed) { + total_failed ++; + } + break; + default: +#ifndef _HPUX + assert_null("BUG: shouldn't be here!"); +#endif + break; + } + } + } + + print_message("[==========] %"PRIdS " test(s) run.\n", tests_executed); + print_error("[ PASSED ] %"PRIdS " test(s).\n", tests_executed - total_failed); + + if (total_failed > 0) { + print_error("[ FAILED ] %"PRIdS " test(s), listed below:\n", total_failed); + for (i = 0; i < total_failed; i++) { + print_error("[ FAILED ] %s\n", failed_names[i]); + } + } else { + print_error("\n %"PRIdS " FAILED TEST(S)\n", total_failed); + } + + if (number_of_test_states != 0) { + print_error("[ ERROR ] Mismatched number of setup %"PRIdS " and " + "teardown %"PRIdS " functions\n", setups, teardowns); + total_failed = (size_t)-1; + } + + free(test_states); + free((void*)failed_names); + + fail_if_blocks_allocated(check_point, "run_tests"); + return (int)total_failed; +} + +int _run_group_tests(const UnitTest * const tests, const size_t number_of_tests) +{ + UnitTestFunction setup = NULL; + const char *setup_name; + size_t num_setups = 0; + UnitTestFunction teardown = NULL; + const char *teardown_name = NULL; + size_t num_teardowns = 0; + size_t current_test = 0; + size_t i; + + /* Number of tests executed. */ + size_t tests_executed = 0; + /* Number of failed tests. */ + size_t total_failed = 0; + /* Check point of the heap state. */ + const ListNode * const check_point = check_point_allocated_blocks(); + const char **failed_names = NULL; + void **current_state = NULL; + TestState group_state = { + .check_point = NULL, + }; + + if (number_of_tests == 0) { + return -1; + } + + failed_names = (const char **)malloc(number_of_tests * + sizeof(*failed_names)); + if (failed_names == NULL) { + return -2; + } + + /* Find setup and teardown function */ + for (i = 0; i < number_of_tests; i++) { + const UnitTest * const test = &tests[i]; + + if (test->function_type == UNIT_TEST_FUNCTION_TYPE_GROUP_SETUP) { + if (setup == NULL) { + setup = test->function; + setup_name = test->name; + num_setups = 1; + } else { + print_error("[ ERROR ] More than one group setup function detected\n"); + exit_test(1); + } + } + + if (test->function_type == UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN) { + if (teardown == NULL) { + teardown = test->function; + teardown_name = test->name; + num_teardowns = 1; + } else { + print_error("[ ERROR ] More than one group teardown function detected\n"); + exit_test(1); + } + } + } + + print_message("[==========] Running %"PRIdS " test(s).\n", + number_of_tests - num_setups - num_teardowns); + + if (setup != NULL) { + int failed; + + group_state.check_point = check_point_allocated_blocks(); + current_state = &group_state.state; + *current_state = NULL; + failed = _run_test(setup_name, + setup, + current_state, + UNIT_TEST_FUNCTION_TYPE_SETUP, + group_state.check_point); + if (failed) { + failed_names[total_failed] = setup_name; + } + + total_failed += failed; + tests_executed++; + } + + while (current_test < number_of_tests) { + int run_test = 0; + const UnitTest * const test = &tests[current_test++]; + if (test->function == NULL) { + continue; + } + + switch (test->function_type) { + case UNIT_TEST_FUNCTION_TYPE_TEST: + run_test = 1; + break; + case UNIT_TEST_FUNCTION_TYPE_SETUP: + case UNIT_TEST_FUNCTION_TYPE_TEARDOWN: + case UNIT_TEST_FUNCTION_TYPE_GROUP_SETUP: + case UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN: + break; + default: + print_error("Invalid unit test function type %d\n", + test->function_type); + break; + } + + if (run_test) { + int failed; + + failed = _run_test(test->name, + test->function, + current_state, + test->function_type, + NULL); + if (failed) { + failed_names[total_failed] = test->name; + } + + total_failed += failed; + tests_executed++; + } + } + + if (teardown != NULL) { + int failed; + + failed = _run_test(teardown_name, + teardown, + current_state, + UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN, + group_state.check_point); + if (failed) { + failed_names[total_failed] = teardown_name; + } + + total_failed += failed; + tests_executed++; + } + + print_message("[==========] %"PRIdS " test(s) run.\n", tests_executed); + print_error("[ PASSED ] %"PRIdS " test(s).\n", tests_executed - total_failed); + + if (total_failed) { + print_error("[ FAILED ] %"PRIdS " test(s), listed below:\n", total_failed); + for (i = 0; i < total_failed; i++) { + print_error("[ FAILED ] %s\n", failed_names[i]); + } + } else { + print_error("\n %"PRIdS " FAILED TEST(S)\n", total_failed); + } + + free((void*)failed_names); + fail_if_blocks_allocated(check_point, "run_group_tests"); + + return (int)total_failed; +} diff --git a/ldb-2.0.8/third_party/cmocka/cmocka.h b/ldb-2.0.8/third_party/cmocka/cmocka.h new file mode 100644 index 0000000..e6861c8 --- /dev/null +++ b/ldb-2.0.8/third_party/cmocka/cmocka.h @@ -0,0 +1,2298 @@ +/* + * Copyright 2008 Google Inc. + * Copyright 2014-2018 Andreas Schneider + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef CMOCKA_H_ +#define CMOCKA_H_ + +#ifdef _WIN32 +# ifdef _MSC_VER + +#define __func__ __FUNCTION__ + +# ifndef inline +#define inline __inline +# endif /* inline */ + +# if _MSC_VER < 1500 +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ +int __stdcall IsDebuggerPresent(); +# ifdef __cplusplus +} /* extern "C" */ +# endif /* __cplusplus */ +# endif /* _MSC_VER < 1500 */ +# endif /* _MSC_VER */ +#endif /* _WIN32 */ + +/** + * @defgroup cmocka The CMocka API + * + * These headers or their equivalents should be included prior to including + * this header file. + * @code + * #include + * #include + * #include + * @endcode + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + * @{ + */ + +/* If __WORDSIZE is not set, try to figure it out and default to 32 bit. */ +#ifndef __WORDSIZE +# if (defined(__x86_64__) && !defined(__ILP32__)) || defined(__sparc_v9__) || defined(__sparcv9) +# define __WORDSIZE 64 +# else +# define __WORDSIZE 32 +# endif +#endif + +#ifdef DOXYGEN +/** + * Largest integral type. This type should be large enough to hold any + * pointer or integer supported by the compiler. + */ +typedef uintmax_t LargestIntegralType; +#else /* DOXGEN */ +#ifndef LargestIntegralType +# if __WORDSIZE == 64 && !defined(_WIN64) +# define LargestIntegralType unsigned long int +# else +# define LargestIntegralType unsigned long long int +# endif +#endif /* LargestIntegralType */ +#endif /* DOXYGEN */ + +/* Printf format used to display LargestIntegralType as a hexidecimal. */ +#ifndef LargestIntegralTypePrintfFormat +# ifdef _WIN32 +# define LargestIntegralTypePrintfFormat "0x%I64x" +# else +# if __WORDSIZE == 64 +# define LargestIntegralTypePrintfFormat "%#lx" +# else +# define LargestIntegralTypePrintfFormat "%#llx" +# endif +# endif /* _WIN32 */ +#endif /* LargestIntegralTypePrintfFormat */ + +/* Printf format used to display LargestIntegralType as a decimal. */ +#ifndef LargestIntegralTypePrintfFormatDecimal +# ifdef _WIN32 +# define LargestIntegralTypePrintfFormatDecimal "%I64u" +# else +# if __WORDSIZE == 64 +# define LargestIntegralTypePrintfFormatDecimal "%lu" +# else +# define LargestIntegralTypePrintfFormatDecimal "%llu" +# endif +# endif /* _WIN32 */ +#endif /* LargestIntegralTypePrintfFormat */ + +/* Perform an unsigned cast to LargestIntegralType. */ +#define cast_to_largest_integral_type(value) \ + ((LargestIntegralType)(value)) + +/* Smallest integral type capable of holding a pointer. */ +#if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) +# if defined(_WIN32) + /* WIN32 is an ILP32 platform */ + typedef unsigned int uintptr_t; +# elif defined(_WIN64) + typedef unsigned long int uintptr_t +# else /* _WIN32 */ + +/* ILP32 and LP64 platforms */ +# ifdef __WORDSIZE /* glibc */ +# if __WORDSIZE == 64 + typedef unsigned long int uintptr_t; +# else + typedef unsigned int uintptr_t; +# endif /* __WORDSIZE == 64 */ +# else /* __WORDSIZE */ +# if defined(_LP64) || defined(_I32LPx) + typedef unsigned long int uintptr_t; +# else + typedef unsigned int uintptr_t; +# endif +# endif /* __WORDSIZE */ +# endif /* _WIN32 */ + +# define _UINTPTR_T +# define _UINTPTR_T_DEFINED +#endif /* !defined(_UINTPTR_T) || !defined(_UINTPTR_T_DEFINED) */ + +/* Perform an unsigned cast to uintptr_t. */ +#define cast_to_pointer_integral_type(value) \ + ((uintptr_t)((size_t)(value))) + +/* Perform a cast of a pointer to LargestIntegralType */ +#define cast_ptr_to_largest_integral_type(value) \ +cast_to_largest_integral_type(cast_to_pointer_integral_type(value)) + +/* GCC have printf type attribute check. */ +#ifdef __GNUC__ +#define CMOCKA_PRINTF_ATTRIBUTE(a,b) \ + __attribute__ ((__format__ (__printf__, a, b))) +#else +#define CMOCKA_PRINTF_ATTRIBUTE(a,b) +#endif /* __GNUC__ */ + +#if defined(__GNUC__) +#define CMOCKA_DEPRECATED __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define CMOCKA_DEPRECATED __declspec(deprecated) +#else +#define CMOCKA_DEPRECATED +#endif + +#define WILL_RETURN_ALWAYS -1 +#define WILL_RETURN_ONCE -2 + +/** + * @defgroup cmocka_mock Mock Objects + * @ingroup cmocka + * + * Mock objects mock objects are simulated objects that mimic the behavior of + * real objects. Instead of calling the real objects, the tested object calls a + * mock object that merely asserts that the correct methods were called, with + * the expected parameters, in the correct order. + * + *

    + *
  • will_return(function, value) - The will_return() macro + * pushes a value onto a stack of mock values. This macro is intended to be + * used by the unit test itself, while programming the behaviour of the mocked + * object.
  • + * + *
  • mock() - the mock macro pops a value from a stack of + * test values. The user of the mock() macro is the mocked object that uses it + * to learn how it should behave.
  • + *
+ * + * Because the will_return() and mock() are intended to be used in pairs, the + * cmocka library would fail the test if there are more values pushed onto the + * stack using will_return() than consumed with mock() and vice-versa. + * + * The following unit test stub illustrates how would a unit test instruct the + * mock object to return a particular value: + * + * @code + * will_return(chef_cook, "hotdog"); + * will_return(chef_cook, 0); + * @endcode + * + * Now the mock object can check if the parameter it received is the parameter + * which is expected by the test driver. This can be done the following way: + * + * @code + * int chef_cook(const char *order, char **dish_out) + * { + * check_expected(order); + * } + * @endcode + * + * For a complete example please at a look + * here. + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief Retrieve a return value of the current function. + * + * @return The value which was stored to return by this function. + * + * @see will_return() + */ +LargestIntegralType mock(void); +#else +#define mock() _mock(__func__, __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Retrieve a typed return value of the current function. + * + * The value would be casted to type internally to avoid having the + * caller to do the cast manually. + * + * @param[in] #type The expected type of the return value + * + * @return The value which was stored to return by this function. + * + * @code + * int param; + * + * param = mock_type(int); + * @endcode + * + * @see will_return() + * @see mock() + * @see mock_ptr_type() + */ +#type mock_type(#type); +#else +#define mock_type(type) ((type) mock()) +#endif + +#ifdef DOXYGEN +/** + * @brief Retrieve a typed return value of the current function. + * + * The value would be casted to type internally to avoid having the + * caller to do the cast manually but also casted to uintptr_t to make + * sure the result has a valid size to be used as a pointer. + * + * @param[in] #type The expected type of the return value + * + * @return The value which was stored to return by this function. + * + * @code + * char *param; + * + * param = mock_ptr_type(char *); + * @endcode + * + * @see will_return() + * @see mock() + * @see mock_type() + */ +type mock_ptr_type(#type); +#else +#define mock_ptr_type(type) ((type) (uintptr_t) mock()) +#endif + + +#ifdef DOXYGEN +/** + * @brief Store a value to be returned by mock() later. + * + * @param[in] #function The function which should return the given value. + * + * @param[in] value The value to be returned by mock(). + * + * @code + * int return_integer(void) + * { + * return (int)mock(); + * } + * + * static void test_integer_return(void **state) + * { + * will_return(return_integer, 42); + * + * assert_int_equal(my_function_calling_return_integer(), 42); + * } + * @endcode + * + * @see mock() + * @see will_return_count() + */ +void will_return(#function, LargestIntegralType value); +#else +#define will_return(function, value) \ + _will_return(#function, __FILE__, __LINE__, \ + cast_to_largest_integral_type(value), 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Store a value to be returned by mock() later. + * + * @param[in] #function The function which should return the given value. + * + * @param[in] value The value to be returned by mock(). + * + * @param[in] count The parameter indicates the number of times the value should + * be returned by mock(). If count is set to -1, the value + * will always be returned but must be returned at least once. + * If count is set to -2, the value will always be returned + * by mock(), but is not required to be returned. + * + * @see mock() + */ +void will_return_count(#function, LargestIntegralType value, int count); +#else +#define will_return_count(function, value, count) \ + _will_return(#function, __FILE__, __LINE__, \ + cast_to_largest_integral_type(value), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Store a value that will be always returned by mock(). + * + * @param[in] #function The function which should return the given value. + * + * @param[in] #value The value to be returned by mock(). + * + * This is equivalent to: + * @code + * will_return_count(function, value, -1); + * @endcode + * + * @see will_return_count() + * @see mock() + */ +void will_return_always(#function, LargestIntegralType value); +#else +#define will_return_always(function, value) \ + will_return_count(function, (value), WILL_RETURN_ALWAYS) +#endif + +#ifdef DOXYGEN +/** + * @brief Store a value that may be always returned by mock(). + * + * This stores a value which will always be returned by mock() but is not + * required to be returned by at least one call to mock(). Therefore, + * in contrast to will_return_always() which causes a test failure if it + * is not returned at least once, will_return_maybe() will never cause a test + * to fail if its value is not returned. + * + * @param[in] #function The function which should return the given value. + * + * @param[in] #value The value to be returned by mock(). + * + * This is equivalent to: + * @code + * will_return_count(function, value, -2); + * @endcode + * + * @see will_return_count() + * @see mock() + */ +void will_return_maybe(#function, LargestIntegralType value); +#else +#define will_return_maybe(function, value) \ + will_return_count(function, (value), WILL_RETURN_ONCE) +#endif +/** @} */ + +/** + * @defgroup cmocka_param Checking Parameters + * @ingroup cmocka + * + * Functionality to store expected values for mock function parameters. + * + * In addition to storing the return values of mock functions, cmocka provides + * functionality to store expected values for mock function parameters using + * the expect_*() functions provided. A mock function parameter can then be + * validated using the check_expected() macro. + * + * Successive calls to expect_*() macros for a parameter queues values to check + * the specified parameter. check_expected() checks a function parameter + * against the next value queued using expect_*(), if the parameter check fails + * a test failure is signalled. In addition if check_expected() is called and + * no more parameter values are queued a test failure occurs. + * + * The following test stub illustrates how to do this. First is the the function + * we call in the test driver: + * + * @code + * static void test_driver(void **state) + * { + * expect_string(chef_cook, order, "hotdog"); + * } + * @endcode + * + * Now the chef_cook function can check if the parameter we got passed is the + * parameter which is expected by the test driver. This can be done the + * following way: + * + * @code + * int chef_cook(const char *order, char **dish_out) + * { + * check_expected(order); + * } + * @endcode + * + * For a complete example please at a look at + * here + * + * @{ + */ + +/* + * Add a custom parameter checking function. If the event parameter is NULL + * the event structure is allocated internally by this function. If event + * parameter is provided it must be allocated on the heap and doesn't need to + * be deallocated by the caller. + */ +#ifdef DOXYGEN +/** + * @brief Add a custom parameter checking function. + * + * If the event parameter is NULL the event structure is allocated internally + * by this function. If the parameter is provided it must be allocated on the + * heap and doesn't need to be deallocated by the caller. + * + * @param[in] #function The function to add a custom parameter checking + * function for. + * + * @param[in] #parameter The parameters passed to the function. + * + * @param[in] #check_function The check function to call. + * + * @param[in] check_data The data to pass to the check function. + */ +void expect_check(#function, #parameter, #check_function, const void *check_data); +#else +#define expect_check(function, parameter, check_function, check_data) \ + _expect_check(#function, #parameter, __FILE__, __LINE__, check_function, \ + cast_to_largest_integral_type(check_data), NULL, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value is part of the provided + * array. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value_array[] The array to check for the value. + * + * @see check_expected(). + */ +void expect_in_set(#function, #parameter, LargestIntegralType value_array[]); +#else +#define expect_in_set(function, parameter, value_array) \ + expect_in_set_count(function, parameter, value_array, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value is part of the provided + * array. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value_array[] The array to check for the value. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_in_set_count(#function, #parameter, LargestIntegralType value_array[], size_t count); +#else +#define expect_in_set_count(function, parameter, value_array, count) \ + _expect_in_set(#function, #parameter, __FILE__, __LINE__, value_array, \ + sizeof(value_array) / sizeof((value_array)[0]), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value is not part of the + * provided array. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value_array[] The array to check for the value. + * + * @see check_expected(). + */ +void expect_not_in_set(#function, #parameter, LargestIntegralType value_array[]); +#else +#define expect_not_in_set(function, parameter, value_array) \ + expect_not_in_set_count(function, parameter, value_array, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value is not part of the + * provided array. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value_array[] The array to check for the value. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_not_in_set_count(#function, #parameter, LargestIntegralType value_array[], size_t count); +#else +#define expect_not_in_set_count(function, parameter, value_array, count) \ + _expect_not_in_set( \ + #function, #parameter, __FILE__, __LINE__, value_array, \ + sizeof(value_array) / sizeof((value_array)[0]), count) +#endif + + +#ifdef DOXYGEN +/** + * @brief Add an event to check a parameter is inside a numerical range. + * The check would succeed if minimum <= value <= maximum. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] minimum The lower boundary of the interval to check against. + * + * @param[in] maximum The upper boundary of the interval to check against. + * + * @see check_expected(). + */ +void expect_in_range(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum); +#else +#define expect_in_range(function, parameter, minimum, maximum) \ + expect_in_range_count(function, parameter, minimum, maximum, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to repeatedly check a parameter is inside a + * numerical range. The check would succeed if minimum <= value <= maximum. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] minimum The lower boundary of the interval to check against. + * + * @param[in] maximum The upper boundary of the interval to check against. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_in_range_count(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum, size_t count); +#else +#define expect_in_range_count(function, parameter, minimum, maximum, count) \ + _expect_in_range(#function, #parameter, __FILE__, __LINE__, minimum, \ + maximum, count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check a parameter is outside a numerical range. + * The check would succeed if minimum > value > maximum. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] minimum The lower boundary of the interval to check against. + * + * @param[in] maximum The upper boundary of the interval to check against. + * + * @see check_expected(). + */ +void expect_not_in_range(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum); +#else +#define expect_not_in_range(function, parameter, minimum, maximum) \ + expect_not_in_range_count(function, parameter, minimum, maximum, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to repeatedly check a parameter is outside a + * numerical range. The check would succeed if minimum > value > maximum. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] minimum The lower boundary of the interval to check against. + * + * @param[in] maximum The upper boundary of the interval to check against. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_not_in_range_count(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum, size_t count); +#else +#define expect_not_in_range_count(function, parameter, minimum, maximum, \ + count) \ + _expect_not_in_range(#function, #parameter, __FILE__, __LINE__, \ + minimum, maximum, count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if a parameter is the given value. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value The value to check. + * + * @see check_expected(). + */ +void expect_value(#function, #parameter, LargestIntegralType value); +#else +#define expect_value(function, parameter, value) \ + expect_value_count(function, parameter, value, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to repeatedly check if a parameter is the given value. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value The value to check. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_value_count(#function, #parameter, LargestIntegralType value, size_t count); +#else +#define expect_value_count(function, parameter, value, count) \ + _expect_value(#function, #parameter, __FILE__, __LINE__, \ + cast_to_largest_integral_type(value), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if a parameter isn't the given value. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value The value to check. + * + * @see check_expected(). + */ +void expect_not_value(#function, #parameter, LargestIntegralType value); +#else +#define expect_not_value(function, parameter, value) \ + expect_not_value_count(function, parameter, value, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to repeatedly check if a parameter isn't the given value. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] value The value to check. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_not_value_count(#function, #parameter, LargestIntegralType value, size_t count); +#else +#define expect_not_value_count(function, parameter, value, count) \ + _expect_not_value(#function, #parameter, __FILE__, __LINE__, \ + cast_to_largest_integral_type(value), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value is equal to the + * provided string. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] string The string value to compare. + * + * @see check_expected(). + */ +void expect_string(#function, #parameter, const char *string); +#else +#define expect_string(function, parameter, string) \ + expect_string_count(function, parameter, string, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value is equal to the + * provided string. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] string The string value to compare. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_string_count(#function, #parameter, const char *string, size_t count); +#else +#define expect_string_count(function, parameter, string, count) \ + _expect_string(#function, #parameter, __FILE__, __LINE__, \ + (const char*)(string), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value isn't equal to the + * provided string. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] string The string value to compare. + * + * @see check_expected(). + */ +void expect_not_string(#function, #parameter, const char *string); +#else +#define expect_not_string(function, parameter, string) \ + expect_not_string_count(function, parameter, string, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter value isn't equal to the + * provided string. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] string The string value to compare. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_not_string_count(#function, #parameter, const char *string, size_t count); +#else +#define expect_not_string_count(function, parameter, string, count) \ + _expect_not_string(#function, #parameter, __FILE__, __LINE__, \ + (const char*)(string), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter does match an area of memory. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] memory The memory to compare. + * + * @param[in] size The size of the memory to compare. + * + * @see check_expected(). + */ +void expect_memory(#function, #parameter, void *memory, size_t size); +#else +#define expect_memory(function, parameter, memory, size) \ + expect_memory_count(function, parameter, memory, size, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to repeatedly check if the parameter does match an area + * of memory. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] memory The memory to compare. + * + * @param[in] size The size of the memory to compare. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_memory_count(#function, #parameter, void *memory, size_t size, size_t count); +#else +#define expect_memory_count(function, parameter, memory, size, count) \ + _expect_memory(#function, #parameter, __FILE__, __LINE__, \ + (const void*)(memory), size, count) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to check if the parameter doesn't match an area of + * memory. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] memory The memory to compare. + * + * @param[in] size The size of the memory to compare. + * + * @see check_expected(). + */ +void expect_not_memory(#function, #parameter, void *memory, size_t size); +#else +#define expect_not_memory(function, parameter, memory, size) \ + expect_not_memory_count(function, parameter, memory, size, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to repeatedly check if the parameter doesn't match an + * area of memory. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] memory The memory to compare. + * + * @param[in] size The size of the memory to compare. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_not_memory_count(#function, #parameter, void *memory, size_t size, size_t count); +#else +#define expect_not_memory_count(function, parameter, memory, size, count) \ + _expect_not_memory(#function, #parameter, __FILE__, __LINE__, \ + (const void*)(memory), size, count) +#endif + + +#ifdef DOXYGEN +/** + * @brief Add an event to check if a parameter (of any value) has been passed. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @see check_expected(). + */ +void expect_any(#function, #parameter); +#else +#define expect_any(function, parameter) \ + expect_any_count(function, parameter, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Add an event to repeatedly check if a parameter (of any value) has + * been passed. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @param[in] count The count parameter returns the number of times the value + * should be returned by check_expected(). If count is set + * to -1 the value will always be returned. + * + * @see check_expected(). + */ +void expect_any_count(#function, #parameter, size_t count); +#else +#define expect_any_count(function, parameter, count) \ + _expect_any(#function, #parameter, __FILE__, __LINE__, count) +#endif + +#ifdef DOXYGEN +/** + * @brief Determine whether a function parameter is correct. + * + * This ensures the next value queued by one of the expect_*() macros matches + * the specified variable. + * + * This function needs to be called in the mock object. + * + * @param[in] #parameter The parameter to check. + */ +void check_expected(#parameter); +#else +#define check_expected(parameter) \ + _check_expected(__func__, #parameter, __FILE__, __LINE__, \ + cast_to_largest_integral_type(parameter)) +#endif + +#ifdef DOXYGEN +/** + * @brief Determine whether a function parameter is correct. + * + * This ensures the next value queued by one of the expect_*() macros matches + * the specified variable. + * + * This function needs to be called in the mock object. + * + * @param[in] #parameter The pointer to check. + */ +void check_expected_ptr(#parameter); +#else +#define check_expected_ptr(parameter) \ + _check_expected(__func__, #parameter, __FILE__, __LINE__, \ + cast_ptr_to_largest_integral_type(parameter)) +#endif + +/** @} */ + +/** + * @defgroup cmocka_asserts Assert Macros + * @ingroup cmocka + * + * This is a set of useful assert macros like the standard C libary's + * assert(3) macro. + * + * On an assertion failure a cmocka assert macro will write the failure to the + * standard error stream and signal a test failure. Due to limitations of the C + * language the general C standard library assert() and cmocka's assert_true() + * and assert_false() macros can only display the expression that caused the + * assert failure. cmocka's type specific assert macros, assert_{type}_equal() + * and assert_{type}_not_equal(), display the data that caused the assertion + * failure which increases data visibility aiding debugging of failing test + * cases. + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief Assert that the given expression is true. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if expression is false (i.e., compares equal to + * zero). + * + * @param[in] expression The expression to evaluate. + * + * @see assert_int_equal() + * @see assert_string_equal() + */ +void assert_true(scalar expression); +#else +#define assert_true(c) _assert_true(cast_to_largest_integral_type(c), #c, \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the given expression is false. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if expression is true. + * + * @param[in] expression The expression to evaluate. + * + * @see assert_int_equal() + * @see assert_string_equal() + */ +void assert_false(scalar expression); +#else +#define assert_false(c) _assert_true(!(cast_to_largest_integral_type(c)), #c, \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the return_code is greater than or equal to 0. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the return code is smaller than 0. If the function + * you check sets an errno if it fails you can pass it to the function and + * it will be printed as part of the error message. + * + * @param[in] rc The return code to evaluate. + * + * @param[in] error Pass errno here or 0. + */ +void assert_return_code(int rc, int error); +#else +#define assert_return_code(rc, error) \ + _assert_return_code(cast_to_largest_integral_type(rc), \ + sizeof(rc), \ + cast_to_largest_integral_type(error), \ + #rc, __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the given pointer is non-NULL. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the pointer is NULL. + * + * @param[in] pointer The pointer to evaluate. + * + * @see assert_null() + */ +void assert_non_null(void *pointer); +#else +#define assert_non_null(c) _assert_true(cast_ptr_to_largest_integral_type(c), #c, \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the given pointer is NULL. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the pointer is non-NULL. + * + * @param[in] pointer The pointer to evaluate. + * + * @see assert_non_null() + */ +void assert_null(void *pointer); +#else +#define assert_null(c) _assert_true(!(cast_ptr_to_largest_integral_type(c)), #c, \ +__FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given pointers are equal. + * + * The function prints an error message and terminates the test by calling + * fail() if the pointers are not equal. + * + * @param[in] a The first pointer to compare. + * + * @param[in] b The pointer to compare against the first one. + */ +void assert_ptr_equal(void *a, void *b); +#else +#define assert_ptr_equal(a, b) \ + _assert_int_equal(cast_ptr_to_largest_integral_type(a), \ + cast_ptr_to_largest_integral_type(b), \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given pointers are not equal. + * + * The function prints an error message and terminates the test by calling + * fail() if the pointers are equal. + * + * @param[in] a The first pointer to compare. + * + * @param[in] b The pointer to compare against the first one. + */ +void assert_ptr_not_equal(void *a, void *b); +#else +#define assert_ptr_not_equal(a, b) \ + _assert_int_not_equal(cast_ptr_to_largest_integral_type(a), \ + cast_ptr_to_largest_integral_type(b), \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given integers are equal. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the integers are not equal. + * + * @param[in] a The first integer to compare. + * + * @param[in] b The integer to compare against the first one. + */ +void assert_int_equal(int a, int b); +#else +#define assert_int_equal(a, b) \ + _assert_int_equal(cast_to_largest_integral_type(a), \ + cast_to_largest_integral_type(b), \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given integers are not equal. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the integers are equal. + * + * @param[in] a The first integer to compare. + * + * @param[in] b The integer to compare against the first one. + * + * @see assert_int_equal() + */ +void assert_int_not_equal(int a, int b); +#else +#define assert_int_not_equal(a, b) \ + _assert_int_not_equal(cast_to_largest_integral_type(a), \ + cast_to_largest_integral_type(b), \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given strings are equal. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the strings are not equal. + * + * @param[in] a The string to check. + * + * @param[in] b The other string to compare. + */ +void assert_string_equal(const char *a, const char *b); +#else +#define assert_string_equal(a, b) \ + _assert_string_equal((const char*)(a), (const char*)(b), __FILE__, \ + __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given strings are not equal. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the strings are equal. + * + * @param[in] a The string to check. + * + * @param[in] b The other string to compare. + */ +void assert_string_not_equal(const char *a, const char *b); +#else +#define assert_string_not_equal(a, b) \ + _assert_string_not_equal((const char*)(a), (const char*)(b), __FILE__, \ + __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given areas of memory are equal, otherwise fail. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the memory is not equal. + * + * @param[in] a The first memory area to compare + * (interpreted as unsigned char). + * + * @param[in] b The second memory area to compare + * (interpreted as unsigned char). + * + * @param[in] size The first n bytes of the memory areas to compare. + */ +void assert_memory_equal(const void *a, const void *b, size_t size); +#else +#define assert_memory_equal(a, b, size) \ + _assert_memory_equal((const void*)(a), (const void*)(b), size, __FILE__, \ + __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given areas of memory are not equal. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the memory is equal. + * + * @param[in] a The first memory area to compare + * (interpreted as unsigned char). + * + * @param[in] b The second memory area to compare + * (interpreted as unsigned char). + * + * @param[in] size The first n bytes of the memory areas to compare. + */ +void assert_memory_not_equal(const void *a, const void *b, size_t size); +#else +#define assert_memory_not_equal(a, b, size) \ + _assert_memory_not_equal((const void*)(a), (const void*)(b), size, \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the specified value is not smaller than the minimum + * and and not greater than the maximum. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if value is not in range. + * + * @param[in] value The value to check. + * + * @param[in] minimum The minimum value allowed. + * + * @param[in] maximum The maximum value allowed. + */ +void assert_in_range(LargestIntegralType value, LargestIntegralType minimum, LargestIntegralType maximum); +#else +#define assert_in_range(value, minimum, maximum) \ + _assert_in_range( \ + cast_to_largest_integral_type(value), \ + cast_to_largest_integral_type(minimum), \ + cast_to_largest_integral_type(maximum), __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the specified value is smaller than the minimum or + * greater than the maximum. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if value is in range. + * + * @param[in] value The value to check. + * + * @param[in] minimum The minimum value to compare. + * + * @param[in] maximum The maximum value to compare. + */ +void assert_not_in_range(LargestIntegralType value, LargestIntegralType minimum, LargestIntegralType maximum); +#else +#define assert_not_in_range(value, minimum, maximum) \ + _assert_not_in_range( \ + cast_to_largest_integral_type(value), \ + cast_to_largest_integral_type(minimum), \ + cast_to_largest_integral_type(maximum), __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the specified value is within a set. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if value is not within a set. + * + * @param[in] value The value to look up + * + * @param[in] values[] The array to check for the value. + * + * @param[in] count The size of the values array. + */ +void assert_in_set(LargestIntegralType value, LargestIntegralType values[], size_t count); +#else +#define assert_in_set(value, values, number_of_values) \ + _assert_in_set(value, values, number_of_values, __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the specified value is not within a set. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if value is within a set. + * + * @param[in] value The value to look up + * + * @param[in] values[] The array to check for the value. + * + * @param[in] count The size of the values array. + */ +void assert_not_in_set(LargestIntegralType value, LargestIntegralType values[], size_t count); +#else +#define assert_not_in_set(value, values, number_of_values) \ + _assert_not_in_set(value, values, number_of_values, __FILE__, __LINE__) +#endif + +/** @} */ + +/** + * @defgroup cmocka_call_order Call Ordering + * @ingroup cmocka + * + * It is often beneficial to make sure that functions are called in an + * order. This is independent of mock returns and parameter checking as both + * of the aforementioned do not check the order in which they are called from + * different functions. + * + *
    + *
  • expect_function_call(function) - The + * expect_function_call() macro pushes an expectation onto the stack of + * expected calls.
  • + * + *
  • function_called() - pops a value from the stack of + * expected calls. function_called() is invoked within the mock object + * that uses it. + *
+ * + * expect_function_call() and function_called() are intended to be used in + * pairs. Cmocka will fail a test if there are more or less expected calls + * created (e.g. expect_function_call()) than consumed with function_called(). + * There are provisions such as ignore_function_calls() which allow this + * restriction to be circumvented in tests where mock calls for the code under + * test are not the focus of the test. + * + * The following example illustrates how a unit test instructs cmocka + * to expect a function_called() from a particular mock, + * chef_sing(): + * + * @code + * void chef_sing(void); + * + * void code_under_test() + * { + * chef_sing(); + * } + * + * void some_test(void **state) + * { + * expect_function_call(chef_sing); + * code_under_test(); + * } + * @endcode + * + * The implementation of the mock then must check whether it was meant to + * be called by invoking function_called(): + * + * @code + * void chef_sing() + * { + * function_called(); + * } + * @endcode + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief Check that current mocked function is being called in the expected + * order + * + * @see expect_function_call() + */ +void function_called(void); +#else +#define function_called() _function_called(__func__, __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Store expected call(s) to a mock to be checked by function_called() + * later. + * + * @param[in] #function The function which should should be called + * + * @param[in] times number of times this mock must be called + * + * @see function_called() + */ +void expect_function_calls(#function, const int times); +#else +#define expect_function_calls(function, times) \ + _expect_function_call(#function, __FILE__, __LINE__, times) +#endif + +#ifdef DOXYGEN +/** + * @brief Store expected single call to a mock to be checked by + * function_called() later. + * + * @param[in] #function The function which should should be called + * + * @see function_called() + */ +void expect_function_call(#function); +#else +#define expect_function_call(function) \ + _expect_function_call(#function, __FILE__, __LINE__, 1) +#endif + +#ifdef DOXYGEN +/** + * @brief Expects function_called() from given mock at least once + * + * @param[in] #function The function which should should be called + * + * @see function_called() + */ +void expect_function_call_any(#function); +#else +#define expect_function_call_any(function) \ + _expect_function_call(#function, __FILE__, __LINE__, -1) +#endif + +#ifdef DOXYGEN +/** + * @brief Ignores function_called() invocations from given mock function. + * + * @param[in] #function The function which should should be called + * + * @see function_called() + */ +void ignore_function_calls(#function); +#else +#define ignore_function_calls(function) \ + _expect_function_call(#function, __FILE__, __LINE__, -2) +#endif + +/** @} */ + +/** + * @defgroup cmocka_exec Running Tests + * @ingroup cmocka + * + * This is the way tests are executed with CMocka. + * + * The following example illustrates this macro's use with the unit_test macro. + * + * @code + * void Test0(void **state); + * void Test1(void **state); + * + * int main(void) + * { + * const struct CMUnitTest tests[] = { + * cmocka_unit_test(Test0), + * cmocka_unit_test(Test1), + * }; + * + * return cmocka_run_group_tests(tests, NULL, NULL); + * } + * @endcode + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief Forces the test to fail immediately and quit. + */ +void fail(void); +#else +#define fail() _fail(__FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Forces the test to not be executed, but marked as skipped + */ +void skip(void); +#else +#define skip() _skip(__FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Forces the test to fail immediately and quit, printing the reason. + * + * @code + * fail_msg("This is some error message for test"); + * @endcode + * + * or + * + * @code + * char *error_msg = "This is some error message for test"; + * fail_msg("%s", error_msg); + * @endcode + */ +void fail_msg(const char *msg, ...); +#else +#define fail_msg(msg, ...) do { \ + print_error("ERROR: " msg "\n", ##__VA_ARGS__); \ + fail(); \ +} while (0) +#endif + +#ifdef DOXYGEN +/** + * @brief Generic method to run a single test. + * + * @deprecated This function was deprecated in favor of cmocka_run_group_tests + * + * @param[in] #function The function to test. + * + * @return 0 on success, 1 if an error occured. + * + * @code + * // A test case that does nothing and succeeds. + * void null_test_success(void **state) { + * } + * + * int main(void) { + * return run_test(null_test_success); + * } + * @endcode + */ +int run_test(#function); +#else +#define run_test(f) _run_test(#f, f, NULL, UNIT_TEST_FUNCTION_TYPE_TEST, NULL) +#endif + +static inline void _unit_test_dummy(void **state) { + (void)state; +} + +/** Initializes a UnitTest structure. + * + * @deprecated This function was deprecated in favor of cmocka_unit_test + */ +#define unit_test(f) { #f, f, UNIT_TEST_FUNCTION_TYPE_TEST } + +#define _unit_test_setup(test, setup) \ + { #test "_" #setup, setup, UNIT_TEST_FUNCTION_TYPE_SETUP } + +/** Initializes a UnitTest structure with a setup function. + * + * @deprecated This function was deprecated in favor of cmocka_unit_test_setup + */ +#define unit_test_setup(test, setup) \ + _unit_test_setup(test, setup), \ + unit_test(test), \ + _unit_test_teardown(test, _unit_test_dummy) + +#define _unit_test_teardown(test, teardown) \ + { #test "_" #teardown, teardown, UNIT_TEST_FUNCTION_TYPE_TEARDOWN } + +/** Initializes a UnitTest structure with a teardown function. + * + * @deprecated This function was deprecated in favor of cmocka_unit_test_teardown + */ +#define unit_test_teardown(test, teardown) \ + _unit_test_setup(test, _unit_test_dummy), \ + unit_test(test), \ + _unit_test_teardown(test, teardown) + +/** Initializes a UnitTest structure for a group setup function. + * + * @deprecated This function was deprecated in favor of cmocka_run_group_tests + */ +#define group_test_setup(setup) \ + { "group_" #setup, setup, UNIT_TEST_FUNCTION_TYPE_GROUP_SETUP } + +/** Initializes a UnitTest structure for a group teardown function. + * + * @deprecated This function was deprecated in favor of cmocka_run_group_tests + */ +#define group_test_teardown(teardown) \ + { "group_" #teardown, teardown, UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN } + +/** + * Initialize an array of UnitTest structures with a setup function for a test + * and a teardown function. Either setup or teardown can be NULL. + * + * @deprecated This function was deprecated in favor of + * cmocka_unit_test_setup_teardown + */ +#define unit_test_setup_teardown(test, setup, teardown) \ + _unit_test_setup(test, setup), \ + unit_test(test), \ + _unit_test_teardown(test, teardown) + + +/** Initializes a CMUnitTest structure. */ +#define cmocka_unit_test(f) { #f, f, NULL, NULL, NULL } + +/** Initializes a CMUnitTest structure with a setup function. */ +#define cmocka_unit_test_setup(f, setup) { #f, f, setup, NULL, NULL } + +/** Initializes a CMUnitTest structure with a teardown function. */ +#define cmocka_unit_test_teardown(f, teardown) { #f, f, NULL, teardown, NULL } + +/** + * Initialize an array of CMUnitTest structures with a setup function for a test + * and a teardown function. Either setup or teardown can be NULL. + */ +#define cmocka_unit_test_setup_teardown(f, setup, teardown) { #f, f, setup, teardown, NULL } + +/** + * Initialize a CMUnitTest structure with given initial state. It will be passed + * to test function as an argument later. It can be used when test state does + * not need special initialization or was initialized already. + * @note If the group setup function initialized the state already, it won't be + * overridden by the initial state defined here. + */ +#define cmocka_unit_test_prestate(f, state) { #f, f, NULL, NULL, state } + +/** + * Initialize a CMUnitTest structure with given initial state, setup and + * teardown function. Any of these values can be NULL. Initial state is passed + * later to setup function, or directly to test if none was given. + * @note If the group setup function initialized the state already, it won't be + * overridden by the initial state defined here. + */ +#define cmocka_unit_test_prestate_setup_teardown(f, setup, teardown, state) { #f, f, setup, teardown, state } + +#define run_tests(tests) _run_tests(tests, sizeof(tests) / sizeof((tests)[0])) +#define run_group_tests(tests) _run_group_tests(tests, sizeof(tests) / sizeof((tests)[0])) + +#ifdef DOXYGEN +/** + * @brief Run tests specified by an array of CMUnitTest structures. + * + * @param[in] group_tests[] The array of unit tests to execute. + * + * @param[in] group_setup The setup function which should be called before + * all unit tests are executed. + * + * @param[in] group_teardown The teardown function to be called after all + * tests have finished. + * + * @return 0 on success, or the number of failed tests. + * + * @code + * static int setup(void **state) { + * int *answer = malloc(sizeof(int)); + * if (*answer == NULL) { + * return -1; + * } + * *answer = 42; + * + * *state = answer; + * + * return 0; + * } + * + * static int teardown(void **state) { + * free(*state); + * + * return 0; + * } + * + * static void null_test_success(void **state) { + * (void) state; + * } + * + * static void int_test_success(void **state) { + * int *answer = *state; + * assert_int_equal(*answer, 42); + * } + * + * int main(void) { + * const struct CMUnitTest tests[] = { + * cmocka_unit_test(null_test_success), + * cmocka_unit_test_setup_teardown(int_test_success, setup, teardown), + * }; + * + * return cmocka_run_group_tests(tests, NULL, NULL); + * } + * @endcode + * + * @see cmocka_unit_test + * @see cmocka_unit_test_setup + * @see cmocka_unit_test_teardown + * @see cmocka_unit_test_setup_teardown + */ +int cmocka_run_group_tests(const struct CMUnitTest group_tests[], + CMFixtureFunction group_setup, + CMFixtureFunction group_teardown); +#else +# define cmocka_run_group_tests(group_tests, group_setup, group_teardown) \ + _cmocka_run_group_tests(#group_tests, group_tests, sizeof(group_tests) / sizeof((group_tests)[0]), group_setup, group_teardown) +#endif + +#ifdef DOXYGEN +/** + * @brief Run tests specified by an array of CMUnitTest structures and specify + * a name. + * + * @param[in] group_name The name of the group test. + * + * @param[in] group_tests[] The array of unit tests to execute. + * + * @param[in] group_setup The setup function which should be called before + * all unit tests are executed. + * + * @param[in] group_teardown The teardown function to be called after all + * tests have finished. + * + * @return 0 on success, or the number of failed tests. + * + * @code + * static int setup(void **state) { + * int *answer = malloc(sizeof(int)); + * if (*answer == NULL) { + * return -1; + * } + * *answer = 42; + * + * *state = answer; + * + * return 0; + * } + * + * static int teardown(void **state) { + * free(*state); + * + * return 0; + * } + * + * static void null_test_success(void **state) { + * (void) state; + * } + * + * static void int_test_success(void **state) { + * int *answer = *state; + * assert_int_equal(*answer, 42); + * } + * + * int main(void) { + * const struct CMUnitTest tests[] = { + * cmocka_unit_test(null_test_success), + * cmocka_unit_test_setup_teardown(int_test_success, setup, teardown), + * }; + * + * return cmocka_run_group_tests_name("success_test", tests, NULL, NULL); + * } + * @endcode + * + * @see cmocka_unit_test + * @see cmocka_unit_test_setup + * @see cmocka_unit_test_teardown + * @see cmocka_unit_test_setup_teardown + */ +int cmocka_run_group_tests_name(const char *group_name, + const struct CMUnitTest group_tests[], + CMFixtureFunction group_setup, + CMFixtureFunction group_teardown); +#else +# define cmocka_run_group_tests_name(group_name, group_tests, group_setup, group_teardown) \ + _cmocka_run_group_tests(group_name, group_tests, sizeof(group_tests) / sizeof((group_tests)[0]), group_setup, group_teardown) +#endif + +/** @} */ + +/** + * @defgroup cmocka_alloc Dynamic Memory Allocation + * @ingroup cmocka + * + * Memory leaks, buffer overflows and underflows can be checked using cmocka. + * + * To test for memory leaks, buffer overflows and underflows a module being + * tested by cmocka should replace calls to malloc(), calloc() and free() to + * test_malloc(), test_calloc() and test_free() respectively. Each time a block + * is deallocated using test_free() it is checked for corruption, if a corrupt + * block is found a test failure is signalled. All blocks allocated using the + * test_*() allocation functions are tracked by the cmocka library. When a test + * completes if any allocated blocks (memory leaks) remain they are reported + * and a test failure is signalled. + * + * For simplicity cmocka currently executes all tests in one process. Therefore + * all test cases in a test application share a single address space which + * means memory corruption from a single test case could potentially cause the + * test application to exit prematurely. + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief Test function overriding malloc. + * + * @param[in] size The bytes which should be allocated. + * + * @return A pointer to the allocated memory or NULL on error. + * + * @code + * #ifdef UNIT_TESTING + * extern void* _test_malloc(const size_t size, const char* file, const int line); + * + * #define malloc(size) _test_malloc(size, __FILE__, __LINE__) + * #endif + * + * void leak_memory() { + * int * const temporary = (int*)malloc(sizeof(int)); + * *temporary = 0; + * } + * @endcode + * + * @see malloc(3) + */ +void *test_malloc(size_t size); +#else +#define test_malloc(size) _test_malloc(size, __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Test function overriding calloc. + * + * The memory is set to zero. + * + * @param[in] nmemb The number of elements for an array to be allocated. + * + * @param[in] size The size in bytes of each array element to allocate. + * + * @return A pointer to the allocated memory, NULL on error. + * + * @see calloc(3) + */ +void *test_calloc(size_t nmemb, size_t size); +#else +#define test_calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Test function overriding realloc which detects buffer overruns + * and memoery leaks. + * + * @param[in] ptr The memory block which should be changed. + * + * @param[in] size The bytes which should be allocated. + * + * @return The newly allocated memory block, NULL on error. + */ +void *test_realloc(void *ptr, size_t size); +#else +#define test_realloc(ptr, size) _test_realloc(ptr, size, __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Test function overriding free(3). + * + * @param[in] ptr The pointer to the memory space to free. + * + * @see free(3). + */ +void test_free(void *ptr); +#else +#define test_free(ptr) _test_free(ptr, __FILE__, __LINE__) +#endif + +/* Redirect malloc, calloc and free to the unit test allocators. */ +#ifdef UNIT_TESTING +#define malloc test_malloc +#define realloc test_realloc +#define calloc test_calloc +#define free test_free +#endif /* UNIT_TESTING */ + +/** @} */ + + +/** + * @defgroup cmocka_mock_assert Standard Assertions + * @ingroup cmocka + * + * How to handle assert(3) of the standard C library. + * + * Runtime assert macros like the standard C library's assert() should be + * redefined in modules being tested to use cmocka's mock_assert() function. + * Normally mock_assert() signals a test failure. If a function is called using + * the expect_assert_failure() macro, any calls to mock_assert() within the + * function will result in the execution of the test. If no calls to + * mock_assert() occur during the function called via expect_assert_failure() a + * test failure is signalled. + * + * @{ + */ + +/** + * @brief Function to replace assert(3) in tested code. + * + * In conjuction with check_assert() it's possible to determine whether an + * assert condition has failed without stopping a test. + * + * @param[in] result The expression to assert. + * + * @param[in] expression The expression as string. + * + * @param[in] file The file mock_assert() is called. + * + * @param[in] line The line mock_assert() is called. + * + * @code + * #ifdef UNIT_TESTING + * extern void mock_assert(const int result, const char* const expression, + * const char * const file, const int line); + * + * #undef assert + * #define assert(expression) \ + * mock_assert((int)(expression), #expression, __FILE__, __LINE__); + * #endif + * + * void increment_value(int * const value) { + * assert(value); + * (*value) ++; + * } + * @endcode + * + * @see assert(3) + * @see expect_assert_failure + */ +void mock_assert(const int result, const char* const expression, + const char * const file, const int line); + +#ifdef DOXYGEN +/** + * @brief Ensure that mock_assert() is called. + * + * If mock_assert() is called the assert expression string is returned. + * + * @param[in] fn_call The function will will call mock_assert(). + * + * @code + * #define assert mock_assert + * + * void showmessage(const char *message) { + * assert(message); + * } + * + * int main(int argc, const char* argv[]) { + * expect_assert_failure(show_message(NULL)); + * printf("succeeded\n"); + * return 0; + * } + * @endcode + * + */ +void expect_assert_failure(function fn_call); +#else +#define expect_assert_failure(function_call) \ + { \ + const int result = setjmp(global_expect_assert_env); \ + global_expecting_assert = 1; \ + if (result) { \ + print_message("Expected assertion %s occurred\n", \ + global_last_failed_assert); \ + global_expecting_assert = 0; \ + } else { \ + function_call ; \ + global_expecting_assert = 0; \ + print_error("Expected assert in %s\n", #function_call); \ + _fail(__FILE__, __LINE__); \ + } \ + } +#endif + +/** @} */ + +/* Function prototype for setup, test and teardown functions. */ +typedef void (*UnitTestFunction)(void **state); + +/* Function that determines whether a function parameter value is correct. */ +typedef int (*CheckParameterValue)(const LargestIntegralType value, + const LargestIntegralType check_value_data); + +/* Type of the unit test function. */ +typedef enum UnitTestFunctionType { + UNIT_TEST_FUNCTION_TYPE_TEST = 0, + UNIT_TEST_FUNCTION_TYPE_SETUP, + UNIT_TEST_FUNCTION_TYPE_TEARDOWN, + UNIT_TEST_FUNCTION_TYPE_GROUP_SETUP, + UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN, +} UnitTestFunctionType; + +/* + * Stores a unit test function with its name and type. + * NOTE: Every setup function must be paired with a teardown function. It's + * possible to specify NULL function pointers. + */ +typedef struct UnitTest { + const char* name; + UnitTestFunction function; + UnitTestFunctionType function_type; +} UnitTest; + +typedef struct GroupTest { + UnitTestFunction setup; + UnitTestFunction teardown; + const UnitTest *tests; + const size_t number_of_tests; +} GroupTest; + +/* Function prototype for test functions. */ +typedef void (*CMUnitTestFunction)(void **state); + +/* Function prototype for setup and teardown functions. */ +typedef int (*CMFixtureFunction)(void **state); + +struct CMUnitTest { + const char *name; + CMUnitTestFunction test_func; + CMFixtureFunction setup_func; + CMFixtureFunction teardown_func; + void *initial_state; +}; + +/* Location within some source code. */ +typedef struct SourceLocation { + const char* file; + int line; +} SourceLocation; + +/* Event that's called to check a parameter value. */ +typedef struct CheckParameterEvent { + SourceLocation location; + const char *parameter_name; + CheckParameterValue check_value; + LargestIntegralType check_value_data; +} CheckParameterEvent; + +/* Used by expect_assert_failure() and mock_assert(). */ +extern int global_expecting_assert; +extern jmp_buf global_expect_assert_env; +extern const char * global_last_failed_assert; + +/* Retrieves a value for the given function, as set by "will_return". */ +LargestIntegralType _mock(const char * const function, const char* const file, + const int line); + +void _expect_function_call( + const char * const function_name, + const char * const file, + const int line, + const int count); + +void _function_called(const char * const function, const char* const file, + const int line); + +void _expect_check( + const char* const function, const char* const parameter, + const char* const file, const int line, + const CheckParameterValue check_function, + const LargestIntegralType check_data, CheckParameterEvent * const event, + const int count); + +void _expect_in_set( + const char* const function, const char* const parameter, + const char* const file, const int line, const LargestIntegralType values[], + const size_t number_of_values, const int count); +void _expect_not_in_set( + const char* const function, const char* const parameter, + const char* const file, const int line, const LargestIntegralType values[], + const size_t number_of_values, const int count); + +void _expect_in_range( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType minimum, + const LargestIntegralType maximum, const int count); +void _expect_not_in_range( + const char* const function, const char* const parameter, + const char* const file, const int line, + const LargestIntegralType minimum, + const LargestIntegralType maximum, const int count); + +void _expect_value( + const char* const function, const char* const parameter, + const char* const file, const int line, const LargestIntegralType value, + const int count); +void _expect_not_value( + const char* const function, const char* const parameter, + const char* const file, const int line, const LargestIntegralType value, + const int count); + +void _expect_string( + const char* const function, const char* const parameter, + const char* const file, const int line, const char* string, + const int count); +void _expect_not_string( + const char* const function, const char* const parameter, + const char* const file, const int line, const char* string, + const int count); + +void _expect_memory( + const char* const function, const char* const parameter, + const char* const file, const int line, const void* const memory, + const size_t size, const int count); +void _expect_not_memory( + const char* const function, const char* const parameter, + const char* const file, const int line, const void* const memory, + const size_t size, const int count); + +void _expect_any( + const char* const function, const char* const parameter, + const char* const file, const int line, const int count); + +void _check_expected( + const char * const function_name, const char * const parameter_name, + const char* file, const int line, const LargestIntegralType value); + +void _will_return(const char * const function_name, const char * const file, + const int line, const LargestIntegralType value, + const int count); +void _assert_true(const LargestIntegralType result, + const char* const expression, + const char * const file, const int line); +void _assert_return_code(const LargestIntegralType result, + size_t rlen, + const LargestIntegralType error, + const char * const expression, + const char * const file, + const int line); +void _assert_int_equal( + const LargestIntegralType a, const LargestIntegralType b, + const char * const file, const int line); +void _assert_int_not_equal( + const LargestIntegralType a, const LargestIntegralType b, + const char * const file, const int line); +void _assert_string_equal(const char * const a, const char * const b, + const char * const file, const int line); +void _assert_string_not_equal(const char * const a, const char * const b, + const char *file, const int line); +void _assert_memory_equal(const void * const a, const void * const b, + const size_t size, const char* const file, + const int line); +void _assert_memory_not_equal(const void * const a, const void * const b, + const size_t size, const char* const file, + const int line); +void _assert_in_range( + const LargestIntegralType value, const LargestIntegralType minimum, + const LargestIntegralType maximum, const char* const file, const int line); +void _assert_not_in_range( + const LargestIntegralType value, const LargestIntegralType minimum, + const LargestIntegralType maximum, const char* const file, const int line); +void _assert_in_set( + const LargestIntegralType value, const LargestIntegralType values[], + const size_t number_of_values, const char* const file, const int line); +void _assert_not_in_set( + const LargestIntegralType value, const LargestIntegralType values[], + const size_t number_of_values, const char* const file, const int line); + +void* _test_malloc(const size_t size, const char* file, const int line); +void* _test_realloc(void *ptr, const size_t size, const char* file, const int line); +void* _test_calloc(const size_t number_of_elements, const size_t size, + const char* file, const int line); +void _test_free(void* const ptr, const char* file, const int line); + +void _fail(const char * const file, const int line); + +void _skip(const char * const file, const int line); + +int _run_test( + const char * const function_name, const UnitTestFunction Function, + void ** const volatile state, const UnitTestFunctionType function_type, + const void* const heap_check_point); +CMOCKA_DEPRECATED int _run_tests(const UnitTest * const tests, + const size_t number_of_tests); +CMOCKA_DEPRECATED int _run_group_tests(const UnitTest * const tests, + const size_t number_of_tests); + +/* Test runner */ +int _cmocka_run_group_tests(const char *group_name, + const struct CMUnitTest * const tests, + const size_t num_tests, + CMFixtureFunction group_setup, + CMFixtureFunction group_teardown); + +/* Standard output and error print methods. */ +void print_message(const char* const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2); +void print_error(const char* const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2); +void vprint_message(const char* const format, va_list args) CMOCKA_PRINTF_ATTRIBUTE(1, 0); +void vprint_error(const char* const format, va_list args) CMOCKA_PRINTF_ATTRIBUTE(1, 0); + +enum cm_message_output { + CM_OUTPUT_STDOUT, + CM_OUTPUT_SUBUNIT, + CM_OUTPUT_TAP, + CM_OUTPUT_XML, +}; + +/** + * @brief Function to set the output format for a test. + * + * The ouput format for the test can either be set globally using this + * function or overriden with environment variable CMOCKA_MESSAGE_OUTPUT. + * + * The environment variable can be set to either STDOUT, SUBUNIT, TAP or XML. + * + * @param[in] output The output format to use for the test. + * + */ +void cmocka_set_message_output(enum cm_message_output output); + + +/** + * @brief Set a pattern to only run the test matching the pattern. + * + * This allows to filter tests and only run the ones matching the pattern. Thep + * pattern can include two wildards. The first is '*', a wildcard that matches + * zero or more characters, or ‘?’, a wildcard that matches exactly one + * character. + * + * @param[in] pattern The pattern to match, e.g. "test_wurst*" + */ +void cmocka_set_test_filter(const char *pattern); + +/** @} */ + +#endif /* CMOCKA_H_ */ diff --git a/ldb-2.0.8/third_party/cmocka/cmocka_private.h b/ldb-2.0.8/third_party/cmocka/cmocka_private.h new file mode 100644 index 0000000..d20d841 --- /dev/null +++ b/ldb-2.0.8/third_party/cmocka/cmocka_private.h @@ -0,0 +1,163 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CMOCKA_PRIVATE_H_ +#define CMOCKA_PRIVATE_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef _WIN32 +#include + +# ifdef _MSC_VER +# include /* _snprintf */ + +# undef inline +# define inline __inline + +# ifndef va_copy +# define va_copy(dest, src) (dest = src) +# endif + +# define strcasecmp _stricmp +# define strncasecmp _strnicmp + +# if defined(HAVE__SNPRINTF_S) +# undef snprintf +# define snprintf(d, n, ...) _snprintf_s((d), (n), _TRUNCATE, __VA_ARGS__) +# else /* HAVE__SNPRINTF_S */ +# if defined(HAVE__SNPRINTF) +# undef snprintf +# define snprintf _snprintf +# else /* HAVE__SNPRINTF */ +# if !defined(HAVE_SNPRINTF) +# error "no snprintf compatible function found" +# endif /* HAVE_SNPRINTF */ +# endif /* HAVE__SNPRINTF */ +# endif /* HAVE__SNPRINTF_S */ + +# if defined(HAVE__VSNPRINTF_S) +# undef vsnprintf +# define vsnprintf(s, n, f, v) _vsnprintf_s((s), (n), _TRUNCATE, (f), (v)) +# else /* HAVE__VSNPRINTF_S */ +# if defined(HAVE__VSNPRINTF) +# undef vsnprintf +# define vsnprintf _vsnprintf +# else +# if !defined(HAVE_VSNPRINTF) +# error "No vsnprintf compatible function found" +# endif /* HAVE_VSNPRINTF */ +# endif /* HAVE__VSNPRINTF */ +# endif /* HAVE__VSNPRINTF_S */ +# endif /* _MSC_VER */ + +/* + * Backwards compatibility with headers shipped with Visual Studio 2005 and + * earlier. + */ +WINBASEAPI BOOL WINAPI IsDebuggerPresent(VOID); + +#ifndef PRIdS +# define PRIdS "Id" +#endif + +#ifndef PRIu64 +# define PRIu64 "I64u" +#endif + +#ifndef PRIuMAX +# define PRIuMAX PRIu64 +#endif + +#ifndef PRIxMAX +#define PRIxMAX "I64x" +#endif + +#ifndef PRIXMAX +#define PRIXMAX "I64X" +#endif + +#else /* _WIN32 */ + +#ifndef __PRI64_PREFIX +# if __WORDSIZE == 64 +# define __PRI64_PREFIX "l" +# else +# define __PRI64_PREFIX "ll" +# endif +#endif + +#ifndef PRIdS +# define PRIdS "zd" +#endif + +#ifndef PRIu64 +# define PRIu64 __PRI64_PREFIX "u" +#endif + +#ifndef PRIuMAX +# define PRIuMAX __PRI64_PREFIX "u" +#endif + +#ifndef PRIxMAX +#define PRIxMAX __PRI64_PREFIX "x" +#endif + +#ifndef PRIXMAX +#define PRIXMAX __PRI64_PREFIX "X" +#endif + +#endif /* _WIN32 */ + +/** Free memory space */ +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) + +/** Zero a structure */ +#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) + +/** Zero a structure given a pointer to the structure */ +#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) + +/** Get the size of an array */ +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/** Overwrite the complete string with 'X' */ +#define BURN_STRING(x) do { if ((x) != NULL) memset((x), 'X', strlen((x))); } while(0) + +/** + * This is a hack to fix warnings. The idea is to use this everywhere that we + * get the "discarding const" warning by the compiler. That doesn't actually + * fix the real issue, but marks the place and you can search the code for + * discard_const. + * + * Please use this macro only when there is no other way to fix the warning. + * We should use this function in only in a very few places. + * + * Also, please call this via the discard_const_p() macro interface, as that + * makes the return type safe. + */ +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) + +/** + * Type-safe version of discard_const + */ +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) + +#endif /* CMOCKA_PRIVATE_H_ */ diff --git a/ldb-2.0.8/third_party/cmocka/wscript b/ldb-2.0.8/third_party/cmocka/wscript new file mode 100644 index 0000000..3c2ad50 --- /dev/null +++ b/ldb-2.0.8/third_party/cmocka/wscript @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +from waflib import Options + +def configure(conf): + conf.CHECK_FUNCS('longjmp siglongjmp') + + if conf.CHECK_CMOCKA(): + conf.define('USING_SYSTEM_CMOCKA', 1) + +def build(bld): + if bld.CONFIG_SET('USING_SYSTEM_CMOCKA'): + return + + extra_libs='' + + # Link to librt if needed for clock_gettime() + if bld.CONFIG_SET('HAVE_LIBRT'): extra_libs += ' rt' + + bld.SAMBA_LIBRARY('cmocka', + source='cmocka.c', + deps=extra_libs, + allow_warnings=True, + private_library=True) diff --git a/ldb-2.0.8/third_party/popt/CHANGES b/ldb-2.0.8/third_party/popt/CHANGES new file mode 100644 index 0000000..db16a5f --- /dev/null +++ b/ldb-2.0.8/third_party/popt/CHANGES @@ -0,0 +1,46 @@ +1.5 -> 1.6 + - add ability to perform callbacks for every, not just first, match. + +1.3 -> 1.5 + - heavy dose of const's + - poptParseArgvString() now NULL terminates the list + +1.2.3 -> 1.3 + - added support for single - + - misc bug fixes + - portability improvements + +1.2.2 -> 1.2.3 + - fixed memset() in help message generation (Dale Hawkins) + - added extern "C" stuff to popt.h for C++ compilers (Dale Hawkins) + - const'ified poptParseArgvString (Jeff Garzik) + +1.2.1 -> 1.2.2 + - fixed bug in chaind alias happens which seems to have only + affected --triggers in rpm + - added POPT_ARG_VAL + - popt.3 installed by default + +1.2 -> 1.2.1 + - added POPT_ARG_INTL_DOMAIN (Elliot Lee) + - updated Makefile's to be more GNUish (Elliot Lee) + +1.1 -> 1.2 + - added popt.3 man page (Robert Lynch) + - don't use mmap anymore (its lack of portability isn't worth the + trouble) + - added test script + - added support for exec + - removed support for *_POPT_ALIASES env variable -- it was a bad + idea + - reorganized into multiple source files + - added automatic help generation, POPT_AUTOHELP + - added table callbacks + - added table inclusion + - updated man page for new features + - added test scripts + +1.0 -> 1.1 + - moved to autoconf (Fred Fish) + - added STRERROR replacement (Norbert Warmuth) + - added const keywords (Bruce Perens) diff --git a/ldb-2.0.8/third_party/popt/COPYING b/ldb-2.0.8/third_party/popt/COPYING new file mode 100644 index 0000000..b4c7ca8 --- /dev/null +++ b/ldb-2.0.8/third_party/popt/COPYING @@ -0,0 +1,22 @@ +Copyright (c) 1998 Red Hat Software + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. diff --git a/ldb-2.0.8/third_party/popt/README b/ldb-2.0.8/third_party/popt/README new file mode 100644 index 0000000..c66432d --- /dev/null +++ b/ldb-2.0.8/third_party/popt/README @@ -0,0 +1,16 @@ +This is the popt(3) command line option parsing library. While it is similiar +to getopt(3), it contains a number of enhancements, including: + + 1) popt is fully reentrant + 2) popt can parse arbitrary argv[] style arrays while + getopt(3) makes this quite difficult + 3) popt allows users to alias command line arguments + 4) popt provides convience functions for parsing strings + into argv[] style arrays + +Complete documentation on popt(3) is available in popt.ps (included in this +tarball), which is excerpted with permission from the book "Linux +Application Development" by Michael K. Johnson and Erik Troan (available +from Addison Wesley in May, 1998). + +Comments on popt should be addressed to popt-devel@rpm5.org. diff --git a/ldb-2.0.8/third_party/popt/findme.h b/ldb-2.0.8/third_party/popt/findme.h new file mode 100644 index 0000000..a016b86 --- /dev/null +++ b/ldb-2.0.8/third_party/popt/findme.h @@ -0,0 +1,20 @@ +/** \ingroup popt + * \file popt/findme.h + */ + +/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.rpm.org/pub/rpm/dist. */ + +#ifndef H_FINDME +#define H_FINDME + +/** + * Return absolute path to executable by searching PATH. + * @param argv0 name of executable + * @return (malloc'd) absolute path to executable (or NULL) + */ +/*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0) + /*@*/; + +#endif diff --git a/ldb-2.0.8/third_party/popt/lookup3.c b/ldb-2.0.8/third_party/popt/lookup3.c new file mode 100644 index 0000000..eb4e5ce --- /dev/null +++ b/ldb-2.0.8/third_party/popt/lookup3.c @@ -0,0 +1,969 @@ +/* -------------------------------------------------------------------- */ +/* + * lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * + * These are functions for producing 32-bit hashes for hash table lookup. + * jlu32w(), jlu32l(), jlu32lpair(), jlu32b(), _JLU3_MIX(), and _JLU3_FINAL() + * are externally useful functions. Routines to test the hash are included + * if SELF_TEST is defined. You can use this free for any purpose. It's in + * the public domain. It has no warranty. + * + * You probably want to use jlu32l(). jlu32l() and jlu32b() + * hash byte arrays. jlu32l() is is faster than jlu32b() on + * little-endian machines. Intel and AMD are little-endian machines. + * On second thought, you probably want jlu32lpair(), which is identical to + * jlu32l() except it returns two 32-bit hashes for the price of one. + * You could implement jlu32bpair() if you wanted but I haven't bothered here. + * + * If you want to find a hash of, say, exactly 7 integers, do + * a = i1; b = i2; c = i3; + * _JLU3_MIX(a,b,c); + * a += i4; b += i5; c += i6; + * _JLU3_MIX(a,b,c); + * a += i7; + * _JLU3_FINAL(a,b,c); + * then use c as the hash value. If you have a variable size array of + * 4-byte integers to hash, use jlu32w(). If you have a byte array (like + * a character string), use jlu32l(). If you have several byte arrays, or + * a mix of things, see the comments above jlu32l(). + * + * Why is this so big? I read 12 bytes at a time into 3 4-byte integers, + * then mix those integers. This is fast (you can do a lot more thorough + * mixing with 12*3 instructions on 3 integers than you can with 3 instructions + * on 1 byte), but shoehorning those bytes into integers efficiently is messy. +*/ +/* -------------------------------------------------------------------- */ + +#include + +#if defined(_JLU3_SELFTEST) +# define _JLU3_jlu32w 1 +# define _JLU3_jlu32l 1 +# define _JLU3_jlu32lpair 1 +# define _JLU3_jlu32b 1 +#endif + +/*@-redef@*/ +/*@unchecked@*/ +static const union _dbswap { + const uint32_t ui; + const unsigned char uc[4]; +} endian = { .ui = 0x11223344 }; +# define HASH_LITTLE_ENDIAN (endian.uc[0] == (unsigned char) 0x44) +# define HASH_BIG_ENDIAN (endian.uc[0] == (unsigned char) 0x11) +/*@=redef@*/ + +#ifndef ROTL32 +# define ROTL32(x, s) (((x) << (s)) | ((x) >> (32 - (s)))) +#endif + +/* NOTE: The _size parameter should be in bytes. */ +#define _JLU3_INIT(_h, _size) (0xdeadbeef + ((uint32_t)(_size)) + (_h)) + +/* -------------------------------------------------------------------- */ +/* + * _JLU3_MIX -- mix 3 32-bit values reversibly. + * + * This is reversible, so any information in (a,b,c) before _JLU3_MIX() is + * still in (a,b,c) after _JLU3_MIX(). + * + * If four pairs of (a,b,c) inputs are run through _JLU3_MIX(), or through + * _JLU3_MIX() in reverse, there are at least 32 bits of the output that + * are sometimes the same for one pair and different for another pair. + * This was tested for: + * * pairs that differed by one bit, by two bits, in any combination + * of top bits of (a,b,c), or in any combination of bottom bits of + * (a,b,c). + * * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + * the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + * is commonly produced by subtraction) look like a single 1-bit + * difference. + * * the base values were pseudorandom, all zero but one bit set, or + * all zero plus a counter that starts at zero. + * + * Some k values for my "a-=c; a^=ROTL32(c,k); c+=b;" arrangement that + * satisfy this are + * 4 6 8 16 19 4 + * 9 15 3 18 27 15 + * 14 9 3 7 17 3 + * Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing + * for "differ" defined as + with a one-bit base and a two-bit delta. I + * used http://burtleburtle.net/bob/hash/avalanche.html to choose + * the operations, constants, and arrangements of the variables. + * + * This does not achieve avalanche. There are input bits of (a,b,c) + * that fail to affect some output bits of (a,b,c), especially of a. The + * most thoroughly mixed value is c, but it doesn't really even achieve + * avalanche in c. + * + * This allows some parallelism. Read-after-writes are good at doubling + * the number of bits affected, so the goal of mixing pulls in the opposite + * direction as the goal of parallelism. I did what I could. Rotates + * seem to cost as much as shifts on every machine I could lay my hands + * on, and rotates are much kinder to the top and bottom bits, so I used + * rotates. + */ +/* -------------------------------------------------------------------- */ +#define _JLU3_MIX(a,b,c) \ +{ \ + a -= c; a ^= ROTL32(c, 4); c += b; \ + b -= a; b ^= ROTL32(a, 6); a += c; \ + c -= b; c ^= ROTL32(b, 8); b += a; \ + a -= c; a ^= ROTL32(c,16); c += b; \ + b -= a; b ^= ROTL32(a,19); a += c; \ + c -= b; c ^= ROTL32(b, 4); b += a; \ +} + +/* -------------------------------------------------------------------- */ +/** + * _JLU3_FINAL -- final mixing of 3 32-bit values (a,b,c) into c + * + * Pairs of (a,b,c) values differing in only a few bits will usually + * produce values of c that look totally different. This was tested for + * * pairs that differed by one bit, by two bits, in any combination + * of top bits of (a,b,c), or in any combination of bottom bits of + * (a,b,c). + * * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + * the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + * is commonly produced by subtraction) look like a single 1-bit + * difference. + * * the base values were pseudorandom, all zero but one bit set, or + * all zero plus a counter that starts at zero. + * + * These constants passed: + * 14 11 25 16 4 14 24 + * 12 14 25 16 4 14 24 + * and these came close: + * 4 8 15 26 3 22 24 + * 10 8 15 26 3 22 24 + * 11 8 15 26 3 22 24 + */ +/* -------------------------------------------------------------------- */ +#define _JLU3_FINAL(a,b,c) \ +{ \ + c ^= b; c -= ROTL32(b,14); \ + a ^= c; a -= ROTL32(c,11); \ + b ^= a; b -= ROTL32(a,25); \ + c ^= b; c -= ROTL32(b,16); \ + a ^= c; a -= ROTL32(c,4); \ + b ^= a; b -= ROTL32(a,14); \ + c ^= b; c -= ROTL32(b,24); \ +} + +#if defined(_JLU3_jlu32w) +uint32_t jlu32w(uint32_t h, /*@null@*/ const uint32_t *k, size_t size) + /*@*/; +/* -------------------------------------------------------------------- */ +/** + * This works on all machines. To be useful, it requires + * -- that the key be an array of uint32_t's, and + * -- that the size be the number of uint32_t's in the key + * + * The function jlu32w() is identical to jlu32l() on little-endian + * machines, and identical to jlu32b() on big-endian machines, + * except that the size has to be measured in uint32_ts rather than in + * bytes. jlu32l() is more complicated than jlu32w() only because + * jlu32l() has to dance around fitting the key bytes into registers. + * + * @param h the previous hash, or an arbitrary value + * @param *k the key, an array of uint32_t values + * @param size the size of the key, in uint32_ts + * @return the lookup3 hash + */ +/* -------------------------------------------------------------------- */ +uint32_t jlu32w(uint32_t h, const uint32_t *k, size_t size) +{ + uint32_t a = _JLU3_INIT(h, (size * sizeof(*k))); + uint32_t b = a; + uint32_t c = a; + + if (k == NULL) + goto exit; + + /*----------------------------------------------- handle most of the key */ + while (size > 3) { + a += k[0]; + b += k[1]; + c += k[2]; + _JLU3_MIX(a,b,c); + size -= 3; + k += 3; + } + + /*----------------------------------------- handle the last 3 uint32_t's */ + switch (size) { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + _JLU3_FINAL(a,b,c); + /*@fallthrough@*/ + case 0: + break; + } + /*---------------------------------------------------- report the result */ +exit: + return c; +} +#endif /* defined(_JLU3_jlu32w) */ + +#if defined(_JLU3_jlu32l) +uint32_t jlu32l(uint32_t h, const void *key, size_t size) + /*@*/; +/* -------------------------------------------------------------------- */ +/* + * jlu32l() -- hash a variable-length key into a 32-bit value + * h : can be any 4-byte value + * k : the key (the unaligned variable-length array of bytes) + * size : the size of the key, counting by bytes + * Returns a 32-bit value. Every bit of the key affects every bit of + * the return value. Two keys differing by one or two bits will have + * totally different hash values. + * + * The best hash table sizes are powers of 2. There is no need to do + * mod a prime (mod is sooo slow!). If you need less than 32 bits, + * use a bitmask. For example, if you need only 10 bits, do + * h = (h & hashmask(10)); + * In which case, the hash table should have hashsize(10) elements. + * + * If you are hashing n strings (uint8_t **)k, do it like this: + * for (i=0, h=0; i 12) { + a += k[0]; + b += k[1]; + c += k[2]; + _JLU3_MIX(a,b,c); + size -= 12; + k += 3; + } + + /*------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch (size) { + case 12: c += k[2]; b+=k[1]; a+=k[0]; break; + case 11: c += k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c += k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9: c += k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8: b += k[1]; a+=k[0]; break; + case 7: b += k[1]&0xffffff; a+=k[0]; break; + case 6: b += k[1]&0xffff; a+=k[0]; break; + case 5: b += k[1]&0xff; a+=k[0]; break; + case 4: a += k[0]; break; + case 3: a += k[0]&0xffffff; break; + case 2: a += k[0]&0xffff; break; + case 1: a += k[0]&0xff; break; + case 0: goto exit; + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch (size) { + case 12: c += k[2]; b+=k[1]; a+=k[0] break; + case 11: c += ((uint32_t)k8[10])<<16; /*@fallthrough@*/ + case 10: c += ((uint32_t)k8[9])<<8; /*@fallthrough@*/ + case 9: c += k8[8]; /*@fallthrough@*/ + case 8: b += k[1]; a+=k[0]; break; + case 7: b += ((uint32_t)k8[6])<<16; /*@fallthrough@*/ + case 6: b += ((uint32_t)k8[5])<<8; /*@fallthrough@*/ + case 5: b += k8[4]; /*@fallthrough@*/ + case 4: a += k[0]; break; + case 3: a += ((uint32_t)k8[2])<<16; /*@fallthrough@*/ + case 2: a += ((uint32_t)k8[1])<<8; /*@fallthrough@*/ + case 1: a += k8[0]; break; + case 0: goto exit; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*----------- all but last block: aligned reads and different mixing */ + while (size > 12) { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + _JLU3_MIX(a,b,c); + size -= 12; + k += 6; + } + + /*------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch (size) { + case 12: + c += k[4]+(((uint32_t)k[5])<<16); + b += k[2]+(((uint32_t)k[3])<<16); + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 11: + c += ((uint32_t)k8[10])<<16; + /*@fallthrough@*/ + case 10: + c += (uint32_t)k[4]; + b += k[2]+(((uint32_t)k[3])<<16); + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 9: + c += (uint32_t)k8[8]; + /*@fallthrough@*/ + case 8: + b += k[2]+(((uint32_t)k[3])<<16); + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 7: + b += ((uint32_t)k8[6])<<16; + /*@fallthrough@*/ + case 6: + b += (uint32_t)k[2]; + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 5: + b += (uint32_t)k8[4]; + /*@fallthrough@*/ + case 4: + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 3: + a += ((uint32_t)k8[2])<<16; + /*@fallthrough@*/ + case 2: + a += (uint32_t)k[0]; + break; + case 1: + a += (uint32_t)k8[0]; + break; + case 0: + goto exit; + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*----------- all but the last block: affect some 32 bits of (a,b,c) */ + while (size > 12) { + a += (uint32_t)k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += (uint32_t)k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += (uint32_t)k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + _JLU3_MIX(a,b,c); + size -= 12; + k += 12; + } + + /*---------------------------- last block: affect all 32 bits of (c) */ + switch (size) { + case 12: c += ((uint32_t)k[11])<<24; /*@fallthrough@*/ + case 11: c += ((uint32_t)k[10])<<16; /*@fallthrough@*/ + case 10: c += ((uint32_t)k[9])<<8; /*@fallthrough@*/ + case 9: c += (uint32_t)k[8]; /*@fallthrough@*/ + case 8: b += ((uint32_t)k[7])<<24; /*@fallthrough@*/ + case 7: b += ((uint32_t)k[6])<<16; /*@fallthrough@*/ + case 6: b += ((uint32_t)k[5])<<8; /*@fallthrough@*/ + case 5: b += (uint32_t)k[4]; /*@fallthrough@*/ + case 4: a += ((uint32_t)k[3])<<24; /*@fallthrough@*/ + case 3: a += ((uint32_t)k[2])<<16; /*@fallthrough@*/ + case 2: a += ((uint32_t)k[1])<<8; /*@fallthrough@*/ + case 1: a += (uint32_t)k[0]; + break; + case 0: + goto exit; + } + } + + _JLU3_FINAL(a,b,c); + +exit: + return c; +} +#endif /* defined(_JLU3_jlu32l) */ + +#if defined(_JLU3_jlu32lpair) +/** + * jlu32lpair: return 2 32-bit hash values. + * + * This is identical to jlu32l(), except it returns two 32-bit hash + * values instead of just one. This is good enough for hash table + * lookup with 2^^64 buckets, or if you want a second hash if you're not + * happy with the first, or if you want a probably-unique 64-bit ID for + * the key. *pc is better mixed than *pb, so use *pc first. If you want + * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". + * + * @param h the previous hash, or an arbitrary value + * @param *key the key, an array of uint8_t values + * @param size the size of the key in bytes + * @retval *pc, IN: primary initval, OUT: primary hash + * *retval *pb IN: secondary initval, OUT: secondary hash + */ +void jlu32lpair(const void *key, size_t size, uint32_t *pc, uint32_t *pb) +{ + union { const void *ptr; size_t i; } u; + uint32_t a = _JLU3_INIT(*pc, size); + uint32_t b = a; + uint32_t c = a; + + if (key == NULL) + goto exit; + + c += *pb; /* Add the secondary hash. */ + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ +#ifdef VALGRIND + const uint8_t *k8; +#endif + + /*-- all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (size > (size_t)12) { + a += k[0]; + b += k[1]; + c += k[2]; + _JLU3_MIX(a,b,c); + size -= 12; + k += 3; + } + /*------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch (size) { + case 12: c += k[2]; b+=k[1]; a+=k[0]; break; + case 11: c += k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c += k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9: c += k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8: b += k[1]; a+=k[0]; break; + case 7: b += k[1]&0xffffff; a+=k[0]; break; + case 6: b += k[1]&0xffff; a+=k[0]; break; + case 5: b += k[1]&0xff; a+=k[0]; break; + case 4: a += k[0]; break; + case 3: a += k[0]&0xffffff; break; + case 2: a += k[0]&0xffff; break; + case 1: a += k[0]&0xff; break; + case 0: goto exit; + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch (size) { + case 12: c += k[2]; b+=k[1]; a+=k[0]; break; + case 11: c += ((uint32_t)k8[10])<<16; /*@fallthrough@*/ + case 10: c += ((uint32_t)k8[9])<<8; /*@fallthrough@*/ + case 9: c += k8[8]; /*@fallthrough@*/ + case 8: b += k[1]; a+=k[0]; break; + case 7: b += ((uint32_t)k8[6])<<16; /*@fallthrough@*/ + case 6: b += ((uint32_t)k8[5])<<8; /*@fallthrough@*/ + case 5: b += k8[4]; /*@fallthrough@*/ + case 4: a += k[0]; break; + case 3: a += ((uint32_t)k8[2])<<16; /*@fallthrough@*/ + case 2: a += ((uint32_t)k8[1])<<8; /*@fallthrough@*/ + case 1: a += k8[0]; break; + case 0: goto exit; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*----------- all but last block: aligned reads and different mixing */ + while (size > (size_t)12) { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + _JLU3_MIX(a,b,c); + size -= 12; + k += 6; + } + + /*------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch (size) { + case 12: + c += k[4]+(((uint32_t)k[5])<<16); + b += k[2]+(((uint32_t)k[3])<<16); + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 11: + c += ((uint32_t)k8[10])<<16; + /*@fallthrough@*/ + case 10: + c += k[4]; + b += k[2]+(((uint32_t)k[3])<<16); + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 9: + c += k8[8]; + /*@fallthrough@*/ + case 8: + b += k[2]+(((uint32_t)k[3])<<16); + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 7: + b += ((uint32_t)k8[6])<<16; + /*@fallthrough@*/ + case 6: + b += k[2]; + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 5: + b += k8[4]; + /*@fallthrough@*/ + case 4: + a += k[0]+(((uint32_t)k[1])<<16); + break; + case 3: + a += ((uint32_t)k8[2])<<16; + /*@fallthrough@*/ + case 2: + a += k[0]; + break; + case 1: + a += k8[0]; + break; + case 0: + goto exit; + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*----------- all but the last block: affect some 32 bits of (a,b,c) */ + while (size > (size_t)12) { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + _JLU3_MIX(a,b,c); + size -= 12; + k += 12; + } + + /*---------------------------- last block: affect all 32 bits of (c) */ + switch (size) { + case 12: c += ((uint32_t)k[11])<<24; /*@fallthrough@*/ + case 11: c += ((uint32_t)k[10])<<16; /*@fallthrough@*/ + case 10: c += ((uint32_t)k[9])<<8; /*@fallthrough@*/ + case 9: c += k[8]; /*@fallthrough@*/ + case 8: b += ((uint32_t)k[7])<<24; /*@fallthrough@*/ + case 7: b += ((uint32_t)k[6])<<16; /*@fallthrough@*/ + case 6: b += ((uint32_t)k[5])<<8; /*@fallthrough@*/ + case 5: b += k[4]; /*@fallthrough@*/ + case 4: a += ((uint32_t)k[3])<<24; /*@fallthrough@*/ + case 3: a += ((uint32_t)k[2])<<16; /*@fallthrough@*/ + case 2: a += ((uint32_t)k[1])<<8; /*@fallthrough@*/ + case 1: a += k[0]; + break; + case 0: + goto exit; + } + } + + _JLU3_FINAL(a,b,c); + +exit: + *pc = c; + *pb = b; + return; +} +#endif /* defined(_JLU3_jlu32lpair) */ + +#if defined(_JLU3_jlu32b) +uint32_t jlu32b(uint32_t h, /*@null@*/ const void *key, size_t size) + /*@*/; +/* + * jlu32b(): + * This is the same as jlu32w() on big-endian machines. It is different + * from jlu32l() on all machines. jlu32b() takes advantage of + * big-endian byte ordering. + * + * @param h the previous hash, or an arbitrary value + * @param *k the key, an array of uint8_t values + * @param size the size of the key + * @return the lookup3 hash + */ +uint32_t jlu32b(uint32_t h, const void *key, size_t size) +{ + union { const void *ptr; size_t i; } u; + uint32_t a = _JLU3_INIT(h, size); + uint32_t b = a; + uint32_t c = a; + + if (key == NULL) + return h; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ +#ifdef VALGRIND + const uint8_t *k8; +#endif + + /*-- all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (size > 12) { + a += k[0]; + b += k[1]; + c += k[2]; + _JLU3_MIX(a,b,c); + size -= 12; + k += 3; + } + + /*------------------------- handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because the + * string is aligned, the illegal read is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch (size) { + case 12: c += k[2]; b+=k[1]; a+=k[0]; break; + case 11: c += k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; + case 10: c += k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; + case 9: c += k[2]&0xff000000; b+=k[1]; a+=k[0]; break; + case 8: b += k[1]; a+=k[0]; break; + case 7: b += k[1]&0xffffff00; a+=k[0]; break; + case 6: b += k[1]&0xffff0000; a+=k[0]; break; + case 5: b += k[1]&0xff000000; a+=k[0]; break; + case 4: a += k[0]; break; + case 3: a += k[0]&0xffffff00; break; + case 2: a += k[0]&0xffff0000; break; + case 1: a += k[0]&0xff000000; break; + case 0: goto exit; + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch (size) { /* all the case statements fall through */ + case 12: c += k[2]; b+=k[1]; a+=k[0]; break; + case 11: c += ((uint32_t)k8[10])<<8; /*@fallthrough@*/ + case 10: c += ((uint32_t)k8[9])<<16; /*@fallthrough@*/ + case 9: c += ((uint32_t)k8[8])<<24; /*@fallthrough@*/ + case 8: b += k[1]; a+=k[0]; break; + case 7: b += ((uint32_t)k8[6])<<8; /*@fallthrough@*/ + case 6: b += ((uint32_t)k8[5])<<16; /*@fallthrough@*/ + case 5: b += ((uint32_t)k8[4])<<24; /*@fallthrough@*/ + case 4: a += k[0]; break; + case 3: a += ((uint32_t)k8[2])<<8; /*@fallthrough@*/ + case 2: a += ((uint32_t)k8[1])<<16; /*@fallthrough@*/ + case 1: a += ((uint32_t)k8[0])<<24; break; + case 0: goto exit; + } + +#endif /* !VALGRIND */ + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*----------- all but the last block: affect some 32 bits of (a,b,c) */ + while (size > 12) { + a += ((uint32_t)k[0])<<24; + a += ((uint32_t)k[1])<<16; + a += ((uint32_t)k[2])<<8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4])<<24; + b += ((uint32_t)k[5])<<16; + b += ((uint32_t)k[6])<<8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8])<<24; + c += ((uint32_t)k[9])<<16; + c += ((uint32_t)k[10])<<8; + c += ((uint32_t)k[11]); + _JLU3_MIX(a,b,c); + size -= 12; + k += 12; + } + + /*---------------------------- last block: affect all 32 bits of (c) */ + switch (size) { /* all the case statements fall through */ + case 12: c += k[11]; /*@fallthrough@*/ + case 11: c += ((uint32_t)k[10])<<8; /*@fallthrough@*/ + case 10: c += ((uint32_t)k[9])<<16; /*@fallthrough@*/ + case 9: c += ((uint32_t)k[8])<<24; /*@fallthrough@*/ + case 8: b += k[7]; /*@fallthrough@*/ + case 7: b += ((uint32_t)k[6])<<8; /*@fallthrough@*/ + case 6: b += ((uint32_t)k[5])<<16; /*@fallthrough@*/ + case 5: b += ((uint32_t)k[4])<<24; /*@fallthrough@*/ + case 4: a += k[3]; /*@fallthrough@*/ + case 3: a += ((uint32_t)k[2])<<8; /*@fallthrough@*/ + case 2: a += ((uint32_t)k[1])<<16; /*@fallthrough@*/ + case 1: a += ((uint32_t)k[0])<<24; /*@fallthrough@*/ + break; + case 0: + goto exit; + } + } + + _JLU3_FINAL(a,b,c); + +exit: + return c; +} +#endif /* defined(_JLU3_jlu32b) */ + +#if defined(_JLU3_SELFTEST) + +/* used for timings */ +static void driver1(void) + /*@*/ +{ + uint8_t buf[256]; + uint32_t i; + uint32_t h=0; + time_t a,z; + + time(&a); + for (i=0; i<256; ++i) buf[i] = 'x'; + for (i=0; i<1; ++i) { + h = jlu32l(h, &buf[0], sizeof(buf[0])); + } + time(&z); + if (z-a > 0) printf("time %d %.8x\n", (int)(z-a), h); +} + +/* check that every input bit changes every output bit half the time */ +#define HASHSTATE 1 +#define HASHLEN 1 +#define MAXPAIR 60 +#define MAXLEN 70 +static void driver2(void) + /*@*/ +{ + uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; + uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z; + uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; + uint32_t x[HASHSTATE],y[HASHSTATE]; + uint32_t hlen; + + printf("No more than %d trials should ever be needed \n",MAXPAIR/2); + for (hlen=0; hlen < MAXLEN; ++hlen) { + z=0; + for (i=0; i>(8-j)); + c[0] = jlu32l(m, a, hlen); + b[i] ^= ((k+1)<>(8-j)); + d[0] = jlu32l(m, b, hlen); + /* check every bit is 1, 0, set, and not set at least once */ + for (l=0; lz) z=k; + if (k == MAXPAIR) { + printf("Some bit didn't change: "); + printf("%.8x %.8x %.8x %.8x %.8x %.8x ", + e[0],f[0],g[0],h[0],x[0],y[0]); + printf("i %d j %d m %d len %d\n", i, j, m, hlen); + } + if (z == MAXPAIR) goto done; + } + } + } + done: + if (z < MAXPAIR) { + printf("Mix success %2d bytes %2d initvals ",i,m); + printf("required %d trials\n", z/2); + } + } + printf("\n"); +} + +/* Check for reading beyond the end of the buffer and alignment problems */ +static void driver3(void) + /*@*/ +{ + uint8_t buf[MAXLEN+20], *b; + uint32_t len; + uint8_t q[] = "This is the time for all good men to come to the aid of their country..."; + uint32_t h; + uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country..."; + uint32_t i; + uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; + uint32_t j; + uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; + uint32_t ref,x,y; + uint8_t *p; + uint32_t m = 13; + + printf("Endianness. These lines should all be the same (for values filled in):\n"); + printf("%.8x %.8x %.8x\n", + jlu32w(m, (const uint32_t *)q, (sizeof(q)-1)/4), + jlu32w(m, (const uint32_t *)q, (sizeof(q)-5)/4), + jlu32w(m, (const uint32_t *)q, (sizeof(q)-9)/4)); + p = q; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2), + jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4), + jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6), + jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8), + jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10), + jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12)); + p = &qq[1]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2), + jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4), + jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6), + jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8), + jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10), + jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12)); + p = &qqq[2]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2), + jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4), + jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6), + jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8), + jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10), + jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12)); + p = &qqqq[3]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2), + jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4), + jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6), + jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8), + jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10), + jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12)); + printf("\n"); + for (h=0, b=buf+1; h<8; ++h, ++b) { + for (i=0; i +#endif +#include + +#include "poptint.h" + +#ifdef MYDEBUG +/*@unchecked@*/ +int _popt_debug = 0; +#endif + +/*@unchecked@*/ +unsigned int _poptArgMask = POPT_ARG_MASK; +/*@unchecked@*/ +unsigned int _poptGroupMask = POPT_GROUP_MASK; + +#if !defined(HAVE_STRERROR) && !defined(__LCLINT__) +static char * strerror(int errno) +{ + extern int sys_nerr; + extern char * sys_errlist[]; + + if ((0 <= errno) && (errno < sys_nerr)) + return sys_errlist[errno]; + else + return POPT_("unknown errno"); +} +#endif + +#ifdef MYDEBUG +/*@unused@*/ +static void prtcon(const char *msg, poptContext con) +{ + if (msg) fprintf(stderr, "%s", msg); + fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n", + con, con->os, + (con->os->nextCharArg ? con->os->nextCharArg : ""), + (con->os->nextArg ? con->os->nextArg : ""), + con->os->next, + (con->os->argv && con->os->argv[con->os->next] + ? con->os->argv[con->os->next] : "")); +} +#endif + +void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) +{ + con->execPath = _free(con->execPath); + con->execPath = xstrdup(path); + con->execAbsolute = allowAbsolute; + return; +} + +static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt) + /*@globals internalState@*/ + /*@modifies internalState@*/ +{ + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + poptArg arg = { .ptr = opt->arg }; + if (arg.ptr) + switch (poptArgType(opt)) { + case POPT_ARG_INCLUDE_TABLE: /* Recurse on included sub-tables. */ + poptSubstituteHelpI18N(arg.opt); /* XXX side effects */ + invokeCallbacksPRE(con, arg.opt); + /*@switchbreak@*/ break; + case POPT_ARG_CALLBACK: /* Perform callback. */ + if (!CBF_ISSET(opt, PRE)) + /*@switchbreak@*/ break; +/*@-noeffectuncon @*/ /* XXX no known way to annotate (*vector) calls. */ + arg.cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip); +/*@=noeffectuncon @*/ + /*@switchbreak@*/ break; + } + } +} + +static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt) + /*@globals internalState@*/ + /*@modifies internalState@*/ +{ + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + poptArg arg = { .ptr = opt->arg }; + if (arg.ptr) + switch (poptArgType(opt)) { + case POPT_ARG_INCLUDE_TABLE: /* Recurse on included sub-tables. */ + poptSubstituteHelpI18N(arg.opt); /* XXX side effects */ + invokeCallbacksPOST(con, arg.opt); + /*@switchbreak@*/ break; + case POPT_ARG_CALLBACK: /* Perform callback. */ + if (!CBF_ISSET(opt, POST)) + /*@switchbreak@*/ break; +/*@-noeffectuncon @*/ /* XXX no known way to annotate (*vector) calls. */ + arg.cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip); +/*@=noeffectuncon @*/ + /*@switchbreak@*/ break; + } + } +} + +static void invokeCallbacksOPTION(poptContext con, + const struct poptOption * opt, + const struct poptOption * myOpt, + /*@null@*/ const void * myData, int shorty) + /*@globals internalState@*/ + /*@modifies internalState@*/ +{ + const struct poptOption * cbopt = NULL; + poptArg cbarg = { .ptr = NULL }; + + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + poptArg arg = { .ptr = opt->arg }; + switch (poptArgType(opt)) { + case POPT_ARG_INCLUDE_TABLE: /* Recurse on included sub-tables. */ + poptSubstituteHelpI18N(arg.opt); /* XXX side effects */ + if (opt->arg != NULL) + invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty); + /*@switchbreak@*/ break; + case POPT_ARG_CALLBACK: /* Save callback info. */ + if (CBF_ISSET(opt, SKIPOPTION)) + /*@switchbreak@*/ break; + cbopt = opt; + cbarg.ptr = opt->arg; + /*@switchbreak@*/ break; + default: /* Perform callback on matching option. */ + if (cbopt == NULL || cbarg.cb == NULL) + /*@switchbreak@*/ break; + if ((myOpt->shortName && opt->shortName && shorty && + myOpt->shortName == opt->shortName) + || (myOpt->longName != NULL && opt->longName != NULL && + !strcmp(myOpt->longName, opt->longName))) + { const void *cbData = (cbopt->descrip ? cbopt->descrip : myData); +/*@-noeffectuncon @*/ /* XXX no known way to annotate (*vector) calls. */ + cbarg.cb(con, POPT_CALLBACK_REASON_OPTION, + myOpt, con->os->nextArg, cbData); +/*@=noeffectuncon @*/ + /* Terminate (unless explcitly continuing). */ + if (!CBF_ISSET(cbopt, CONTINUE)) + return; + } + /*@switchbreak@*/ break; + } + } +} + +poptContext poptGetContext(const char * name, int argc, const char ** argv, + const struct poptOption * options, unsigned int flags) +{ + poptContext con = malloc(sizeof(*con)); + + if (con == NULL) return NULL; /* XXX can't happen */ + memset(con, 0, sizeof(*con)); + + con->os = con->optionStack; + con->os->argc = argc; +/*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ + con->os->argv = argv; +/*@=dependenttrans =assignexpose@*/ + con->os->argb = NULL; + + if (!(flags & POPT_CONTEXT_KEEP_FIRST)) + con->os->next = 1; /* skip argv[0] */ + + con->leftovers = calloc( (size_t)(argc + 1), sizeof(*con->leftovers) ); +/*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ + con->options = options; +/*@=dependenttrans =assignexpose@*/ + con->aliases = NULL; + con->numAliases = 0; + con->flags = flags; + con->execs = NULL; + con->numExecs = 0; + con->finalArgvAlloced = argc * 2; + con->finalArgv = calloc( (size_t)con->finalArgvAlloced, sizeof(*con->finalArgv) ); + con->execAbsolute = 1; + con->arg_strip = NULL; + + if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER")) + con->flags |= POPT_CONTEXT_POSIXMEHARDER; + + if (name) + con->appName = xstrdup(name); + + invokeCallbacksPRE(con, con->options); + + return con; +} + +static void cleanOSE(/*@special@*/ struct optionStackEntry *os) + /*@uses os @*/ + /*@releases os->nextArg, os->argv, os->argb @*/ + /*@modifies os @*/ +{ + os->nextArg = _free(os->nextArg); + os->argv = _free(os->argv); + os->argb = PBM_FREE(os->argb); +} + +void poptResetContext(poptContext con) +{ + int i; + + if (con == NULL) return; + while (con->os > con->optionStack) { + cleanOSE(con->os--); + } + con->os->argb = PBM_FREE(con->os->argb); + con->os->currAlias = NULL; + con->os->nextCharArg = NULL; + con->os->nextArg = NULL; + con->os->next = 1; /* skip argv[0] */ + + con->numLeftovers = 0; + con->nextLeftover = 0; + con->restLeftover = 0; + con->doExec = NULL; + + if (con->finalArgv != NULL) + for (i = 0; i < con->finalArgvCount; i++) { +/*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */ + con->finalArgv[i] = _free(con->finalArgv[i]); +/*@=unqualifiedtrans@*/ + } + + con->finalArgvCount = 0; + con->arg_strip = PBM_FREE(con->arg_strip); +/*@-nullstate@*/ /* FIX: con->finalArgv != NULL */ + return; +/*@=nullstate@*/ +} + +/* Only one of longName, shortName should be set, not both. */ +static int handleExec(/*@special@*/ poptContext con, + /*@null@*/ const char * longName, char shortName) + /*@uses con->execs, con->numExecs, con->flags, con->doExec, + con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/ + /*@modifies con @*/ +{ + poptItem item; + int i; + + if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */ + return 0; + + for (i = con->numExecs - 1; i >= 0; i--) { + item = con->execs + i; + if (longName && !(item->option.longName && + !strcmp(longName, item->option.longName))) + continue; + else if (shortName != item->option.shortName) + continue; + break; + } + if (i < 0) return 0; + + + if (con->flags & POPT_CONTEXT_NO_EXEC) + return 1; + + if (con->doExec == NULL) { + con->doExec = con->execs + i; + return 1; + } + + /* We already have an exec to do; remember this option for next + time 'round */ + if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof(*con->finalArgv) * con->finalArgvAlloced); + } + + i = con->finalArgvCount++; + if (con->finalArgv != NULL) /* XXX can't happen */ + { char *s = malloc((longName ? strlen(longName) : 0) + sizeof("--")); + if (s != NULL) { /* XXX can't happen */ + con->finalArgv[i] = s; + *s++ = '-'; + if (longName) + s = stpcpy( stpcpy(s, "-"), longName); + else + *s++ = shortName; + *s = '\0'; + } else + con->finalArgv[i] = NULL; + } + + return 1; +} + +/** + * Compare long option for equality, adjusting for POPT_ARGFLAG_TOGGLE. + * @param opt option + * @param longName arg option + * @param longNameLen arg option length + * @return does long option match? + */ +static int +longOptionStrcmp(const struct poptOption * opt, + /*@null@*/ const char * longName, size_t longNameLen) + /*@*/ +{ + const char * optLongName = opt->longName; + int rc; + + if (optLongName == NULL || longName == NULL) /* XXX can't heppen */ + return 0; + + if (F_ISSET(opt, TOGGLE)) { + if (optLongName[0] == 'n' && optLongName[1] == 'o') { + optLongName += sizeof("no") - 1; + if (optLongName[0] == '-') + optLongName++; + } + if (longName[0] == 'n' && longName[1] == 'o') { + longName += sizeof("no") - 1; + longNameLen -= sizeof("no") - 1; + if (longName[0] == '-') { + longName++; + longNameLen--; + } + } + } + rc = (int)(strlen(optLongName) == longNameLen); + if (rc) + rc = (int)(strncmp(optLongName, longName, longNameLen) == 0); + return rc; +} + +/* Only one of longName, shortName may be set at a time */ +static int handleAlias(/*@special@*/ poptContext con, + /*@null@*/ const char * longName, size_t longNameLen, + char shortName, + /*@exposed@*/ /*@null@*/ const char * nextArg) + /*@uses con->aliases, con->numAliases, con->optionStack, con->os, + con->os->currAlias, con->os->currAlias->option.longName @*/ + /*@modifies con @*/ +{ + poptItem item = con->os->currAlias; + int rc; + int i; + + if (item) { + if (longName && item->option.longName != NULL + && longOptionStrcmp(&item->option, longName, longNameLen)) + return 0; + else + if (shortName && shortName == item->option.shortName) + return 0; + } + + if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */ + return 0; + + for (i = con->numAliases - 1; i >= 0; i--) { + item = con->aliases + i; + if (longName) { + if (item->option.longName == NULL) + continue; + if (!longOptionStrcmp(&item->option, longName, longNameLen)) + continue; + } else if (shortName != item->option.shortName) + continue; + break; + } + if (i < 0) return 0; + + if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) + return POPT_ERROR_OPTSTOODEEP; + + if (longName == NULL && nextArg != NULL && *nextArg != '\0') + con->os->nextCharArg = nextArg; + + con->os++; + con->os->next = 0; + con->os->stuffed = 0; + con->os->nextArg = NULL; + con->os->nextCharArg = NULL; + con->os->currAlias = con->aliases + i; + { const char ** av; + int ac = con->os->currAlias->argc; + /* Append --foo=bar arg to alias argv array (if present). */ + if (longName && nextArg != NULL && *nextArg != '\0') { + av = malloc((ac + 1 + 1) * sizeof(*av)); + if (av != NULL) { /* XXX won't happen. */ + for (i = 0; i < ac; i++) { + av[i] = con->os->currAlias->argv[i]; + } + av[ac++] = nextArg; + av[ac] = NULL; + } else /* XXX revert to old popt behavior if malloc fails. */ + av = con->os->currAlias->argv; + } else + av = con->os->currAlias->argv; + rc = poptDupArgv(ac, av, &con->os->argc, &con->os->argv); + if (av != NULL && av != con->os->currAlias->argv) + free(av); + } + con->os->argb = NULL; + + return (rc ? rc : 1); +} + +/** + * Return absolute path to executable by searching PATH. + * @param argv0 name of executable + * @return (malloc'd) absolute path to executable (or NULL) + */ +static /*@null@*/ +const char * findProgramPath(/*@null@*/ const char * argv0) + /*@*/ +{ + char *path = NULL, *s = NULL, *se; + char *t = NULL; + + if (argv0 == NULL) return NULL; /* XXX can't happen */ + + /* If there is a / in argv[0], it has to be an absolute path. */ + /* XXX Hmmm, why not if (argv0[0] == '/') ... instead? */ + if (strchr(argv0, '/')) + return xstrdup(argv0); + + if ((path = getenv("PATH")) == NULL || (path = xstrdup(path)) == NULL) + return NULL; + + /* The return buffer in t is big enough for any path. */ + if ((t = malloc(strlen(path) + strlen(argv0) + sizeof("/"))) != NULL) + for (s = path; s && *s; s = se) { + + /* Snip PATH element into [s,se). */ + if ((se = strchr(s, ':'))) + *se++ = '\0'; + + /* Append argv0 to PATH element. */ + (void) stpcpy(stpcpy(stpcpy(t, s), "/"), argv0); + + /* If file is executable, bingo! */ + if (!access(t, X_OK)) + break; + } + + /* If no executable was found in PATH, return NULL. */ +/*@-compdef@*/ + if (!(s && *s) && t != NULL) + t = _free(t); +/*@=compdef@*/ +/*@-modobserver -observertrans -usedef @*/ + path = _free(path); +/*@=modobserver =observertrans =usedef @*/ + + return t; +} + +static int execCommand(poptContext con) + /*@globals internalState @*/ + /*@modifies internalState @*/ +{ + poptItem item = con->doExec; + poptArgv argv = NULL; + int argc = 0; + int rc; + int ec = POPT_ERROR_ERRNO; + + if (item == NULL) /*XXX can't happen*/ + return POPT_ERROR_NOARG; + + if (item->argv == NULL || item->argc < 1 || + (!con->execAbsolute && strchr(item->argv[0], '/'))) + return POPT_ERROR_NOARG; + + argv = malloc(sizeof(*argv) * + (6 + item->argc + con->numLeftovers + con->finalArgvCount)); + if (argv == NULL) return POPT_ERROR_MALLOC; + + if (!strchr(item->argv[0], '/') && con->execPath != NULL) { + char *s = malloc(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/")); + if (s) + (void)stpcpy(stpcpy(stpcpy(s, con->execPath), "/"), item->argv[0]); + + argv[argc] = s; + } else + argv[argc] = findProgramPath(item->argv[0]); + if (argv[argc++] == NULL) { + ec = POPT_ERROR_NOARG; + goto exit; + } + + if (item->argc > 1) { + memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1)); + argc += (item->argc - 1); + } + + if (con->finalArgv != NULL && con->finalArgvCount > 0) { + memcpy(argv + argc, con->finalArgv, + sizeof(*argv) * con->finalArgvCount); + argc += con->finalArgvCount; + } + + if (con->leftovers != NULL && con->numLeftovers > 0) { + memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers); + argc += con->numLeftovers; + } + + argv[argc] = NULL; + +#if defined(hpux) || defined(__hpux) + rc = setresgid(getgid(), getgid(),-1); + if (rc) goto exit; + rc = setresuid(getuid(), getuid(),-1); + if (rc) goto exit; +#else +/* + * XXX " ... on BSD systems setuid() should be preferred over setreuid()" + * XXX sez' Timur Bakeyev + * XXX from Norbert Warmuth + */ +#if defined(HAVE_SETUID) + rc = setgid(getgid()); + if (rc) goto exit; + rc = setuid(getuid()); + if (rc) goto exit; +#elif defined (HAVE_SETREUID) + rc = setregid(getgid(), getgid()); + if (rc) goto exit; + rc = setreuid(getuid(), getuid()); + if (rc) goto exit; +#else + ; /* Can't drop privileges */ +#endif +#endif + +#ifdef MYDEBUG +if (_popt_debug) + { poptArgv avp; + fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc); + for (avp = argv; *avp; avp++) + fprintf(stderr, " '%s'", *avp); + fprintf(stderr, "\n"); + } +#endif + +/*@-nullstate@*/ + rc = execvp(argv[0], (char *const *)argv); +/*@=nullstate@*/ + +exit: + if (argv) { + if (argv[0]) + free((void *)argv[0]); + free(argv); + } + return ec; +} + +/*@observer@*/ /*@null@*/ +static const struct poptOption * +findOption(const struct poptOption * opt, + /*@null@*/ const char * longName, size_t longNameLen, + char shortName, + /*@null@*/ /*@out@*/ poptCallbackType * callback, + /*@null@*/ /*@out@*/ const void ** callbackData, + unsigned int argInfo) + /*@modifies *callback, *callbackData */ +{ + const struct poptOption * cb = NULL; + poptArg cbarg = { .ptr = NULL }; + + /* This happens when a single - is given */ + if (LF_ISSET(ONEDASH) && !shortName && (longName && *longName == '\0')) + shortName = '-'; + + for (; opt->longName || opt->shortName || opt->arg; opt++) { + poptArg arg = { .ptr = opt->arg }; + + switch (poptArgType(opt)) { + case POPT_ARG_INCLUDE_TABLE: /* Recurse on included sub-tables. */ + { const struct poptOption * opt2; + + poptSubstituteHelpI18N(arg.opt); /* XXX side effects */ + if (arg.ptr == NULL) continue; /* XXX program error */ + opt2 = findOption(arg.opt, longName, longNameLen, shortName, callback, + callbackData, argInfo); + if (opt2 == NULL) continue; + /* Sub-table data will be inheirited if no data yet. */ +/*@-observertrans -dependenttrans @*/ + if (callback && *callback + && callbackData && *callbackData == NULL) + *callbackData = opt->descrip; +/*@=observertrans =dependenttrans @*/ + return opt2; + } /*@notreached@*/ /*@switchbreak@*/ break; + case POPT_ARG_CALLBACK: + cb = opt; + cbarg.ptr = opt->arg; + continue; + /*@notreached@*/ /*@switchbreak@*/ break; + default: + /*@switchbreak@*/ break; + } + + if (longName != NULL && opt->longName != NULL && + (!LF_ISSET(ONEDASH) || F_ISSET(opt, ONEDASH)) && + longOptionStrcmp(opt, longName, longNameLen)) + { + break; + } else if (shortName && shortName == opt->shortName) { + break; + } + } + + if (opt->longName == NULL && !opt->shortName) + return NULL; + +/*@-modobserver -mods @*/ + if (callback) + *callback = (cb ? cbarg.cb : NULL); + if (callbackData) +/*@-observertrans -dependenttrans @*/ + *callbackData = (cb && !CBF_ISSET(cb, INC_DATA) ? cb->descrip : NULL); +/*@=observertrans =dependenttrans @*/ +/*@=modobserver =mods @*/ + + return opt; +} + +static const char * findNextArg(/*@special@*/ poptContext con, + unsigned argx, int delete_arg) + /*@uses con->optionStack, con->os, + con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ + /*@modifies con @*/ +{ + struct optionStackEntry * os = con->os; + const char * arg; + + do { + int i; + arg = NULL; + while (os->next == os->argc && os > con->optionStack) os--; + if (os->next == os->argc && os == con->optionStack) break; + if (os->argv != NULL) + for (i = os->next; i < os->argc; i++) { +/*@-sizeoftype@*/ + if (os->argb && PBM_ISSET(i, os->argb)) + /*@innercontinue@*/ continue; + if (*os->argv[i] == '-') + /*@innercontinue@*/ continue; + if (--argx > 0) + /*@innercontinue@*/ continue; + arg = os->argv[i]; + if (delete_arg) { + if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc); + if (os->argb != NULL) /* XXX can't happen */ + PBM_SET(i, os->argb); + } + /*@innerbreak@*/ break; +/*@=sizeoftype@*/ + } + if (os > con->optionStack) os--; + } while (arg == NULL); + return arg; +} + +static /*@only@*/ /*@null@*/ const char * +expandNextArg(/*@special@*/ poptContext con, const char * s) + /*@uses con->optionStack, con->os, + con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ + /*@modifies con @*/ +{ + const char * a = NULL; + char *t, *te; + size_t tn = strlen(s) + 1; + char c; + + te = t = malloc(tn); + if (t == NULL) return NULL; /* XXX can't happen */ + *t = '\0'; + while ((c = *s++) != '\0') { + switch (c) { +#if 0 /* XXX can't do this */ + case '\\': /* escape */ + c = *s++; + /*@switchbreak@*/ break; +#endif + case '!': + if (!(s[0] == '#' && s[1] == ':' && s[2] == '+')) + /*@switchbreak@*/ break; + /* XXX Make sure that findNextArg deletes only next arg. */ + if (a == NULL) { + if ((a = findNextArg(con, 1U, 1)) == NULL) + /*@switchbreak@*/ break; + } + s += sizeof("#:+") - 1; + + tn += strlen(a); + { size_t pos = (size_t) (te - t); + if ((t = realloc(t, tn)) == NULL) /* XXX can't happen */ + return NULL; + te = stpcpy(t + pos, a); + } + continue; + /*@notreached@*/ /*@switchbreak@*/ break; + default: + /*@switchbreak@*/ break; + } + *te++ = c; + } + *te++ = '\0'; + /* If the new string is longer than needed, shorten. */ + if ((t + tn) > te) { +/*@-usereleased@*/ /* XXX splint can't follow the pointers. */ + if ((te = realloc(t, (size_t)(te - t))) == NULL) + free(t); + t = te; +/*@=usereleased@*/ + } + return t; +} + +static void poptStripArg(/*@special@*/ poptContext con, int which) + /*@uses con->optionStack @*/ + /*@defines con->arg_strip @*/ + /*@modifies con @*/ +{ +/*@-compdef -sizeoftype -usedef @*/ + if (con->arg_strip == NULL) + con->arg_strip = PBM_ALLOC(con->optionStack[0].argc); + if (con->arg_strip != NULL) /* XXX can't happen */ + PBM_SET(which, con->arg_strip); + return; +/*@=compdef =sizeoftype =usedef @*/ +} + +/*@unchecked@*/ +unsigned int _poptBitsN = _POPT_BITS_N; +/*@unchecked@*/ +unsigned int _poptBitsM = _POPT_BITS_M; +/*@unchecked@*/ +unsigned int _poptBitsK = _POPT_BITS_K; + +/*@-sizeoftype@*/ +static int _poptBitsNew(/*@null@*/ poptBits *bitsp) + /*@globals _poptBitsN, _poptBitsM, _poptBitsK @*/ + /*@modifies *bitsp, _poptBitsN, _poptBitsM, _poptBitsK @*/ +{ + if (bitsp == NULL) + return POPT_ERROR_NULLARG; + + /* XXX handle negated initialization. */ + if (*bitsp == NULL) { + if (_poptBitsN == 0) { + _poptBitsN = _POPT_BITS_N; + _poptBitsM = _POPT_BITS_M; + } + if (_poptBitsM == 0U) _poptBitsM = (3 * _poptBitsN) / 2; + if (_poptBitsK == 0U || _poptBitsK > 32U) _poptBitsK = _POPT_BITS_K; + *bitsp = PBM_ALLOC(_poptBitsM-1); + } +/*@-nullstate@*/ + return 0; +/*@=nullstate@*/ +} + +int poptBitsAdd(poptBits bits, const char * s) +{ + size_t ns = (s ? strlen(s) : 0); + uint32_t h0 = 0; + uint32_t h1 = 0; + + if (bits == NULL || ns == 0) + return POPT_ERROR_NULLARG; + + poptJlu32lpair(s, ns, &h0, &h1); + + for (ns = 0; ns < (size_t)_poptBitsK; ns++) { + uint32_t h = h0 + ns * h1; + uint32_t ix = (h % _poptBitsM); + PBM_SET(ix, bits); + } + return 0; +} + +int poptBitsChk(poptBits bits, const char * s) +{ + size_t ns = (s ? strlen(s) : 0); + uint32_t h0 = 0; + uint32_t h1 = 0; + int rc = 1; + + if (bits == NULL || ns == 0) + return POPT_ERROR_NULLARG; + + poptJlu32lpair(s, ns, &h0, &h1); + + for (ns = 0; ns < (size_t)_poptBitsK; ns++) { + uint32_t h = h0 + ns * h1; + uint32_t ix = (h % _poptBitsM); + if (PBM_ISSET(ix, bits)) + continue; + rc = 0; + break; + } + return rc; +} + +int poptBitsClr(poptBits bits) +{ + static size_t nbw = (__PBM_NBITS/8); + size_t nw = (__PBM_IX(_poptBitsM-1) + 1); + + if (bits == NULL) + return POPT_ERROR_NULLARG; + memset(bits, 0, nw * nbw); + return 0; +} + +int poptBitsDel(poptBits bits, const char * s) +{ + size_t ns = (s ? strlen(s) : 0); + uint32_t h0 = 0; + uint32_t h1 = 0; + + if (bits == NULL || ns == 0) + return POPT_ERROR_NULLARG; + + poptJlu32lpair(s, ns, &h0, &h1); + + for (ns = 0; ns < (size_t)_poptBitsK; ns++) { + uint32_t h = h0 + ns * h1; + uint32_t ix = (h % _poptBitsM); + PBM_CLR(ix, bits); + } + return 0; +} + +int poptBitsIntersect(poptBits *ap, const poptBits b) +{ + __pbm_bits *abits; + __pbm_bits *bbits; + __pbm_bits rc = 0; + size_t nw = (__PBM_IX(_poptBitsM-1) + 1); + size_t i; + + if (ap == NULL || b == NULL || _poptBitsNew(ap)) + return POPT_ERROR_NULLARG; + abits = __PBM_BITS(*ap); + bbits = __PBM_BITS(b); + + for (i = 0; i < nw; i++) { + abits[i] &= bbits[i]; + rc |= abits[i]; + } + return (rc ? 1 : 0); +} + +int poptBitsUnion(poptBits *ap, const poptBits b) +{ + __pbm_bits *abits; + __pbm_bits *bbits; + __pbm_bits rc = 0; + size_t nw = (__PBM_IX(_poptBitsM-1) + 1); + size_t i; + + if (ap == NULL || b == NULL || _poptBitsNew(ap)) + return POPT_ERROR_NULLARG; + abits = __PBM_BITS(*ap); + bbits = __PBM_BITS(b); + + for (i = 0; i < nw; i++) { + abits[i] |= bbits[i]; + rc |= abits[i]; + } + return (rc ? 1 : 0); +} + +int poptBitsArgs(poptContext con, poptBits *ap) +{ + const char ** av; + int rc = 0; + + if (con == NULL || ap == NULL || _poptBitsNew(ap) || + con->leftovers == NULL || con->numLeftovers == con->nextLeftover) + return POPT_ERROR_NULLARG; + + /* some apps like [like RPM ;-) ] need this NULL terminated */ + con->leftovers[con->numLeftovers] = NULL; + + for (av = con->leftovers + con->nextLeftover; *av != NULL; av++) { + if ((rc = poptBitsAdd(*ap, *av)) != 0) + break; + } +/*@-nullstate@*/ + return rc; +/*@=nullstate@*/ +} + +int poptSaveBits(poptBits * bitsp, + /*@unused@*/ UNUSED(unsigned int argInfo), const char * s) +{ + char *tbuf = NULL; + char *t, *te; + int rc = 0; + + if (bitsp == NULL || s == NULL || *s == '\0' || _poptBitsNew(bitsp)) + return POPT_ERROR_NULLARG; + + /* Parse comma separated attributes. */ + te = tbuf = xstrdup(s); + while ((t = te) != NULL && *t) { + while (*te != '\0' && *te != ',') + te++; + if (*te != '\0') + *te++ = '\0'; + /* XXX Ignore empty strings. */ + if (*t == '\0') + continue; + /* XXX Permit negated attributes. caveat emptor: false negatives. */ + if (*t == '!') { + t++; + if ((rc = poptBitsChk(*bitsp, t)) > 0) + rc = poptBitsDel(*bitsp, t); + } else + rc = poptBitsAdd(*bitsp, t); + if (rc) + break; + } + tbuf = _free(tbuf); + return rc; +} +/*@=sizeoftype@*/ + +int poptSaveString(const char *** argvp, + /*@unused@*/ UNUSED(unsigned int argInfo), const char * val) +{ + int argc = 0; + + if (argvp == NULL || val == NULL) + return POPT_ERROR_NULLARG; + + /* XXX likely needs an upper bound on argc. */ + if (*argvp != NULL) + while ((*argvp)[argc] != NULL) + argc++; + +/*@-unqualifiedtrans -nullstate@*/ /* XXX no annotation for (*argvp) */ + if ((*argvp = xrealloc(*argvp, (argc + 1 + 1) * sizeof(**argvp))) != NULL) { + (*argvp)[argc++] = xstrdup(val); + (*argvp)[argc ] = NULL; + } + return 0; +/*@=unqualifiedtrans =nullstate@*/ +} + +/*@unchecked@*/ +static unsigned int seed = 0; + +int poptSaveLongLong(long long * arg, unsigned int argInfo, long long aLongLong) +{ + if (arg == NULL +#ifdef NOTYET + /* XXX Check alignment, may fail on funky platforms. */ + || (((unsigned long long)arg) & (sizeof(*arg)-1)) +#endif + ) + return POPT_ERROR_NULLARG; + + if (aLongLong != 0 && LF_ISSET(RANDOM)) { +#if defined(HAVE_SRANDOM) + if (!seed) { + srandom((unsigned)getpid()); + srandom((unsigned)random()); + } + aLongLong = (long long)(random() % (aLongLong > 0 ? aLongLong : -aLongLong)); + aLongLong++; +#else + /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */ + return POPT_ERROR_BADOPERATION; +#endif + } + if (LF_ISSET(NOT)) + aLongLong = ~aLongLong; + switch (LF_ISSET(LOGICALOPS)) { + case 0: + *arg = aLongLong; + break; + case POPT_ARGFLAG_OR: + *(unsigned long long *)arg |= (unsigned long long)aLongLong; + break; + case POPT_ARGFLAG_AND: + *(unsigned long long *)arg &= (unsigned long long)aLongLong; + break; + case POPT_ARGFLAG_XOR: + *(unsigned long long *)arg ^= (unsigned long long)aLongLong; + break; + default: + return POPT_ERROR_BADOPERATION; + /*@notreached@*/ break; + } + return 0; +} + +int poptSaveLong(long * arg, unsigned int argInfo, long aLong) +{ + /* XXX Check alignment, may fail on funky platforms. */ + if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) + return POPT_ERROR_NULLARG; + + if (aLong != 0 && LF_ISSET(RANDOM)) { +#if defined(HAVE_SRANDOM) + if (!seed) { + srandom((unsigned)getpid()); + srandom((unsigned)random()); + } + aLong = random() % (aLong > 0 ? aLong : -aLong); + aLong++; +#else + /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */ + return POPT_ERROR_BADOPERATION; +#endif + } + if (LF_ISSET(NOT)) + aLong = ~aLong; + switch (LF_ISSET(LOGICALOPS)) { + case 0: *arg = aLong; break; + case POPT_ARGFLAG_OR: *(unsigned long *)arg |= (unsigned long)aLong; break; + case POPT_ARGFLAG_AND: *(unsigned long *)arg &= (unsigned long)aLong; break; + case POPT_ARGFLAG_XOR: *(unsigned long *)arg ^= (unsigned long)aLong; break; + default: + return POPT_ERROR_BADOPERATION; + /*@notreached@*/ break; + } + return 0; +} + +int poptSaveInt(/*@null@*/ int * arg, unsigned int argInfo, long aLong) +{ + /* XXX Check alignment, may fail on funky platforms. */ + if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) + return POPT_ERROR_NULLARG; + + if (aLong != 0 && LF_ISSET(RANDOM)) { +#if defined(HAVE_SRANDOM) + if (!seed) { + srandom((unsigned)getpid()); + srandom((unsigned)random()); + } + aLong = random() % (aLong > 0 ? aLong : -aLong); + aLong++; +#else + /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */ + return POPT_ERROR_BADOPERATION; +#endif + } + if (LF_ISSET(NOT)) + aLong = ~aLong; + switch (LF_ISSET(LOGICALOPS)) { + case 0: *arg = (int) aLong; break; + case POPT_ARGFLAG_OR: *(unsigned int *)arg |= (unsigned int) aLong; break; + case POPT_ARGFLAG_AND: *(unsigned int *)arg &= (unsigned int) aLong; break; + case POPT_ARGFLAG_XOR: *(unsigned int *)arg ^= (unsigned int) aLong; break; + default: + return POPT_ERROR_BADOPERATION; + /*@notreached@*/ break; + } + return 0; +} + +int poptSaveShort(/*@null@*/ short * arg, unsigned int argInfo, long aLong) +{ + /* XXX Check alignment, may fail on funky platforms. */ + if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) + return POPT_ERROR_NULLARG; + + if (aLong != 0 && LF_ISSET(RANDOM)) { +#if defined(HAVE_SRANDOM) + if (!seed) { + srandom((unsigned)getpid()); + srandom((unsigned)random()); + } + aLong = random() % (aLong > 0 ? aLong : -aLong); + aLong++; +#else + /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */ + return POPT_ERROR_BADOPERATION; +#endif + } + if (LF_ISSET(NOT)) + aLong = ~aLong; + switch (LF_ISSET(LOGICALOPS)) { + case 0: *arg = (short) aLong; + break; + case POPT_ARGFLAG_OR: *(unsigned short *)arg |= (unsigned short) aLong; + break; + case POPT_ARGFLAG_AND: *(unsigned short *)arg &= (unsigned short) aLong; + break; + case POPT_ARGFLAG_XOR: *(unsigned short *)arg ^= (unsigned short) aLong; + break; + default: return POPT_ERROR_BADOPERATION; + /*@notreached@*/ break; + } + return 0; +} + +/** + * Return argInfo field, handling POPT_ARGFLAG_TOGGLE overrides. + * @param con context + * @param opt option + * @return argInfo + */ +static unsigned int poptArgInfo(poptContext con, const struct poptOption * opt) + /*@*/ +{ + unsigned int argInfo = opt->argInfo; + + if (con->os->argv != NULL && con->os->next > 0 && opt->longName != NULL) + if (LF_ISSET(TOGGLE)) { + const char * longName = con->os->argv[con->os->next-1]; + while (*longName == '-') longName++; + /* XXX almost good enough but consider --[no]nofoo corner cases. */ + if (longName[0] != opt->longName[0] || longName[1] != opt->longName[1]) + { + if (!LF_ISSET(XOR)) { /* XXX dont toggle with XOR */ + /* Toggle POPT_BIT_SET <=> POPT_BIT_CLR. */ + if (LF_ISSET(LOGICALOPS)) + argInfo ^= (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND); + argInfo ^= POPT_ARGFLAG_NOT; + } + } + } + return argInfo; +} + +/** + * Parse an integer expression. + * @retval *llp integer expression value + * @param argInfo integer expression type + * @param val integer expression string + * @return 0 on success, otherwise POPT_* error. + */ +static int poptParseInteger(long long * llp, + /*@unused@*/ UNUSED(unsigned int argInfo), + /*@null@*/ const char * val) + /*@modifies *llp @*/ +{ + if (val) { + char *end = NULL; + *llp = strtoll(val, &end, 0); + + /* XXX parse scaling suffixes here. */ + + if (!(end && *end == '\0')) + return POPT_ERROR_BADNUMBER; + } else + *llp = 0; + return 0; +} + +/** + * Save the option argument through the (*opt->arg) pointer. + * @param con context + * @param opt option + * @return 0 on success, otherwise POPT_* error. + */ +static int poptSaveArg(poptContext con, const struct poptOption * opt) + /*@globals fileSystem, internalState @*/ + /*@modifies con, fileSystem, internalState @*/ +{ + poptArg arg = { .ptr = opt->arg }; + int rc = 0; /* assume success */ + + switch (poptArgType(opt)) { + case POPT_ARG_BITSET: + /* XXX memory leak, application is responsible for free. */ + rc = poptSaveBits(arg.ptr, opt->argInfo, con->os->nextArg); + /*@switchbreak@*/ break; + case POPT_ARG_ARGV: + /* XXX memory leak, application is responsible for free. */ + rc = poptSaveString(arg.ptr, opt->argInfo, con->os->nextArg); + /*@switchbreak@*/ break; + case POPT_ARG_STRING: + /* XXX memory leak, application is responsible for free. */ + arg.argv[0] = (con->os->nextArg) ? xstrdup(con->os->nextArg) : NULL; + /*@switchbreak@*/ break; + + case POPT_ARG_INT: + case POPT_ARG_SHORT: + case POPT_ARG_LONG: + case POPT_ARG_LONGLONG: + { unsigned int argInfo = poptArgInfo(con, opt); + long long aNUM = 0; + + if ((rc = poptParseInteger(&aNUM, argInfo, con->os->nextArg)) != 0) + break; + + switch (poptArgType(opt)) { + case POPT_ARG_LONGLONG: +/* XXX let's not demand C99 compiler flags for quite yet. */ +#if !defined(LLONG_MAX) +# define LLONG_MAX 9223372036854775807LL +# define LLONG_MIN (-LLONG_MAX - 1LL) +#endif + rc = !(aNUM == LLONG_MIN || aNUM == LLONG_MAX) + ? poptSaveLongLong(arg.longlongp, argInfo, aNUM) + : POPT_ERROR_OVERFLOW; + /*@innerbreak@*/ break; + case POPT_ARG_LONG: + rc = !(aNUM < (long long)LONG_MIN || aNUM > (long long)LONG_MAX) + ? poptSaveLong(arg.longp, argInfo, (long)aNUM) + : POPT_ERROR_OVERFLOW; + /*@innerbreak@*/ break; + case POPT_ARG_INT: + rc = !(aNUM < (long long)INT_MIN || aNUM > (long long)INT_MAX) + ? poptSaveInt(arg.intp, argInfo, (long)aNUM) + : POPT_ERROR_OVERFLOW; + /*@innerbreak@*/ break; + case POPT_ARG_SHORT: + rc = !(aNUM < (long long)SHRT_MIN || aNUM > (long long)SHRT_MAX) + ? poptSaveShort(arg.shortp, argInfo, (long)aNUM) + : POPT_ERROR_OVERFLOW; + /*@innerbreak@*/ break; + } + } /*@switchbreak@*/ break; + + case POPT_ARG_FLOAT: + case POPT_ARG_DOUBLE: + { char *end = NULL; + double aDouble = 0.0; + + if (con->os->nextArg) { +/*@-mods@*/ + int saveerrno = errno; + errno = 0; + aDouble = strtod(con->os->nextArg, &end); + if (errno == ERANGE) { + rc = POPT_ERROR_OVERFLOW; + break; + } + errno = saveerrno; +/*@=mods@*/ + if (*end != '\0') { + rc = POPT_ERROR_BADNUMBER; + break; + } + } + + switch (poptArgType(opt)) { + case POPT_ARG_DOUBLE: + arg.doublep[0] = aDouble; + /*@innerbreak@*/ break; + case POPT_ARG_FLOAT: +#if !defined(DBL_EPSILON) && !defined(__LCLINT__) +#define DBL_EPSILON 2.2204460492503131e-16 +#endif +#define POPT_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a)) + if ((FLT_MIN - POPT_ABS(aDouble)) > DBL_EPSILON + || (POPT_ABS(aDouble) - FLT_MAX) > DBL_EPSILON) + rc = POPT_ERROR_OVERFLOW; + else + arg.floatp[0] = (float) aDouble; + /*@innerbreak@*/ break; + } + } /*@switchbreak@*/ break; + case POPT_ARG_MAINCALL: +/*@-assignexpose -type@*/ + con->maincall = opt->arg; +/*@=assignexpose =type@*/ + /*@switchbreak@*/ break; + default: + fprintf(stdout, POPT_("option type (%u) not implemented in popt\n"), + poptArgType(opt)); + exit(EXIT_FAILURE); + /*@notreached@*/ /*@switchbreak@*/ break; + } + return rc; +} + +/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ +int poptGetNextOpt(poptContext con) +{ + const struct poptOption * opt = NULL; + int done = 0; + + if (con == NULL) + return -1; + while (!done) { + const char * origOptString = NULL; + poptCallbackType cb = NULL; + const void * cbData = NULL; + const char * longArg = NULL; + int canstrip = 0; + int shorty = 0; + + while (!con->os->nextCharArg && con->os->next == con->os->argc + && con->os > con->optionStack) { + cleanOSE(con->os--); + } + if (!con->os->nextCharArg && con->os->next == con->os->argc) { + invokeCallbacksPOST(con, con->options); + + if (con->maincall) { + /*@-noeffectuncon @*/ + (void) (*con->maincall) (con->finalArgvCount, con->finalArgv); + /*@=noeffectuncon @*/ + return -1; + } + + if (con->doExec) return execCommand(con); + return -1; + } + + /* Process next long option */ + if (!con->os->nextCharArg) { + const char * optString; + size_t optStringLen; + int thisopt; + +/*@-sizeoftype@*/ + if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) { + con->os->next++; + continue; + } +/*@=sizeoftype@*/ + thisopt = con->os->next; + if (con->os->argv != NULL) /* XXX can't happen */ + origOptString = con->os->argv[con->os->next++]; + + if (origOptString == NULL) /* XXX can't happen */ + return POPT_ERROR_BADOPT; + + if (con->restLeftover || *origOptString != '-' || + (*origOptString == '-' && origOptString[1] == '\0')) + { + if (con->flags & POPT_CONTEXT_POSIXMEHARDER) + con->restLeftover = 1; + if (con->flags & POPT_CONTEXT_ARG_OPTS) { + con->os->nextArg = xstrdup(origOptString); + return 0; + } + if (con->leftovers != NULL) /* XXX can't happen */ + con->leftovers[con->numLeftovers++] = origOptString; + continue; + } + + /* Make a copy we can hack at */ + optString = origOptString; + + if (optString[0] == '\0') + return POPT_ERROR_BADOPT; + + if (optString[1] == '-' && !optString[2]) { + con->restLeftover = 1; + continue; + } else { + const char *oe; + unsigned int argInfo = 0; + + optString++; + if (*optString == '-') + optString++; + else + argInfo |= POPT_ARGFLAG_ONEDASH; + + /* Check for "--long=arg" option. */ + for (oe = optString; *oe && *oe != '='; oe++) + {}; + optStringLen = (size_t)(oe - optString); + if (*oe == '=') + longArg = oe + 1; + + /* XXX aliases with arg substitution need "--alias=arg" */ + if (handleAlias(con, optString, optStringLen, '\0', longArg)) { + longArg = NULL; + continue; + } + + if (handleExec(con, optString, '\0')) + continue; + + opt = findOption(con->options, optString, optStringLen, '\0', &cb, &cbData, + argInfo); + if (!opt && !LF_ISSET(ONEDASH)) + return POPT_ERROR_BADOPT; + } + + if (!opt) { + con->os->nextCharArg = origOptString + 1; + longArg = NULL; + } else { + if (con->os == con->optionStack && F_ISSET(opt, STRIP)) + { + canstrip = 1; + poptStripArg(con, thisopt); + } + shorty = 0; + } + } + + /* Process next short option */ + if (con->os->nextCharArg) { + const char * nextCharArg = con->os->nextCharArg; + + con->os->nextCharArg = NULL; + + if (handleAlias(con, NULL, 0, *nextCharArg, nextCharArg + 1)) + continue; + + if (handleExec(con, NULL, *nextCharArg)) { + /* Restore rest of short options for further processing */ + nextCharArg++; + if (*nextCharArg != '\0') + con->os->nextCharArg = nextCharArg; + continue; + } + + opt = findOption(con->options, NULL, 0, *nextCharArg, &cb, + &cbData, 0); + if (!opt) + return POPT_ERROR_BADOPT; + shorty = 1; + + nextCharArg++; + if (*nextCharArg != '\0') + con->os->nextCharArg = nextCharArg + (int)(*nextCharArg == '='); + } + + if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */ + if (opt->arg && poptArgType(opt) == POPT_ARG_NONE) { + unsigned int argInfo = poptArgInfo(con, opt); + if (poptSaveInt((int *)opt->arg, argInfo, 1L)) + return POPT_ERROR_BADOPERATION; + } else if (poptArgType(opt) == POPT_ARG_VAL) { + if (opt->arg) { + unsigned int argInfo = poptArgInfo(con, opt); + if (poptSaveInt((int *)opt->arg, argInfo, (long)opt->val)) + return POPT_ERROR_BADOPERATION; + } + } else if (poptArgType(opt) != POPT_ARG_NONE) { + int rc; + + con->os->nextArg = _free(con->os->nextArg); + if (longArg) { + longArg = expandNextArg(con, longArg); + con->os->nextArg = (char *) longArg; + } else if (con->os->nextCharArg) { + longArg = expandNextArg(con, con->os->nextCharArg); + con->os->nextArg = (char *) longArg; + con->os->nextCharArg = NULL; + } else { + while (con->os->next == con->os->argc && + con->os > con->optionStack) + { + cleanOSE(con->os--); + } + if (con->os->next == con->os->argc) { + if (!F_ISSET(opt, OPTIONAL)) + return POPT_ERROR_NOARG; + con->os->nextArg = NULL; + } else { + + /* + * Make sure this isn't part of a short arg or the + * result of an alias expansion. + */ + if (con->os == con->optionStack + && F_ISSET(opt, STRIP) && canstrip) + { + poptStripArg(con, con->os->next); + } + + if (con->os->argv != NULL) { /* XXX can't happen */ + if (F_ISSET(opt, OPTIONAL) && + con->os->argv[con->os->next][0] == '-') { + con->os->nextArg = NULL; + } else { + /* XXX watchout: subtle side-effects live here. */ + longArg = con->os->argv[con->os->next++]; + longArg = expandNextArg(con, longArg); + con->os->nextArg = (char *) longArg; + } + } + } + } + longArg = NULL; + + /* Save the option argument through a (*opt->arg) pointer. */ + if (opt->arg != NULL && (rc = poptSaveArg(con, opt)) != 0) + return rc; + } + + if (cb) + invokeCallbacksOPTION(con, con->options, opt, cbData, shorty); + else if (opt->val && (poptArgType(opt) != POPT_ARG_VAL)) + done = 1; + + if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof(*con->finalArgv) * con->finalArgvAlloced); + } + + if (con->finalArgv != NULL) + { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + sizeof("--")); + if (s != NULL) { /* XXX can't happen */ + con->finalArgv[con->finalArgvCount++] = s; + *s++ = '-'; + if (opt->longName) { + if (!F_ISSET(opt, ONEDASH)) + *s++ = '-'; + s = stpcpy(s, opt->longName); + } else { + *s++ = opt->shortName; + *s = '\0'; + } + } else + con->finalArgv[con->finalArgvCount++] = NULL; + } + + if (opt->arg && poptArgType(opt) == POPT_ARG_NONE) + /*@-ifempty@*/ ; /*@=ifempty@*/ + else if (poptArgType(opt) == POPT_ARG_VAL) + /*@-ifempty@*/ ; /*@=ifempty@*/ + else if (poptArgType(opt) != POPT_ARG_NONE) { + if (con->finalArgv != NULL && con->os->nextArg != NULL) + con->finalArgv[con->finalArgvCount++] = + xstrdup(con->os->nextArg); + } + } + + return (opt ? opt->val : -1); /* XXX can't happen */ +} + +char * poptGetOptArg(poptContext con) +{ + char * ret = NULL; + if (con) { + ret = con->os->nextArg; + con->os->nextArg = NULL; + } + return ret; +} + +const char * poptGetArg(poptContext con) +{ + const char * ret = NULL; + if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers) + ret = con->leftovers[con->nextLeftover++]; + return ret; +} + +const char * poptPeekArg(poptContext con) +{ + const char * ret = NULL; + if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers) + ret = con->leftovers[con->nextLeftover]; + return ret; +} + +const char ** poptGetArgs(poptContext con) +{ + if (con == NULL || + con->leftovers == NULL || con->numLeftovers == con->nextLeftover) + return NULL; + + /* some apps like [like RPM ;-) ] need this NULL terminated */ + con->leftovers[con->numLeftovers] = NULL; + +/*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */ + return (con->leftovers + con->nextLeftover); +/*@=nullret =nullstate @*/ +} + +static /*@null@*/ +poptItem poptFreeItems(/*@only@*/ /*@null@*/ poptItem items, int nitems) + /*@modifies items @*/ +{ + if (items != NULL) { + poptItem item = items; + while (--nitems >= 0) { +/*@-modobserver -observertrans -dependenttrans@*/ + item->option.longName = _free(item->option.longName); + item->option.descrip = _free(item->option.descrip); + item->option.argDescrip = _free(item->option.argDescrip); +/*@=modobserver =observertrans =dependenttrans@*/ + item->argv = _free(item->argv); + item++; + } + items = _free(items); + } + return NULL; +} + +poptContext poptFreeContext(poptContext con) +{ + if (con == NULL) return con; + poptResetContext(con); + con->os->argb = _free(con->os->argb); + + con->aliases = poptFreeItems(con->aliases, con->numAliases); + con->numAliases = 0; + + con->execs = poptFreeItems(con->execs, con->numExecs); + con->numExecs = 0; + + con->leftovers = _free(con->leftovers); + con->finalArgv = _free(con->finalArgv); + con->appName = _free(con->appName); + con->otherHelp = _free(con->otherHelp); + con->execPath = _free(con->execPath); + con->arg_strip = PBM_FREE(con->arg_strip); + + con = _free(con); + return con; +} + +int poptAddAlias(poptContext con, struct poptAlias alias, + /*@unused@*/ UNUSED(int flags)) +{ + struct poptItem_s item_buf; + poptItem item = &item_buf; + memset(item, 0, sizeof(*item)); + item->option.longName = alias.longName; + item->option.shortName = alias.shortName; + item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; + item->option.arg = 0; + item->option.val = 0; + item->option.descrip = NULL; + item->option.argDescrip = NULL; + item->argc = alias.argc; + item->argv = alias.argv; + return poptAddItem(con, item, 0); +} + +int poptAddItem(poptContext con, poptItem newItem, int flags) +{ + poptItem * items, item; + int * nitems; + + switch (flags) { + case 1: + items = &con->execs; + nitems = &con->numExecs; + break; + case 0: + items = &con->aliases; + nitems = &con->numAliases; + break; + default: + return 1; + /*@notreached@*/ break; + } + + *items = realloc((*items), ((*nitems) + 1) * sizeof(**items)); + if ((*items) == NULL) + return 1; + + item = (*items) + (*nitems); + + item->option.longName = + (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL); + item->option.shortName = newItem->option.shortName; + item->option.argInfo = newItem->option.argInfo; + item->option.arg = newItem->option.arg; + item->option.val = newItem->option.val; + item->option.descrip = + (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL); + item->option.argDescrip = + (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL); + item->argc = newItem->argc; + item->argv = newItem->argv; + + (*nitems)++; + + return 0; +} + +const char * poptBadOption(poptContext con, unsigned int flags) +{ + struct optionStackEntry * os = NULL; + + if (con != NULL) + os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os; + + return (os != NULL && os->argv != NULL ? os->argv[os->next - 1] : NULL); +} + +const char * poptStrerror(const int error) +{ + switch (error) { + case POPT_ERROR_NOARG: + return POPT_("missing argument"); + case POPT_ERROR_BADOPT: + return POPT_("unknown option"); + case POPT_ERROR_BADOPERATION: + return POPT_("mutually exclusive logical operations requested"); + case POPT_ERROR_NULLARG: + return POPT_("opt->arg should not be NULL"); + case POPT_ERROR_OPTSTOODEEP: + return POPT_("aliases nested too deeply"); + case POPT_ERROR_BADQUOTE: + return POPT_("error in parameter quoting"); + case POPT_ERROR_BADNUMBER: + return POPT_("invalid numeric value"); + case POPT_ERROR_OVERFLOW: + return POPT_("number too large or too small"); + case POPT_ERROR_MALLOC: + return POPT_("memory allocation failed"); + case POPT_ERROR_BADCONFIG: + return POPT_("config file failed sanity test"); + case POPT_ERROR_ERRNO: + return strerror(errno); + default: + return POPT_("unknown error"); + } +} + +int poptStuffArgs(poptContext con, const char ** argv) +{ + int argc; + int rc; + + if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) + return POPT_ERROR_OPTSTOODEEP; + + for (argc = 0; argv[argc]; argc++) + {}; + + con->os++; + con->os->next = 0; + con->os->nextArg = NULL; + con->os->nextCharArg = NULL; + con->os->currAlias = NULL; + rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv); + con->os->argb = NULL; + con->os->stuffed = 1; + + return rc; +} + +const char * poptGetInvocationName(poptContext con) +{ + return (con->os->argv ? con->os->argv[0] : ""); +} + +int poptStrippedArgv(poptContext con, int argc, char ** argv) +{ + int numargs = argc; + int j = 1; + int i; + +/*@-sizeoftype@*/ + if (con->arg_strip) + for (i = 1; i < argc; i++) { + if (PBM_ISSET(i, con->arg_strip)) + numargs--; + } + + for (i = 1; i < argc; i++) { + if (con->arg_strip && PBM_ISSET(i, con->arg_strip)) + continue; + argv[j] = (j < numargs) ? argv[i] : NULL; + j++; + } +/*@=sizeoftype@*/ + + return numargs; +} diff --git a/ldb-2.0.8/third_party/popt/popt.h b/ldb-2.0.8/third_party/popt/popt.h new file mode 100644 index 0000000..a12d143 --- /dev/null +++ b/ldb-2.0.8/third_party/popt/popt.h @@ -0,0 +1,744 @@ +/** \file popt/popt.h + * \ingroup popt + */ + +/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.rpm.org/pub/rpm/dist. */ + +#ifndef H_POPT +#define H_POPT + +#include /* for FILE * */ + +#define POPT_OPTION_DEPTH 10 + +/** \ingroup popt + * \name Arg type identifiers + */ +/*@{*/ +#define POPT_ARG_NONE 0U /*!< no arg */ +#define POPT_ARG_STRING 1U /*!< arg will be saved as string */ +#define POPT_ARG_INT 2U /*!< arg ==> int */ +#define POPT_ARG_LONG 3U /*!< arg ==> long */ +#define POPT_ARG_INCLUDE_TABLE 4U /*!< arg points to table */ +#define POPT_ARG_CALLBACK 5U /*!< table-wide callback... must be + set first in table; arg points + to callback, descrip points to + callback data to pass */ +#define POPT_ARG_INTL_DOMAIN 6U /*!< set the translation domain + for this table and any + included tables; arg points + to the domain string */ +#define POPT_ARG_VAL 7U /*!< arg should take value val */ +#define POPT_ARG_FLOAT 8U /*!< arg ==> float */ +#define POPT_ARG_DOUBLE 9U /*!< arg ==> double */ +#define POPT_ARG_LONGLONG 10U /*!< arg ==> long long */ + +#define POPT_ARG_MAINCALL 16U+11U /*!< EXPERIMENTAL: return (*arg) (argc, argv) */ +#define POPT_ARG_ARGV 12U /*!< dupe'd arg appended to realloc'd argv array. */ +#define POPT_ARG_SHORT 13U /*!< arg ==> short */ +#define POPT_ARG_BITSET 16U+14U /*!< arg ==> bit set */ + +#define POPT_ARG_MASK 0x000000FFU +#define POPT_GROUP_MASK 0x0000FF00U + +/*@}*/ + +/** \ingroup popt + * \name Arg modifiers + */ +/*@{*/ +#define POPT_ARGFLAG_ONEDASH 0x80000000U /*!< allow -longoption */ +#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000U /*!< don't show in help/usage */ +#define POPT_ARGFLAG_STRIP 0x20000000U /*!< strip this arg from argv(only applies to long args) */ +#define POPT_ARGFLAG_OPTIONAL 0x10000000U /*!< arg may be missing */ + +#define POPT_ARGFLAG_OR 0x08000000U /*!< arg will be or'ed */ +#define POPT_ARGFLAG_NOR 0x09000000U /*!< arg will be nor'ed */ +#define POPT_ARGFLAG_AND 0x04000000U /*!< arg will be and'ed */ +#define POPT_ARGFLAG_NAND 0x05000000U /*!< arg will be nand'ed */ +#define POPT_ARGFLAG_XOR 0x02000000U /*!< arg will be xor'ed */ +#define POPT_ARGFLAG_NOT 0x01000000U /*!< arg will be negated */ +#define POPT_ARGFLAG_LOGICALOPS \ + (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR) + +#define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR) + /*!< set arg bit(s) */ +#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND) + /*!< clear arg bit(s) */ + +#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000U /*!< show default value in --help */ +#define POPT_ARGFLAG_RANDOM 0x00400000U /*!< random value in [1,arg] */ +#define POPT_ARGFLAG_TOGGLE 0x00200000U /*!< permit --[no]opt prefix toggle */ + +/*@}*/ + +/** \ingroup popt + * \name Callback modifiers + */ +/*@{*/ +#define POPT_CBFLAG_PRE 0x80000000U /*!< call the callback before parse */ +#define POPT_CBFLAG_POST 0x40000000U /*!< call the callback after parse */ +#define POPT_CBFLAG_INC_DATA 0x20000000U /*!< use data from the include line, + not the subtable */ +#define POPT_CBFLAG_SKIPOPTION 0x10000000U /*!< don't callback with option */ +#define POPT_CBFLAG_CONTINUE 0x08000000U /*!< continue callbacks with option */ +/*@}*/ + +/** \ingroup popt + * \name Error return values + */ +/*@{*/ +#define POPT_ERROR_NOARG -10 /*!< missing argument */ +#define POPT_ERROR_BADOPT -11 /*!< unknown option */ +#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */ +#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */ +#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */ +#define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */ +#define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */ +#define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */ +#define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */ +#define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */ +#define POPT_ERROR_BADCONFIG -22 /*!< config file failed sanity test */ +/*@}*/ + +/** \ingroup popt + * \name poptBadOption() flags + */ +/*@{*/ +#define POPT_BADOPTION_NOALIAS (1U << 0) /*!< don't go into an alias */ +/*@}*/ + +/** \ingroup popt + * \name poptGetContext() flags + */ +/*@{*/ +#define POPT_CONTEXT_NO_EXEC (1U << 0) /*!< ignore exec expansions */ +#define POPT_CONTEXT_KEEP_FIRST (1U << 1) /*!< pay attention to argv[0] */ +#define POPT_CONTEXT_POSIXMEHARDER (1U << 2) /*!< options can't follow args */ +#define POPT_CONTEXT_ARG_OPTS (1U << 4) /*!< return args as options with value 0 */ +/*@}*/ + +/** \ingroup popt + */ +struct poptOption { +/*@observer@*/ /*@null@*/ + const char * longName; /*!< may be NULL */ + char shortName; /*!< may be NUL */ + unsigned int argInfo; +/*@shared@*/ /*@null@*/ + void * arg; /*!< depends on argInfo */ + int val; /*!< 0 means don't return, just update flag */ +/*@observer@*/ /*@null@*/ + const char * descrip; /*!< description for autohelp -- may be NULL */ +/*@observer@*/ /*@null@*/ + const char * argDescrip; /*!< argument description for autohelp */ +}; + +/** \ingroup popt + * A popt alias argument for poptAddAlias(). + */ +struct poptAlias { +/*@owned@*/ /*@null@*/ + const char * longName; /*!< may be NULL */ + char shortName; /*!< may be NUL */ + int argc; +/*@owned@*/ + const char ** argv; /*!< must be free()able */ +}; + +/** \ingroup popt + * A popt alias or exec argument for poptAddItem(). + */ +/*@-exporttype@*/ +typedef struct poptItem_s { + struct poptOption option; /*!< alias/exec name(s) and description. */ + int argc; /*!< (alias) no. of args. */ +/*@owned@*/ + const char ** argv; /*!< (alias) args, must be free()able. */ +} * poptItem; +/*@=exporttype@*/ + +/** \ingroup popt + * \name Auto-generated help/usage + */ +/*@{*/ + +/** + * Empty table marker to enable displaying popt alias/exec options. + */ +/*@-exportvar@*/ +/*@unchecked@*/ /*@observer@*/ +extern struct poptOption poptAliasOptions[]; +/*@=exportvar@*/ +#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \ + 0, "Options implemented via popt alias/exec:", NULL }, + +/** + * Auto help table options. + */ +/*@-exportvar@*/ +/*@unchecked@*/ /*@observer@*/ +extern struct poptOption poptHelpOptions[]; +/*@=exportvar@*/ + +/*@-exportvar@*/ +/*@unchecked@*/ /*@observer@*/ +extern struct poptOption * poptHelpOptionsI18N; +/*@=exportvar@*/ + +#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \ + 0, "Help options:", NULL }, + +#define POPT_TABLEEND { NULL, '\0', 0, NULL, 0, NULL, NULL } +/*@}*/ + +/** \ingroup popt + */ +/*@-exporttype@*/ +typedef /*@abstract@*/ struct poptContext_s * poptContext; +/*@=exporttype@*/ + +/** \ingroup popt + */ +#ifndef __cplusplus +/*@-exporttype -typeuse@*/ +typedef struct poptOption * poptOption; +/*@=exporttype =typeuse@*/ +#endif + +/** \ingroup popt + */ +/*@-exportconst@*/ +enum poptCallbackReason { + POPT_CALLBACK_REASON_PRE = 0, + POPT_CALLBACK_REASON_POST = 1, + POPT_CALLBACK_REASON_OPTION = 2 +}; +/*@=exportconst@*/ + +#ifdef __cplusplus +extern "C" { +#endif +/*@-type@*/ + +/** \ingroup popt + * Table callback prototype. + * @param con context + * @param reason reason for callback + * @param opt option that triggered callback + * @param arg @todo Document. + * @param data @todo Document. + */ +typedef void (*poptCallbackType) (poptContext con, + enum poptCallbackReason reason, + /*@null@*/ const struct poptOption * opt, + /*@null@*/ const char * arg, + /*@null@*/ const void * data) + /*@globals internalState @*/ + /*@modifies internalState @*/; + +/** \ingroup popt + * Destroy context. + * @param con context + * @return NULL always + */ +/*@null@*/ +poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Initialize popt context. + * @param name context name (usually argv[0] program name) + * @param argc no. of arguments + * @param argv argument array + * @param options address of popt option table + * @param flags or'd POPT_CONTEXT_* bits + * @return initialized popt context + */ +/*@only@*/ /*@null@*/ +poptContext poptGetContext( + /*@dependent@*/ /*@keep@*/ const char * name, + int argc, /*@dependent@*/ /*@keep@*/ const char ** argv, + /*@dependent@*/ /*@keep@*/ const struct poptOption * options, + unsigned int flags) + /*@globals internalState @*/ + /*@modifies internalState @*/; + +/** \ingroup popt + * Destroy context (alternative implementation). + * @param con context + * @return NULL always + */ +/*@null@*/ +poptContext poptFini( /*@only@*/ /*@null@*/ poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Initialize popt context (alternative implementation). + * This routine does poptGetContext() and then poptReadConfigFiles(). + * @param argc no. of arguments + * @param argv argument array + * @param options address of popt option table + * @param configPaths colon separated file path(s) to read. + * @return initialized popt context (NULL on error). + */ +/*@only@*/ /*@null@*/ /*@unused@*/ +poptContext poptInit(int argc, /*@dependent@*/ /*@keep@*/ const char ** argv, + /*@dependent@*/ /*@keep@*/ const struct poptOption * options, + /*@null@*/ const char * configPaths) + /*@globals fileSystem, internalState @*/ + /*@modifies fileSystem, internalState @*/; + +/** \ingroup popt + * Reinitialize popt context. + * @param con context + */ +/*@unused@*/ +void poptResetContext(/*@null@*/poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Return value of next option found. + * @param con context + * @return next option val, -1 on last item, POPT_ERROR_* on error + */ +int poptGetNextOpt(/*@null@*/poptContext con) + /*@globals fileSystem, internalState @*/ + /*@modifies con, fileSystem, internalState @*/; + +/** \ingroup popt + * Return next option argument (if any). + * @param con context + * @return option argument, NULL if no argument is available + */ +/*@observer@*/ /*@null@*/ /*@unused@*/ +char * poptGetOptArg(/*@null@*/poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Return next argument. + * @param con context + * @return next argument, NULL if no argument is available + */ +/*@observer@*/ /*@null@*/ /*@unused@*/ +const char * poptGetArg(/*@null@*/poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Peek at current argument. + * @param con context + * @return current argument, NULL if no argument is available + */ +/*@observer@*/ /*@null@*/ /*@unused@*/ +const char * poptPeekArg(/*@null@*/poptContext con) + /*@*/; + +/** \ingroup popt + * Return remaining arguments. + * @param con context + * @return argument array, NULL terminated + */ +/*@observer@*/ /*@null@*/ +const char ** poptGetArgs(/*@null@*/poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Return the option which caused the most recent error. + * @param con context + * @param flags + * @return offending option + */ +/*@observer@*/ +const char * poptBadOption(/*@null@*/poptContext con, unsigned int flags) + /*@*/; + +/** \ingroup popt + * Add arguments to context. + * @param con context + * @param argv argument array, NULL terminated + * @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure + */ +/*@unused@*/ +int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv) + /*@modifies con @*/; + +/** \ingroup popt + * Add alias to context. + * @todo Pass alias by reference, not value. + * @deprecated Use poptAddItem instead. + * @param con context + * @param alias alias to add + * @param flags (unused) + * @return 0 on success + */ +/*@unused@*/ +int poptAddAlias(poptContext con, struct poptAlias alias, int flags) + /*@modifies con @*/; + +/** \ingroup popt + * Add alias/exec item to context. + * @param con context + * @param newItem alias/exec item to add + * @param flags 0 for alias, 1 for exec + * @return 0 on success + */ +int poptAddItem(poptContext con, poptItem newItem, int flags) + /*@modifies con @*/; + +/** \ingroup popt + * Perform sanity checks on a file path. + * @param fn file name + * @return 0 on OK, 1 on NOTOK. + */ +int poptSaneFile(const char * fn) + /*@globals errno, internalState @*/ + /*@modifies errno, internalState @*/; + +/** + * Read a file into a buffer. + * @param fn file name + * @retval *bp buffer (malloc'd) (or NULL) + * @retval *nbp no. of bytes in buffer (including final NUL) (or NULL) + * @param flags 1 to trim escaped newlines + * return 0 on success + */ +int poptReadFile(const char * fn, /*@null@*/ /*@out@*/ char ** bp, + /*@null@*/ /*@out@*/ size_t * nbp, int flags) + /*@globals errno, fileSystem, internalState @*/ + /*@modifies *bp, *nbp, errno, fileSystem, internalState @*/; +#define POPT_READFILE_TRIMNEWLINES 1 + +/** \ingroup popt + * Read configuration file. + * @param con context + * @param fn file name to read + * @return 0 on success, POPT_ERROR_ERRNO on failure + */ +int poptReadConfigFile(poptContext con, const char * fn) + /*@globals errno, fileSystem, internalState @*/ + /*@modifies con->execs, con->numExecs, + errno, fileSystem, internalState @*/; + +/** \ingroup popt + * Read configuration file(s). + * Colon separated files to read, looping over poptReadConfigFile(). + * Note that an '@' character preceeding a path in the list will + * also perform additional sanity checks on the file before reading. + * @param con context + * @param paths colon separated file name(s) to read + * @return 0 on success, POPT_ERROR_BADCONFIG on failure + */ +int poptReadConfigFiles(poptContext con, /*@null@*/ const char * paths) + /*@globals errno, fileSystem, internalState @*/ + /*@modifies con->execs, con->numExecs, + errno, fileSystem, internalState @*/; + +/** \ingroup popt + * Read default configuration from /etc/popt and $HOME/.popt. + * @param con context + * @param useEnv (unused) + * @return 0 on success, POPT_ERROR_ERRNO on failure + */ +/*@unused@*/ +int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) + /*@globals fileSystem, internalState @*/ + /*@modifies con->execs, con->numExecs, + fileSystem, internalState @*/; + +/** \ingroup popt + * Duplicate an argument array. + * @note: The argument array is malloc'd as a single area, so only argv must + * be free'd. + * + * @param argc no. of arguments + * @param argv argument array + * @retval argcPtr address of returned no. of arguments + * @retval argvPtr address of returned argument array + * @return 0 on success, POPT_ERROR_NOARG on failure + */ +int poptDupArgv(int argc, /*@null@*/ const char **argv, + /*@null@*/ /*@out@*/ int * argcPtr, + /*@null@*/ /*@out@*/ const char *** argvPtr) + /*@modifies *argcPtr, *argvPtr @*/; + +/** \ingroup popt + * Parse a string into an argument array. + * The parse allows ', ", and \ quoting, but ' is treated the same as " and + * both may include \ quotes. + * @note: The argument array is malloc'd as a single area, so only argv must + * be free'd. + * + * @param s string to parse + * @retval argcPtr address of returned no. of arguments + * @retval argvPtr address of returned argument array + */ +int poptParseArgvString(const char * s, + /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr) + /*@modifies *argcPtr, *argvPtr @*/; + +/** \ingroup popt + * Parses an input configuration file and returns an string that is a + * command line. For use with popt. You must free the return value when done. + * + * Given the file: +\verbatim +# this line is ignored + # this one too +aaa + bbb + ccc +bla=bla + +this_is = fdsafdas + bad_line= + reall bad line + reall bad line = again +5555= 55555 + test = with lots of spaces +\endverbatim +* +* The result is: +\verbatim +--aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces" +\endverbatim +* +* Passing this to poptParseArgvString() yields an argv of: +\verbatim +'--aaa' +'--bbb' +'--ccc' +'--bla=bla' +'--this_is=fdsafdas' +'--5555=55555' +'--test=with lots of spaces' +\endverbatim + * + * @bug NULL is returned if file line is too long. + * @bug Silently ignores invalid lines. + * + * @param fp file handle to read + * @param *argstrp return string of options (malloc'd) + * @param flags unused + * @return 0 on success + * @see poptParseArgvString + */ +/*@-fcnuse@*/ +int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags) + /*@globals fileSystem @*/ + /*@modifies *fp, *argstrp, fileSystem @*/; +/*@=fcnuse@*/ + +/** \ingroup popt + * Return formatted error string for popt failure. + * @param error popt error + * @return error string + */ +/*@observer@*/ +const char * poptStrerror(const int error) + /*@*/; + +/** \ingroup popt + * Limit search for executables. + * @param con context + * @param path single path to search for executables + * @param allowAbsolute absolute paths only? + */ +/*@unused@*/ +void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) + /*@modifies con @*/; + +/** \ingroup popt + * Print detailed description of options. + * @param con context + * @param fp ouput file handle + * @param flags (unused) + */ +void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags) + /*@globals fileSystem @*/ + /*@modifies fp, fileSystem @*/; + +/** \ingroup popt + * Print terse description of options. + * @param con context + * @param fp ouput file handle + * @param flags (unused) + */ +void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags) + /*@globals fileSystem @*/ + /*@modifies fp, fileSystem @*/; + +/** \ingroup popt + * Provide text to replace default "[OPTION...]" in help/usage output. + * @param con context + * @param text replacement text + */ +/*@-fcnuse@*/ +void poptSetOtherOptionHelp(poptContext con, const char * text) + /*@modifies con @*/; +/*@=fcnuse@*/ + +/** \ingroup popt + * Return argv[0] from context. + * @param con context + * @return argv[0] + */ +/*@-fcnuse@*/ +/*@observer@*/ +const char * poptGetInvocationName(poptContext con) + /*@*/; +/*@=fcnuse@*/ + +/** \ingroup popt + * Shuffle argv pointers to remove stripped args, returns new argc. + * @param con context + * @param argc no. of args + * @param argv arg vector + * @return new argc + */ +/*@-fcnuse@*/ +int poptStrippedArgv(poptContext con, int argc, char ** argv) + /*@modifies *argv @*/; +/*@=fcnuse@*/ + +/** + * Add a string to an argv array. + * @retval *argvp argv array + * @param argInfo (unused) + * @param val string arg to add (using strdup) + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@unused@*/ +int poptSaveString(/*@null@*/ const char *** argvp, unsigned int argInfo, + /*@null@*/const char * val) + /*@modifies *argvp @*/; + +/** + * Save a long long, performing logical operation with value. + * @warning Alignment check may be too strict on certain platorms. + * @param arg integer pointer, aligned on int boundary. + * @param argInfo logical operation (see POPT_ARGFLAG_*) + * @param aLongLong value to use + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@-incondefs@*/ +/*@unused@*/ +int poptSaveLongLong(/*@null@*/ long long * arg, unsigned int argInfo, + long long aLongLong) + /*@globals internalState @*/ + /*@modifies *arg, internalState @*/ + /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; +/*@=incondefs@*/ + +/** + * Save a long, performing logical operation with value. + * @warning Alignment check may be too strict on certain platorms. + * @param arg integer pointer, aligned on int boundary. + * @param argInfo logical operation (see POPT_ARGFLAG_*) + * @param aLong value to use + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@-incondefs@*/ +/*@unused@*/ +int poptSaveLong(/*@null@*/ long * arg, unsigned int argInfo, long aLong) + /*@globals internalState @*/ + /*@modifies *arg, internalState @*/ + /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; +/*@=incondefs@*/ + +/** + * Save a short integer, performing logical operation with value. + * @warning Alignment check may be too strict on certain platorms. + * @param arg short pointer, aligned on short boundary. + * @param argInfo logical operation (see POPT_ARGFLAG_*) + * @param aLong value to use + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@-incondefs@*/ +/*@unused@*/ +int poptSaveShort(/*@null@*/ short * arg, unsigned int argInfo, long aLong) + /*@globals internalState @*/ + /*@modifies *arg, internalState @*/ + /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; +/*@=incondefs@*/ + +/** + * Save an integer, performing logical operation with value. + * @warning Alignment check may be too strict on certain platorms. + * @param arg integer pointer, aligned on int boundary. + * @param argInfo logical operation (see POPT_ARGFLAG_*) + * @param aLong value to use + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@-incondefs@*/ +/*@unused@*/ +int poptSaveInt(/*@null@*/ int * arg, unsigned int argInfo, long aLong) + /*@globals internalState @*/ + /*@modifies *arg, internalState @*/ + /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; +/*@=incondefs@*/ + +/* The bit set typedef. */ +/*@-exporttype@*/ +typedef struct poptBits_s { + unsigned int bits[1]; +} * poptBits; +/*@=exporttype@*/ + +#define _POPT_BITS_N 1024U /* estimated population */ +#define _POPT_BITS_M ((3U * _POPT_BITS_N) / 2U) +#define _POPT_BITS_K 16U /* no. of linear hash combinations */ + +/*@-exportlocal -exportvar -globuse @*/ +/*@unchecked@*/ +extern unsigned int _poptBitsN; +/*@unchecked@*/ +extern unsigned int _poptBitsM; +/*@unchecked@*/ +extern unsigned int _poptBitsK; +/*@=exportlocal =exportvar =globuse @*/ + +/*@-exportlocal@*/ +int poptBitsAdd(/*@null@*/poptBits bits, /*@null@*/const char * s) + /*@modifies bits @*/; +/*@=exportlocal@*/ +int poptBitsChk(/*@null@*/poptBits bits, /*@null@*/const char * s) + /*@*/; +int poptBitsClr(/*@null@*/poptBits bits) + /*@modifies bits @*/; +/*@-exportlocal@*/ +int poptBitsDel(/*@null@*/poptBits bits, /*@null@*/const char * s) + /*@modifies bits @*/; +/*@-fcnuse@*/ +int poptBitsIntersect(/*@null@*/ poptBits * ap, /*@null@*/ const poptBits b) + /*@modifies *ap @*/; +int poptBitsUnion(/*@null@*/ poptBits * ap, /*@null@*/ const poptBits b) + /*@modifies *ap @*/; +int poptBitsArgs(/*@null@*/ poptContext con, /*@null@*/ poptBits * ap) + /*@modifies con, *ap @*/; +/*@=fcnuse@*/ +/*@=exportlocal@*/ + +/** + * Save a string into a bit set (experimental). + * @retval *bits bit set (lazily malloc'd if NULL) + * @param argInfo logical operation (see POPT_ARGFLAG_*) + * @param s string to add to bit set + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@-incondefs@*/ +/*@unused@*/ +int poptSaveBits(/*@null@*/ poptBits * bitsp, unsigned int argInfo, + /*@null@*/ const char * s) + /*@globals _poptBitsN, _poptBitsM, _poptBitsK, internalState @*/ + /*@modifies *bitsp, _poptBitsN, _poptBitsM, _poptBitsK, internalState @*/; +/*@=incondefs@*/ + +/*@=type@*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ldb-2.0.8/third_party/popt/poptconfig.c b/ldb-2.0.8/third_party/popt/poptconfig.c new file mode 100644 index 0000000..f0a92e0 --- /dev/null +++ b/ldb-2.0.8/third_party/popt/poptconfig.c @@ -0,0 +1,582 @@ +/** \ingroup popt + * \file popt/poptconfig.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.rpm.org/pub/rpm/dist. */ + +#include "system.h" +#include "poptint.h" +#include + +#if defined(HAVE_FNMATCH_H) +#include + +#if defined(__LCLINT__) +/*@-declundef -exportheader -incondefs -protoparammatch -redecl -type @*/ +extern int fnmatch (const char *__pattern, const char *__name, int __flags) + /*@*/; +/*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/ +#endif /* __LCLINT__ */ +#endif + +#if defined(HAVE_GLOB_H) +#include + +#if defined(__LCLINT__) +/*@-declundef -exportheader -incondefs -protoparammatch -redecl -type @*/ +extern int glob (const char *__pattern, int __flags, + /*@null@*/ int (*__errfunc) (const char *, int), + /*@out@*/ glob_t *__pglob) + /*@globals errno, fileSystem @*/ + /*@modifies *__pglob, errno, fileSystem @*/; + +/* XXX only annotation is a white lie */ +extern void globfree (/*@only@*/ glob_t *__pglob) + /*@modifies *__pglob @*/; + +/* XXX _GNU_SOURCE ifdef and/or retrofit is needed for portability. */ +extern int glob_pattern_p (const char *__pattern, int __quote) + /*@*/; +/*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/ +#endif /* __LCLINT__ */ + +#if !defined(__GLIBC__) +/* Return nonzero if PATTERN contains any metacharacters. + Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ +static int +glob_pattern_p (const char * pattern, int quote) + /*@*/ +{ + const char * p; + int open = 0; + + for (p = pattern; *p != '\0'; ++p) + switch (*p) { + case '?': + case '*': + return 1; + /*@notreached@*/ /*@switchbreak@*/ break; + case '\\': + if (quote && p[1] != '\0') + ++p; + /*@switchbreak@*/ break; + case '[': + open = 1; + /*@switchbreak@*/ break; + case ']': + if (open) + return 1; + /*@switchbreak@*/ break; + } + return 0; +} +#endif /* !defined(__GLIBC__) */ + +/*@unchecked@*/ +static int poptGlobFlags = 0; + +static int poptGlob_error(/*@unused@*/ UNUSED(const char * epath), + /*@unused@*/ UNUSED(int eerrno)) + /*@*/ +{ + return 1; +} +#endif /* HAVE_GLOB_H */ + +/** + * Return path(s) from a glob pattern. + * @param con context + * @param pattern glob pattern + * @retval *acp no. of paths + * @retval *avp array of paths + * @return 0 on success + */ +static int poptGlob(/*@unused@*/ UNUSED(poptContext con), const char * pattern, + /*@out@*/ int * acp, /*@out@*/ const char *** avp) + /*@modifies *acp, *avp @*/ +{ + const char * pat = pattern; + int rc = 0; /* assume success */ + + /* XXX skip the attention marker. */ + if (pat[0] == '@' && pat[1] != '(') + pat++; + +#if defined(HAVE_GLOB_H) + if (glob_pattern_p(pat, 0)) { + glob_t _g, *pglob = &_g; + + if (!glob(pat, poptGlobFlags, poptGlob_error, pglob)) { + if (acp) { + *acp = (int) pglob->gl_pathc; + pglob->gl_pathc = 0; + } + if (avp) { +/*@-onlytrans@*/ + *avp = (const char **) pglob->gl_pathv; +/*@=onlytrans@*/ + pglob->gl_pathv = NULL; + } +/*@-nullstate@*/ + globfree(pglob); +/*@=nullstate@*/ + } else + rc = POPT_ERROR_ERRNO; + } else +#endif /* HAVE_GLOB_H */ + { + if (acp) + *acp = 1; + if (avp && (*avp = calloc((size_t)(1 + 1), sizeof (**avp))) != NULL) + (*avp)[0] = xstrdup(pat); + } + + return rc; +} + +/*@access poptContext @*/ + +int poptSaneFile(const char * fn) +{ + struct stat sb; + uid_t uid = getuid(); + + if (stat(fn, &sb) == -1) + return 1; + if ((uid_t)sb.st_uid != uid) + return 0; + if (!S_ISREG(sb.st_mode)) + return 0; +/*@-bitwisesigned@*/ + if (sb.st_mode & (S_IWGRP|S_IWOTH)) + return 0; +/*@=bitwisesigned@*/ + return 1; +} + +int poptReadFile(const char * fn, char ** bp, size_t * nbp, int flags) +{ + int fdno; + char * b = NULL; + off_t nb = 0; + char * s, * t, * se; + int rc = POPT_ERROR_ERRNO; /* assume failure */ + + fdno = open(fn, O_RDONLY); + if (fdno < 0) + goto exit; + + if ((nb = lseek(fdno, 0, SEEK_END)) == (off_t)-1 + || lseek(fdno, 0, SEEK_SET) == (off_t)-1 + || (b = calloc(sizeof(*b), (size_t)nb + 1)) == NULL + || read(fdno, (char *)b, (size_t)nb) != (ssize_t)nb) + { + int oerrno = errno; + (void) close(fdno); + errno = oerrno; + goto exit; + } + if (close(fdno) == -1) + goto exit; + if (b == NULL) { + rc = POPT_ERROR_MALLOC; + goto exit; + } + rc = 0; + + /* Trim out escaped newlines. */ +/*@-bitwisesigned@*/ + if (flags & POPT_READFILE_TRIMNEWLINES) +/*@=bitwisesigned@*/ + { + for (t = b, s = b, se = b + nb; *s && s < se; s++) { + switch (*s) { + case '\\': + if (s[1] == '\n') { + s++; + continue; + } + /*@fallthrough@*/ + default: + *t++ = *s; + /*@switchbreak@*/ break; + } + } + *t++ = '\0'; + nb = (off_t)(t - b); + } + +exit: + if (rc != 0) { +/*@-usedef@*/ + if (b) + free(b); +/*@=usedef@*/ + b = NULL; + nb = 0; + } + if (bp) + *bp = b; +/*@-usereleased@*/ + else if (b) + free(b); +/*@=usereleased@*/ + if (nbp) + *nbp = (size_t)nb; +/*@-compdef -nullstate @*/ /* XXX cannot annotate char ** correctly */ + return rc; +/*@=compdef =nullstate @*/ +} + +/** + * Check for application match. + * @param con context + * @param s config application name + * return 0 if config application matches + */ +static int configAppMatch(poptContext con, const char * s) + /*@*/ +{ + int rc = 1; + + if (con->appName == NULL) /* XXX can't happen. */ + return rc; + +#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H) + if (glob_pattern_p(s, 1)) { +/*@-bitwisesigned@*/ + static int flags = FNM_PATHNAME | FNM_PERIOD; +#ifdef FNM_EXTMATCH + flags |= FNM_EXTMATCH; +#endif +/*@=bitwisesigned@*/ + rc = fnmatch(s, con->appName, flags); + } else +#endif + rc = strcmp(s, con->appName); + return rc; +} + +/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */ +static int poptConfigLine(poptContext con, char * line) + /*@globals fileSystem, internalState @*/ + /*@modifies con, fileSystem, internalState @*/ +{ + char *b = NULL; + size_t nb = 0; + char * se = line; + const char * appName; + const char * entryType; + const char * opt; + struct poptItem_s item_buf; + poptItem item = &item_buf; + int i, j; + int rc = POPT_ERROR_BADCONFIG; + + if (con->appName == NULL) + goto exit; + + memset(item, 0, sizeof(*item)); + + appName = se; + while (*se != '\0' && !_isspaceptr(se)) se++; + if (*se == '\0') + goto exit; + else + *se++ = '\0'; + + if (configAppMatch(con, appName)) goto exit; + + while (*se != '\0' && _isspaceptr(se)) se++; + entryType = se; + while (*se != '\0' && !_isspaceptr(se)) se++; + if (*se != '\0') *se++ = '\0'; + + while (*se != '\0' && _isspaceptr(se)) se++; + if (*se == '\0') goto exit; + opt = se; + while (*se != '\0' && !_isspaceptr(se)) se++; + if (opt[0] == '-' && *se == '\0') goto exit; + if (*se != '\0') *se++ = '\0'; + + while (*se != '\0' && _isspaceptr(se)) se++; + if (opt[0] == '-' && *se == '\0') goto exit; + +/*@-temptrans@*/ /* FIX: line alias is saved */ + if (opt[0] == '-' && opt[1] == '-') + item->option.longName = opt + 2; + else if (opt[0] == '-' && opt[2] == '\0') + item->option.shortName = opt[1]; + else { + const char * fn = opt; + + /* XXX handle globs and directories in fn? */ + if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0) + goto exit; + if (b == NULL || nb == 0) + goto exit; + + /* Append remaining text to the interpolated file option text. */ + if (*se != '\0') { + size_t nse = strlen(se) + 1; + if ((b = realloc(b, (nb + nse))) == NULL) /* XXX can't happen */ + goto exit; + (void) stpcpy( stpcpy(&b[nb-1], " "), se); + nb += nse; + } + se = b; + + /* Use the basename of the path as the long option name. */ + { const char * longName = strrchr(fn, '/'); + if (longName != NULL) + longName++; + else + longName = fn; + if (longName == NULL) /* XXX can't happen. */ + goto exit; + /* Single character basenames are treated as short options. */ + if (longName[1] != '\0') + item->option.longName = longName; + else + item->option.shortName = longName[0]; + } + } +/*@=temptrans@*/ + + if (poptParseArgvString(se, &item->argc, &item->argv)) goto exit; + +/*@-modobserver@*/ + item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; + for (i = 0, j = 0; i < item->argc; i++, j++) { + const char * f; + if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) { + f = item->argv[i] + sizeof("--POPTdesc="); + if (f[0] == '$' && f[1] == '"') f++; + item->option.descrip = f; + item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; + j--; + } else + if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) { + f = item->argv[i] + sizeof("--POPTargs="); + if (f[0] == '$' && f[1] == '"') f++; + item->option.argDescrip = f; + item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; + item->option.argInfo |= POPT_ARG_STRING; + j--; + } else + if (j != i) + item->argv[j] = item->argv[i]; + } + if (j != i) { + item->argv[j] = NULL; + item->argc = j; + } +/*@=modobserver@*/ + +/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */ + if (!strcmp(entryType, "alias")) + rc = poptAddItem(con, item, 0); + else if (!strcmp(entryType, "exec")) + rc = poptAddItem(con, item, 1); +/*@=nullstate@*/ +exit: + rc = 0; /* XXX for now, always return success */ + if (b) + free(b); + return rc; +} +/*@=compmempass@*/ + +int poptReadConfigFile(poptContext con, const char * fn) +{ + char * b = NULL, *be; + size_t nb = 0; + const char *se; + char *t, *te; + int rc; + int xx; + + if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0) + return (errno == ENOENT ? 0 : rc); + if (b == NULL || nb == 0) + return POPT_ERROR_BADCONFIG; + + if ((t = malloc(nb + 1)) == NULL) + goto exit; + te = t; + + be = (b + nb); + for (se = b; se < be; se++) { + switch (*se) { + case '\n': + *te = '\0'; + te = t; + while (*te && _isspaceptr(te)) te++; + if (*te && *te != '#') + xx = poptConfigLine(con, te); + /*@switchbreak@*/ break; +/*@-usedef@*/ /* XXX *se may be uninitialized */ + case '\\': + *te = *se++; + /* \ at the end of a line does not insert a \n */ + if (se < be && *se != '\n') { + te++; + *te++ = *se; + } + /*@switchbreak@*/ break; + default: + *te++ = *se; + /*@switchbreak@*/ break; +/*@=usedef@*/ + } + } + + free(t); + rc = 0; + +exit: + if (b) + free(b); + return rc; +} + +int poptReadConfigFiles(poptContext con, const char * paths) +{ + char * buf = (paths ? xstrdup(paths) : NULL); + const char * p; + char * pe; + int rc = 0; /* assume success */ + + for (p = buf; p != NULL && *p != '\0'; p = pe) { + const char ** av = NULL; + int ac = 0; + int i; + int xx; + + /* locate start of next path element */ + pe = strchr(p, ':'); + if (pe != NULL && *pe == ':') + *pe++ = '\0'; + else + pe = (char *) (p + strlen(p)); + + xx = poptGlob(con, p, &ac, &av); + + /* work-off each resulting file from the path element */ + for (i = 0; i < ac; i++) { + const char * fn = av[i]; + if (av[i] == NULL) /* XXX can't happen */ + /*@innercontinue@*/ continue; + /* XXX should '@' attention be pushed into poptReadConfigFile? */ + if (p[0] == '@' && p[1] != '(') { + if (fn[0] == '@' && fn[1] != '(') + fn++; + xx = poptSaneFile(fn); + if (!xx && rc == 0) + rc = POPT_ERROR_BADCONFIG; + /*@innercontinue@*/ continue; + } + xx = poptReadConfigFile(con, fn); + if (xx && rc == 0) + rc = xx; + free((void *)av[i]); + av[i] = NULL; + } + free(av); + av = NULL; + } + +/*@-usedef@*/ + if (buf) + free(buf); +/*@=usedef@*/ + + return rc; +} + +int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv)) +{ + static const char _popt_sysconfdir[] = POPT_SYSCONFDIR "/popt"; + static const char _popt_etc[] = "/etc/popt"; + char * home; + struct stat sb; + int rc = 0; /* assume success */ + + if (con->appName == NULL) goto exit; + + if (strcmp(_popt_sysconfdir, _popt_etc)) { + rc = poptReadConfigFile(con, _popt_sysconfdir); + if (rc) goto exit; + } + + rc = poptReadConfigFile(con, _popt_etc); + if (rc) goto exit; + +#if defined(HAVE_GLOB_H) + if (!stat("/etc/popt.d", &sb) && S_ISDIR(sb.st_mode)) { + const char ** av = NULL; + int ac = 0; + int i; + + if ((rc = poptGlob(con, "/etc/popt.d/*", &ac, &av)) == 0) { + for (i = 0; rc == 0 && i < ac; i++) { + const char * fn = av[i]; + if (fn == NULL || strstr(fn, ".rpmnew") || strstr(fn, ".rpmsave")) + continue; + if (!stat(fn, &sb)) { + if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) + continue; + } + rc = poptReadConfigFile(con, fn); + free((void *)av[i]); + av[i] = NULL; + } + free(av); + av = NULL; + } + } + if (rc) goto exit; +#endif + + if ((home = getenv("HOME"))) { + char * fn = malloc(strlen(home) + 20); + if (fn != NULL) { + (void) stpcpy(stpcpy(fn, home), "/.popt"); + rc = poptReadConfigFile(con, fn); + free(fn); + } else + rc = POPT_ERROR_ERRNO; + if (rc) goto exit; + } + +exit: + return rc; +} + +poptContext +poptFini(poptContext con) +{ + return poptFreeContext(con); +} + +poptContext +poptInit(int argc, const char ** argv, + const struct poptOption * options, const char * configPaths) +{ + poptContext con = NULL; + const char * argv0; + + if (argv == NULL || argv[0] == NULL || options == NULL) + return con; + + if ((argv0 = strrchr(argv[0], '/')) != NULL) argv0++; + else argv0 = argv[0]; + + con = poptGetContext(argv0, argc, (const char **)argv, options, 0); + if (con != NULL&& poptReadConfigFiles(con, configPaths)) + con = poptFini(con); + + return con; +} diff --git a/ldb-2.0.8/third_party/popt/popthelp.c b/ldb-2.0.8/third_party/popt/popthelp.c new file mode 100644 index 0000000..0d8548b --- /dev/null +++ b/ldb-2.0.8/third_party/popt/popthelp.c @@ -0,0 +1,925 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/** \ingroup popt + * \file popt/popthelp.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.rpm.org/pub/rpm/dist. */ + +#include "system.h" + +#define POPT_USE_TIOCGWINSZ +#ifdef POPT_USE_TIOCGWINSZ +#include +#endif + +#define POPT_WCHAR_HACK +#ifdef POPT_WCHAR_HACK +#include /* for mbsrtowcs */ +/*@access mbstate_t @*/ +#endif +#include "poptint.h" + +/*@access poptContext@*/ + +/** + * Display arguments. + * @param con context + * @param foo (unused) + * @param key option(s) + * @param arg (unused) + * @param data (unused) + */ +/*@exits@*/ +static void displayArgs(poptContext con, + /*@unused@*/ UNUSED(enum poptCallbackReason foo), + struct poptOption * key, + /*@unused@*/ UNUSED(const char * arg), + /*@unused@*/ UNUSED(void * data)) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ +{ + if (key->shortName == '?') + poptPrintHelp(con, stdout, 0); + else + poptPrintUsage(con, stdout, 0); + +#if !defined(__LCLINT__) /* XXX keep both splint & valgrind happy */ + con = poptFreeContext(con); +#endif + exit(0); +} + +#ifdef NOTYET +/*@unchecked@*/ +static int show_option_defaults = 0; +#endif + +/** + * Empty table marker to enable displaying popt alias/exec options. + */ +/*@observer@*/ /*@unchecked@*/ +struct poptOption poptAliasOptions[] = { + POPT_TABLEEND +}; + +/** + * Auto help table options. + */ +/*@-castfcnptr@*/ +/*@observer@*/ /*@unchecked@*/ +struct poptOption poptHelpOptions[] = { + { NULL, '\0', POPT_ARG_CALLBACK, (void *)displayArgs, 0, NULL, NULL }, + { "help", '?', 0, NULL, (int)'?', N_("Show this help message"), NULL }, + { "usage", '\0', 0, NULL, (int)'u', N_("Display brief usage message"), NULL }, + POPT_TABLEEND +} ; + +/*@observer@*/ /*@unchecked@*/ +static struct poptOption poptHelpOptions2[] = { +/*@-readonlytrans@*/ + { NULL, '\0', POPT_ARG_INTL_DOMAIN, PACKAGE, 0, NULL, NULL}, +/*@=readonlytrans@*/ + { NULL, '\0', POPT_ARG_CALLBACK, (void *)displayArgs, 0, NULL, NULL }, + { "help", '?', 0, NULL, (int)'?', N_("Show this help message"), NULL }, + { "usage", '\0', 0, NULL, (int)'u', N_("Display brief usage message"), NULL }, +#ifdef NOTYET + { "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0, + N_("Display option defaults in message"), NULL }, +#endif + { "", '\0', 0, NULL, 0, N_("Terminate options"), NULL }, + POPT_TABLEEND +} ; + +/*@observer@*/ /*@unchecked@*/ +struct poptOption * poptHelpOptionsI18N = poptHelpOptions2; +/*@=castfcnptr@*/ + +#define _POPTHELP_MAXLINE ((size_t)79) + +typedef struct columns_s { + size_t cur; + size_t max; +} * columns_t; + +/** + * Return no. of columns in output window. + * @param fp FILE + * @return no. of columns + */ +static size_t maxColumnWidth(FILE *fp) + /*@*/ +{ + size_t maxcols = _POPTHELP_MAXLINE; +#if defined(TIOCGWINSZ) + struct winsize ws; + int fdno = fileno(fp ? fp : stdout); + + memset(&ws, 0, sizeof(ws)); + if (fdno >= 0 && !ioctl(fdno, (unsigned long)TIOCGWINSZ, &ws)) { + size_t ws_col = (size_t)ws.ws_col; + if (ws_col > maxcols && ws_col < (size_t)256) + maxcols = ws_col - 1; + } +#endif + return maxcols; +} + +/** + * Determine number of display characters in a string. + * @param s string + * @return no. of display characters. + */ +static inline size_t stringDisplayWidth(const char *s) + /*@*/ +{ + size_t n = strlen(s); +#ifdef POPT_WCHAR_HACK + mbstate_t t; + + memset ((void *)&t, 0, sizeof (t)); /* In initial state. */ + /* Determine number of display characters. */ + n = mbsrtowcs (NULL, &s, n, &t); +#else + n = 0; + for (; *s; s = POPT_next_char(s)) + n++; +#endif + + return n; +} + +/** + * @param opt option(s) + */ +/*@observer@*/ /*@null@*/ static const char * +getTableTranslationDomain(/*@null@*/ const struct poptOption *opt) + /*@*/ +{ + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + if (opt->argInfo == POPT_ARG_INTL_DOMAIN) + return opt->arg; + } + return NULL; +} + +/** + * @param opt option(s) + * @param translation_domain translation domain + */ +/*@observer@*/ /*@null@*/ static const char * +getArgDescrip(const struct poptOption * opt, + /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ + /*@null@*/ const char * translation_domain) + /*@=paramuse@*/ + /*@*/ +{ + if (!poptArgType(opt)) return NULL; + + if (poptArgType(opt) == POPT_ARG_MAINCALL) + return opt->argDescrip; + if (poptArgType(opt) == POPT_ARG_ARGV) + return opt->argDescrip; + + if (opt->argDescrip) { + /* Some strings need popt library, not application, i18n domain. */ + if (opt == (poptHelpOptions + 1) + || opt == (poptHelpOptions + 2) + || !strcmp(opt->argDescrip, N_("Help options:")) + || !strcmp(opt->argDescrip, N_("Options implemented via popt alias/exec:"))) + return POPT_(opt->argDescrip); + + /* Use the application i18n domain. */ + return D_(translation_domain, opt->argDescrip); + } + + switch (poptArgType(opt)) { + case POPT_ARG_NONE: return POPT_("NONE"); +#ifdef DYING + case POPT_ARG_VAL: return POPT_("VAL"); +#else + case POPT_ARG_VAL: return NULL; +#endif + case POPT_ARG_INT: return POPT_("INT"); + case POPT_ARG_SHORT: return POPT_("SHORT"); + case POPT_ARG_LONG: return POPT_("LONG"); + case POPT_ARG_LONGLONG: return POPT_("LONGLONG"); + case POPT_ARG_STRING: return POPT_("STRING"); + case POPT_ARG_FLOAT: return POPT_("FLOAT"); + case POPT_ARG_DOUBLE: return POPT_("DOUBLE"); + case POPT_ARG_MAINCALL: return NULL; + case POPT_ARG_ARGV: return NULL; + default: return POPT_("ARG"); + } +} + +/** + * Display default value for an option. + * @param lineLength display positions remaining + * @param opt option(s) + * @param translation_domain translation domain + * @return + */ +static /*@only@*/ /*@null@*/ char * +singleOptionDefaultValue(size_t lineLength, + const struct poptOption * opt, + /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ + /*@null@*/ const char * translation_domain) + /*@=paramuse@*/ + /*@*/ +{ + const char * defstr = D_(translation_domain, "default"); + char * le = malloc(4*lineLength + 1); + char * l = le; + + if (le == NULL) return NULL; /* XXX can't happen */ + *le = '\0'; + *le++ = '('; + le = stpcpy(le, defstr); + *le++ = ':'; + *le++ = ' '; + if (opt->arg) { /* XXX programmer error */ + poptArg arg = { .ptr = opt->arg }; + switch (poptArgType(opt)) { + case POPT_ARG_VAL: + case POPT_ARG_INT: + le += sprintf(le, "%d", arg.intp[0]); + break; + case POPT_ARG_SHORT: + le += sprintf(le, "%hd", arg.shortp[0]); + break; + case POPT_ARG_LONG: + le += sprintf(le, "%ld", arg.longp[0]); + break; + case POPT_ARG_LONGLONG: + le += sprintf(le, "%lld", arg.longlongp[0]); + break; + case POPT_ARG_FLOAT: + { double aDouble = (double) arg.floatp[0]; + le += sprintf(le, "%g", aDouble); + } break; + case POPT_ARG_DOUBLE: + le += sprintf(le, "%g", arg.doublep[0]); + break; + case POPT_ARG_MAINCALL: + le += sprintf(le, "%p", opt->arg); + break; + case POPT_ARG_ARGV: + le += sprintf(le, "%p", opt->arg); + break; + case POPT_ARG_STRING: + { const char * s = arg.argv[0]; + if (s == NULL) + le = stpcpy(le, "null"); + else { + size_t limit = 4*lineLength - (le - l) - sizeof("\"\")"); + size_t slen; + *le++ = '"'; + strncpy(le, s, limit); le[limit] = '\0'; le += (slen = strlen(le)); + if (slen == limit && s[limit]) + le[-1] = le[-2] = le[-3] = '.'; + *le++ = '"'; + } + } break; + case POPT_ARG_NONE: + default: + l = _free(l); + return NULL; + /*@notreached@*/ break; + } + } + *le++ = ')'; + *le = '\0'; + + return l; +} + +/** + * Display help text for an option. + * @param fp output file handle + * @param columns output display width control + * @param opt option(s) + * @param translation_domain translation domain + */ +static void singleOptionHelp(FILE * fp, columns_t columns, + const struct poptOption * opt, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies fp, fileSystem @*/ +{ + size_t maxLeftCol = columns->cur; + size_t indentLength = maxLeftCol + 5; + size_t lineLength = columns->max - indentLength; + const char * help = D_(translation_domain, opt->descrip); + const char * argDescrip = getArgDescrip(opt, translation_domain); + /* Display shortName iff printable non-space. */ + int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' '); + size_t helpLength; + char * defs = NULL; + char * left; + size_t nb = maxLeftCol + 1; + int displaypad = 0; + int xx; + + /* Make sure there's more than enough room in target buffer. */ + if (opt->longName) nb += strlen(opt->longName); + if (F_ISSET(opt, TOGGLE)) nb += sizeof("[no]") - 1; + if (argDescrip) nb += strlen(argDescrip); + + left = malloc(nb); + if (left == NULL) return; /* XXX can't happen */ + left[0] = '\0'; + left[maxLeftCol] = '\0'; + +#define prtlong (opt->longName != NULL) /* XXX splint needs a clue */ + if (!(prtshort || prtlong)) + goto out; + if (prtshort && prtlong) { + char *dash = F_ISSET(opt, ONEDASH) ? "-" : "--"; + left[0] = '-'; + left[1] = opt->shortName; + (void) stpcpy(stpcpy(stpcpy(left+2, ", "), dash), opt->longName); + } else if (prtshort) { + left[0] = '-'; + left[1] = opt->shortName; + left[2] = '\0'; + } else if (prtlong) { + /* XXX --long always padded for alignment with/without "-X, ". */ + char *dash = poptArgType(opt) == POPT_ARG_MAINCALL ? "" + : (F_ISSET(opt, ONEDASH) ? "-" : "--"); + const char *longName = opt->longName; + const char *toggle; + if (F_ISSET(opt, TOGGLE)) { + toggle = "[no]"; + if (longName[0] == 'n' && longName[1] == 'o') { + longName += sizeof("no") - 1; + if (longName[0] == '-') + longName++; + } + } else + toggle = ""; + (void) stpcpy(stpcpy(stpcpy(stpcpy(left, " "), dash), toggle), longName); + } +#undef prtlong + + if (argDescrip) { + char * le = left + strlen(left); + + if (F_ISSET(opt, OPTIONAL)) + *le++ = '['; + + /* Choose type of output */ + if (F_ISSET(opt, SHOW_DEFAULT)) { + defs = singleOptionDefaultValue(lineLength, opt, translation_domain); + if (defs) { + char * t = malloc((help ? strlen(help) : 0) + + strlen(defs) + sizeof(" ")); + if (t) { + char * te = t; + if (help) + te = stpcpy(te, help); + *te++ = ' '; + strcpy(te, defs); + defs = _free(defs); + defs = t; + } + } + } + + if (opt->argDescrip == NULL) { + switch (poptArgType(opt)) { + case POPT_ARG_NONE: + break; + case POPT_ARG_VAL: +#ifdef NOTNOW /* XXX pug ugly nerdy output */ + { long aLong = opt->val; + int ops = F_ISSET(opt, LOGICALOPS); + int negate = F_ISSET(opt, NOT); + + /* Don't bother displaying typical values */ + if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L)) + break; + *le++ = '['; + switch (ops) { + case POPT_ARGFLAG_OR: + *le++ = '|'; + /*@innerbreak@*/ break; + case POPT_ARGFLAG_AND: + *le++ = '&'; + /*@innerbreak@*/ break; + case POPT_ARGFLAG_XOR: + *le++ = '^'; + /*@innerbreak@*/ break; + default: + /*@innerbreak@*/ break; + } + *le++ = (opt->longName != NULL ? '=' : ' '); + if (negate) *le++ = '~'; + /*@-formatconst@*/ + le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong); + /*@=formatconst@*/ + *le++ = ']'; + } +#endif + break; + case POPT_ARG_INT: + case POPT_ARG_SHORT: + case POPT_ARG_LONG: + case POPT_ARG_LONGLONG: + case POPT_ARG_FLOAT: + case POPT_ARG_DOUBLE: + case POPT_ARG_STRING: + *le++ = (opt->longName != NULL ? '=' : ' '); + le = stpcpy(le, argDescrip); + break; + default: + break; + } + } else { + char *leo; + + /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */ + if (!strchr(" =(", argDescrip[0])) + *le++ = ((poptArgType(opt) == POPT_ARG_MAINCALL) ? ' ' : + (poptArgType(opt) == POPT_ARG_ARGV) ? ' ' : '='); + le = stpcpy(leo = le, argDescrip); + + /* Adjust for (possible) wide characters. */ + displaypad = (int)((le - leo) - stringDisplayWidth(argDescrip)); + } + if (F_ISSET(opt, OPTIONAL)) + *le++ = ']'; + *le = '\0'; + } + + if (help) + xx = POPT_fprintf(fp," %-*s ", (int)(maxLeftCol+displaypad), left); + else { + xx = POPT_fprintf(fp," %s\n", left); + goto out; + } + + left = _free(left); + if (defs) + help = defs; + + helpLength = strlen(help); + while (helpLength > lineLength) { + const char * ch; + char format[16]; + + ch = help + lineLength - 1; + while (ch > help && !_isspaceptr(ch)) + ch = POPT_prev_char(ch); + if (ch == help) break; /* give up */ + while (ch > (help + 1) && _isspaceptr(ch)) + ch = POPT_prev_char (ch); + ch = POPT_next_char(ch); + + /* + * XXX strdup is necessary to add NUL terminator so that an unknown + * no. of (possible) multi-byte characters can be displayed. + */ + { char * fmthelp = xstrdup(help); + if (fmthelp) { + fmthelp[ch - help] = '\0'; + sprintf(format, "%%s\n%%%ds", (int) indentLength); + /*@-formatconst@*/ + xx = POPT_fprintf(fp, format, fmthelp, " "); + /*@=formatconst@*/ + free(fmthelp); + } + } + + help = ch; + while (_isspaceptr(help) && *help) + help = POPT_next_char(help); + helpLength = strlen(help); + } + + if (helpLength) fprintf(fp, "%s\n", help); + help = NULL; + +out: + /*@-dependenttrans@*/ + defs = _free(defs); + /*@=dependenttrans@*/ + left = _free(left); +} + +/** + * Find display width for longest argument string. + * @param opt option(s) + * @param translation_domain translation domain + * @return display width + */ +static size_t maxArgWidth(const struct poptOption * opt, + /*@null@*/ const char * translation_domain) + /*@*/ +{ + size_t max = 0; + size_t len = 0; + const char * argDescrip; + + if (opt != NULL) + while (opt->longName || opt->shortName || opt->arg) { + if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) { + if (opt->arg) /* XXX program error */ + len = maxArgWidth(opt->arg, translation_domain); + if (len > max) max = len; + } else if (!F_ISSET(opt, DOC_HIDDEN)) { + len = sizeof(" ")-1; + /* XXX --long always padded for alignment with/without "-X, ". */ + len += sizeof("-X, ")-1; + if (opt->longName) { + len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1; + len += strlen(opt->longName); + } + + argDescrip = getArgDescrip(opt, translation_domain); + + if (argDescrip) { + + /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */ + if (!strchr(" =(", argDescrip[0])) len += sizeof("=")-1; + + /* Adjust for (possible) wide characters. */ + len += stringDisplayWidth(argDescrip); + } + + if (F_ISSET(opt, OPTIONAL)) len += sizeof("[]")-1; + if (len > max) max = len; + } + opt++; + } + + return max; +} + +/** + * Display popt alias and exec help. + * @param fp output file handle + * @param items alias/exec array + * @param nitems no. of alias/exec entries + * @param columns output display width control + * @param translation_domain translation domain + */ +static void itemHelp(FILE * fp, + /*@null@*/ poptItem items, int nitems, + columns_t columns, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies fp, fileSystem @*/ +{ + poptItem item; + int i; + + if (items != NULL) + for (i = 0, item = items; i < nitems; i++, item++) { + const struct poptOption * opt; + opt = &item->option; + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) + singleOptionHelp(fp, columns, opt, translation_domain); + } +} + +/** + * Display help text for a table of options. + * @param con context + * @param fp output file handle + * @param table option(s) + * @param columns output display width control + * @param translation_domain translation domain + */ +static void singleTableHelp(poptContext con, FILE * fp, + /*@null@*/ const struct poptOption * table, + columns_t columns, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies fp, columns->cur, fileSystem @*/ +{ + const struct poptOption * opt; + const char *sub_transdom; + int xx; + + if (table == poptAliasOptions) { + itemHelp(fp, con->aliases, con->numAliases, columns, NULL); + itemHelp(fp, con->execs, con->numExecs, columns, NULL); + return; + } + + if (table != NULL) + for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) { + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) + singleOptionHelp(fp, columns, opt, translation_domain); + } + + if (table != NULL) + for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) { + if (poptArgType(opt) != POPT_ARG_INCLUDE_TABLE) + continue; + sub_transdom = getTableTranslationDomain(opt->arg); + if (sub_transdom == NULL) + sub_transdom = translation_domain; + + /* If no popt aliases/execs, skip poptAliasOption processing. */ + if (opt->arg == poptAliasOptions && !(con->numAliases || con->numExecs)) + continue; + if (opt->descrip) + xx = POPT_fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip)); + + singleTableHelp(con, fp, opt->arg, columns, sub_transdom); + } +} + +/** + * @param con context + * @param fp output file handle + */ +static size_t showHelpIntro(poptContext con, FILE * fp) + /*@globals fileSystem @*/ + /*@modifies fp, fileSystem @*/ +{ + size_t len = (size_t)6; + int xx; + + xx = POPT_fprintf(fp, POPT_("Usage:")); + if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { + struct optionStackEntry * os = con->optionStack; + const char * fn = (os->argv ? os->argv[0] : NULL); + if (fn == NULL) return len; + if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1; + /* XXX POPT_fprintf not needed for argv[0] display. */ + fprintf(fp, " %s", fn); + len += strlen(fn) + 1; + } + + return len; +} + +void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags)) +{ + columns_t columns = calloc((size_t)1, sizeof(*columns)); + int xx; + + (void) showHelpIntro(con, fp); + if (con->otherHelp) + xx = POPT_fprintf(fp, " %s\n", con->otherHelp); + else + xx = POPT_fprintf(fp, " %s\n", POPT_("[OPTION...]")); + + if (columns) { + columns->cur = maxArgWidth(con->options, NULL); + columns->max = maxColumnWidth(fp); + singleTableHelp(con, fp, con->options, columns, NULL); + free(columns); + } +} + +/** + * Display usage text for an option. + * @param fp output file handle + * @param columns output display width control + * @param opt option(s) + * @param translation_domain translation domain + */ +static size_t singleOptionUsage(FILE * fp, columns_t columns, + const struct poptOption * opt, + /*@null@*/ const char *translation_domain) + /*@globals fileSystem @*/ + /*@modifies fp, columns->cur, fileSystem @*/ +{ + size_t len = sizeof(" []")-1; + const char * argDescrip = getArgDescrip(opt, translation_domain); + /* Display shortName iff printable non-space. */ + int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' '); + +#define prtlong (opt->longName != NULL) /* XXX splint needs a clue */ + if (!(prtshort || prtlong)) + return columns->cur; + + len = sizeof(" []")-1; + if (prtshort) + len += sizeof("-c")-1; + if (prtlong) { + if (prtshort) len += sizeof("|")-1; + len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1; + len += strlen(opt->longName); + } + + if (argDescrip) { + + /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */ + if (!strchr(" =(", argDescrip[0])) len += sizeof("=")-1; + + /* Adjust for (possible) wide characters. */ + len += stringDisplayWidth(argDescrip); + } + + if ((columns->cur + len) > columns->max) { + fprintf(fp, "\n "); + columns->cur = (size_t)7; + } + + fprintf(fp, " ["); + if (prtshort) + fprintf(fp, "-%c", opt->shortName); + if (prtlong) + fprintf(fp, "%s%s%s", + (prtshort ? "|" : ""), + (F_ISSET(opt, ONEDASH) ? "-" : "--"), + opt->longName); +#undef prtlong + + if (argDescrip) { + /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */ + if (!strchr(" =(", argDescrip[0])) fprintf(fp, "="); + fprintf(fp, "%s", argDescrip); + } + fprintf(fp, "]"); + + return columns->cur + len + 1; +} + +/** + * Display popt alias and exec usage. + * @param fp output file handle + * @param columns output display width control + * @param item alias/exec array + * @param nitems no. of ara/exec entries + * @param translation_domain translation domain + */ +static size_t itemUsage(FILE * fp, columns_t columns, + /*@null@*/ poptItem item, int nitems, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies fp, columns->cur, fileSystem @*/ +{ + int i; + + if (item != NULL) + for (i = 0; i < nitems; i++, item++) { + const struct poptOption * opt; + opt = &item->option; + if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) { + translation_domain = (const char *)opt->arg; + } else + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) { + columns->cur = singleOptionUsage(fp, columns, opt, translation_domain); + } + } + + return columns->cur; +} + +/** + * Keep track of option tables already processed. + */ +typedef struct poptDone_s { + int nopts; + int maxopts; +/*@null@*/ + const void ** opts; +} * poptDone; + +/** + * Display usage text for a table of options. + * @param con context + * @param fp output file handle + * @param columns output display width control + * @param opt option(s) + * @param translation_domain translation domain + * @param done tables already processed + * @return + */ +static size_t singleTableUsage(poptContext con, FILE * fp, columns_t columns, + /*@null@*/ const struct poptOption * opt, + /*@null@*/ const char * translation_domain, + /*@null@*/ poptDone done) + /*@globals fileSystem @*/ + /*@modifies fp, columns->cur, done, fileSystem @*/ +{ + if (opt != NULL) + for (; (opt->longName || opt->shortName || opt->arg) ; opt++) { + if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) { + translation_domain = (const char *)opt->arg; + } else + if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) { + if (done) { + int i = 0; + if (done->opts != NULL) + for (i = 0; i < done->nopts; i++) { + const void * that = done->opts[i]; + if (that == NULL || that != opt->arg) + /*@innercontinue@*/ continue; + /*@innerbreak@*/ break; + } + /* Skip if this table has already been processed. */ + if (opt->arg == NULL || i < done->nopts) + continue; + if (done->opts != NULL && done->nopts < done->maxopts) + done->opts[done->nopts++] = (const void *) opt->arg; + } + columns->cur = singleTableUsage(con, fp, columns, opt->arg, + translation_domain, done); + } else + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) { + columns->cur = singleOptionUsage(fp, columns, opt, translation_domain); + } + } + + return columns->cur; +} + +/** + * Return concatenated short options for display. + * @todo Sub-tables should be recursed. + * @param opt option(s) + * @param fp output file handle + * @retval str concatenation of short options + * @return length of display string + */ +static size_t showShortOptions(const struct poptOption * opt, FILE * fp, + /*@null@*/ char * str) + /*@globals fileSystem @*/ + /*@modifies str, *fp, fileSystem @*/ + /*@requires maxRead(str) >= 0 @*/ +{ + /* bufsize larger then the ascii set, lazy allocation on top level call. */ + size_t nb = (size_t)300; + char * s = (str != NULL ? str : calloc((size_t)1, nb)); + size_t len = (size_t)0; + + if (s == NULL) + return 0; + + if (opt != NULL) + for (; (opt->longName || opt->shortName || opt->arg); opt++) { + if (!F_ISSET(opt, DOC_HIDDEN) && opt->shortName && !poptArgType(opt)) + { + /* Display shortName iff unique printable non-space. */ + if (!strchr(s, opt->shortName) && isprint((int)opt->shortName) + && opt->shortName != ' ') + s[strlen(s)] = opt->shortName; + } else if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) + if (opt->arg) /* XXX program error */ + len = showShortOptions(opt->arg, fp, s); + } + + /* On return to top level, print the short options, return print length. */ + if (s != str && *s != '\0') { + fprintf(fp, " [-%s]", s); + len = strlen(s) + sizeof(" [-]")-1; + } +/*@-temptrans@*/ /* LCL: local s, not str arg, is being freed. */ + if (s != str) + free(s); +/*@=temptrans@*/ + return len; +} + +void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags)) +{ + columns_t columns = calloc((size_t)1, sizeof(*columns)); + struct poptDone_s done_buf; + poptDone done = &done_buf; + + memset(done, 0, sizeof(*done)); + done->nopts = 0; + done->maxopts = 64; + if (columns) { + columns->cur = done->maxopts * sizeof(*done->opts); + columns->max = maxColumnWidth(fp); + done->opts = calloc((size_t)1, columns->cur); + /*@-keeptrans@*/ + if (done->opts != NULL) + done->opts[done->nopts++] = (const void *) con->options; + /*@=keeptrans@*/ + + columns->cur = showHelpIntro(con, fp); + columns->cur += showShortOptions(con->options, fp, NULL); + columns->cur = singleTableUsage(con, fp, columns, con->options, NULL, done); + columns->cur = itemUsage(fp, columns, con->aliases, con->numAliases, NULL); + columns->cur = itemUsage(fp, columns, con->execs, con->numExecs, NULL); + + if (con->otherHelp) { + columns->cur += strlen(con->otherHelp) + 1; + if (columns->cur > columns->max) fprintf(fp, "\n "); + fprintf(fp, " %s", con->otherHelp); + } + + fprintf(fp, "\n"); + if (done->opts != NULL) + free(done->opts); + free(columns); + } +} + +void poptSetOtherOptionHelp(poptContext con, const char * text) +{ + con->otherHelp = _free(con->otherHelp); + con->otherHelp = xstrdup(text); +} diff --git a/ldb-2.0.8/third_party/popt/poptint.c b/ldb-2.0.8/third_party/popt/poptint.c new file mode 100644 index 0000000..1af46ff --- /dev/null +++ b/ldb-2.0.8/third_party/popt/poptint.c @@ -0,0 +1,199 @@ +#include "system.h" +#include +#include "poptint.h" + +/* Any pair of 32 bit hashes can be used. lookup3.c generates pairs, will do. */ +#define _JLU3_jlu32lpair 1 +#define jlu32lpair poptJlu32lpair +#include "lookup3.c" + +/*@-varuse +charint +ignoresigns @*/ +/*@unchecked@*/ /*@observer@*/ +static const unsigned char utf8_skip_data[256] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1 +}; +/*@=varuse =charint =ignoresigns @*/ + +const char * +POPT_prev_char (const char *str) +{ + const char *p = str; + + while (1) { + p--; + if (((unsigned)*p & 0xc0) != (unsigned)0x80) + return p; + } +} + +const char * +POPT_next_char (const char *str) +{ + const char *p = str; + + while (*p != '\0') { + p++; + if (((unsigned)*p & 0xc0) != (unsigned)0x80) + break; + } + return p; +} + +#if !defined(POPT_fprintf) /* XXX lose all the goop ... */ + +#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) +/* + * Rebind a "UTF-8" codeset for popt's internal use. + */ +char * +POPT_dgettext(const char * dom, const char * str) +{ + char * codeset = NULL; + char * retval = NULL; + + if (!dom) + dom = textdomain(NULL); + codeset = bind_textdomain_codeset(dom, NULL); + bind_textdomain_codeset(dom, "UTF-8"); + retval = dgettext(dom, str); + bind_textdomain_codeset(dom, codeset); + + return retval; +} +#endif + +#ifdef HAVE_ICONV +/** + * Return malloc'd string converted from UTF-8 to current locale. + * @param istr input string (UTF-8 encoding assumed) + * @return localized string + */ +static /*@only@*/ /*@null@*/ char * +strdup_locale_from_utf8 (/*@null@*/ char * istr) + /*@*/ +{ + char * codeset = NULL; + char * ostr = NULL; + iconv_t cd; + + if (istr == NULL) + return NULL; + +#ifdef HAVE_LANGINFO_H + codeset = nl_langinfo ((nl_item)CODESET); +#endif + + if (codeset != NULL && strcmp(codeset, "UTF-8") != 0 + && (cd = iconv_open(codeset, "UTF-8")) != (iconv_t)-1) + { + char * shift_pin = NULL; + size_t db = strlen(istr); +/*@owned@*/ + char * dstr = malloc((db + 1) * sizeof(*dstr)); + char * pin = istr; + char * pout = dstr; + size_t ib = db; + size_t ob = db; + size_t err; + + if (dstr == NULL) + return NULL; + err = iconv(cd, NULL, NULL, NULL, NULL); + while (1) { + *pout = '\0'; + err = iconv(cd, &pin, &ib, &pout, &ob); + if (err != (size_t)-1) { + if (shift_pin == NULL) { + shift_pin = pin; + pin = NULL; + ib = 0; + continue; + } + } else + switch (errno) { + case E2BIG: + { size_t used = (size_t)(pout - dstr); + db *= 2; + dstr = realloc(dstr, (db + 1) * sizeof(*dstr)); + if (dstr != NULL) { + pout = dstr + used; + ob = db - used; + continue; + } + } /*@switchbreak@*/ break; + case EINVAL: + case EILSEQ: + default: + /*@switchbreak@*/ break; + } + break; + } + (void) iconv_close(cd); + *pout = '\0'; + ostr = xstrdup(dstr); + free(dstr); + } else + ostr = xstrdup(istr); + + return ostr; +} +#endif + +int +POPT_fprintf (FILE * stream, const char * format, ...) +{ + char * b = NULL, * ob = NULL; + int rc; + va_list ap; + +#if defined(HAVE_VASPRINTF) && !defined(__LCLINT__) + va_start(ap, format); + if ((rc = vasprintf(&b, format, ap)) < 0) + b = NULL; + va_end(ap); +#else + size_t nb = (size_t)1; + + /* HACK: add +1 to the realloc no. of bytes "just in case". */ + /* XXX Likely unneeded, the issues wrto vsnprintf(3) return b0rkage have + * to do with whether the final '\0' is counted (or not). The code + * below already adds +1 for the (possibly already counted) trailing NUL. + */ + while ((b = realloc(b, nb+1)) != NULL) { + va_start(ap, format); + rc = vsnprintf(b, nb, format, ap); + va_end(ap); + if (rc > -1) { /* glibc 2.1 */ + if ((size_t)rc < nb) + break; + nb = (size_t)(rc + 1); /* precise buffer length known */ + } else /* glibc 2.0 */ + nb += (nb < (size_t)100 ? (size_t)100 : nb); + ob = b; + } +#endif + + rc = 0; + if (b != NULL) { +#ifdef HAVE_ICONV + ob = strdup_locale_from_utf8(b); + if (ob != NULL) { + rc = fprintf(stream, "%s", ob); + free(ob); + } else +#endif + rc = fprintf(stream, "%s", b); + free (b); + } + + return rc; +} + +#endif /* !defined(POPT_fprintf) */ diff --git a/ldb-2.0.8/third_party/popt/poptint.h b/ldb-2.0.8/third_party/popt/poptint.h new file mode 100644 index 0000000..80cbaca --- /dev/null +++ b/ldb-2.0.8/third_party/popt/poptint.h @@ -0,0 +1,222 @@ +/** \ingroup popt + * \file popt/poptint.h + */ + +/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.rpm.org/pub/rpm/dist. */ + +#ifndef H_POPTINT +#define H_POPTINT + +#include + +/** + * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL. + * @param p memory to free + * @retval NULL always + */ +/*@unused@*/ static inline /*@null@*/ void * +_free(/*@only@*/ /*@null@*/ const void * p) + /*@modifies p @*/ +{ + if (p != NULL) free((void *)p); + return NULL; +} + +/* Bit mask macros. */ +/*@-exporttype -redef @*/ +typedef unsigned int __pbm_bits; +/*@=exporttype =redef @*/ +#define __PBM_NBITS (8 * sizeof (__pbm_bits)) +#define __PBM_IX(d) ((d) / __PBM_NBITS) +#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS)) +/*@-exporttype -redef @*/ +typedef struct { + __pbm_bits bits[1]; +} pbm_set; +/*@=exporttype =redef @*/ +#define __PBM_BITS(set) ((set)->bits) + +#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) +#define PBM_FREE(s) _free(s); +#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) +#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d)) +#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0) + +extern void poptJlu32lpair(/*@null@*/ const void *key, size_t size, + uint32_t *pc, uint32_t *pb) + /*@modifies *pc, *pb@*/; + +/** \ingroup popt + * Typedef's for string and array of strings. + */ +/*@-exporttype@*/ +typedef const char * poptString; +typedef poptString * poptArgv; +/*@=exporttype@*/ + +/** \ingroup popt + * A union to simplify opt->arg access without casting. + */ +/*@-exporttype -fielduse@*/ +typedef union poptArg_u { +/*@shared@*/ + void * ptr; + int * intp; + short * shortp; + long * longp; + long long * longlongp; + float * floatp; + double * doublep; + const char ** argv; + poptCallbackType cb; +/*@shared@*/ + poptOption opt; +} poptArg; +/*@=exporttype =fielduse@*/ + +/*@-exportvar@*/ +/*@unchecked@*/ +extern unsigned int _poptArgMask; +/*@unchecked@*/ +extern unsigned int _poptGroupMask; +/*@=exportvar@*/ + +#define poptArgType(_opt) ((_opt)->argInfo & _poptArgMask) +#define poptGroup(_opt) ((_opt)->argInfo & _poptGroupMask) + +#define F_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_ARGFLAG_##_FLAG) +#define LF_ISSET(_FLAG) (argInfo & POPT_ARGFLAG_##_FLAG) +#define CBF_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_CBFLAG_##_FLAG) + +/* XXX sick hack to preserve pretense of a popt-1.x ABI. */ +#define poptSubstituteHelpI18N(opt) \ + { /*@-observertrans@*/ \ + if ((opt) == poptHelpOptions) (opt) = poptHelpOptionsI18N; \ + /*@=observertrans@*/ } + +struct optionStackEntry { + int argc; +/*@only@*/ /*@null@*/ + poptArgv argv; +/*@only@*/ /*@null@*/ + pbm_set * argb; + int next; +/*@only@*/ /*@null@*/ + char * nextArg; +/*@observer@*/ /*@null@*/ + const char * nextCharArg; +/*@dependent@*/ /*@null@*/ + poptItem currAlias; + int stuffed; +}; + +struct poptContext_s { + struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; +/*@dependent@*/ + struct optionStackEntry * os; +/*@owned@*/ /*@null@*/ + poptArgv leftovers; + int numLeftovers; + int nextLeftover; +/*@keep@*/ + const struct poptOption * options; + int restLeftover; +/*@only@*/ /*@null@*/ + const char * appName; +/*@only@*/ /*@null@*/ + poptItem aliases; + int numAliases; + unsigned int flags; +/*@owned@*/ /*@null@*/ + poptItem execs; + int numExecs; +/*@only@*/ /*@null@*/ + poptArgv finalArgv; + int finalArgvCount; + int finalArgvAlloced; +/*@null@*/ + int (*maincall) (int argc, const char **argv); +/*@dependent@*/ /*@null@*/ + poptItem doExec; +/*@only@*/ /*@null@*/ + const char * execPath; + int execAbsolute; +/*@only@*/ /*@relnull@*/ + const char * otherHelp; +/*@null@*/ + pbm_set * arg_strip; +}; + +#if defined(POPT_fprintf) +#define POPT_dgettext dgettext +#else +#ifdef HAVE_ICONV +#include +#if defined(__LCLINT__) +/*@-declundef -incondefs @*/ +extern /*@only@*/ iconv_t iconv_open(const char *__tocode, const char *__fromcode) + /*@*/; + +extern size_t iconv(iconv_t __cd, /*@null@*/ char ** __inbuf, + /*@null@*/ /*@out@*/ size_t * __inbytesleft, + /*@null@*/ /*@out@*/ char ** __outbuf, + /*@null@*/ /*@out@*/ size_t * __outbytesleft) + /*@modifies __cd, + *__inbuf, *__inbytesleft, *__outbuf, *__outbytesleft @*/; + +extern int iconv_close(/*@only@*/ iconv_t __cd) + /*@modifies __cd @*/; +/*@=declundef =incondefs @*/ +#endif +#endif + +#ifdef HAVE_LANGINFO_H +#include +#if defined(__LCLINT__) +/*@-declundef -incondefs @*/ +extern char *nl_langinfo (nl_item __item) + /*@*/; +/*@=declundef =incondefs @*/ +#endif +#endif + +#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) +char *POPT_dgettext(const char * dom, const char * str) + /*@*/; +#endif + +int POPT_fprintf (FILE* stream, const char *format, ...) + /*@globals fileSystem @*/ + /*@modifies stream, fileSystem @*/; +#endif /* !defined(POPT_fprintf) */ + +const char *POPT_prev_char (/*@returned@*/ const char *str) + /*@*/; + +const char *POPT_next_char (/*@returned@*/ const char *str) + /*@*/; + +#endif + +#if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H) +#include +#endif + +#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT) && !defined(__LCLINT__) +#define _(foo) gettext(foo) +#else +#define _(foo) foo +#endif + +#if defined(ENABLE_NLS) && defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) +#define D_(dom, str) POPT_dgettext(dom, str) +#define POPT_(foo) D_("popt", foo) +#else +#define D_(dom, str) str +#define POPT_(foo) foo +#endif + +#define N_(foo) foo + diff --git a/ldb-2.0.8/third_party/popt/poptparse.c b/ldb-2.0.8/third_party/popt/poptparse.c new file mode 100644 index 0000000..39bf1aa --- /dev/null +++ b/ldb-2.0.8/third_party/popt/poptparse.c @@ -0,0 +1,230 @@ +/** \ingroup popt + * \file popt/poptparse.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.rpm.org/pub/rpm/dist. */ + +#include "system.h" + +#define POPT_ARGV_ARRAY_GROW_DELTA 5 + +int poptDupArgv(int argc, const char **argv, + int * argcPtr, const char *** argvPtr) +{ + size_t nb = (argc + 1) * sizeof(*argv); + const char ** argv2; + char * dst; + int i; + + if (argc <= 0 || argv == NULL) /* XXX can't happen */ + return POPT_ERROR_NOARG; + for (i = 0; i < argc; i++) { + if (argv[i] == NULL) + return POPT_ERROR_NOARG; + nb += strlen(argv[i]) + 1; + } + + dst = malloc(nb); + if (dst == NULL) /* XXX can't happen */ + return POPT_ERROR_MALLOC; + argv2 = (void *) dst; + dst += (argc + 1) * sizeof(*argv); + *dst = '\0'; + + for (i = 0; i < argc; i++) { + argv2[i] = dst; + dst = stpcpy(dst, argv[i]); + dst++; /* trailing NUL */ + } + argv2[argc] = NULL; + + if (argvPtr) { + *argvPtr = argv2; + } else { + free(argv2); + argv2 = NULL; + } + if (argcPtr) + *argcPtr = argc; + return 0; +} + +int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) +{ + const char * src; + char quote = '\0'; + int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; + const char ** argv = malloc(sizeof(*argv) * argvAlloced); + int argc = 0; + size_t buflen = strlen(s) + 1; + char * buf, * bufOrig = NULL; + int rc = POPT_ERROR_MALLOC; + + if (argv == NULL) return rc; + buf = bufOrig = calloc((size_t)1, buflen); + if (buf == NULL) { + free(argv); + return rc; + } + argv[argc] = buf; + + for (src = s; *src != '\0'; src++) { + if (quote == *src) { + quote = '\0'; + } else if (quote != '\0') { + if (*src == '\\') { + src++; + if (!*src) { + rc = POPT_ERROR_BADQUOTE; + goto exit; + } + if (*src != quote) *buf++ = '\\'; + } + *buf++ = *src; + } else if (_isspaceptr(src)) { + if (*argv[argc] != '\0') { + buf++, argc++; + if (argc == argvAlloced) { + argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; + argv = realloc(argv, sizeof(*argv) * argvAlloced); + if (argv == NULL) goto exit; + } + argv[argc] = buf; + } + } else switch (*src) { + case '"': + case '\'': + quote = *src; + /*@switchbreak@*/ break; + case '\\': + src++; + if (!*src) { + rc = POPT_ERROR_BADQUOTE; + goto exit; + } + /*@fallthrough@*/ + default: + *buf++ = *src; + /*@switchbreak@*/ break; + } + } + + if (strlen(argv[argc])) { + argc++, buf++; + } + + rc = poptDupArgv(argc, argv, argcPtr, argvPtr); + +exit: + if (bufOrig) free(bufOrig); + if (argv) free(argv); + return rc; +} + +/* still in the dev stage. + * return values, perhaps 1== file erro + * 2== line to long + * 3== umm.... more? + */ +int poptConfigFileToString(FILE *fp, char ** argstrp, + /*@unused@*/ UNUSED(int flags)) +{ + char line[999]; + char * argstr; + char * p; + char * q; + char * x; + size_t t; + size_t argvlen = 0; + size_t maxlinelen = sizeof(line); + size_t linelen; + size_t maxargvlen = (size_t)480; + + *argstrp = NULL; + + /* | this_is = our_line + * p q x + */ + + if (fp == NULL) + return POPT_ERROR_NULLARG; + + argstr = calloc(maxargvlen, sizeof(*argstr)); + if (argstr == NULL) return POPT_ERROR_MALLOC; + + while (fgets(line, (int)maxlinelen, fp) != NULL) { + p = line; + + /* loop until first non-space char or EOL */ + while( *p != '\0' && _isspaceptr(p) ) + p++; + + linelen = strlen(p); + if (linelen >= maxlinelen-1) { + free(argstr); + return POPT_ERROR_OVERFLOW; /* XXX line too long */ + } + + if (*p == '\0' || *p == '\n') continue; /* line is empty */ + if (*p == '#') continue; /* comment line */ + + q = p; + + while (*q != '\0' && (!_isspaceptr(q)) && *q != '=') + q++; + + if (_isspaceptr(q)) { + /* a space after the name, find next non space */ + *q++='\0'; + while( *q != '\0' && _isspaceptr(q) ) q++; + } + if (*q == '\0') { + /* single command line option (ie, no name=val, just name) */ + q[-1] = '\0'; /* kill off newline from fgets() call */ + argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1); + if (argvlen >= maxargvlen) { + maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; + argstr = realloc(argstr, maxargvlen); + if (argstr == NULL) return POPT_ERROR_MALLOC; + } + strcat(argstr, " --"); + strcat(argstr, p); + continue; + } + if (*q != '=') + continue; /* XXX for now, silently ignore bogus line */ + + /* *q is an equal sign. */ + *q++ = '\0'; + + /* find next non-space letter of value */ + while (*q != '\0' && _isspaceptr(q)) + q++; + if (*q == '\0') + continue; /* XXX silently ignore missing value */ + + /* now, loop and strip all ending whitespace */ + x = p + linelen; + while (_isspaceptr(--x)) + *x = '\0'; /* null out last char if space (including fgets() NL) */ + + /* rest of line accept */ + t = (size_t)(x - p); + argvlen += t + (sizeof("' --='")-1); + if (argvlen >= maxargvlen) { + maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; + argstr = realloc(argstr, maxargvlen); + if (argstr == NULL) return POPT_ERROR_MALLOC; + } + strcat(argstr, " --"); + strcat(argstr, p); + strcat(argstr, "=\""); + strcat(argstr, q); + strcat(argstr, "\""); + } + + *argstrp = argstr; + return 0; +} diff --git a/ldb-2.0.8/third_party/popt/system.h b/ldb-2.0.8/third_party/popt/system.h new file mode 100644 index 0000000..452bf40 --- /dev/null +++ b/ldb-2.0.8/third_party/popt/system.h @@ -0,0 +1,103 @@ +/** + * \file popt/system.h + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined (__GLIBC__) && defined(__LCLINT__) +/*@-declundef@*/ +/*@unchecked@*/ +extern __const __int32_t *__ctype_tolower; +/*@unchecked@*/ +extern __const __int32_t *__ctype_toupper; +/*@=declundef@*/ +#endif + +#include + +/* XXX isspace(3) has i18n encoding signednesss issues on Solaris. */ +#define _isspaceptr(_chp) isspace((int)(*(unsigned char *)(_chp))) + +#include +#include +#include + +#ifdef HAVE_MCHECK_H +#include +#endif + +#include +#include +#include + +#if defined(HAVE_UNISTD_H) && !defined(__LCLINT__) +#include +#endif + +#ifdef __NeXT +/* access macros are not declared in non posix mode in unistd.h - + don't try to use posix on NeXTstep 3.3 ! */ +#include +#endif + +/*@-incondefs@*/ +/*@mayexit@*/ /*@only@*/ /*@out@*/ /*@unused@*/ +void * xmalloc (size_t size) + /*@globals errno @*/ + /*@ensures maxSet(result) == (size - 1) @*/ + /*@modifies errno @*/; + +/*@mayexit@*/ /*@only@*/ /*@unused@*/ +void * xcalloc (size_t nmemb, size_t size) + /*@ensures maxSet(result) == (nmemb - 1) @*/ + /*@*/; + +/*@mayexit@*/ /*@only@*/ /*@unused@*/ +void * xrealloc (/*@null@*/ /*@only@*/ void * ptr, size_t size) + /*@ensures maxSet(result) == (size - 1) @*/ + /*@modifies *ptr @*/; + +/*@mayexit@*/ /*@only@*/ /*@unused@*/ +char * xstrdup (const char *str) + /*@*/; +/*@=incondefs@*/ + +#if !defined(HAVE_STPCPY) +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +static inline char * stpcpy (char *dest, const char * src) { + register char *d = dest; + register const char *s = src; + + do + *d++ = *s; + while (*s++ != '\0'); + return d - 1; +} +#endif + +/* Memory allocation via macro defs to get meaningful locations from mtrace() */ +#if defined(HAVE_MCHECK_H) && defined(__GNUC__) +#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) +#define xmalloc(_size) (malloc(_size) ? : vmefail()) +#define xcalloc(_nmemb, _size) (calloc((_nmemb), (_size)) ? : vmefail()) +#define xrealloc(_ptr, _size) (realloc((_ptr), (_size)) ? : vmefail()) +#define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str))) +#else +#define xmalloc(_size) malloc(_size) +#define xcalloc(_nmemb, _size) calloc((_nmemb), (_size)) +#define xrealloc(_ptr, _size) realloc((_ptr), (_size)) +#define xstrdup(_str) strdup(_str) +#endif /* defined(HAVE_MCHECK_H) && defined(__GNUC__) */ + +#if defined(HAVE___SECURE_GETENV) && !defined(__LCLINT__) +#define getenv(_s) __secure_getenv(_s) +#endif + +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif +#define UNUSED(x) x __attribute__((__unused__)) + +#include "popt.h" diff --git a/ldb-2.0.8/third_party/popt/wscript b/ldb-2.0.8/third_party/popt/wscript new file mode 100644 index 0000000..ea655bb --- /dev/null +++ b/ldb-2.0.8/third_party/popt/wscript @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +from waflib import Options + +def configure(conf): + if conf.CHECK_POPT(): + conf.define('USING_SYSTEM_POPT', 1) + return + + conf.CHECK_HEADERS('float.h') + conf.CHECK_FUNCS('stpcpy') + conf.CHECK_LIB('iconv', shlib=True) + +def build(bld): + if bld.CONFIG_SET('USING_SYSTEM_POPT'): + return + + cflags = '-DPACKAGE="popt" -DPOPT_SYSCONFDIR="%s"' % bld.env.SYSCONFDIR + bld.SAMBA_LIBRARY('popt', + source='popt.c poptconfig.c popthelp.c poptint.c poptparse.c', + cflags=cflags, + deps='iconv', + allow_warnings=True, + private_library=True) diff --git a/ldb-2.0.8/third_party/waf/waflib/Build.py b/ldb-2.0.8/third_party/waf/waflib/Build.py new file mode 100644 index 0000000..39f0991 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Build.py @@ -0,0 +1,1512 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Classes related to the build phase (build, clean, install, step, etc) + +The inheritance tree is the following: + +""" + +import os, sys, errno, re, shutil, stat +try: + import cPickle +except ImportError: + import pickle as cPickle +from waflib import Node, Runner, TaskGen, Utils, ConfigSet, Task, Logs, Options, Context, Errors + +CACHE_DIR = 'c4che' +"""Name of the cache directory""" + +CACHE_SUFFIX = '_cache.py' +"""ConfigSet cache files for variants are written under :py:attr:´waflib.Build.CACHE_DIR´ in the form ´variant_name´_cache.py""" + +INSTALL = 1337 +"""Positive value '->' install, see :py:attr:`waflib.Build.BuildContext.is_install`""" + +UNINSTALL = -1337 +"""Negative value '<-' uninstall, see :py:attr:`waflib.Build.BuildContext.is_install`""" + +SAVED_ATTRS = 'root node_sigs task_sigs imp_sigs raw_deps node_deps'.split() +"""Build class members to save between the runs; these should be all dicts +except for `root` which represents a :py:class:`waflib.Node.Node` instance +""" + +CFG_FILES = 'cfg_files' +"""Files from the build directory to hash before starting the build (``config.h`` written during the configuration)""" + +POST_AT_ONCE = 0 +"""Post mode: all task generators are posted before any task executed""" + +POST_LAZY = 1 +"""Post mode: post the task generators group after group, the tasks in the next group are created when the tasks in the previous groups are done""" + +PROTOCOL = -1 +if sys.platform == 'cli': + PROTOCOL = 0 + +class BuildContext(Context.Context): + '''executes the build''' + + cmd = 'build' + variant = '' + + def __init__(self, **kw): + super(BuildContext, self).__init__(**kw) + + self.is_install = 0 + """Non-zero value when installing or uninstalling file""" + + self.top_dir = kw.get('top_dir', Context.top_dir) + """See :py:attr:`waflib.Context.top_dir`; prefer :py:attr:`waflib.Build.BuildContext.srcnode`""" + + self.out_dir = kw.get('out_dir', Context.out_dir) + """See :py:attr:`waflib.Context.out_dir`; prefer :py:attr:`waflib.Build.BuildContext.bldnode`""" + + self.run_dir = kw.get('run_dir', Context.run_dir) + """See :py:attr:`waflib.Context.run_dir`""" + + self.launch_dir = Context.launch_dir + """See :py:attr:`waflib.Context.out_dir`; prefer :py:meth:`waflib.Build.BuildContext.launch_node`""" + + self.post_mode = POST_LAZY + """Whether to post the task generators at once or group-by-group (default is group-by-group)""" + + self.cache_dir = kw.get('cache_dir') + if not self.cache_dir: + self.cache_dir = os.path.join(self.out_dir, CACHE_DIR) + + self.all_envs = {} + """Map names to :py:class:`waflib.ConfigSet.ConfigSet`, the empty string must map to the default environment""" + + # ======================================= # + # cache variables + + self.node_sigs = {} + """Dict mapping build nodes to task identifier (uid), it indicates whether a task created a particular file (persists across builds)""" + + self.task_sigs = {} + """Dict mapping task identifiers (uid) to task signatures (persists across builds)""" + + self.imp_sigs = {} + """Dict mapping task identifiers (uid) to implicit task dependencies used for scanning targets (persists across builds)""" + + self.node_deps = {} + """Dict mapping task identifiers (uid) to node dependencies found by :py:meth:`waflib.Task.Task.scan` (persists across builds)""" + + self.raw_deps = {} + """Dict mapping task identifiers (uid) to custom data returned by :py:meth:`waflib.Task.Task.scan` (persists across builds)""" + + self.task_gen_cache_names = {} + + self.jobs = Options.options.jobs + """Amount of jobs to run in parallel""" + + self.targets = Options.options.targets + """List of targets to build (default: \\*)""" + + self.keep = Options.options.keep + """Whether the build should continue past errors""" + + self.progress_bar = Options.options.progress_bar + """ + Level of progress status: + + 0. normal output + 1. progress bar + 2. IDE output + 3. No output at all + """ + + # Manual dependencies. + self.deps_man = Utils.defaultdict(list) + """Manual dependencies set by :py:meth:`waflib.Build.BuildContext.add_manual_dependency`""" + + # just the structure here + self.current_group = 0 + """ + Current build group + """ + + self.groups = [] + """ + List containing lists of task generators + """ + + self.group_names = {} + """ + Map group names to the group lists. See :py:meth:`waflib.Build.BuildContext.add_group` + """ + + for v in SAVED_ATTRS: + if not hasattr(self, v): + setattr(self, v, {}) + + def get_variant_dir(self): + """Getter for the variant_dir attribute""" + if not self.variant: + return self.out_dir + return os.path.join(self.out_dir, os.path.normpath(self.variant)) + variant_dir = property(get_variant_dir, None) + + def __call__(self, *k, **kw): + """ + Create a task generator and add it to the current build group. The following forms are equivalent:: + + def build(bld): + tg = bld(a=1, b=2) + + def build(bld): + tg = bld() + tg.a = 1 + tg.b = 2 + + def build(bld): + tg = TaskGen.task_gen(a=1, b=2) + bld.add_to_group(tg, None) + + :param group: group name to add the task generator to + :type group: string + """ + kw['bld'] = self + ret = TaskGen.task_gen(*k, **kw) + self.task_gen_cache_names = {} # reset the cache, each time + self.add_to_group(ret, group=kw.get('group')) + return ret + + def __copy__(self): + """ + Build contexts cannot be copied + + :raises: :py:class:`waflib.Errors.WafError` + """ + raise Errors.WafError('build contexts cannot be copied') + + def load_envs(self): + """ + The configuration command creates files of the form ``build/c4che/NAMEcache.py``. This method + creates a :py:class:`waflib.ConfigSet.ConfigSet` instance for each ``NAME`` by reading those + files and stores them in :py:attr:`waflib.Build.BuildContext.allenvs`. + """ + node = self.root.find_node(self.cache_dir) + if not node: + raise Errors.WafError('The project was not configured: run "waf configure" first!') + lst = node.ant_glob('**/*%s' % CACHE_SUFFIX, quiet=True) + + if not lst: + raise Errors.WafError('The cache directory is empty: reconfigure the project') + + for x in lst: + name = x.path_from(node).replace(CACHE_SUFFIX, '').replace('\\', '/') + env = ConfigSet.ConfigSet(x.abspath()) + self.all_envs[name] = env + for f in env[CFG_FILES]: + newnode = self.root.find_resource(f) + if not newnode or not newnode.exists(): + raise Errors.WafError('Missing configuration file %r, reconfigure the project!' % f) + + def init_dirs(self): + """ + Initialize the project directory and the build directory by creating the nodes + :py:attr:`waflib.Build.BuildContext.srcnode` and :py:attr:`waflib.Build.BuildContext.bldnode` + corresponding to ``top_dir`` and ``variant_dir`` respectively. The ``bldnode`` directory is + created if necessary. + """ + if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): + raise Errors.WafError('The project was not configured: run "waf configure" first!') + + self.path = self.srcnode = self.root.find_dir(self.top_dir) + self.bldnode = self.root.make_node(self.variant_dir) + self.bldnode.mkdir() + + def execute(self): + """ + Restore data from previous builds and call :py:meth:`waflib.Build.BuildContext.execute_build`. + Overrides from :py:func:`waflib.Context.Context.execute` + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.execute_build() + + def execute_build(self): + """ + Execute the build by: + + * reading the scripts (see :py:meth:`waflib.Context.Context.recurse`) + * calling :py:meth:`waflib.Build.BuildContext.pre_build` to call user build functions + * calling :py:meth:`waflib.Build.BuildContext.compile` to process the tasks + * calling :py:meth:`waflib.Build.BuildContext.post_build` to call user build functions + """ + + Logs.info("Waf: Entering directory `%s'", self.variant_dir) + self.recurse([self.run_dir]) + self.pre_build() + + # display the time elapsed in the progress bar + self.timer = Utils.Timer() + + try: + self.compile() + finally: + if self.progress_bar == 1 and sys.stderr.isatty(): + c = self.producer.processed or 1 + m = self.progress_line(c, c, Logs.colors.BLUE, Logs.colors.NORMAL) + Logs.info(m, extra={'stream': sys.stderr, 'c1': Logs.colors.cursor_off, 'c2' : Logs.colors.cursor_on}) + Logs.info("Waf: Leaving directory `%s'", self.variant_dir) + try: + self.producer.bld = None + del self.producer + except AttributeError: + pass + self.post_build() + + def restore(self): + """ + Load data from a previous run, sets the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS` + """ + try: + env = ConfigSet.ConfigSet(os.path.join(self.cache_dir, 'build.config.py')) + except EnvironmentError: + pass + else: + if env.version < Context.HEXVERSION: + raise Errors.WafError('Project was configured with a different version of Waf, please reconfigure it') + + for t in env.tools: + self.setup(**t) + + dbfn = os.path.join(self.variant_dir, Context.DBFILE) + try: + data = Utils.readf(dbfn, 'rb') + except (EnvironmentError, EOFError): + # handle missing file/empty file + Logs.debug('build: Could not load the build cache %s (missing)', dbfn) + else: + try: + Node.pickle_lock.acquire() + Node.Nod3 = self.node_class + try: + data = cPickle.loads(data) + except Exception as e: + Logs.debug('build: Could not pickle the build cache %s: %r', dbfn, e) + else: + for x in SAVED_ATTRS: + setattr(self, x, data.get(x, {})) + finally: + Node.pickle_lock.release() + + self.init_dirs() + + def store(self): + """ + Store data for next runs, set the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS`. Uses a temporary + file to avoid problems on ctrl+c. + """ + data = {} + for x in SAVED_ATTRS: + data[x] = getattr(self, x) + db = os.path.join(self.variant_dir, Context.DBFILE) + + try: + Node.pickle_lock.acquire() + Node.Nod3 = self.node_class + x = cPickle.dumps(data, PROTOCOL) + finally: + Node.pickle_lock.release() + + Utils.writef(db + '.tmp', x, m='wb') + + try: + st = os.stat(db) + os.remove(db) + if not Utils.is_win32: # win32 has no chown but we're paranoid + os.chown(db + '.tmp', st.st_uid, st.st_gid) + except (AttributeError, OSError): + pass + + # do not use shutil.move (copy is not thread-safe) + os.rename(db + '.tmp', db) + + def compile(self): + """ + Run the build by creating an instance of :py:class:`waflib.Runner.Parallel` + The cache file is written when at least a task was executed. + + :raises: :py:class:`waflib.Errors.BuildError` in case the build fails + """ + Logs.debug('build: compile()') + + # delegate the producer-consumer logic to another object to reduce the complexity + self.producer = Runner.Parallel(self, self.jobs) + self.producer.biter = self.get_build_iterator() + try: + self.producer.start() + except KeyboardInterrupt: + if self.is_dirty(): + self.store() + raise + else: + if self.is_dirty(): + self.store() + + if self.producer.error: + raise Errors.BuildError(self.producer.error) + + def is_dirty(self): + return self.producer.dirty + + def setup(self, tool, tooldir=None, funs=None): + """ + Import waf tools defined during the configuration:: + + def configure(conf): + conf.load('glib2') + + def build(bld): + pass # glib2 is imported implicitly + + :param tool: tool list + :type tool: list + :param tooldir: optional tool directory (sys.path) + :type tooldir: list of string + :param funs: unused variable + """ + if isinstance(tool, list): + for i in tool: + self.setup(i, tooldir) + return + + module = Context.load_tool(tool, tooldir) + if hasattr(module, "setup"): + module.setup(self) + + def get_env(self): + """Getter for the env property""" + try: + return self.all_envs[self.variant] + except KeyError: + return self.all_envs[''] + def set_env(self, val): + """Setter for the env property""" + self.all_envs[self.variant] = val + + env = property(get_env, set_env) + + def add_manual_dependency(self, path, value): + """ + Adds a dependency from a node object to a value:: + + def build(bld): + bld.add_manual_dependency( + bld.path.find_resource('wscript'), + bld.root.find_resource('/etc/fstab')) + + :param path: file path + :type path: string or :py:class:`waflib.Node.Node` + :param value: value to depend + :type value: :py:class:`waflib.Node.Node`, byte object, or function returning a byte object + """ + if not path: + raise ValueError('Invalid input path %r' % path) + + if isinstance(path, Node.Node): + node = path + elif os.path.isabs(path): + node = self.root.find_resource(path) + else: + node = self.path.find_resource(path) + if not node: + raise ValueError('Could not find the path %r' % path) + + if isinstance(value, list): + self.deps_man[node].extend(value) + else: + self.deps_man[node].append(value) + + def launch_node(self): + """Returns the launch directory as a :py:class:`waflib.Node.Node` object (cached)""" + try: + # private cache + return self.p_ln + except AttributeError: + self.p_ln = self.root.find_dir(self.launch_dir) + return self.p_ln + + def hash_env_vars(self, env, vars_lst): + """ + Hashes configuration set variables:: + + def build(bld): + bld.hash_env_vars(bld.env, ['CXX', 'CC']) + + This method uses an internal cache. + + :param env: Configuration Set + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :param vars_lst: list of variables + :type vars_list: list of string + """ + + if not env.table: + env = env.parent + if not env: + return Utils.SIG_NIL + + idx = str(id(env)) + str(vars_lst) + try: + cache = self.cache_env + except AttributeError: + cache = self.cache_env = {} + else: + try: + return self.cache_env[idx] + except KeyError: + pass + + lst = [env[a] for a in vars_lst] + cache[idx] = ret = Utils.h_list(lst) + Logs.debug('envhash: %s %r', Utils.to_hex(ret), lst) + return ret + + def get_tgen_by_name(self, name): + """ + Fetches a task generator by its name or its target attribute; + the name must be unique in a build:: + + def build(bld): + tg = bld(name='foo') + tg == bld.get_tgen_by_name('foo') + + This method use a private internal cache. + + :param name: Task generator name + :raises: :py:class:`waflib.Errors.WafError` in case there is no task genenerator by that name + """ + cache = self.task_gen_cache_names + if not cache: + # create the index lazily + for g in self.groups: + for tg in g: + try: + cache[tg.name] = tg + except AttributeError: + # raised if not a task generator, which should be uncommon + pass + try: + return cache[name] + except KeyError: + raise Errors.WafError('Could not find a task generator for the name %r' % name) + + def progress_line(self, idx, total, col1, col2): + """ + Computes a progress bar line displayed when running ``waf -p`` + + :returns: progress bar line + :rtype: string + """ + if not sys.stderr.isatty(): + return '' + + n = len(str(total)) + + Utils.rot_idx += 1 + ind = Utils.rot_chr[Utils.rot_idx % 4] + + pc = (100. * idx)/total + fs = "[%%%dd/%%d][%%s%%2d%%%%%%s][%s][" % (n, ind) + left = fs % (idx, total, col1, pc, col2) + right = '][%s%s%s]' % (col1, self.timer, col2) + + cols = Logs.get_term_cols() - len(left) - len(right) + 2*len(col1) + 2*len(col2) + if cols < 7: + cols = 7 + + ratio = ((cols * idx)//total) - 1 + + bar = ('='*ratio+'>').ljust(cols) + msg = Logs.indicator % (left, bar, right) + + return msg + + def declare_chain(self, *k, **kw): + """ + Wraps :py:func:`waflib.TaskGen.declare_chain` for convenience + """ + return TaskGen.declare_chain(*k, **kw) + + def pre_build(self): + """Executes user-defined methods before the build starts, see :py:meth:`waflib.Build.BuildContext.add_pre_fun`""" + for m in getattr(self, 'pre_funs', []): + m(self) + + def post_build(self): + """Executes user-defined methods after the build is successful, see :py:meth:`waflib.Build.BuildContext.add_post_fun`""" + for m in getattr(self, 'post_funs', []): + m(self) + + def add_pre_fun(self, meth): + """ + Binds a callback method to execute after the scripts are read and before the build starts:: + + def mycallback(bld): + print("Hello, world!") + + def build(bld): + bld.add_pre_fun(mycallback) + """ + try: + self.pre_funs.append(meth) + except AttributeError: + self.pre_funs = [meth] + + def add_post_fun(self, meth): + """ + Binds a callback method to execute immediately after the build is successful:: + + def call_ldconfig(bld): + bld.exec_command('/sbin/ldconfig') + + def build(bld): + if bld.cmd == 'install': + bld.add_pre_fun(call_ldconfig) + """ + try: + self.post_funs.append(meth) + except AttributeError: + self.post_funs = [meth] + + def get_group(self, x): + """ + Returns the build group named `x`, or the current group if `x` is None + + :param x: name or number or None + :type x: string, int or None + """ + if not self.groups: + self.add_group() + if x is None: + return self.groups[self.current_group] + if x in self.group_names: + return self.group_names[x] + return self.groups[x] + + def add_to_group(self, tgen, group=None): + """Adds a task or a task generator to the build; there is no attempt to remove it if it was already added.""" + assert(isinstance(tgen, TaskGen.task_gen) or isinstance(tgen, Task.Task)) + tgen.bld = self + self.get_group(group).append(tgen) + + def get_group_name(self, g): + """ + Returns the name of the input build group + + :param g: build group object or build group index + :type g: integer or list + :return: name + :rtype: string + """ + if not isinstance(g, list): + g = self.groups[g] + for x in self.group_names: + if id(self.group_names[x]) == id(g): + return x + return '' + + def get_group_idx(self, tg): + """ + Returns the index of the group containing the task generator given as argument:: + + def build(bld): + tg = bld(name='nada') + 0 == bld.get_group_idx(tg) + + :param tg: Task generator object + :type tg: :py:class:`waflib.TaskGen.task_gen` + :rtype: int + """ + se = id(tg) + for i, tmp in enumerate(self.groups): + for t in tmp: + if id(t) == se: + return i + return None + + def add_group(self, name=None, move=True): + """ + Adds a new group of tasks/task generators. By default the new group becomes + the default group for new task generators (make sure to create build groups in order). + + :param name: name for this group + :type name: string + :param move: set this new group as default group (True by default) + :type move: bool + :raises: :py:class:`waflib.Errors.WafError` if a group by the name given already exists + """ + if name and name in self.group_names: + raise Errors.WafError('add_group: name %s already present', name) + g = [] + self.group_names[name] = g + self.groups.append(g) + if move: + self.current_group = len(self.groups) - 1 + + def set_group(self, idx): + """ + Sets the build group at position idx as current so that newly added + task generators are added to this one by default:: + + def build(bld): + bld(rule='touch ${TGT}', target='foo.txt') + bld.add_group() # now the current group is 1 + bld(rule='touch ${TGT}', target='bar.txt') + bld.set_group(0) # now the current group is 0 + bld(rule='touch ${TGT}', target='truc.txt') # build truc.txt before bar.txt + + :param idx: group name or group index + :type idx: string or int + """ + if isinstance(idx, str): + g = self.group_names[idx] + for i, tmp in enumerate(self.groups): + if id(g) == id(tmp): + self.current_group = i + break + else: + self.current_group = idx + + def total(self): + """ + Approximate task count: this value may be inaccurate if task generators + are posted lazily (see :py:attr:`waflib.Build.BuildContext.post_mode`). + The value :py:attr:`waflib.Runner.Parallel.total` is updated during the task execution. + + :rtype: int + """ + total = 0 + for group in self.groups: + for tg in group: + try: + total += len(tg.tasks) + except AttributeError: + total += 1 + return total + + def get_targets(self): + """ + This method returns a pair containing the index of the last build group to post, + and the list of task generator objects corresponding to the target names. + + This is used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` + to perform partial builds:: + + $ waf --targets=myprogram,myshlib + + :return: the minimum build group index, and list of task generators + :rtype: tuple + """ + to_post = [] + min_grp = 0 + for name in self.targets.split(','): + tg = self.get_tgen_by_name(name) + m = self.get_group_idx(tg) + if m > min_grp: + min_grp = m + to_post = [tg] + elif m == min_grp: + to_post.append(tg) + return (min_grp, to_post) + + def get_all_task_gen(self): + """ + Returns a list of all task generators for troubleshooting purposes. + """ + lst = [] + for g in self.groups: + lst.extend(g) + return lst + + def post_group(self): + """ + Post task generators from the group indexed by self.current_group; used internally + by :py:meth:`waflib.Build.BuildContext.get_build_iterator` + """ + def tgpost(tg): + try: + f = tg.post + except AttributeError: + pass + else: + f() + + if self.targets == '*': + for tg in self.groups[self.current_group]: + tgpost(tg) + elif self.targets: + if self.current_group < self._min_grp: + for tg in self.groups[self.current_group]: + tgpost(tg) + else: + for tg in self._exact_tg: + tg.post() + else: + ln = self.launch_node() + if ln.is_child_of(self.bldnode): + Logs.warn('Building from the build directory, forcing --targets=*') + ln = self.srcnode + elif not ln.is_child_of(self.srcnode): + Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath()) + ln = self.srcnode + + def is_post(tg, ln): + try: + p = tg.path + except AttributeError: + pass + else: + if p.is_child_of(ln): + return True + + def is_post_group(): + for i, g in enumerate(self.groups): + if i > self.current_group: + for tg in g: + if is_post(tg, ln): + return True + + if self.post_mode == POST_LAZY and ln != self.srcnode: + # partial folder builds require all targets from a previous build group + if is_post_group(): + ln = self.srcnode + + for tg in self.groups[self.current_group]: + if is_post(tg, ln): + tgpost(tg) + + def get_tasks_group(self, idx): + """ + Returns all task instances for the build group at position idx, + used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` + + :rtype: list of :py:class:`waflib.Task.Task` + """ + tasks = [] + for tg in self.groups[idx]: + try: + tasks.extend(tg.tasks) + except AttributeError: # not a task generator + tasks.append(tg) + return tasks + + def get_build_iterator(self): + """ + Creates a Python generator object that returns lists of tasks that may be processed in parallel. + + :return: tasks which can be executed immediately + :rtype: generator returning lists of :py:class:`waflib.Task.Task` + """ + if self.targets and self.targets != '*': + (self._min_grp, self._exact_tg) = self.get_targets() + + if self.post_mode != POST_LAZY: + for self.current_group, _ in enumerate(self.groups): + self.post_group() + + for self.current_group, _ in enumerate(self.groups): + # first post the task generators for the group + if self.post_mode != POST_AT_ONCE: + self.post_group() + + # then extract the tasks + tasks = self.get_tasks_group(self.current_group) + + # if the constraints are set properly (ext_in/ext_out, before/after) + # the call to set_file_constraints may be removed (can be a 15% penalty on no-op rebuilds) + # (but leave set_file_constraints for the installation step) + # + # if the tasks have only files, set_file_constraints is required but set_precedence_constraints is not necessary + # + Task.set_file_constraints(tasks) + Task.set_precedence_constraints(tasks) + + self.cur_tasks = tasks + if tasks: + yield tasks + + while 1: + # the build stops once there are no tasks to process + yield [] + + def install_files(self, dest, files, **kw): + """ + Creates a task generator to install files on the system:: + + def build(bld): + bld.install_files('${DATADIR}', self.path.find_resource('wscript')) + + :param dest: path representing the destination directory + :type dest: :py:class:`waflib.Node.Node` or string (absolute path) + :param files: input files + :type files: list of strings or list of :py:class:`waflib.Node.Node` + :param env: configuration set to expand *dest* + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :param relative_trick: preserve the folder hierarchy when installing whole folders + :type relative_trick: bool + :param cwd: parent node for searching srcfile, when srcfile is not an instance of :py:class:`waflib.Node.Node` + :type cwd: :py:class:`waflib.Node.Node` + :param postpone: execute the task immediately to perform the installation (False by default) + :type postpone: bool + """ + assert(dest) + tg = self(features='install_task', install_to=dest, install_from=files, **kw) + tg.dest = tg.install_to + tg.type = 'install_files' + if not kw.get('postpone', True): + tg.post() + return tg + + def install_as(self, dest, srcfile, **kw): + """ + Creates a task generator to install a file on the system with a different name:: + + def build(bld): + bld.install_as('${PREFIX}/bin', 'myapp', chmod=Utils.O755) + + :param dest: destination file + :type dest: :py:class:`waflib.Node.Node` or string (absolute path) + :param srcfile: input file + :type srcfile: string or :py:class:`waflib.Node.Node` + :param cwd: parent node for searching srcfile, when srcfile is not an instance of :py:class:`waflib.Node.Node` + :type cwd: :py:class:`waflib.Node.Node` + :param env: configuration set for performing substitutions in dest + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :param postpone: execute the task immediately to perform the installation (False by default) + :type postpone: bool + """ + assert(dest) + tg = self(features='install_task', install_to=dest, install_from=srcfile, **kw) + tg.dest = tg.install_to + tg.type = 'install_as' + if not kw.get('postpone', True): + tg.post() + return tg + + def symlink_as(self, dest, src, **kw): + """ + Creates a task generator to install a symlink:: + + def build(bld): + bld.symlink_as('${PREFIX}/lib/libfoo.so', 'libfoo.so.1.2.3') + + :param dest: absolute path of the symlink + :type dest: :py:class:`waflib.Node.Node` or string (absolute path) + :param src: link contents, which is a relative or absolute path which may exist or not + :type src: string + :param env: configuration set for performing substitutions in dest + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started + :type add: bool + :param postpone: execute the task immediately to perform the installation + :type postpone: bool + :param relative_trick: make the symlink relative (default: ``False``) + :type relative_trick: bool + """ + assert(dest) + tg = self(features='install_task', install_to=dest, install_from=src, **kw) + tg.dest = tg.install_to + tg.type = 'symlink_as' + tg.link = src + # TODO if add: self.add_to_group(tsk) + if not kw.get('postpone', True): + tg.post() + return tg + +@TaskGen.feature('install_task') +@TaskGen.before_method('process_rule', 'process_source') +def process_install_task(self): + """Creates the installation task for the current task generator; uses :py:func:`waflib.Build.add_install_task` internally.""" + self.add_install_task(**self.__dict__) + +@TaskGen.taskgen_method +def add_install_task(self, **kw): + """ + Creates the installation task for the current task generator, and executes it immediately if necessary + + :returns: An installation task + :rtype: :py:class:`waflib.Build.inst` + """ + if not self.bld.is_install: + return + if not kw['install_to']: + return + + if kw['type'] == 'symlink_as' and Utils.is_win32: + if kw.get('win32_install'): + kw['type'] = 'install_as' + else: + # just exit + return + + tsk = self.install_task = self.create_task('inst') + tsk.chmod = kw.get('chmod', Utils.O644) + tsk.link = kw.get('link', '') or kw.get('install_from', '') + tsk.relative_trick = kw.get('relative_trick', False) + tsk.type = kw['type'] + tsk.install_to = tsk.dest = kw['install_to'] + tsk.install_from = kw['install_from'] + tsk.relative_base = kw.get('cwd') or kw.get('relative_base', self.path) + tsk.install_user = kw.get('install_user') + tsk.install_group = kw.get('install_group') + tsk.init_files() + if not kw.get('postpone', True): + tsk.run_now() + return tsk + +@TaskGen.taskgen_method +def add_install_files(self, **kw): + """ + Creates an installation task for files + + :returns: An installation task + :rtype: :py:class:`waflib.Build.inst` + """ + kw['type'] = 'install_files' + return self.add_install_task(**kw) + +@TaskGen.taskgen_method +def add_install_as(self, **kw): + """ + Creates an installation task for a single file + + :returns: An installation task + :rtype: :py:class:`waflib.Build.inst` + """ + kw['type'] = 'install_as' + return self.add_install_task(**kw) + +@TaskGen.taskgen_method +def add_symlink_as(self, **kw): + """ + Creates an installation task for a symbolic link + + :returns: An installation task + :rtype: :py:class:`waflib.Build.inst` + """ + kw['type'] = 'symlink_as' + return self.add_install_task(**kw) + +class inst(Task.Task): + """Task that installs files or symlinks; it is typically executed by :py:class:`waflib.Build.InstallContext` and :py:class:`waflib.Build.UnInstallContext`""" + def __str__(self): + """Returns an empty string to disable the standard task display""" + return '' + + def uid(self): + """Returns a unique identifier for the task""" + lst = self.inputs + self.outputs + [self.link, self.generator.path.abspath()] + return Utils.h_list(lst) + + def init_files(self): + """ + Initializes the task input and output nodes + """ + if self.type == 'symlink_as': + inputs = [] + else: + inputs = self.generator.to_nodes(self.install_from) + if self.type == 'install_as': + assert len(inputs) == 1 + self.set_inputs(inputs) + + dest = self.get_install_path() + outputs = [] + if self.type == 'symlink_as': + if self.relative_trick: + self.link = os.path.relpath(self.link, os.path.dirname(dest)) + outputs.append(self.generator.bld.root.make_node(dest)) + elif self.type == 'install_as': + outputs.append(self.generator.bld.root.make_node(dest)) + else: + for y in inputs: + if self.relative_trick: + destfile = os.path.join(dest, y.path_from(self.relative_base)) + else: + destfile = os.path.join(dest, y.name) + outputs.append(self.generator.bld.root.make_node(destfile)) + self.set_outputs(outputs) + + def runnable_status(self): + """ + Installation tasks are always executed, so this method returns either :py:const:`waflib.Task.ASK_LATER` or :py:const:`waflib.Task.RUN_ME`. + """ + ret = super(inst, self).runnable_status() + if ret == Task.SKIP_ME and self.generator.bld.is_install: + return Task.RUN_ME + return ret + + def post_run(self): + """ + Disables any post-run operations + """ + pass + + def get_install_path(self, destdir=True): + """ + Returns the destination path where files will be installed, pre-pending `destdir`. + + Relative paths will be interpreted relative to `PREFIX` if no `destdir` is given. + + :rtype: string + """ + if isinstance(self.install_to, Node.Node): + dest = self.install_to.abspath() + else: + dest = os.path.normpath(Utils.subst_vars(self.install_to, self.env)) + if not os.path.isabs(dest): + dest = os.path.join(self.env.PREFIX, dest) + if destdir and Options.options.destdir: + dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep)) + return dest + + def copy_fun(self, src, tgt): + """ + Copies a file from src to tgt, preserving permissions and trying to work + around path limitations on Windows platforms. On Unix-like platforms, + the owner/group of the target file may be set through install_user/install_group + + :param src: absolute path + :type src: string + :param tgt: absolute path + :type tgt: string + """ + # override this if you want to strip executables + # kw['tsk'].source is the task that created the files in the build + if Utils.is_win32 and len(tgt) > 259 and not tgt.startswith('\\\\?\\'): + tgt = '\\\\?\\' + tgt + shutil.copy2(src, tgt) + self.fix_perms(tgt) + + def rm_empty_dirs(self, tgt): + """ + Removes empty folders recursively when uninstalling. + + :param tgt: absolute path + :type tgt: string + """ + while tgt: + tgt = os.path.dirname(tgt) + try: + os.rmdir(tgt) + except OSError: + break + + def run(self): + """ + Performs file or symlink installation + """ + is_install = self.generator.bld.is_install + if not is_install: # unnecessary? + return + + for x in self.outputs: + if is_install == INSTALL: + x.parent.mkdir() + if self.type == 'symlink_as': + fun = is_install == INSTALL and self.do_link or self.do_unlink + fun(self.link, self.outputs[0].abspath()) + else: + fun = is_install == INSTALL and self.do_install or self.do_uninstall + launch_node = self.generator.bld.launch_node() + for x, y in zip(self.inputs, self.outputs): + fun(x.abspath(), y.abspath(), x.path_from(launch_node)) + + def run_now(self): + """ + Try executing the installation task right now + + :raises: :py:class:`waflib.Errors.TaskNotReady` + """ + status = self.runnable_status() + if status not in (Task.RUN_ME, Task.SKIP_ME): + raise Errors.TaskNotReady('Could not process %r: status %r' % (self, status)) + self.run() + self.hasrun = Task.SUCCESS + + def do_install(self, src, tgt, lbl, **kw): + """ + Copies a file from src to tgt with given file permissions. The actual copy is only performed + if the source and target file sizes or timestamps differ. When the copy occurs, + the file is always first removed and then copied so as to prevent stale inodes. + + :param src: file name as absolute path + :type src: string + :param tgt: file destination, as absolute path + :type tgt: string + :param lbl: file source description + :type lbl: string + :param chmod: installation mode + :type chmod: int + :raises: :py:class:`waflib.Errors.WafError` if the file cannot be written + """ + if not Options.options.force: + # check if the file is already there to avoid a copy + try: + st1 = os.stat(tgt) + st2 = os.stat(src) + except OSError: + pass + else: + # same size and identical timestamps -> make no copy + if st1.st_mtime + 2 >= st2.st_mtime and st1.st_size == st2.st_size: + if not self.generator.bld.progress_bar: + + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + + Logs.info('%s- install %s%s%s (from %s)', c1, c2, tgt, c1, lbl) + return False + + if not self.generator.bld.progress_bar: + + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + + Logs.info('%s+ install %s%s%s (from %s)', c1, c2, tgt, c1, lbl) + + # Give best attempt at making destination overwritable, + # like the 'install' utility used by 'make install' does. + try: + os.chmod(tgt, Utils.O644 | stat.S_IMODE(os.stat(tgt).st_mode)) + except EnvironmentError: + pass + + # following is for shared libs and stale inodes (-_-) + try: + os.remove(tgt) + except OSError: + pass + + try: + self.copy_fun(src, tgt) + except EnvironmentError as e: + if not os.path.exists(src): + Logs.error('File %r does not exist', src) + elif not os.path.isfile(src): + Logs.error('Input %r is not a file', src) + raise Errors.WafError('Could not install the file %r' % tgt, e) + + def fix_perms(self, tgt): + """ + Change the ownership of the file/folder/link pointed by the given path + This looks up for `install_user` or `install_group` attributes + on the task or on the task generator:: + + def build(bld): + bld.install_as('${PREFIX}/wscript', + 'wscript', + install_user='nobody', install_group='nogroup') + bld.symlink_as('${PREFIX}/wscript_link', + Utils.subst_vars('${PREFIX}/wscript', bld.env), + install_user='nobody', install_group='nogroup') + """ + if not Utils.is_win32: + user = getattr(self, 'install_user', None) or getattr(self.generator, 'install_user', None) + group = getattr(self, 'install_group', None) or getattr(self.generator, 'install_group', None) + if user or group: + Utils.lchown(tgt, user or -1, group or -1) + if not os.path.islink(tgt): + os.chmod(tgt, self.chmod) + + def do_link(self, src, tgt, **kw): + """ + Creates a symlink from tgt to src. + + :param src: file name as absolute path + :type src: string + :param tgt: file destination, as absolute path + :type tgt: string + """ + if os.path.islink(tgt) and os.readlink(tgt) == src: + if not self.generator.bld.progress_bar: + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s- symlink %s%s%s (to %s)', c1, c2, tgt, c1, src) + else: + try: + os.remove(tgt) + except OSError: + pass + if not self.generator.bld.progress_bar: + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s+ symlink %s%s%s (to %s)', c1, c2, tgt, c1, src) + os.symlink(src, tgt) + self.fix_perms(tgt) + + def do_uninstall(self, src, tgt, lbl, **kw): + """ + See :py:meth:`waflib.Build.inst.do_install` + """ + if not self.generator.bld.progress_bar: + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s- remove %s%s%s', c1, c2, tgt, c1) + + #self.uninstall.append(tgt) + try: + os.remove(tgt) + except OSError as e: + if e.errno != errno.ENOENT: + if not getattr(self, 'uninstall_error', None): + self.uninstall_error = True + Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)') + if Logs.verbose > 1: + Logs.warn('Could not remove %s (error code %r)', e.filename, e.errno) + self.rm_empty_dirs(tgt) + + def do_unlink(self, src, tgt, **kw): + """ + See :py:meth:`waflib.Build.inst.do_link` + """ + try: + if not self.generator.bld.progress_bar: + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s- remove %s%s%s', c1, c2, tgt, c1) + os.remove(tgt) + except OSError: + pass + self.rm_empty_dirs(tgt) + +class InstallContext(BuildContext): + '''installs the targets on the system''' + cmd = 'install' + + def __init__(self, **kw): + super(InstallContext, self).__init__(**kw) + self.is_install = INSTALL + +class UninstallContext(InstallContext): + '''removes the targets installed''' + cmd = 'uninstall' + + def __init__(self, **kw): + super(UninstallContext, self).__init__(**kw) + self.is_install = UNINSTALL + +class CleanContext(BuildContext): + '''cleans the project''' + cmd = 'clean' + def execute(self): + """ + See :py:func:`waflib.Build.BuildContext.execute`. + """ + self.restore() + if not self.all_envs: + self.load_envs() + + self.recurse([self.run_dir]) + try: + self.clean() + finally: + self.store() + + def clean(self): + """ + Remove most files from the build directory, and reset all caches. + + Custom lists of files to clean can be declared as `bld.clean_files`. + For example, exclude `build/program/myprogram` from getting removed:: + + def build(bld): + bld.clean_files = bld.bldnode.ant_glob('**', + excl='.lock* config.log c4che/* config.h program/myprogram', + quiet=True, generator=True) + """ + Logs.debug('build: clean called') + + if hasattr(self, 'clean_files'): + for n in self.clean_files: + n.delete() + elif self.bldnode != self.srcnode: + # would lead to a disaster if top == out + lst = [] + for env in self.all_envs.values(): + lst.extend(self.root.find_or_declare(f) for f in env[CFG_FILES]) + excluded_dirs = '.lock* *conf_check_*/** config.log %s/*' % CACHE_DIR + for n in self.bldnode.ant_glob('**/*', excl=excluded_dirs, quiet=True): + if n in lst: + continue + n.delete() + self.root.children = {} + + for v in SAVED_ATTRS: + if v == 'root': + continue + setattr(self, v, {}) + +class ListContext(BuildContext): + '''lists the targets to execute''' + cmd = 'list' + + def execute(self): + """ + In addition to printing the name of each build target, + a description column will include text for each task + generator which has a "description" field set. + + See :py:func:`waflib.Build.BuildContext.execute`. + """ + self.restore() + if not self.all_envs: + self.load_envs() + + self.recurse([self.run_dir]) + self.pre_build() + + # display the time elapsed in the progress bar + self.timer = Utils.Timer() + + for g in self.groups: + for tg in g: + try: + f = tg.post + except AttributeError: + pass + else: + f() + + try: + # force the cache initialization + self.get_tgen_by_name('') + except Errors.WafError: + pass + + targets = sorted(self.task_gen_cache_names) + + # figure out how much to left-justify, for largest target name + line_just = max(len(t) for t in targets) if targets else 0 + + for target in targets: + tgen = self.task_gen_cache_names[target] + + # Support displaying the description for the target + # if it was set on the tgen + descript = getattr(tgen, 'description', '') + if descript: + target = target.ljust(line_just) + descript = ': %s' % descript + + Logs.pprint('GREEN', target, label=descript) + +class StepContext(BuildContext): + '''executes tasks in a step-by-step fashion, for debugging''' + cmd = 'step' + + def __init__(self, **kw): + super(StepContext, self).__init__(**kw) + self.files = Options.options.files + + def compile(self): + """ + Overrides :py:meth:`waflib.Build.BuildContext.compile` to perform a partial build + on tasks matching the input/output pattern given (regular expression matching):: + + $ waf step --files=foo.c,bar.c,in:truc.c,out:bar.o + $ waf step --files=in:foo.cpp.1.o # link task only + + """ + if not self.files: + Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"') + BuildContext.compile(self) + return + + targets = [] + if self.targets and self.targets != '*': + targets = self.targets.split(',') + + for g in self.groups: + for tg in g: + if targets and tg.name not in targets: + continue + + try: + f = tg.post + except AttributeError: + pass + else: + f() + + for pat in self.files.split(','): + matcher = self.get_matcher(pat) + for tg in g: + if isinstance(tg, Task.Task): + lst = [tg] + else: + lst = tg.tasks + for tsk in lst: + do_exec = False + for node in tsk.inputs: + if matcher(node, output=False): + do_exec = True + break + for node in tsk.outputs: + if matcher(node, output=True): + do_exec = True + break + if do_exec: + ret = tsk.run() + Logs.info('%s -> exit %r', tsk, ret) + + def get_matcher(self, pat): + """ + Converts a step pattern into a function + + :param: pat: pattern of the form in:truc.c,out:bar.o + :returns: Python function that uses Node objects as inputs and returns matches + :rtype: function + """ + # this returns a function + inn = True + out = True + if pat.startswith('in:'): + out = False + pat = pat.replace('in:', '') + elif pat.startswith('out:'): + inn = False + pat = pat.replace('out:', '') + + anode = self.root.find_node(pat) + pattern = None + if not anode: + if not pat.startswith('^'): + pat = '^.+?%s' % pat + if not pat.endswith('$'): + pat = '%s$' % pat + pattern = re.compile(pat) + + def match(node, output): + if output and not out: + return False + if not output and not inn: + return False + + if anode: + return anode == node + else: + return pattern.match(node.abspath()) + return match + +class EnvContext(BuildContext): + """Subclass EnvContext to create commands that require configuration data in 'env'""" + fun = cmd = None + def execute(self): + """ + See :py:func:`waflib.Build.BuildContext.execute`. + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + diff --git a/ldb-2.0.8/third_party/waf/waflib/ConfigSet.py b/ldb-2.0.8/third_party/waf/waflib/ConfigSet.py new file mode 100644 index 0000000..901fba6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/ConfigSet.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" + +ConfigSet: a special dict + +The values put in :py:class:`ConfigSet` must be serializable (dicts, lists, strings) +""" + +import copy, re, os +from waflib import Logs, Utils +re_imp = re.compile(r'^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) + +class ConfigSet(object): + """ + A copy-on-write dict with human-readable serialized format. The serialization format + is human-readable (python-like) and performed by using eval() and repr(). + For high performance prefer pickle. Do not store functions as they are not serializable. + + The values can be accessed by attributes or by keys:: + + from waflib.ConfigSet import ConfigSet + env = ConfigSet() + env.FOO = 'test' + env['FOO'] = 'test' + """ + __slots__ = ('table', 'parent') + def __init__(self, filename=None): + self.table = {} + """ + Internal dict holding the object values + """ + #self.parent = None + + if filename: + self.load(filename) + + def __contains__(self, key): + """ + Enables the *in* syntax:: + + if 'foo' in env: + print(env['foo']) + """ + if key in self.table: + return True + try: + return self.parent.__contains__(key) + except AttributeError: + return False # parent may not exist + + def keys(self): + """Dict interface""" + keys = set() + cur = self + while cur: + keys.update(cur.table.keys()) + cur = getattr(cur, 'parent', None) + keys = list(keys) + keys.sort() + return keys + + def __iter__(self): + return iter(self.keys()) + + def __str__(self): + """Text representation of the ConfigSet (for debugging purposes)""" + return "\n".join(["%r %r" % (x, self.__getitem__(x)) for x in self.keys()]) + + def __getitem__(self, key): + """ + Dictionary interface: get value from key:: + + def configure(conf): + conf.env['foo'] = {} + print(env['foo']) + """ + try: + while 1: + x = self.table.get(key) + if not x is None: + return x + self = self.parent + except AttributeError: + return [] + + def __setitem__(self, key, value): + """ + Dictionary interface: set value from key + """ + self.table[key] = value + + def __delitem__(self, key): + """ + Dictionary interface: mark the value as missing + """ + self[key] = [] + + def __getattr__(self, name): + """ + Attribute access provided for convenience. The following forms are equivalent:: + + def configure(conf): + conf.env.value + conf.env['value'] + """ + if name in self.__slots__: + return object.__getattribute__(self, name) + else: + return self[name] + + def __setattr__(self, name, value): + """ + Attribute access provided for convenience. The following forms are equivalent:: + + def configure(conf): + conf.env.value = x + env['value'] = x + """ + if name in self.__slots__: + object.__setattr__(self, name, value) + else: + self[name] = value + + def __delattr__(self, name): + """ + Attribute access provided for convenience. The following forms are equivalent:: + + def configure(conf): + del env.value + del env['value'] + """ + if name in self.__slots__: + object.__delattr__(self, name) + else: + del self[name] + + def derive(self): + """ + Returns a new ConfigSet deriving from self. The copy returned + will be a shallow copy:: + + from waflib.ConfigSet import ConfigSet + env = ConfigSet() + env.append_value('CFLAGS', ['-O2']) + child = env.derive() + child.CFLAGS.append('test') # warning! this will modify 'env' + child.CFLAGS = ['-O3'] # new list, ok + child.append_value('CFLAGS', ['-O3']) # ok + + Use :py:func:`ConfigSet.detach` to detach the child from the parent. + """ + newenv = ConfigSet() + newenv.parent = self + return newenv + + def detach(self): + """ + Detaches this instance from its parent (if present) + + Modifying the parent :py:class:`ConfigSet` will not change the current object + Modifying this :py:class:`ConfigSet` will not modify the parent one. + """ + tbl = self.get_merged_dict() + try: + delattr(self, 'parent') + except AttributeError: + pass + else: + keys = tbl.keys() + for x in keys: + tbl[x] = copy.deepcopy(tbl[x]) + self.table = tbl + return self + + def get_flat(self, key): + """ + Returns a value as a string. If the input is a list, the value returned is space-separated. + + :param key: key to use + :type key: string + """ + s = self[key] + if isinstance(s, str): + return s + return ' '.join(s) + + def _get_list_value_for_modification(self, key): + """ + Returns a list value for further modification. + + The list may be modified inplace and there is no need to do this afterwards:: + + self.table[var] = value + """ + try: + value = self.table[key] + except KeyError: + try: + value = self.parent[key] + except AttributeError: + value = [] + else: + if isinstance(value, list): + # force a copy + value = value[:] + else: + value = [value] + self.table[key] = value + else: + if not isinstance(value, list): + self.table[key] = value = [value] + return value + + def append_value(self, var, val): + """ + Appends a value to the specified config key:: + + def build(bld): + bld.env.append_value('CFLAGS', ['-O2']) + + The value must be a list or a tuple + """ + if isinstance(val, str): # if there were string everywhere we could optimize this + val = [val] + current_value = self._get_list_value_for_modification(var) + current_value.extend(val) + + def prepend_value(self, var, val): + """ + Prepends a value to the specified item:: + + def configure(conf): + conf.env.prepend_value('CFLAGS', ['-O2']) + + The value must be a list or a tuple + """ + if isinstance(val, str): + val = [val] + self.table[var] = val + self._get_list_value_for_modification(var) + + def append_unique(self, var, val): + """ + Appends a value to the specified item only if it's not already present:: + + def build(bld): + bld.env.append_unique('CFLAGS', ['-O2', '-g']) + + The value must be a list or a tuple + """ + if isinstance(val, str): + val = [val] + current_value = self._get_list_value_for_modification(var) + + for x in val: + if x not in current_value: + current_value.append(x) + + def get_merged_dict(self): + """ + Computes the merged dictionary from the fusion of self and all its parent + + :rtype: a ConfigSet object + """ + table_list = [] + env = self + while 1: + table_list.insert(0, env.table) + try: + env = env.parent + except AttributeError: + break + merged_table = {} + for table in table_list: + merged_table.update(table) + return merged_table + + def store(self, filename): + """ + Serializes the :py:class:`ConfigSet` data to a file. See :py:meth:`ConfigSet.load` for reading such files. + + :param filename: file to use + :type filename: string + """ + try: + os.makedirs(os.path.split(filename)[0]) + except OSError: + pass + + buf = [] + merged_table = self.get_merged_dict() + keys = list(merged_table.keys()) + keys.sort() + + try: + fun = ascii + except NameError: + fun = repr + + for k in keys: + if k != 'undo_stack': + buf.append('%s = %s\n' % (k, fun(merged_table[k]))) + Utils.writef(filename, ''.join(buf)) + + def load(self, filename): + """ + Restores contents from a file (current values are not cleared). Files are written using :py:meth:`ConfigSet.store`. + + :param filename: file to use + :type filename: string + """ + tbl = self.table + code = Utils.readf(filename, m='r') + for m in re_imp.finditer(code): + g = m.group + tbl[g(2)] = eval(g(3)) + Logs.debug('env: %s', self.table) + + def update(self, d): + """ + Dictionary interface: replace values with the ones from another dict + + :param d: object to use the value from + :type d: dict-like object + """ + self.table.update(d) + + def stash(self): + """ + Stores the object state to provide transactionality semantics:: + + env = ConfigSet() + env.stash() + try: + env.append_value('CFLAGS', '-O3') + call_some_method(env) + finally: + env.revert() + + The history is kept in a stack, and is lost during the serialization by :py:meth:`ConfigSet.store` + """ + orig = self.table + tbl = self.table = self.table.copy() + for x in tbl.keys(): + tbl[x] = copy.deepcopy(tbl[x]) + self.undo_stack = self.undo_stack + [orig] + + def commit(self): + """ + Commits transactional changes. See :py:meth:`ConfigSet.stash` + """ + self.undo_stack.pop(-1) + + def revert(self): + """ + Reverts the object to a previous state. See :py:meth:`ConfigSet.stash` + """ + self.table = self.undo_stack.pop(-1) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Configure.py b/ldb-2.0.8/third_party/waf/waflib/Configure.py new file mode 100644 index 0000000..5762eb6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Configure.py @@ -0,0 +1,649 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Configuration system + +A :py:class:`waflib.Configure.ConfigurationContext` instance is created when ``waf configure`` is called, it is used to: + +* create data dictionaries (ConfigSet instances) +* store the list of modules to import +* hold configuration routines such as ``find_program``, etc +""" + +import os, re, shlex, shutil, sys, time, traceback +from waflib import ConfigSet, Utils, Options, Logs, Context, Build, Errors + +WAF_CONFIG_LOG = 'config.log' +"""Name of the configuration log file""" + +autoconfig = False +"""Execute the configuration automatically""" + +conf_template = '''# project %(app)s configured on %(now)s by +# waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s) +# using %(args)s +#''' + +class ConfigurationContext(Context.Context): + '''configures the project''' + + cmd = 'configure' + + error_handlers = [] + """ + Additional functions to handle configuration errors + """ + + def __init__(self, **kw): + super(ConfigurationContext, self).__init__(**kw) + self.environ = dict(os.environ) + self.all_envs = {} + + self.top_dir = None + self.out_dir = None + + self.tools = [] # tools loaded in the configuration, and that will be loaded when building + + self.hash = 0 + self.files = [] + + self.tool_cache = [] + + self.setenv('') + + def setenv(self, name, env=None): + """ + Set a new config set for conf.env. If a config set of that name already exists, + recall it without modification. + + The name is the filename prefix to save to ``c4che/NAME_cache.py``, and it + is also used as *variants* by the build commands. + Though related to variants, whatever kind of data may be stored in the config set:: + + def configure(cfg): + cfg.env.ONE = 1 + cfg.setenv('foo') + cfg.env.ONE = 2 + + def build(bld): + 2 == bld.env_of_name('foo').ONE + + :param name: name of the configuration set + :type name: string + :param env: ConfigSet to copy, or an empty ConfigSet is created + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + """ + if name not in self.all_envs or env: + if not env: + env = ConfigSet.ConfigSet() + self.prepare_env(env) + else: + env = env.derive() + self.all_envs[name] = env + self.variant = name + + def get_env(self): + """Getter for the env property""" + return self.all_envs[self.variant] + def set_env(self, val): + """Setter for the env property""" + self.all_envs[self.variant] = val + + env = property(get_env, set_env) + + def init_dirs(self): + """ + Initialize the project directory and the build directory + """ + + top = self.top_dir + if not top: + top = Options.options.top + if not top: + top = getattr(Context.g_module, Context.TOP, None) + if not top: + top = self.path.abspath() + top = os.path.abspath(top) + + self.srcnode = (os.path.isabs(top) and self.root or self.path).find_dir(top) + assert(self.srcnode) + + out = self.out_dir + if not out: + out = Options.options.out + if not out: + out = getattr(Context.g_module, Context.OUT, None) + if not out: + out = Options.lockfile.replace('.lock-waf_%s_' % sys.platform, '').replace('.lock-waf', '') + + # someone can be messing with symlinks + out = os.path.realpath(out) + + self.bldnode = (os.path.isabs(out) and self.root or self.path).make_node(out) + self.bldnode.mkdir() + + if not os.path.isdir(self.bldnode.abspath()): + self.fatal('Could not create the build directory %s' % self.bldnode.abspath()) + + def execute(self): + """ + See :py:func:`waflib.Context.Context.execute` + """ + self.init_dirs() + + self.cachedir = self.bldnode.make_node(Build.CACHE_DIR) + self.cachedir.mkdir() + + path = os.path.join(self.bldnode.abspath(), WAF_CONFIG_LOG) + self.logger = Logs.make_logger(path, 'cfg') + + app = getattr(Context.g_module, 'APPNAME', '') + if app: + ver = getattr(Context.g_module, 'VERSION', '') + if ver: + app = "%s (%s)" % (app, ver) + + params = {'now': time.ctime(), 'pyver': sys.hexversion, 'systype': sys.platform, 'args': " ".join(sys.argv), 'wafver': Context.WAFVERSION, 'abi': Context.ABI, 'app': app} + self.to_log(conf_template % params) + self.msg('Setting top to', self.srcnode.abspath()) + self.msg('Setting out to', self.bldnode.abspath()) + + if id(self.srcnode) == id(self.bldnode): + Logs.warn('Setting top == out') + elif id(self.path) != id(self.srcnode): + if self.srcnode.is_child_of(self.path): + Logs.warn('Are you certain that you do not want to set top="." ?') + + super(ConfigurationContext, self).execute() + + self.store() + + Context.top_dir = self.srcnode.abspath() + Context.out_dir = self.bldnode.abspath() + + # this will write a configure lock so that subsequent builds will + # consider the current path as the root directory (see prepare_impl). + # to remove: use 'waf distclean' + env = ConfigSet.ConfigSet() + env.argv = sys.argv + env.options = Options.options.__dict__ + env.config_cmd = self.cmd + + env.run_dir = Context.run_dir + env.top_dir = Context.top_dir + env.out_dir = Context.out_dir + + # conf.hash & conf.files hold wscript files paths and hash + # (used only by Configure.autoconfig) + env.hash = self.hash + env.files = self.files + env.environ = dict(self.environ) + env.launch_dir = Context.launch_dir + + if not (self.env.NO_LOCK_IN_RUN or env.environ.get('NO_LOCK_IN_RUN') or getattr(Options.options, 'no_lock_in_run')): + env.store(os.path.join(Context.run_dir, Options.lockfile)) + if not (self.env.NO_LOCK_IN_TOP or env.environ.get('NO_LOCK_IN_TOP') or getattr(Options.options, 'no_lock_in_top')): + env.store(os.path.join(Context.top_dir, Options.lockfile)) + if not (self.env.NO_LOCK_IN_OUT or env.environ.get('NO_LOCK_IN_OUT') or getattr(Options.options, 'no_lock_in_out')): + env.store(os.path.join(Context.out_dir, Options.lockfile)) + + def prepare_env(self, env): + """ + Insert *PREFIX*, *BINDIR* and *LIBDIR* values into ``env`` + + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :param env: a ConfigSet, usually ``conf.env`` + """ + if not env.PREFIX: + if Options.options.prefix or Utils.is_win32: + env.PREFIX = Options.options.prefix + else: + env.PREFIX = '/' + if not env.BINDIR: + if Options.options.bindir: + env.BINDIR = Options.options.bindir + else: + env.BINDIR = Utils.subst_vars('${PREFIX}/bin', env) + if not env.LIBDIR: + if Options.options.libdir: + env.LIBDIR = Options.options.libdir + else: + env.LIBDIR = Utils.subst_vars('${PREFIX}/lib%s' % Utils.lib64(), env) + + def store(self): + """Save the config results into the cache file""" + n = self.cachedir.make_node('build.config.py') + n.write('version = 0x%x\ntools = %r\n' % (Context.HEXVERSION, self.tools)) + + if not self.all_envs: + self.fatal('nothing to store in the configuration context!') + + for key in self.all_envs: + tmpenv = self.all_envs[key] + tmpenv.store(os.path.join(self.cachedir.abspath(), key + Build.CACHE_SUFFIX)) + + def load(self, tool_list, tooldir=None, funs=None, with_sys_path=True, cache=False): + """ + Load Waf tools, which will be imported whenever a build is started. + + :param tool_list: waf tools to import + :type tool_list: list of string + :param tooldir: paths for the imports + :type tooldir: list of string + :param funs: functions to execute from the waf tools + :type funs: list of string + :param cache: whether to prevent the tool from running twice + :type cache: bool + """ + + tools = Utils.to_list(tool_list) + if tooldir: + tooldir = Utils.to_list(tooldir) + for tool in tools: + # avoid loading the same tool more than once with the same functions + # used by composite projects + + if cache: + mag = (tool, id(self.env), tooldir, funs) + if mag in self.tool_cache: + self.to_log('(tool %s is already loaded, skipping)' % tool) + continue + self.tool_cache.append(mag) + + module = None + try: + module = Context.load_tool(tool, tooldir, ctx=self, with_sys_path=with_sys_path) + except ImportError as e: + self.fatal('Could not load the Waf tool %r from %r\n%s' % (tool, getattr(e, 'waf_sys_path', sys.path), e)) + except Exception as e: + self.to_log('imp %r (%r & %r)' % (tool, tooldir, funs)) + self.to_log(traceback.format_exc()) + raise + + if funs is not None: + self.eval_rules(funs) + else: + func = getattr(module, 'configure', None) + if func: + if type(func) is type(Utils.readf): + func(self) + else: + self.eval_rules(func) + + self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs}) + + def post_recurse(self, node): + """ + Records the path and a hash of the scripts visited, see :py:meth:`waflib.Context.Context.post_recurse` + + :param node: script + :type node: :py:class:`waflib.Node.Node` + """ + super(ConfigurationContext, self).post_recurse(node) + self.hash = Utils.h_list((self.hash, node.read('rb'))) + self.files.append(node.abspath()) + + def eval_rules(self, rules): + """ + Execute configuration tests provided as list of functions to run + + :param rules: list of configuration method names + :type rules: list of string + """ + self.rules = Utils.to_list(rules) + for x in self.rules: + f = getattr(self, x) + if not f: + self.fatal('No such configuration function %r' % x) + f() + +def conf(f): + """ + Decorator: attach new configuration functions to :py:class:`waflib.Build.BuildContext` and + :py:class:`waflib.Configure.ConfigurationContext`. The methods bound will accept a parameter + named 'mandatory' to disable the configuration errors:: + + def configure(conf): + conf.find_program('abc', mandatory=False) + + :param f: method to bind + :type f: function + """ + def fun(*k, **kw): + mandatory = kw.pop('mandatory', True) + try: + return f(*k, **kw) + except Errors.ConfigurationError: + if mandatory: + raise + + fun.__name__ = f.__name__ + setattr(ConfigurationContext, f.__name__, fun) + setattr(Build.BuildContext, f.__name__, fun) + return f + +@conf +def add_os_flags(self, var, dest=None, dup=False): + """ + Import operating system environment values into ``conf.env`` dict:: + + def configure(conf): + conf.add_os_flags('CFLAGS') + + :param var: variable to use + :type var: string + :param dest: destination variable, by default the same as var + :type dest: string + :param dup: add the same set of flags again + :type dup: bool + """ + try: + flags = shlex.split(self.environ[var]) + except KeyError: + return + if dup or ''.join(flags) not in ''.join(Utils.to_list(self.env[dest or var])): + self.env.append_value(dest or var, flags) + +@conf +def cmd_to_list(self, cmd): + """ + Detect if a command is written in pseudo shell like ``ccache g++`` and return a list. + + :param cmd: command + :type cmd: a string or a list of string + """ + if isinstance(cmd, str): + if os.path.isfile(cmd): + # do not take any risk + return [cmd] + if os.sep == '/': + return shlex.split(cmd) + else: + try: + return shlex.split(cmd, posix=False) + except TypeError: + # Python 2.5 on windows? + return shlex.split(cmd) + return cmd + +@conf +def check_waf_version(self, mini='1.9.99', maxi='2.1.0', **kw): + """ + Raise a Configuration error if the Waf version does not strictly match the given bounds:: + + conf.check_waf_version(mini='1.9.99', maxi='2.1.0') + + :type mini: number, tuple or string + :param mini: Minimum required version + :type maxi: number, tuple or string + :param maxi: Maximum allowed version + """ + self.start_msg('Checking for waf version in %s-%s' % (str(mini), str(maxi)), **kw) + ver = Context.HEXVERSION + if Utils.num2ver(mini) > ver: + self.fatal('waf version should be at least %r (%r found)' % (Utils.num2ver(mini), ver)) + if Utils.num2ver(maxi) < ver: + self.fatal('waf version should be at most %r (%r found)' % (Utils.num2ver(maxi), ver)) + self.end_msg('ok', **kw) + +@conf +def find_file(self, filename, path_list=[]): + """ + Find a file in a list of paths + + :param filename: name of the file to search for + :param path_list: list of directories to search + :return: the first matching filename; else a configuration exception is raised + """ + for n in Utils.to_list(filename): + for d in Utils.to_list(path_list): + p = os.path.expanduser(os.path.join(d, n)) + if os.path.exists(p): + return p + self.fatal('Could not find %r' % filename) + +@conf +def find_program(self, filename, **kw): + """ + Search for a program on the operating system + + When var is used, you may set os.environ[var] to help find a specific program version, for example:: + + $ CC='ccache gcc' waf configure + + :param path_list: paths to use for searching + :type param_list: list of string + :param var: store the result to conf.env[var] where var defaults to filename.upper() if not provided; the result is stored as a list of strings + :type var: string + :param value: obtain the program from the value passed exclusively + :type value: list or string (list is preferred) + :param exts: list of extensions for the binary (do not add an extension for portability) + :type exts: list of string + :param msg: name to display in the log, by default filename is used + :type msg: string + :param interpreter: interpreter for the program + :type interpreter: ConfigSet variable key + :raises: :py:class:`waflib.Errors.ConfigurationError` + """ + + exts = kw.get('exts', Utils.is_win32 and '.exe,.com,.bat,.cmd' or ',.sh,.pl,.py') + + environ = kw.get('environ', getattr(self, 'environ', os.environ)) + + ret = '' + + filename = Utils.to_list(filename) + msg = kw.get('msg', ', '.join(filename)) + + var = kw.get('var', '') + if not var: + var = re.sub(r'[-.]', '_', filename[0].upper()) + + path_list = kw.get('path_list', '') + if path_list: + path_list = Utils.to_list(path_list) + else: + path_list = environ.get('PATH', '').split(os.pathsep) + + if kw.get('value'): + # user-provided in command-line options and passed to find_program + ret = self.cmd_to_list(kw['value']) + elif environ.get(var): + # user-provided in the os environment + ret = self.cmd_to_list(environ[var]) + elif self.env[var]: + # a default option in the wscript file + ret = self.cmd_to_list(self.env[var]) + else: + if not ret: + ret = self.find_binary(filename, exts.split(','), path_list) + if not ret and Utils.winreg: + ret = Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER, filename) + if not ret and Utils.winreg: + ret = Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE, filename) + ret = self.cmd_to_list(ret) + + if ret: + if len(ret) == 1: + retmsg = ret[0] + else: + retmsg = ret + else: + retmsg = False + + self.msg('Checking for program %r' % msg, retmsg, **kw) + if not kw.get('quiet'): + self.to_log('find program=%r paths=%r var=%r -> %r' % (filename, path_list, var, ret)) + + if not ret: + self.fatal(kw.get('errmsg', '') or 'Could not find the program %r' % filename) + + interpreter = kw.get('interpreter') + if interpreter is None: + if not Utils.check_exe(ret[0], env=environ): + self.fatal('Program %r is not executable' % ret) + self.env[var] = ret + else: + self.env[var] = self.env[interpreter] + ret + + return ret + +@conf +def find_binary(self, filenames, exts, paths): + for f in filenames: + for ext in exts: + exe_name = f + ext + if os.path.isabs(exe_name): + if os.path.isfile(exe_name): + return exe_name + else: + for path in paths: + x = os.path.expanduser(os.path.join(path, exe_name)) + if os.path.isfile(x): + return x + return None + +@conf +def run_build(self, *k, **kw): + """ + Create a temporary build context to execute a build. A reference to that build + context is kept on self.test_bld for debugging purposes, and you should not rely + on it too much (read the note on the cache below). + The parameters given in the arguments to this function are passed as arguments for + a single task generator created in the build. Only three parameters are obligatory: + + :param features: features to pass to a task generator created in the build + :type features: list of string + :param compile_filename: file to create for the compilation (default: *test.c*) + :type compile_filename: string + :param code: code to write in the filename to compile + :type code: string + + Though this function returns *0* by default, the build may set an attribute named *retval* on the + build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. + + This function also features a cache which can be enabled by the following option:: + + def options(opt): + opt.add_option('--confcache', dest='confcache', default=0, + action='count', help='Use a configuration cache') + + And execute the configuration with the following command-line:: + + $ waf configure --confcache + + """ + buf = [] + for key in sorted(kw.keys()): + v = kw[key] + if hasattr(v, '__call__'): + buf.append(Utils.h_fun(v)) + else: + buf.append(str(v)) + h = Utils.h_list(buf) + dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) + + cachemode = kw.get('confcache', getattr(Options.options, 'confcache', None)) + + if not cachemode and os.path.exists(dir): + shutil.rmtree(dir) + + try: + os.makedirs(dir) + except OSError: + pass + + try: + os.stat(dir) + except OSError: + self.fatal('cannot use the configuration test folder %r' % dir) + + if cachemode == 1: + try: + proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_build')) + except EnvironmentError: + pass + else: + ret = proj['cache_run_build'] + if isinstance(ret, str) and ret.startswith('Test does not build'): + self.fatal(ret) + return ret + + bdir = os.path.join(dir, 'testbuild') + + if not os.path.exists(bdir): + os.makedirs(bdir) + + cls_name = kw.get('run_build_cls') or getattr(self, 'run_build_cls', 'build') + self.test_bld = bld = Context.create_context(cls_name, top_dir=dir, out_dir=bdir) + bld.init_dirs() + bld.progress_bar = 0 + bld.targets = '*' + + bld.logger = self.logger + bld.all_envs.update(self.all_envs) # not really necessary + bld.env = kw['env'] + + bld.kw = kw + bld.conf = self + kw['build_fun'](bld) + ret = -1 + try: + try: + bld.compile() + except Errors.WafError: + ret = 'Test does not build: %s' % traceback.format_exc() + self.fatal(ret) + else: + ret = getattr(bld, 'retval', 0) + finally: + if cachemode: + # cache the results each time + proj = ConfigSet.ConfigSet() + proj['cache_run_build'] = ret + proj.store(os.path.join(dir, 'cache_run_build')) + else: + shutil.rmtree(dir) + return ret + +@conf +def ret_msg(self, msg, args): + if isinstance(msg, str): + return msg + return msg(args) + +@conf +def test(self, *k, **kw): + + if not 'env' in kw: + kw['env'] = self.env.derive() + + # validate_c for example + if kw.get('validate'): + kw['validate'](kw) + + self.start_msg(kw['msg'], **kw) + ret = None + try: + ret = self.run_build(*k, **kw) + except self.errors.ConfigurationError: + self.end_msg(kw['errmsg'], 'YELLOW', **kw) + if Logs.verbose > 1: + raise + else: + self.fatal('The configuration failed') + else: + kw['success'] = ret + + if kw.get('post_check'): + ret = kw['post_check'](kw) + + if ret: + self.end_msg(kw['errmsg'], 'YELLOW', **kw) + self.fatal('The configuration failed %r' % ret) + else: + self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) + return ret + diff --git a/ldb-2.0.8/third_party/waf/waflib/Context.py b/ldb-2.0.8/third_party/waf/waflib/Context.py new file mode 100644 index 0000000..e3305fa --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Context.py @@ -0,0 +1,737 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010-2018 (ita) + +""" +Classes and functions enabling the command system +""" + +import os, re, imp, sys +from waflib import Utils, Errors, Logs +import waflib.Node + +# the following 3 constants are updated on each new release (do not touch) +HEXVERSION=0x2001200 +"""Constant updated on new releases""" + +WAFVERSION="2.0.18" +"""Constant updated on new releases""" + +WAFREVISION="314689b8994259a84f0de0aaef74d7ce91f541ad" +"""Git revision when the waf version is updated""" + +ABI = 20 +"""Version of the build data cache file format (used in :py:const:`waflib.Context.DBFILE`)""" + +DBFILE = '.wafpickle-%s-%d-%d' % (sys.platform, sys.hexversion, ABI) +"""Name of the pickle file for storing the build data""" + +APPNAME = 'APPNAME' +"""Default application name (used by ``waf dist``)""" + +VERSION = 'VERSION' +"""Default application version (used by ``waf dist``)""" + +TOP = 'top' +"""The variable name for the top-level directory in wscript files""" + +OUT = 'out' +"""The variable name for the output directory in wscript files""" + +WSCRIPT_FILE = 'wscript' +"""Name of the waf script files""" + +launch_dir = '' +"""Directory from which waf has been called""" +run_dir = '' +"""Location of the wscript file to use as the entry point""" +top_dir = '' +"""Location of the project directory (top), if the project was configured""" +out_dir = '' +"""Location of the build directory (out), if the project was configured""" +waf_dir = '' +"""Directory containing the waf modules""" + +default_encoding = Utils.console_encoding() +"""Encoding to use when reading outputs from other processes""" + +g_module = None +""" +Module representing the top-level wscript file (see :py:const:`waflib.Context.run_dir`) +""" + +STDOUT = 1 +STDERR = -1 +BOTH = 0 + +classes = [] +""" +List of :py:class:`waflib.Context.Context` subclasses that can be used as waf commands. The classes +are added automatically by a metaclass. +""" + +def create_context(cmd_name, *k, **kw): + """ + Returns a new :py:class:`waflib.Context.Context` instance corresponding to the given command. + Used in particular by :py:func:`waflib.Scripting.run_command` + + :param cmd_name: command name + :type cmd_name: string + :param k: arguments to give to the context class initializer + :type k: list + :param k: keyword arguments to give to the context class initializer + :type k: dict + :return: Context object + :rtype: :py:class:`waflib.Context.Context` + """ + for x in classes: + if x.cmd == cmd_name: + return x(*k, **kw) + ctx = Context(*k, **kw) + ctx.fun = cmd_name + return ctx + +class store_context(type): + """ + Metaclass that registers command classes into the list :py:const:`waflib.Context.classes` + Context classes must provide an attribute 'cmd' representing the command name, and a function + attribute 'fun' representing the function name that the command uses. + """ + def __init__(cls, name, bases, dct): + super(store_context, cls).__init__(name, bases, dct) + name = cls.__name__ + + if name in ('ctx', 'Context'): + return + + try: + cls.cmd + except AttributeError: + raise Errors.WafError('Missing command for the context class %r (cmd)' % name) + + if not getattr(cls, 'fun', None): + cls.fun = cls.cmd + + classes.insert(0, cls) + +ctx = store_context('ctx', (object,), {}) +"""Base class for all :py:class:`waflib.Context.Context` classes""" + +class Context(ctx): + """ + Default context for waf commands, and base class for new command contexts. + + Context objects are passed to top-level functions:: + + def foo(ctx): + print(ctx.__class__.__name__) # waflib.Context.Context + + Subclasses must define the class attributes 'cmd' and 'fun': + + :param cmd: command to execute as in ``waf cmd`` + :type cmd: string + :param fun: function name to execute when the command is called + :type fun: string + + .. inheritance-diagram:: waflib.Context.Context waflib.Build.BuildContext waflib.Build.InstallContext waflib.Build.UninstallContext waflib.Build.StepContext waflib.Build.ListContext waflib.Configure.ConfigurationContext waflib.Scripting.Dist waflib.Scripting.DistCheck waflib.Build.CleanContext + + """ + + errors = Errors + """ + Shortcut to :py:mod:`waflib.Errors` provided for convenience + """ + + tools = {} + """ + A module cache for wscript files; see :py:meth:`Context.Context.load` + """ + + def __init__(self, **kw): + try: + rd = kw['run_dir'] + except KeyError: + rd = run_dir + + # binds the context to the nodes in use to avoid a context singleton + self.node_class = type('Nod3', (waflib.Node.Node,), {}) + self.node_class.__module__ = 'waflib.Node' + self.node_class.ctx = self + + self.root = self.node_class('', None) + self.cur_script = None + self.path = self.root.find_dir(rd) + + self.stack_path = [] + self.exec_dict = {'ctx':self, 'conf':self, 'bld':self, 'opt':self} + self.logger = None + + def finalize(self): + """ + Called to free resources such as logger files + """ + try: + logger = self.logger + except AttributeError: + pass + else: + Logs.free_logger(logger) + delattr(self, 'logger') + + def load(self, tool_list, *k, **kw): + """ + Loads a Waf tool as a module, and try calling the function named :py:const:`waflib.Context.Context.fun` + from it. A ``tooldir`` argument may be provided as a list of module paths. + + :param tool_list: list of Waf tool names to load + :type tool_list: list of string or space-separated string + """ + tools = Utils.to_list(tool_list) + path = Utils.to_list(kw.get('tooldir', '')) + with_sys_path = kw.get('with_sys_path', True) + + for t in tools: + module = load_tool(t, path, with_sys_path=with_sys_path) + fun = getattr(module, kw.get('name', self.fun), None) + if fun: + fun(self) + + def execute(self): + """ + Here, it calls the function name in the top-level wscript file. Most subclasses + redefine this method to provide additional functionality. + """ + self.recurse([os.path.dirname(g_module.root_path)]) + + def pre_recurse(self, node): + """ + Method executed immediately before a folder is read by :py:meth:`waflib.Context.Context.recurse`. + The current script is bound as a Node object on ``self.cur_script``, and the current path + is bound to ``self.path`` + + :param node: script + :type node: :py:class:`waflib.Node.Node` + """ + self.stack_path.append(self.cur_script) + + self.cur_script = node + self.path = node.parent + + def post_recurse(self, node): + """ + Restores ``self.cur_script`` and ``self.path`` right after :py:meth:`waflib.Context.Context.recurse` terminates. + + :param node: script + :type node: :py:class:`waflib.Node.Node` + """ + self.cur_script = self.stack_path.pop() + if self.cur_script: + self.path = self.cur_script.parent + + def recurse(self, dirs, name=None, mandatory=True, once=True, encoding=None): + """ + Runs user-provided functions from the supplied list of directories. + The directories can be either absolute, or relative to the directory + of the wscript file + + The methods :py:meth:`waflib.Context.Context.pre_recurse` and + :py:meth:`waflib.Context.Context.post_recurse` are called immediately before + and after a script has been executed. + + :param dirs: List of directories to visit + :type dirs: list of string or space-separated string + :param name: Name of function to invoke from the wscript + :type name: string + :param mandatory: whether sub wscript files are required to exist + :type mandatory: bool + :param once: read the script file once for a particular context + :type once: bool + """ + try: + cache = self.recurse_cache + except AttributeError: + cache = self.recurse_cache = {} + + for d in Utils.to_list(dirs): + + if not os.path.isabs(d): + # absolute paths only + d = os.path.join(self.path.abspath(), d) + + WSCRIPT = os.path.join(d, WSCRIPT_FILE) + WSCRIPT_FUN = WSCRIPT + '_' + (name or self.fun) + + node = self.root.find_node(WSCRIPT_FUN) + if node and (not once or node not in cache): + cache[node] = True + self.pre_recurse(node) + try: + function_code = node.read('r', encoding) + exec(compile(function_code, node.abspath(), 'exec'), self.exec_dict) + finally: + self.post_recurse(node) + elif not node: + node = self.root.find_node(WSCRIPT) + tup = (node, name or self.fun) + if node and (not once or tup not in cache): + cache[tup] = True + self.pre_recurse(node) + try: + wscript_module = load_module(node.abspath(), encoding=encoding) + user_function = getattr(wscript_module, (name or self.fun), None) + if not user_function: + if not mandatory: + continue + raise Errors.WafError('No function %r defined in %s' % (name or self.fun, node.abspath())) + user_function(self) + finally: + self.post_recurse(node) + elif not node: + if not mandatory: + continue + try: + os.listdir(d) + except OSError: + raise Errors.WafError('Cannot read the folder %r' % d) + raise Errors.WafError('No wscript file in directory %s' % d) + + def log_command(self, cmd, kw): + if Logs.verbose: + fmt = os.environ.get('WAF_CMD_FORMAT') + if fmt == 'string': + if not isinstance(cmd, str): + cmd = Utils.shell_escape(cmd) + Logs.debug('runner: %r', cmd) + Logs.debug('runner_env: kw=%s', kw) + + def exec_command(self, cmd, **kw): + """ + Runs an external process and returns the exit status:: + + def run(tsk): + ret = tsk.generator.bld.exec_command('touch foo.txt') + return ret + + If the context has the attribute 'log', then captures and logs the process stderr/stdout. + Unlike :py:meth:`waflib.Context.Context.cmd_and_log`, this method does not return the + stdout/stderr values captured. + + :param cmd: command argument for subprocess.Popen + :type cmd: string or list + :param kw: keyword arguments for subprocess.Popen. The parameters input/timeout will be passed to wait/communicate. + :type kw: dict + :returns: process exit status + :rtype: integer + :raises: :py:class:`waflib.Errors.WafError` if an invalid executable is specified for a non-shell process + :raises: :py:class:`waflib.Errors.WafError` in case of execution failure + """ + subprocess = Utils.subprocess + kw['shell'] = isinstance(cmd, str) + self.log_command(cmd, kw) + + if self.logger: + self.logger.info(cmd) + + if 'stdout' not in kw: + kw['stdout'] = subprocess.PIPE + if 'stderr' not in kw: + kw['stderr'] = subprocess.PIPE + + if Logs.verbose and not kw['shell'] and not Utils.check_exe(cmd[0]): + raise Errors.WafError('Program %s not found!' % cmd[0]) + + cargs = {} + if 'timeout' in kw: + if sys.hexversion >= 0x3030000: + cargs['timeout'] = kw['timeout'] + if not 'start_new_session' in kw: + kw['start_new_session'] = True + del kw['timeout'] + if 'input' in kw: + if kw['input']: + cargs['input'] = kw['input'] + kw['stdin'] = subprocess.PIPE + del kw['input'] + + if 'cwd' in kw: + if not isinstance(kw['cwd'], str): + kw['cwd'] = kw['cwd'].abspath() + + encoding = kw.pop('decode_as', default_encoding) + + try: + ret, out, err = Utils.run_process(cmd, kw, cargs) + except Exception as e: + raise Errors.WafError('Execution failure: %s' % str(e), ex=e) + + if out: + if not isinstance(out, str): + out = out.decode(encoding, errors='replace') + if self.logger: + self.logger.debug('out: %s', out) + else: + Logs.info(out, extra={'stream':sys.stdout, 'c1': ''}) + if err: + if not isinstance(err, str): + err = err.decode(encoding, errors='replace') + if self.logger: + self.logger.error('err: %s' % err) + else: + Logs.info(err, extra={'stream':sys.stderr, 'c1': ''}) + + return ret + + def cmd_and_log(self, cmd, **kw): + """ + Executes a process and returns stdout/stderr if the execution is successful. + An exception is thrown when the exit status is non-0. In that case, both stderr and stdout + will be bound to the WafError object (configuration tests):: + + def configure(conf): + out = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.STDOUT, quiet=waflib.Context.BOTH) + (out, err) = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.BOTH) + (out, err) = conf.cmd_and_log(cmd, input='\\n'.encode(), output=waflib.Context.STDOUT) + try: + conf.cmd_and_log(['which', 'someapp'], output=waflib.Context.BOTH) + except Errors.WafError as e: + print(e.stdout, e.stderr) + + :param cmd: args for subprocess.Popen + :type cmd: list or string + :param kw: keyword arguments for subprocess.Popen. The parameters input/timeout will be passed to wait/communicate. + :type kw: dict + :returns: a tuple containing the contents of stdout and stderr + :rtype: string + :raises: :py:class:`waflib.Errors.WafError` if an invalid executable is specified for a non-shell process + :raises: :py:class:`waflib.Errors.WafError` in case of execution failure; stdout/stderr/returncode are bound to the exception object + """ + subprocess = Utils.subprocess + kw['shell'] = isinstance(cmd, str) + self.log_command(cmd, kw) + + quiet = kw.pop('quiet', None) + to_ret = kw.pop('output', STDOUT) + + if Logs.verbose and not kw['shell'] and not Utils.check_exe(cmd[0]): + raise Errors.WafError('Program %r not found!' % cmd[0]) + + kw['stdout'] = kw['stderr'] = subprocess.PIPE + if quiet is None: + self.to_log(cmd) + + cargs = {} + if 'timeout' in kw: + if sys.hexversion >= 0x3030000: + cargs['timeout'] = kw['timeout'] + if not 'start_new_session' in kw: + kw['start_new_session'] = True + del kw['timeout'] + if 'input' in kw: + if kw['input']: + cargs['input'] = kw['input'] + kw['stdin'] = subprocess.PIPE + del kw['input'] + + if 'cwd' in kw: + if not isinstance(kw['cwd'], str): + kw['cwd'] = kw['cwd'].abspath() + + encoding = kw.pop('decode_as', default_encoding) + + try: + ret, out, err = Utils.run_process(cmd, kw, cargs) + except Exception as e: + raise Errors.WafError('Execution failure: %s' % str(e), ex=e) + + if not isinstance(out, str): + out = out.decode(encoding, errors='replace') + if not isinstance(err, str): + err = err.decode(encoding, errors='replace') + + if out and quiet != STDOUT and quiet != BOTH: + self.to_log('out: %s' % out) + if err and quiet != STDERR and quiet != BOTH: + self.to_log('err: %s' % err) + + if ret: + e = Errors.WafError('Command %r returned %r' % (cmd, ret)) + e.returncode = ret + e.stderr = err + e.stdout = out + raise e + + if to_ret == BOTH: + return (out, err) + elif to_ret == STDERR: + return err + return out + + def fatal(self, msg, ex=None): + """ + Prints an error message in red and stops command execution; this is + usually used in the configuration section:: + + def configure(conf): + conf.fatal('a requirement is missing') + + :param msg: message to display + :type msg: string + :param ex: optional exception object + :type ex: exception + :raises: :py:class:`waflib.Errors.ConfigurationError` + """ + if self.logger: + self.logger.info('from %s: %s' % (self.path.abspath(), msg)) + try: + logfile = self.logger.handlers[0].baseFilename + except AttributeError: + pass + else: + if os.environ.get('WAF_PRINT_FAILURE_LOG'): + # see #1930 + msg = 'Log from (%s):\n%s\n' % (logfile, Utils.readf(logfile)) + else: + msg = '%s\n(complete log in %s)' % (msg, logfile) + raise self.errors.ConfigurationError(msg, ex=ex) + + def to_log(self, msg): + """ + Logs information to the logger (if present), or to stderr. + Empty messages are not printed:: + + def build(bld): + bld.to_log('starting the build') + + Provide a logger on the context class or override this method if necessary. + + :param msg: message + :type msg: string + """ + if not msg: + return + if self.logger: + self.logger.info(msg) + else: + sys.stderr.write(str(msg)) + sys.stderr.flush() + + + def msg(self, *k, **kw): + """ + Prints a configuration message of the form ``msg: result``. + The second part of the message will be in colors. The output + can be disabled easly by setting ``in_msg`` to a positive value:: + + def configure(conf): + self.in_msg = 1 + conf.msg('Checking for library foo', 'ok') + # no output + + :param msg: message to display to the user + :type msg: string + :param result: result to display + :type result: string or boolean + :param color: color to use, see :py:const:`waflib.Logs.colors_lst` + :type color: string + """ + try: + msg = kw['msg'] + except KeyError: + msg = k[0] + + self.start_msg(msg, **kw) + + try: + result = kw['result'] + except KeyError: + result = k[1] + + color = kw.get('color') + if not isinstance(color, str): + color = result and 'GREEN' or 'YELLOW' + + self.end_msg(result, color, **kw) + + def start_msg(self, *k, **kw): + """ + Prints the beginning of a 'Checking for xxx' message. See :py:meth:`waflib.Context.Context.msg` + """ + if kw.get('quiet'): + return + + msg = kw.get('msg') or k[0] + try: + if self.in_msg: + self.in_msg += 1 + return + except AttributeError: + self.in_msg = 0 + self.in_msg += 1 + + try: + self.line_just = max(self.line_just, len(msg)) + except AttributeError: + self.line_just = max(40, len(msg)) + for x in (self.line_just * '-', msg): + self.to_log(x) + Logs.pprint('NORMAL', "%s :" % msg.ljust(self.line_just), sep='') + + def end_msg(self, *k, **kw): + """Prints the end of a 'Checking for' message. See :py:meth:`waflib.Context.Context.msg`""" + if kw.get('quiet'): + return + self.in_msg -= 1 + if self.in_msg: + return + + result = kw.get('result') or k[0] + + defcolor = 'GREEN' + if result is True: + msg = 'ok' + elif not result: + msg = 'not found' + defcolor = 'YELLOW' + else: + msg = str(result) + + self.to_log(msg) + try: + color = kw['color'] + except KeyError: + if len(k) > 1 and k[1] in Logs.colors_lst: + # compatibility waf 1.7 + color = k[1] + else: + color = defcolor + Logs.pprint(color, msg) + + def load_special_tools(self, var, ban=[]): + """ + Loads third-party extensions modules for certain programming languages + by trying to list certain files in the extras/ directory. This method + is typically called once for a programming language group, see for + example :py:mod:`waflib.Tools.compiler_c` + + :param var: glob expression, for example 'cxx\\_\\*.py' + :type var: string + :param ban: list of exact file names to exclude + :type ban: list of string + """ + if os.path.isdir(waf_dir): + lst = self.root.find_node(waf_dir).find_node('waflib/extras').ant_glob(var) + for x in lst: + if not x.name in ban: + load_tool(x.name.replace('.py', '')) + else: + from zipfile import PyZipFile + waflibs = PyZipFile(waf_dir) + lst = waflibs.namelist() + for x in lst: + if not re.match('waflib/extras/%s' % var.replace('*', '.*'), var): + continue + f = os.path.basename(x) + doban = False + for b in ban: + r = b.replace('*', '.*') + if re.match(r, f): + doban = True + if not doban: + f = f.replace('.py', '') + load_tool(f) + +cache_modules = {} +""" +Dictionary holding already loaded modules (wscript), indexed by their absolute path. +The modules are added automatically by :py:func:`waflib.Context.load_module` +""" + +def load_module(path, encoding=None): + """ + Loads a wscript file as a python module. This method caches results in :py:attr:`waflib.Context.cache_modules` + + :param path: file path + :type path: string + :return: Loaded Python module + :rtype: module + """ + try: + return cache_modules[path] + except KeyError: + pass + + module = imp.new_module(WSCRIPT_FILE) + try: + code = Utils.readf(path, m='r', encoding=encoding) + except EnvironmentError: + raise Errors.WafError('Could not read the file %r' % path) + + module_dir = os.path.dirname(path) + sys.path.insert(0, module_dir) + try: + exec(compile(code, path, 'exec'), module.__dict__) + finally: + sys.path.remove(module_dir) + + cache_modules[path] = module + return module + +def load_tool(tool, tooldir=None, ctx=None, with_sys_path=True): + """ + Imports a Waf tool as a python module, and stores it in the dict :py:const:`waflib.Context.Context.tools` + + :type tool: string + :param tool: Name of the tool + :type tooldir: list + :param tooldir: List of directories to search for the tool module + :type with_sys_path: boolean + :param with_sys_path: whether or not to search the regular sys.path, besides waf_dir and potentially given tooldirs + """ + if tool == 'java': + tool = 'javaw' # jython + else: + tool = tool.replace('++', 'xx') + + if not with_sys_path: + back_path = sys.path + sys.path = [] + try: + if tooldir: + assert isinstance(tooldir, list) + sys.path = tooldir + sys.path + try: + __import__(tool) + except ImportError as e: + e.waf_sys_path = list(sys.path) + raise + finally: + for d in tooldir: + sys.path.remove(d) + ret = sys.modules[tool] + Context.tools[tool] = ret + return ret + else: + if not with_sys_path: + sys.path.insert(0, waf_dir) + try: + for x in ('waflib.Tools.%s', 'waflib.extras.%s', 'waflib.%s', '%s'): + try: + __import__(x % tool) + break + except ImportError: + x = None + else: # raise an exception + __import__(tool) + except ImportError as e: + e.waf_sys_path = list(sys.path) + raise + finally: + if not with_sys_path: + sys.path.remove(waf_dir) + ret = sys.modules[x % tool] + Context.tools[tool] = ret + return ret + finally: + if not with_sys_path: + sys.path += back_path + diff --git a/ldb-2.0.8/third_party/waf/waflib/Errors.py b/ldb-2.0.8/third_party/waf/waflib/Errors.py new file mode 100644 index 0000000..bf75c1b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Errors.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010-2018 (ita) + +""" +Exceptions used in the Waf code +""" + +import traceback, sys + +class WafError(Exception): + """Base class for all Waf errors""" + def __init__(self, msg='', ex=None): + """ + :param msg: error message + :type msg: string + :param ex: exception causing this error (optional) + :type ex: exception + """ + Exception.__init__(self) + self.msg = msg + assert not isinstance(msg, Exception) + + self.stack = [] + if ex: + if not msg: + self.msg = str(ex) + if isinstance(ex, WafError): + self.stack = ex.stack + else: + self.stack = traceback.extract_tb(sys.exc_info()[2]) + self.stack += traceback.extract_stack()[:-1] + self.verbose_msg = ''.join(traceback.format_list(self.stack)) + + def __str__(self): + return str(self.msg) + +class BuildError(WafError): + """Error raised during the build and install phases""" + def __init__(self, error_tasks=[]): + """ + :param error_tasks: tasks that could not complete normally + :type error_tasks: list of task objects + """ + self.tasks = error_tasks + WafError.__init__(self, self.format_error()) + + def format_error(self): + """Formats the error messages from the tasks that failed""" + lst = ['Build failed'] + for tsk in self.tasks: + txt = tsk.format_error() + if txt: + lst.append(txt) + return '\n'.join(lst) + +class ConfigurationError(WafError): + """Configuration exception raised in particular by :py:meth:`waflib.Context.Context.fatal`""" + pass + +class TaskRescan(WafError): + """Task-specific exception type signalling required signature recalculations""" + pass + +class TaskNotReady(WafError): + """Task-specific exception type signalling that task signatures cannot be computed""" + pass + diff --git a/ldb-2.0.8/third_party/waf/waflib/Logs.py b/ldb-2.0.8/third_party/waf/waflib/Logs.py new file mode 100644 index 0000000..298411d --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Logs.py @@ -0,0 +1,382 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +logging, colors, terminal width and pretty-print +""" + +import os, re, traceback, sys +from waflib import Utils, ansiterm + +if not os.environ.get('NOSYNC', False): + # synchronized output is nearly mandatory to prevent garbled output + if sys.stdout.isatty() and id(sys.stdout) == id(sys.__stdout__): + sys.stdout = ansiterm.AnsiTerm(sys.stdout) + if sys.stderr.isatty() and id(sys.stderr) == id(sys.__stderr__): + sys.stderr = ansiterm.AnsiTerm(sys.stderr) + +# import the logging module after since it holds a reference on sys.stderr +# in case someone uses the root logger +import logging + +LOG_FORMAT = os.environ.get('WAF_LOG_FORMAT', '%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s') +HOUR_FORMAT = os.environ.get('WAF_HOUR_FORMAT', '%H:%M:%S') + +zones = [] +""" +See :py:class:`waflib.Logs.log_filter` +""" + +verbose = 0 +""" +Global verbosity level, see :py:func:`waflib.Logs.debug` and :py:func:`waflib.Logs.error` +""" + +colors_lst = { +'USE' : True, +'BOLD' :'\x1b[01;1m', +'RED' :'\x1b[01;31m', +'GREEN' :'\x1b[32m', +'YELLOW':'\x1b[33m', +'PINK' :'\x1b[35m', +'BLUE' :'\x1b[01;34m', +'CYAN' :'\x1b[36m', +'GREY' :'\x1b[37m', +'NORMAL':'\x1b[0m', +'cursor_on' :'\x1b[?25h', +'cursor_off' :'\x1b[?25l', +} + +indicator = '\r\x1b[K%s%s%s' + +try: + unicode +except NameError: + unicode = None + +def enable_colors(use): + """ + If *1* is given, then the system will perform a few verifications + before enabling colors, such as checking whether the interpreter + is running in a terminal. A value of zero will disable colors, + and a value above *1* will force colors. + + :param use: whether to enable colors or not + :type use: integer + """ + if use == 1: + if not (sys.stderr.isatty() or sys.stdout.isatty()): + use = 0 + if Utils.is_win32 and os.name != 'java': + term = os.environ.get('TERM', '') # has ansiterm + else: + term = os.environ.get('TERM', 'dumb') + + if term in ('dumb', 'emacs'): + use = 0 + + if use >= 1: + os.environ['TERM'] = 'vt100' + + colors_lst['USE'] = use + +# If console packages are available, replace the dummy function with a real +# implementation +try: + get_term_cols = ansiterm.get_term_cols +except AttributeError: + def get_term_cols(): + return 80 + +get_term_cols.__doc__ = """ + Returns the console width in characters. + + :return: the number of characters per line + :rtype: int + """ + +def get_color(cl): + """ + Returns the ansi sequence corresponding to the given color name. + An empty string is returned when coloring is globally disabled. + + :param cl: color name in capital letters + :type cl: string + """ + if colors_lst['USE']: + return colors_lst.get(cl, '') + return '' + +class color_dict(object): + """attribute-based color access, eg: colors.PINK""" + def __getattr__(self, a): + return get_color(a) + def __call__(self, a): + return get_color(a) + +colors = color_dict() + +re_log = re.compile(r'(\w+): (.*)', re.M) +class log_filter(logging.Filter): + """ + Waf logs are of the form 'name: message', and can be filtered by 'waf --zones=name'. + For example, the following:: + + from waflib import Logs + Logs.debug('test: here is a message') + + Will be displayed only when executing:: + + $ waf --zones=test + """ + def __init__(self, name=''): + logging.Filter.__init__(self, name) + + def filter(self, rec): + """ + Filters log records by zone and by logging level + + :param rec: log entry + """ + rec.zone = rec.module + if rec.levelno >= logging.INFO: + return True + + m = re_log.match(rec.msg) + if m: + rec.zone = m.group(1) + rec.msg = m.group(2) + + if zones: + return getattr(rec, 'zone', '') in zones or '*' in zones + elif not verbose > 2: + return False + return True + +class log_handler(logging.StreamHandler): + """Dispatches messages to stderr/stdout depending on the severity level""" + def emit(self, record): + """ + Delegates the functionality to :py:meth:`waflib.Log.log_handler.emit_override` + """ + # default implementation + try: + try: + self.stream = record.stream + except AttributeError: + if record.levelno >= logging.WARNING: + record.stream = self.stream = sys.stderr + else: + record.stream = self.stream = sys.stdout + self.emit_override(record) + self.flush() + except (KeyboardInterrupt, SystemExit): + raise + except: # from the python library -_- + self.handleError(record) + + def emit_override(self, record, **kw): + """ + Writes the log record to the desired stream (stderr/stdout) + """ + self.terminator = getattr(record, 'terminator', '\n') + stream = self.stream + if unicode: + # python2 + msg = self.formatter.format(record) + fs = '%s' + self.terminator + try: + if (isinstance(msg, unicode) and getattr(stream, 'encoding', None)): + fs = fs.decode(stream.encoding) + try: + stream.write(fs % msg) + except UnicodeEncodeError: + stream.write((fs % msg).encode(stream.encoding)) + else: + stream.write(fs % msg) + except UnicodeError: + stream.write((fs % msg).encode('utf-8')) + else: + logging.StreamHandler.emit(self, record) + +class formatter(logging.Formatter): + """Simple log formatter which handles colors""" + def __init__(self): + logging.Formatter.__init__(self, LOG_FORMAT, HOUR_FORMAT) + + def format(self, rec): + """ + Formats records and adds colors as needed. The records do not get + a leading hour format if the logging level is above *INFO*. + """ + try: + msg = rec.msg.decode('utf-8') + except Exception: + msg = rec.msg + + use = colors_lst['USE'] + if (use == 1 and rec.stream.isatty()) or use == 2: + + c1 = getattr(rec, 'c1', None) + if c1 is None: + c1 = '' + if rec.levelno >= logging.ERROR: + c1 = colors.RED + elif rec.levelno >= logging.WARNING: + c1 = colors.YELLOW + elif rec.levelno >= logging.INFO: + c1 = colors.GREEN + c2 = getattr(rec, 'c2', colors.NORMAL) + msg = '%s%s%s' % (c1, msg, c2) + else: + # remove single \r that make long lines in text files + # and other terminal commands + msg = re.sub(r'\r(?!\n)|\x1B\[(K|.*?(m|h|l))', '', msg) + + if rec.levelno >= logging.INFO: + # the goal of this is to format without the leading "Logs, hour" prefix + if rec.args: + try: + return msg % rec.args + except UnicodeDecodeError: + return msg.encode('utf-8') % rec.args + return msg + + rec.msg = msg + rec.c1 = colors.PINK + rec.c2 = colors.NORMAL + return logging.Formatter.format(self, rec) + +log = None +"""global logger for Logs.debug, Logs.error, etc""" + +def debug(*k, **kw): + """ + Wraps logging.debug and discards messages if the verbosity level :py:attr:`waflib.Logs.verbose` ≤ 0 + """ + if verbose: + k = list(k) + k[0] = k[0].replace('\n', ' ') + log.debug(*k, **kw) + +def error(*k, **kw): + """ + Wrap logging.errors, adds the stack trace when the verbosity level :py:attr:`waflib.Logs.verbose` ≥ 2 + """ + log.error(*k, **kw) + if verbose > 2: + st = traceback.extract_stack() + if st: + st = st[:-1] + buf = [] + for filename, lineno, name, line in st: + buf.append(' File %r, line %d, in %s' % (filename, lineno, name)) + if line: + buf.append(' %s' % line.strip()) + if buf: + log.error('\n'.join(buf)) + +def warn(*k, **kw): + """ + Wraps logging.warning + """ + log.warning(*k, **kw) + +def info(*k, **kw): + """ + Wraps logging.info + """ + log.info(*k, **kw) + +def init_log(): + """ + Initializes the logger :py:attr:`waflib.Logs.log` + """ + global log + log = logging.getLogger('waflib') + log.handlers = [] + log.filters = [] + hdlr = log_handler() + hdlr.setFormatter(formatter()) + log.addHandler(hdlr) + log.addFilter(log_filter()) + log.setLevel(logging.DEBUG) + +def make_logger(path, name): + """ + Creates a simple logger, which is often used to redirect the context command output:: + + from waflib import Logs + bld.logger = Logs.make_logger('test.log', 'build') + bld.check(header_name='sadlib.h', features='cxx cprogram', mandatory=False) + + # have the file closed immediately + Logs.free_logger(bld.logger) + + # stop logging + bld.logger = None + + The method finalize() of the command will try to free the logger, if any + + :param path: file name to write the log output to + :type path: string + :param name: logger name (loggers are reused) + :type name: string + """ + logger = logging.getLogger(name) + if sys.hexversion > 0x3000000: + encoding = sys.stdout.encoding + else: + encoding = None + hdlr = logging.FileHandler(path, 'w', encoding=encoding) + formatter = logging.Formatter('%(message)s') + hdlr.setFormatter(formatter) + logger.addHandler(hdlr) + logger.setLevel(logging.DEBUG) + return logger + +def make_mem_logger(name, to_log, size=8192): + """ + Creates a memory logger to avoid writing concurrently to the main logger + """ + from logging.handlers import MemoryHandler + logger = logging.getLogger(name) + hdlr = MemoryHandler(size, target=to_log) + formatter = logging.Formatter('%(message)s') + hdlr.setFormatter(formatter) + logger.addHandler(hdlr) + logger.memhandler = hdlr + logger.setLevel(logging.DEBUG) + return logger + +def free_logger(logger): + """ + Frees the resources held by the loggers created through make_logger or make_mem_logger. + This is used for file cleanup and for handler removal (logger objects are re-used). + """ + try: + for x in logger.handlers: + x.close() + logger.removeHandler(x) + except Exception: + pass + +def pprint(col, msg, label='', sep='\n'): + """ + Prints messages in color immediately on stderr:: + + from waflib import Logs + Logs.pprint('RED', 'Something bad just happened') + + :param col: color name to use in :py:const:`Logs.colors_lst` + :type col: string + :param msg: message to display + :type msg: string or a value that can be printed by %s + :param label: a message to add after the colored output + :type label: string + :param sep: a string to append at the end (line separator) + :type sep: string + """ + info('%s%s%s %s', colors(col), msg, colors.NORMAL, label, extra={'terminator':sep}) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Node.py b/ldb-2.0.8/third_party/waf/waflib/Node.py new file mode 100644 index 0000000..2ad1846 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Node.py @@ -0,0 +1,969 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Node: filesystem structure + +#. Each file/folder is represented by exactly one node. + +#. Some potential class properties are stored on :py:class:`waflib.Build.BuildContext` : nodes to depend on, etc. + Unused class members can increase the `.wafpickle` file size sensibly. + +#. Node objects should never be created directly, use + the methods :py:func:`Node.make_node` or :py:func:`Node.find_node` for the low-level operations + +#. The methods :py:func:`Node.find_resource`, :py:func:`Node.find_dir` :py:func:`Node.find_or_declare` must be + used when a build context is present + +#. Each instance of :py:class:`waflib.Context.Context` has a unique :py:class:`Node` subclass required for serialization. + (:py:class:`waflib.Node.Nod3`, see the :py:class:`waflib.Context.Context` initializer). A reference to the context + owning a node is held as *self.ctx* +""" + +import os, re, sys, shutil +from waflib import Utils, Errors + +exclude_regs = ''' +**/*~ +**/#*# +**/.#* +**/%*% +**/._* +**/*.swp +**/CVS +**/CVS/** +**/.cvsignore +**/SCCS +**/SCCS/** +**/vssver.scc +**/.svn +**/.svn/** +**/BitKeeper +**/.git +**/.git/** +**/.gitignore +**/.bzr +**/.bzrignore +**/.bzr/** +**/.hg +**/.hg/** +**/_MTN +**/_MTN/** +**/.arch-ids +**/{arch} +**/_darcs +**/_darcs/** +**/.intlcache +**/.DS_Store''' +""" +Ant patterns for files and folders to exclude while doing the +recursive traversal in :py:meth:`waflib.Node.Node.ant_glob` +""" + +def ant_matcher(s, ignorecase): + reflags = re.I if ignorecase else 0 + ret = [] + for x in Utils.to_list(s): + x = x.replace('\\', '/').replace('//', '/') + if x.endswith('/'): + x += '**' + accu = [] + for k in x.split('/'): + if k == '**': + accu.append(k) + else: + k = k.replace('.', '[.]').replace('*', '.*').replace('?', '.').replace('+', '\\+') + k = '^%s$' % k + try: + exp = re.compile(k, flags=reflags) + except Exception as e: + raise Errors.WafError('Invalid pattern: %s' % k, e) + else: + accu.append(exp) + ret.append(accu) + return ret + +def ant_sub_filter(name, nn): + ret = [] + for lst in nn: + if not lst: + pass + elif lst[0] == '**': + ret.append(lst) + if len(lst) > 1: + if lst[1].match(name): + ret.append(lst[2:]) + else: + ret.append([]) + elif lst[0].match(name): + ret.append(lst[1:]) + return ret + +def ant_sub_matcher(name, pats): + nacc = ant_sub_filter(name, pats[0]) + nrej = ant_sub_filter(name, pats[1]) + if [] in nrej: + nacc = [] + return [nacc, nrej] + +class Node(object): + """ + This class is organized in two parts: + + * The basic methods meant for filesystem access (compute paths, create folders, etc) + * The methods bound to a :py:class:`waflib.Build.BuildContext` (require ``bld.srcnode`` and ``bld.bldnode``) + """ + + dict_class = dict + """ + Subclasses can provide a dict class to enable case insensitivity for example. + """ + + __slots__ = ('name', 'parent', 'children', 'cache_abspath', 'cache_isdir') + def __init__(self, name, parent): + """ + .. note:: Use :py:func:`Node.make_node` or :py:func:`Node.find_node` instead of calling this constructor + """ + self.name = name + self.parent = parent + if parent: + if name in parent.children: + raise Errors.WafError('node %s exists in the parent files %r already' % (name, parent)) + parent.children[name] = self + + def __setstate__(self, data): + "Deserializes node information, used for persistence" + self.name = data[0] + self.parent = data[1] + if data[2] is not None: + # Issue 1480 + self.children = self.dict_class(data[2]) + + def __getstate__(self): + "Serializes node information, used for persistence" + return (self.name, self.parent, getattr(self, 'children', None)) + + def __str__(self): + """ + String representation (abspath), for debugging purposes + + :rtype: string + """ + return self.abspath() + + def __repr__(self): + """ + String representation (abspath), for debugging purposes + + :rtype: string + """ + return self.abspath() + + def __copy__(self): + """ + Provided to prevent nodes from being copied + + :raises: :py:class:`waflib.Errors.WafError` + """ + raise Errors.WafError('nodes are not supposed to be copied') + + def read(self, flags='r', encoding='latin-1'): + """ + Reads and returns the contents of the file represented by this node, see :py:func:`waflib.Utils.readf`:: + + def build(bld): + bld.path.find_node('wscript').read() + + :param flags: Open mode + :type flags: string + :param encoding: encoding value for Python3 + :type encoding: string + :rtype: string or bytes + :return: File contents + """ + return Utils.readf(self.abspath(), flags, encoding) + + def write(self, data, flags='w', encoding='latin-1'): + """ + Writes data to the file represented by this node, see :py:func:`waflib.Utils.writef`:: + + def build(bld): + bld.path.make_node('foo.txt').write('Hello, world!') + + :param data: data to write + :type data: string + :param flags: Write mode + :type flags: string + :param encoding: encoding value for Python3 + :type encoding: string + """ + Utils.writef(self.abspath(), data, flags, encoding) + + def read_json(self, convert=True, encoding='utf-8'): + """ + Reads and parses the contents of this node as JSON (Python ≥ 2.6):: + + def build(bld): + bld.path.find_node('abc.json').read_json() + + Note that this by default automatically decodes unicode strings on Python2, unlike what the Python JSON module does. + + :type convert: boolean + :param convert: Prevents decoding of unicode strings on Python2 + :type encoding: string + :param encoding: The encoding of the file to read. This default to UTF8 as per the JSON standard + :rtype: object + :return: Parsed file contents + """ + import json # Python 2.6 and up + object_pairs_hook = None + if convert and sys.hexversion < 0x3000000: + try: + _type = unicode + except NameError: + _type = str + + def convert(value): + if isinstance(value, list): + return [convert(element) for element in value] + elif isinstance(value, _type): + return str(value) + else: + return value + + def object_pairs(pairs): + return dict((str(pair[0]), convert(pair[1])) for pair in pairs) + + object_pairs_hook = object_pairs + + return json.loads(self.read(encoding=encoding), object_pairs_hook=object_pairs_hook) + + def write_json(self, data, pretty=True): + """ + Writes a python object as JSON to disk (Python ≥ 2.6) as UTF-8 data (JSON standard):: + + def build(bld): + bld.path.find_node('xyz.json').write_json(199) + + :type data: object + :param data: The data to write to disk + :type pretty: boolean + :param pretty: Determines if the JSON will be nicely space separated + """ + import json # Python 2.6 and up + indent = 2 + separators = (',', ': ') + sort_keys = pretty + newline = os.linesep + if not pretty: + indent = None + separators = (',', ':') + newline = '' + output = json.dumps(data, indent=indent, separators=separators, sort_keys=sort_keys) + newline + self.write(output, encoding='utf-8') + + def exists(self): + """ + Returns whether the Node is present on the filesystem + + :rtype: bool + """ + return os.path.exists(self.abspath()) + + def isdir(self): + """ + Returns whether the Node represents a folder + + :rtype: bool + """ + return os.path.isdir(self.abspath()) + + def chmod(self, val): + """ + Changes the file/dir permissions:: + + def build(bld): + bld.path.chmod(493) # 0755 + """ + os.chmod(self.abspath(), val) + + def delete(self, evict=True): + """ + Removes the file/folder from the filesystem (equivalent to `rm -rf`), and remove this object from the Node tree. + Do not use this object after calling this method. + """ + try: + try: + if os.path.isdir(self.abspath()): + shutil.rmtree(self.abspath()) + else: + os.remove(self.abspath()) + except OSError: + if os.path.exists(self.abspath()): + raise + finally: + if evict: + self.evict() + + def evict(self): + """ + Removes this node from the Node tree + """ + del self.parent.children[self.name] + + def suffix(self): + """ + Returns the file rightmost extension, for example `a.b.c.d → .d` + + :rtype: string + """ + k = max(0, self.name.rfind('.')) + return self.name[k:] + + def height(self): + """ + Returns the depth in the folder hierarchy from the filesystem root or from all the file drives + + :returns: filesystem depth + :rtype: integer + """ + d = self + val = -1 + while d: + d = d.parent + val += 1 + return val + + def listdir(self): + """ + Lists the folder contents + + :returns: list of file/folder names ordered alphabetically + :rtype: list of string + """ + lst = Utils.listdir(self.abspath()) + lst.sort() + return lst + + def mkdir(self): + """ + Creates a folder represented by this node. Intermediate folders are created as needed. + + :raises: :py:class:`waflib.Errors.WafError` when the folder is missing + """ + if self.isdir(): + return + + try: + self.parent.mkdir() + except OSError: + pass + + if self.name: + try: + os.makedirs(self.abspath()) + except OSError: + pass + + if not self.isdir(): + raise Errors.WafError('Could not create the directory %r' % self) + + try: + self.children + except AttributeError: + self.children = self.dict_class() + + def find_node(self, lst): + """ + Finds a node on the file system (files or folders), and creates the corresponding Node objects if it exists + + :param lst: relative path + :type lst: string or list of string + :returns: The corresponding Node object or None if no entry was found on the filesystem + :rtype: :py:class:´waflib.Node.Node´ + """ + + if isinstance(lst, str): + lst = [x for x in Utils.split_path(lst) if x and x != '.'] + + if lst and lst[0].startswith('\\\\') and not self.parent: + node = self.ctx.root.make_node(lst[0]) + node.cache_isdir = True + return node.find_node(lst[1:]) + + cur = self + for x in lst: + if x == '..': + cur = cur.parent or cur + continue + + try: + ch = cur.children + except AttributeError: + cur.children = self.dict_class() + else: + try: + cur = ch[x] + continue + except KeyError: + pass + + # optimistic: create the node first then look if it was correct to do so + cur = self.__class__(x, cur) + if not cur.exists(): + cur.evict() + return None + + if not cur.exists(): + cur.evict() + return None + + return cur + + def make_node(self, lst): + """ + Returns or creates a Node object corresponding to the input path without considering the filesystem. + + :param lst: relative path + :type lst: string or list of string + :rtype: :py:class:´waflib.Node.Node´ + """ + if isinstance(lst, str): + lst = [x for x in Utils.split_path(lst) if x and x != '.'] + + cur = self + for x in lst: + if x == '..': + cur = cur.parent or cur + continue + + try: + cur = cur.children[x] + except AttributeError: + cur.children = self.dict_class() + except KeyError: + pass + else: + continue + cur = self.__class__(x, cur) + return cur + + def search_node(self, lst): + """ + Returns a Node previously defined in the data structure. The filesystem is not considered. + + :param lst: relative path + :type lst: string or list of string + :rtype: :py:class:´waflib.Node.Node´ or None if there is no entry in the Node datastructure + """ + if isinstance(lst, str): + lst = [x for x in Utils.split_path(lst) if x and x != '.'] + + cur = self + for x in lst: + if x == '..': + cur = cur.parent or cur + else: + try: + cur = cur.children[x] + except (AttributeError, KeyError): + return None + return cur + + def path_from(self, node): + """ + Path of this node seen from the other:: + + def build(bld): + n1 = bld.path.find_node('foo/bar/xyz.txt') + n2 = bld.path.find_node('foo/stuff/') + n1.path_from(n2) # '../bar/xyz.txt' + + :param node: path to use as a reference + :type node: :py:class:`waflib.Node.Node` + :returns: a relative path or an absolute one if that is better + :rtype: string + """ + c1 = self + c2 = node + + c1h = c1.height() + c2h = c2.height() + + lst = [] + up = 0 + + while c1h > c2h: + lst.append(c1.name) + c1 = c1.parent + c1h -= 1 + + while c2h > c1h: + up += 1 + c2 = c2.parent + c2h -= 1 + + while not c1 is c2: + lst.append(c1.name) + up += 1 + + c1 = c1.parent + c2 = c2.parent + + if c1.parent: + lst.extend(['..'] * up) + lst.reverse() + return os.sep.join(lst) or '.' + else: + return self.abspath() + + def abspath(self): + """ + Returns the absolute path. A cache is kept in the context as ``cache_node_abspath`` + + :rtype: string + """ + try: + return self.cache_abspath + except AttributeError: + pass + # think twice before touching this (performance + complexity + correctness) + + if not self.parent: + val = os.sep + elif not self.parent.name: + val = os.sep + self.name + else: + val = self.parent.abspath() + os.sep + self.name + self.cache_abspath = val + return val + + if Utils.is_win32: + def abspath(self): + try: + return self.cache_abspath + except AttributeError: + pass + if not self.parent: + val = '' + elif not self.parent.name: + val = self.name + os.sep + else: + val = self.parent.abspath().rstrip(os.sep) + os.sep + self.name + self.cache_abspath = val + return val + + def is_child_of(self, node): + """ + Returns whether the object belongs to a subtree of the input node:: + + def build(bld): + node = bld.path.find_node('wscript') + node.is_child_of(bld.path) # True + + :param node: path to use as a reference + :type node: :py:class:`waflib.Node.Node` + :rtype: bool + """ + p = self + diff = self.height() - node.height() + while diff > 0: + diff -= 1 + p = p.parent + return p is node + + def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True, quiet=False): + """ + Recursive method used by :py:meth:`waflib.Node.ant_glob`. + + :param accept: function used for accepting/rejecting a node, returns the patterns that can be still accepted in recursion + :type accept: function + :param maxdepth: maximum depth in the filesystem (25) + :type maxdepth: int + :param pats: list of patterns to accept and list of patterns to exclude + :type pats: tuple + :param dir: return folders too (False by default) + :type dir: bool + :param src: return files (True by default) + :type src: bool + :param remove: remove files/folders that do not exist (True by default) + :type remove: bool + :param quiet: disable build directory traversal warnings (verbose mode) + :type quiet: bool + :returns: A generator object to iterate from + :rtype: iterator + """ + dircont = self.listdir() + + try: + lst = set(self.children.keys()) + except AttributeError: + self.children = self.dict_class() + else: + if remove: + for x in lst - set(dircont): + self.children[x].evict() + + for name in dircont: + npats = accept(name, pats) + if npats and npats[0]: + accepted = [] in npats[0] + + node = self.make_node([name]) + + isdir = node.isdir() + if accepted: + if isdir: + if dir: + yield node + elif src: + yield node + + if isdir: + node.cache_isdir = True + if maxdepth: + for k in node.ant_iter(accept=accept, maxdepth=maxdepth - 1, pats=npats, dir=dir, src=src, remove=remove, quiet=quiet): + yield k + + def ant_glob(self, *k, **kw): + """ + Finds files across folders and returns Node objects: + + * ``**/*`` find all files recursively + * ``**/*.class`` find all files ending by .class + * ``..`` find files having two dot characters + + For example:: + + def configure(cfg): + # find all .cpp files + cfg.path.ant_glob('**/*.cpp') + # find particular files from the root filesystem (can be slow) + cfg.root.ant_glob('etc/*.txt') + # simple exclusion rule example + cfg.path.ant_glob('*.c*', excl=['*.c'], src=True, dir=False) + + For more information about the patterns, consult http://ant.apache.org/manual/dirtasks.html + Please remember that the '..' sequence does not represent the parent directory:: + + def configure(cfg): + cfg.path.ant_glob('../*.h') # incorrect + cfg.path.parent.ant_glob('*.h') # correct + + The Node structure is itself a filesystem cache, so certain precautions must + be taken while matching files in the build or installation phases. + Nodes objects that do have a corresponding file or folder are garbage-collected by default. + This garbage collection is usually required to prevent returning files that do not + exist anymore. Yet, this may also remove Node objects of files that are yet-to-be built. + + This typically happens when trying to match files in the build directory, + but there are also cases when files are created in the source directory. + Run ``waf -v`` to display any warnings, and try consider passing ``remove=False`` + when matching files in the build directory. + + Since ant_glob can traverse both source and build folders, it is a best practice + to call this method only from the most specific build node:: + + def build(bld): + # traverses the build directory, may need ``remove=False``: + bld.path.ant_glob('project/dir/**/*.h') + # better, no accidental build directory traversal: + bld.path.find_node('project/dir').ant_glob('**/*.h') # best + + In addition, files and folders are listed immediately. When matching files in the + build folders, consider passing ``generator=True`` so that the generator object + returned can defer computation to a later stage. For example:: + + def build(bld): + bld(rule='tar xvf ${SRC}', source='arch.tar') + bld.add_group() + gen = bld.bldnode.ant_glob("*.h", generator=True, remove=True) + # files will be listed only after the arch.tar is unpacked + bld(rule='ls ${SRC}', source=gen, name='XYZ') + + + :param incl: ant patterns or list of patterns to include + :type incl: string or list of strings + :param excl: ant patterns or list of patterns to exclude + :type excl: string or list of strings + :param dir: return folders too (False by default) + :type dir: bool + :param src: return files (True by default) + :type src: bool + :param maxdepth: maximum depth of recursion + :type maxdepth: int + :param ignorecase: ignore case while matching (False by default) + :type ignorecase: bool + :param generator: Whether to evaluate the Nodes lazily + :type generator: bool + :param remove: remove files/folders that do not exist (True by default) + :type remove: bool + :param quiet: disable build directory traversal warnings (verbose mode) + :type quiet: bool + :returns: The corresponding Node objects as a list or as a generator object (generator=True) + :rtype: by default, list of :py:class:`waflib.Node.Node` instances + """ + src = kw.get('src', True) + dir = kw.get('dir') + excl = kw.get('excl', exclude_regs) + incl = k and k[0] or kw.get('incl', '**') + remove = kw.get('remove', True) + maxdepth = kw.get('maxdepth', 25) + ignorecase = kw.get('ignorecase', False) + quiet = kw.get('quiet', False) + pats = (ant_matcher(incl, ignorecase), ant_matcher(excl, ignorecase)) + + if kw.get('generator'): + return Utils.lazy_generator(self.ant_iter, (ant_sub_matcher, maxdepth, pats, dir, src, remove, quiet)) + + it = self.ant_iter(ant_sub_matcher, maxdepth, pats, dir, src, remove, quiet) + if kw.get('flat'): + # returns relative paths as a space-delimited string + # prefer Node objects whenever possible + return ' '.join(x.path_from(self) for x in it) + return list(it) + + # ---------------------------------------------------------------------------- + # the methods below require the source/build folders (bld.srcnode/bld.bldnode) + + def is_src(self): + """ + Returns True if the node is below the source directory. Note that ``!is_src() ≠ is_bld()`` + + :rtype: bool + """ + cur = self + x = self.ctx.srcnode + y = self.ctx.bldnode + while cur.parent: + if cur is y: + return False + if cur is x: + return True + cur = cur.parent + return False + + def is_bld(self): + """ + Returns True if the node is below the build directory. Note that ``!is_bld() ≠ is_src()`` + + :rtype: bool + """ + cur = self + y = self.ctx.bldnode + while cur.parent: + if cur is y: + return True + cur = cur.parent + return False + + def get_src(self): + """ + Returns the corresponding Node object in the source directory (or self if already + under the source directory). Use this method only if the purpose is to create + a Node object (this is common with folders but not with files, see ticket 1937) + + :rtype: :py:class:`waflib.Node.Node` + """ + cur = self + x = self.ctx.srcnode + y = self.ctx.bldnode + lst = [] + while cur.parent: + if cur is y: + lst.reverse() + return x.make_node(lst) + if cur is x: + return self + lst.append(cur.name) + cur = cur.parent + return self + + def get_bld(self): + """ + Return the corresponding Node object in the build directory (or self if already + under the build directory). Use this method only if the purpose is to create + a Node object (this is common with folders but not with files, see ticket 1937) + + :rtype: :py:class:`waflib.Node.Node` + """ + cur = self + x = self.ctx.srcnode + y = self.ctx.bldnode + lst = [] + while cur.parent: + if cur is y: + return self + if cur is x: + lst.reverse() + return self.ctx.bldnode.make_node(lst) + lst.append(cur.name) + cur = cur.parent + # the file is external to the current project, make a fake root in the current build directory + lst.reverse() + if lst and Utils.is_win32 and len(lst[0]) == 2 and lst[0].endswith(':'): + lst[0] = lst[0][0] + return self.ctx.bldnode.make_node(['__root__'] + lst) + + def find_resource(self, lst): + """ + Use this method in the build phase to find source files corresponding to the relative path given. + + First it looks up the Node data structure to find any declared Node object in the build directory. + If None is found, it then considers the filesystem in the source directory. + + :param lst: relative path + :type lst: string or list of string + :returns: the corresponding Node object or None + :rtype: :py:class:`waflib.Node.Node` + """ + if isinstance(lst, str): + lst = [x for x in Utils.split_path(lst) if x and x != '.'] + + node = self.get_bld().search_node(lst) + if not node: + node = self.get_src().find_node(lst) + if node and node.isdir(): + return None + return node + + def find_or_declare(self, lst): + """ + Use this method in the build phase to declare output files which + are meant to be written in the build directory. + + This method creates the Node object and its parent folder + as needed. + + :param lst: relative path + :type lst: string or list of string + """ + if isinstance(lst, str) and os.path.isabs(lst): + node = self.ctx.root.make_node(lst) + else: + node = self.get_bld().make_node(lst) + node.parent.mkdir() + return node + + def find_dir(self, lst): + """ + Searches for a folder on the filesystem (see :py:meth:`waflib.Node.Node.find_node`) + + :param lst: relative path + :type lst: string or list of string + :returns: The corresponding Node object or None if there is no such folder + :rtype: :py:class:`waflib.Node.Node` + """ + if isinstance(lst, str): + lst = [x for x in Utils.split_path(lst) if x and x != '.'] + + node = self.find_node(lst) + if node and not node.isdir(): + return None + return node + + # helpers for building things + def change_ext(self, ext, ext_in=None): + """ + Declares a build node with a distinct extension; this is uses :py:meth:`waflib.Node.Node.find_or_declare` + + :return: A build node of the same path, but with a different extension + :rtype: :py:class:`waflib.Node.Node` + """ + name = self.name + if ext_in is None: + k = name.rfind('.') + if k >= 0: + name = name[:k] + ext + else: + name = name + ext + else: + name = name[:- len(ext_in)] + ext + + return self.parent.find_or_declare([name]) + + def bldpath(self): + """ + Returns the relative path seen from the build directory ``src/foo.cpp`` + + :rtype: string + """ + return self.path_from(self.ctx.bldnode) + + def srcpath(self): + """ + Returns the relative path seen from the source directory ``../src/foo.cpp`` + + :rtype: string + """ + return self.path_from(self.ctx.srcnode) + + def relpath(self): + """ + If a file in the build directory, returns :py:meth:`waflib.Node.Node.bldpath`, + else returns :py:meth:`waflib.Node.Node.srcpath` + + :rtype: string + """ + cur = self + x = self.ctx.bldnode + while cur.parent: + if cur is x: + return self.bldpath() + cur = cur.parent + return self.srcpath() + + def bld_dir(self): + """ + Equivalent to self.parent.bldpath() + + :rtype: string + """ + return self.parent.bldpath() + + def h_file(self): + """ + See :py:func:`waflib.Utils.h_file` + + :return: a hash representing the file contents + :rtype: string or bytes + """ + return Utils.h_file(self.abspath()) + + def get_bld_sig(self): + """ + Returns a signature (see :py:meth:`waflib.Node.Node.h_file`) for the purpose + of build dependency calculation. This method uses a per-context cache. + + :return: a hash representing the object contents + :rtype: string or bytes + """ + # previous behaviour can be set by returning self.ctx.node_sigs[self] when a build node + try: + cache = self.ctx.cache_sig + except AttributeError: + cache = self.ctx.cache_sig = {} + try: + ret = cache[self] + except KeyError: + p = self.abspath() + try: + ret = cache[self] = self.h_file() + except EnvironmentError: + if self.isdir(): + # allow folders as build nodes, do not use the creation time + st = os.stat(p) + ret = cache[self] = Utils.h_list([p, st.st_ino, st.st_mode]) + return ret + raise + return ret + +pickle_lock = Utils.threading.Lock() +"""Lock mandatory for thread-safe node serialization""" + +class Nod3(Node): + """Mandatory subclass for thread-safe node serialization""" + pass # do not remove + + diff --git a/ldb-2.0.8/third_party/waf/waflib/Options.py b/ldb-2.0.8/third_party/waf/waflib/Options.py new file mode 100644 index 0000000..ad802d4 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Options.py @@ -0,0 +1,342 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Scott Newton, 2005 (scottn) +# Thomas Nagy, 2006-2018 (ita) + +""" +Support for waf command-line options + +Provides default and command-line options, as well the command +that reads the ``options`` wscript function. +""" + +import os, tempfile, optparse, sys, re +from waflib import Logs, Utils, Context, Errors + +options = optparse.Values() +""" +A global dictionary representing user-provided command-line options:: + + $ waf --foo=bar +""" + +commands = [] +""" +List of commands to execute extracted from the command-line. This list +is consumed during the execution by :py:func:`waflib.Scripting.run_commands`. +""" + +envvars = [] +""" +List of environment variable declarations placed after the Waf executable name. +These are detected by searching for "=" in the remaining arguments. +You probably do not want to use this. +""" + +lockfile = os.environ.get('WAFLOCK', '.lock-waf_%s_build' % sys.platform) +""" +Name of the lock file that marks a project as configured +""" + +class opt_parser(optparse.OptionParser): + """ + Command-line options parser. + """ + def __init__(self, ctx, allow_unknown=False): + optparse.OptionParser.__init__(self, conflict_handler='resolve', add_help_option=False, + version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION)) + self.formatter.width = Logs.get_term_cols() + self.ctx = ctx + self.allow_unknown = allow_unknown + + def _process_args(self, largs, rargs, values): + """ + Custom _process_args to allow unknown options according to the allow_unknown status + """ + while rargs: + try: + optparse.OptionParser._process_args(self,largs,rargs,values) + except (optparse.BadOptionError, optparse.AmbiguousOptionError) as e: + if self.allow_unknown: + largs.append(e.opt_str) + else: + self.error(str(e)) + + def print_usage(self, file=None): + return self.print_help(file) + + def get_usage(self): + """ + Builds the message to print on ``waf --help`` + + :rtype: string + """ + cmds_str = {} + for cls in Context.classes: + if not cls.cmd or cls.cmd == 'options' or cls.cmd.startswith( '_' ): + continue + + s = cls.__doc__ or '' + cmds_str[cls.cmd] = s + + if Context.g_module: + for (k, v) in Context.g_module.__dict__.items(): + if k in ('options', 'init', 'shutdown'): + continue + + if type(v) is type(Context.create_context): + if v.__doc__ and not k.startswith('_'): + cmds_str[k] = v.__doc__ + + just = 0 + for k in cmds_str: + just = max(just, len(k)) + + lst = [' %s: %s' % (k.ljust(just), v) for (k, v) in cmds_str.items()] + lst.sort() + ret = '\n'.join(lst) + + return '''waf [commands] [options] + +Main commands (example: ./waf build -j4) +%s +''' % ret + + +class OptionsContext(Context.Context): + """ + Collects custom options from wscript files and parses the command line. + Sets the global :py:const:`waflib.Options.commands` and :py:const:`waflib.Options.options` values. + """ + cmd = 'options' + fun = 'options' + + def __init__(self, **kw): + super(OptionsContext, self).__init__(**kw) + + self.parser = opt_parser(self) + """Instance of :py:class:`waflib.Options.opt_parser`""" + + self.option_groups = {} + + jobs = self.jobs() + p = self.add_option + color = os.environ.get('NOCOLOR', '') and 'no' or 'auto' + if os.environ.get('CLICOLOR', '') == '0': + color = 'no' + elif os.environ.get('CLICOLOR_FORCE', '') == '1': + color = 'yes' + p('-c', '--color', dest='colors', default=color, action='store', help='whether to use colors (yes/no/auto) [default: auto]', choices=('yes', 'no', 'auto')) + p('-j', '--jobs', dest='jobs', default=jobs, type='int', help='amount of parallel jobs (%r)' % jobs) + p('-k', '--keep', dest='keep', default=0, action='count', help='continue despite errors (-kk to try harder)') + p('-v', '--verbose', dest='verbose', default=0, action='count', help='verbosity level -v -vv or -vvv [default: 0]') + p('--zones', dest='zones', default='', action='store', help='debugging zones (task_gen, deps, tasks, etc)') + p('--profile', dest='profile', default=0, action='store_true', help=optparse.SUPPRESS_HELP) + p('--pdb', dest='pdb', default=0, action='store_true', help=optparse.SUPPRESS_HELP) + p('-h', '--help', dest='whelp', default=0, action='store_true', help="show this help message and exit") + + gr = self.add_option_group('Configuration options') + self.option_groups['configure options'] = gr + + gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') + gr.add_option('-t', '--top', action='store', default='', help='src dir for the project', dest='top') + + gr.add_option('--no-lock-in-run', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_run') + gr.add_option('--no-lock-in-out', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_out') + gr.add_option('--no-lock-in-top', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_top') + + default_prefix = getattr(Context.g_module, 'default_prefix', os.environ.get('PREFIX')) + if not default_prefix: + if Utils.unversioned_sys_platform() == 'win32': + d = tempfile.gettempdir() + default_prefix = d[0].upper() + d[1:] + # win32 preserves the case, but gettempdir does not + else: + default_prefix = '/usr/local/' + gr.add_option('--prefix', dest='prefix', default=default_prefix, help='installation prefix [default: %r]' % default_prefix) + gr.add_option('--bindir', dest='bindir', help='bindir') + gr.add_option('--libdir', dest='libdir', help='libdir') + + gr = self.add_option_group('Build and installation options') + self.option_groups['build and install options'] = gr + gr.add_option('-p', '--progress', dest='progress_bar', default=0, action='count', help= '-p: progress bar; -pp: ide output') + gr.add_option('--targets', dest='targets', default='', action='store', help='task generators, e.g. "target1,target2"') + + gr = self.add_option_group('Step options') + self.option_groups['step options'] = gr + gr.add_option('--files', dest='files', default='', action='store', help='files to process, by regexp, e.g. "*/main.c,*/test/main.o"') + + default_destdir = os.environ.get('DESTDIR', '') + + gr = self.add_option_group('Installation and uninstallation options') + self.option_groups['install/uninstall options'] = gr + gr.add_option('--destdir', help='installation root [default: %r]' % default_destdir, default=default_destdir, dest='destdir') + gr.add_option('-f', '--force', dest='force', default=False, action='store_true', help='force file installation') + gr.add_option('--distcheck-args', metavar='ARGS', help='arguments to pass to distcheck', default=None, action='store') + + def jobs(self): + """ + Finds the optimal amount of cpu cores to use for parallel jobs. + At runtime the options can be obtained from :py:const:`waflib.Options.options` :: + + from waflib.Options import options + njobs = options.jobs + + :return: the amount of cpu cores + :rtype: int + """ + count = int(os.environ.get('JOBS', 0)) + if count < 1: + if 'NUMBER_OF_PROCESSORS' in os.environ: + # on Windows, use the NUMBER_OF_PROCESSORS environment variable + count = int(os.environ.get('NUMBER_OF_PROCESSORS', 1)) + else: + # on everything else, first try the POSIX sysconf values + if hasattr(os, 'sysconf_names'): + if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: + count = int(os.sysconf('SC_NPROCESSORS_ONLN')) + elif 'SC_NPROCESSORS_CONF' in os.sysconf_names: + count = int(os.sysconf('SC_NPROCESSORS_CONF')) + if not count and os.name not in ('nt', 'java'): + try: + tmp = self.cmd_and_log(['sysctl', '-n', 'hw.ncpu'], quiet=0) + except Errors.WafError: + pass + else: + if re.match('^[0-9]+$', tmp): + count = int(tmp) + if count < 1: + count = 1 + elif count > 1024: + count = 1024 + return count + + def add_option(self, *k, **kw): + """ + Wraps ``optparse.add_option``:: + + def options(ctx): + ctx.add_option('-u', '--use', dest='use', default=False, + action='store_true', help='a boolean option') + + :rtype: optparse option object + """ + return self.parser.add_option(*k, **kw) + + def add_option_group(self, *k, **kw): + """ + Wraps ``optparse.add_option_group``:: + + def options(ctx): + gr = ctx.add_option_group('some options') + gr.add_option('-u', '--use', dest='use', default=False, action='store_true') + + :rtype: optparse option group object + """ + try: + gr = self.option_groups[k[0]] + except KeyError: + gr = self.parser.add_option_group(*k, **kw) + self.option_groups[k[0]] = gr + return gr + + def get_option_group(self, opt_str): + """ + Wraps ``optparse.get_option_group``:: + + def options(ctx): + gr = ctx.get_option_group('configure options') + gr.add_option('-o', '--out', action='store', default='', + help='build dir for the project', dest='out') + + :rtype: optparse option group object + """ + try: + return self.option_groups[opt_str] + except KeyError: + for group in self.parser.option_groups: + if group.title == opt_str: + return group + return None + + def sanitize_path(self, path, cwd=None): + if not cwd: + cwd = Context.launch_dir + p = os.path.expanduser(path) + p = os.path.join(cwd, p) + p = os.path.normpath(p) + p = os.path.abspath(p) + return p + + def parse_cmd_args(self, _args=None, cwd=None, allow_unknown=False): + """ + Just parse the arguments + """ + self.parser.allow_unknown = allow_unknown + (options, leftover_args) = self.parser.parse_args(args=_args) + envvars = [] + commands = [] + for arg in leftover_args: + if '=' in arg: + envvars.append(arg) + elif arg != 'options': + commands.append(arg) + + for name in 'top out destdir prefix bindir libdir'.split(): + # those paths are usually expanded from Context.launch_dir + if getattr(options, name, None): + path = self.sanitize_path(getattr(options, name), cwd) + setattr(options, name, path) + return options, commands, envvars + + def init_module_vars(self, arg_options, arg_commands, arg_envvars): + options.__dict__.clear() + del commands[:] + del envvars[:] + + options.__dict__.update(arg_options.__dict__) + commands.extend(arg_commands) + envvars.extend(arg_envvars) + + for var in envvars: + (name, value) = var.split('=', 1) + os.environ[name.strip()] = value + + def init_logs(self, options, commands, envvars): + Logs.verbose = options.verbose + if options.verbose >= 1: + self.load('errcheck') + + colors = {'yes' : 2, 'auto' : 1, 'no' : 0}[options.colors] + Logs.enable_colors(colors) + + if options.zones: + Logs.zones = options.zones.split(',') + if not Logs.verbose: + Logs.verbose = 1 + elif Logs.verbose > 0: + Logs.zones = ['runner'] + if Logs.verbose > 2: + Logs.zones = ['*'] + + def parse_args(self, _args=None): + """ + Parses arguments from a list which is not necessarily the command-line. + Initializes the module variables options, commands and envvars + If help is requested, prints it and exit the application + + :param _args: arguments + :type _args: list of strings + """ + options, commands, envvars = self.parse_cmd_args() + self.init_logs(options, commands, envvars) + self.init_module_vars(options, commands, envvars) + + def execute(self): + """ + See :py:func:`waflib.Context.Context.execute` + """ + super(OptionsContext, self).execute() + self.parse_args() + Utils.alloc_process_pool(options.jobs) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Runner.py b/ldb-2.0.8/third_party/waf/waflib/Runner.py new file mode 100644 index 0000000..91d5547 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Runner.py @@ -0,0 +1,622 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Runner.py: Task scheduling and execution +""" + +import heapq, traceback +try: + from queue import Queue, PriorityQueue +except ImportError: + from Queue import Queue + try: + from Queue import PriorityQueue + except ImportError: + class PriorityQueue(Queue): + def _init(self, maxsize): + self.maxsize = maxsize + self.queue = [] + def _put(self, item): + heapq.heappush(self.queue, item) + def _get(self): + return heapq.heappop(self.queue) + +from waflib import Utils, Task, Errors, Logs + +GAP = 5 +""" +Wait for at least ``GAP * njobs`` before trying to enqueue more tasks to run +""" + +class PriorityTasks(object): + def __init__(self): + self.lst = [] + def __len__(self): + return len(self.lst) + def __iter__(self): + return iter(self.lst) + def __str__(self): + return 'PriorityTasks: [%s]' % '\n '.join(str(x) for x in self.lst) + def clear(self): + self.lst = [] + def append(self, task): + heapq.heappush(self.lst, task) + def appendleft(self, task): + "Deprecated, do not use" + heapq.heappush(self.lst, task) + def pop(self): + return heapq.heappop(self.lst) + def extend(self, lst): + if self.lst: + for x in lst: + self.append(x) + else: + if isinstance(lst, list): + self.lst = lst + heapq.heapify(lst) + else: + self.lst = lst.lst + +class Consumer(Utils.threading.Thread): + """ + Daemon thread object that executes a task. It shares a semaphore with + the coordinator :py:class:`waflib.Runner.Spawner`. There is one + instance per task to consume. + """ + def __init__(self, spawner, task): + Utils.threading.Thread.__init__(self) + self.task = task + """Task to execute""" + self.spawner = spawner + """Coordinator object""" + self.setDaemon(1) + self.start() + def run(self): + """ + Processes a single task + """ + try: + if not self.spawner.master.stop: + self.spawner.master.process_task(self.task) + finally: + self.spawner.sem.release() + self.spawner.master.out.put(self.task) + self.task = None + self.spawner = None + +class Spawner(Utils.threading.Thread): + """ + Daemon thread that consumes tasks from :py:class:`waflib.Runner.Parallel` producer and + spawns a consuming thread :py:class:`waflib.Runner.Consumer` for each + :py:class:`waflib.Task.Task` instance. + """ + def __init__(self, master): + Utils.threading.Thread.__init__(self) + self.master = master + """:py:class:`waflib.Runner.Parallel` producer instance""" + self.sem = Utils.threading.Semaphore(master.numjobs) + """Bounded semaphore that prevents spawning more than *n* concurrent consumers""" + self.setDaemon(1) + self.start() + def run(self): + """ + Spawns new consumers to execute tasks by delegating to :py:meth:`waflib.Runner.Spawner.loop` + """ + try: + self.loop() + except Exception: + # Python 2 prints unnecessary messages when shutting down + # we also want to stop the thread properly + pass + def loop(self): + """ + Consumes task objects from the producer; ends when the producer has no more + task to provide. + """ + master = self.master + while 1: + task = master.ready.get() + self.sem.acquire() + if not master.stop: + task.log_display(task.generator.bld) + Consumer(self, task) + +class Parallel(object): + """ + Schedule the tasks obtained from the build context for execution. + """ + def __init__(self, bld, j=2): + """ + The initialization requires a build context reference + for computing the total number of jobs. + """ + + self.numjobs = j + """ + Amount of parallel consumers to use + """ + + self.bld = bld + """ + Instance of :py:class:`waflib.Build.BuildContext` + """ + + self.outstanding = PriorityTasks() + """Heap of :py:class:`waflib.Task.Task` that may be ready to be executed""" + + self.postponed = PriorityTasks() + """Heap of :py:class:`waflib.Task.Task` which are not ready to run for non-DAG reasons""" + + self.incomplete = set() + """List of :py:class:`waflib.Task.Task` waiting for dependent tasks to complete (DAG)""" + + self.ready = PriorityQueue(0) + """List of :py:class:`waflib.Task.Task` ready to be executed by consumers""" + + self.out = Queue(0) + """List of :py:class:`waflib.Task.Task` returned by the task consumers""" + + self.count = 0 + """Amount of tasks that may be processed by :py:class:`waflib.Runner.TaskConsumer`""" + + self.processed = 0 + """Amount of tasks processed""" + + self.stop = False + """Error flag to stop the build""" + + self.error = [] + """Tasks that could not be executed""" + + self.biter = None + """Task iterator which must give groups of parallelizable tasks when calling ``next()``""" + + self.dirty = False + """ + Flag that indicates that the build cache must be saved when a task was executed + (calls :py:meth:`waflib.Build.BuildContext.store`)""" + + self.revdeps = Utils.defaultdict(set) + """ + The reverse dependency graph of dependencies obtained from Task.run_after + """ + + self.spawner = None + """ + Coordinating daemon thread that spawns thread consumers + """ + if self.numjobs > 1: + self.spawner = Spawner(self) + + def get_next_task(self): + """ + Obtains the next Task instance to run + + :rtype: :py:class:`waflib.Task.Task` + """ + if not self.outstanding: + return None + return self.outstanding.pop() + + def postpone(self, tsk): + """ + Adds the task to the list :py:attr:`waflib.Runner.Parallel.postponed`. + The order is scrambled so as to consume as many tasks in parallel as possible. + + :param tsk: task instance + :type tsk: :py:class:`waflib.Task.Task` + """ + self.postponed.append(tsk) + + def refill_task_list(self): + """ + Pulls a next group of tasks to execute in :py:attr:`waflib.Runner.Parallel.outstanding`. + Ensures that all tasks in the current build group are complete before processing the next one. + """ + while self.count > self.numjobs * GAP: + self.get_out() + + while not self.outstanding: + if self.count: + self.get_out() + if self.outstanding: + break + elif self.postponed: + try: + cond = self.deadlock == self.processed + except AttributeError: + pass + else: + if cond: + # The most common reason is conflicting build order declaration + # for example: "X run_after Y" and "Y run_after X" + # Another can be changing "run_after" dependencies while the build is running + # for example: updating "tsk.run_after" in the "runnable_status" method + lst = [] + for tsk in self.postponed: + deps = [id(x) for x in tsk.run_after if not x.hasrun] + lst.append('%s\t-> %r' % (repr(tsk), deps)) + if not deps: + lst.append('\n task %r dependencies are done, check its *runnable_status*?' % id(tsk)) + raise Errors.WafError('Deadlock detected: check the task build order%s' % ''.join(lst)) + self.deadlock = self.processed + + if self.postponed: + self.outstanding.extend(self.postponed) + self.postponed.clear() + elif not self.count: + if self.incomplete: + for x in self.incomplete: + for k in x.run_after: + if not k.hasrun: + break + else: + # dependency added after the build started without updating revdeps + self.incomplete.remove(x) + self.outstanding.append(x) + break + else: + if self.stop or self.error: + break + raise Errors.WafError('Broken revdeps detected on %r' % self.incomplete) + else: + tasks = next(self.biter) + ready, waiting = self.prio_and_split(tasks) + self.outstanding.extend(ready) + self.incomplete.update(waiting) + self.total = self.bld.total() + break + + def add_more_tasks(self, tsk): + """ + If a task provides :py:attr:`waflib.Task.Task.more_tasks`, then the tasks contained + in that list are added to the current build and will be processed before the next build group. + + The priorities for dependent tasks are not re-calculated globally + + :param tsk: task instance + :type tsk: :py:attr:`waflib.Task.Task` + """ + if getattr(tsk, 'more_tasks', None): + more = set(tsk.more_tasks) + groups_done = set() + def iteri(a, b): + for x in a: + yield x + for x in b: + yield x + + # Update the dependency tree + # this assumes that task.run_after values were updated + for x in iteri(self.outstanding, self.incomplete): + for k in x.run_after: + if isinstance(k, Task.TaskGroup): + if k not in groups_done: + groups_done.add(k) + for j in k.prev & more: + self.revdeps[j].add(k) + elif k in more: + self.revdeps[k].add(x) + + ready, waiting = self.prio_and_split(tsk.more_tasks) + self.outstanding.extend(ready) + self.incomplete.update(waiting) + self.total += len(tsk.more_tasks) + + def mark_finished(self, tsk): + def try_unfreeze(x): + # DAG ancestors are likely to be in the incomplete set + # This assumes that the run_after contents have not changed + # after the build starts, else a deadlock may occur + if x in self.incomplete: + # TODO remove dependencies to free some memory? + # x.run_after.remove(tsk) + for k in x.run_after: + if not k.hasrun: + break + else: + self.incomplete.remove(x) + self.outstanding.append(x) + + if tsk in self.revdeps: + for x in self.revdeps[tsk]: + if isinstance(x, Task.TaskGroup): + x.prev.remove(tsk) + if not x.prev: + for k in x.next: + # TODO necessary optimization? + k.run_after.remove(x) + try_unfreeze(k) + # TODO necessary optimization? + x.next = [] + else: + try_unfreeze(x) + del self.revdeps[tsk] + + if hasattr(tsk, 'semaphore'): + sem = tsk.semaphore + try: + sem.release(tsk) + except KeyError: + # TODO + pass + else: + while sem.waiting and not sem.is_locked(): + # take a frozen task, make it ready to run + x = sem.waiting.pop() + self._add_task(x) + + def get_out(self): + """ + Waits for a Task that task consumers add to :py:attr:`waflib.Runner.Parallel.out` after execution. + Adds more Tasks if necessary through :py:attr:`waflib.Runner.Parallel.add_more_tasks`. + + :rtype: :py:attr:`waflib.Task.Task` + """ + tsk = self.out.get() + if not self.stop: + self.add_more_tasks(tsk) + self.mark_finished(tsk) + + self.count -= 1 + self.dirty = True + return tsk + + def add_task(self, tsk): + """ + Enqueue a Task to :py:attr:`waflib.Runner.Parallel.ready` so that consumers can run them. + + :param tsk: task instance + :type tsk: :py:attr:`waflib.Task.Task` + """ + # TODO change in waf 2.1 + self.ready.put(tsk) + + def _add_task(self, tsk): + if hasattr(tsk, 'semaphore'): + sem = tsk.semaphore + try: + sem.acquire(tsk) + except IndexError: + sem.waiting.add(tsk) + return + + self.count += 1 + self.processed += 1 + if self.numjobs == 1: + tsk.log_display(tsk.generator.bld) + try: + self.process_task(tsk) + finally: + self.out.put(tsk) + else: + self.add_task(tsk) + + def process_task(self, tsk): + """ + Processes a task and attempts to stop the build in case of errors + """ + tsk.process() + if tsk.hasrun != Task.SUCCESS: + self.error_handler(tsk) + + def skip(self, tsk): + """ + Mark a task as skipped/up-to-date + """ + tsk.hasrun = Task.SKIPPED + self.mark_finished(tsk) + + def cancel(self, tsk): + """ + Mark a task as failed because of unsatisfiable dependencies + """ + tsk.hasrun = Task.CANCELED + self.mark_finished(tsk) + + def error_handler(self, tsk): + """ + Called when a task cannot be executed. The flag :py:attr:`waflib.Runner.Parallel.stop` is set, + unless the build is executed with:: + + $ waf build -k + + :param tsk: task instance + :type tsk: :py:attr:`waflib.Task.Task` + """ + if not self.bld.keep: + self.stop = True + self.error.append(tsk) + + def task_status(self, tsk): + """ + Obtains the task status to decide whether to run it immediately or not. + + :return: the exit status, for example :py:attr:`waflib.Task.ASK_LATER` + :rtype: integer + """ + try: + return tsk.runnable_status() + except Exception: + self.processed += 1 + tsk.err_msg = traceback.format_exc() + if not self.stop and self.bld.keep: + self.skip(tsk) + if self.bld.keep == 1: + # if -k stop on the first exception, if -kk try to go as far as possible + if Logs.verbose > 1 or not self.error: + self.error.append(tsk) + self.stop = True + else: + if Logs.verbose > 1: + self.error.append(tsk) + return Task.EXCEPTION + + tsk.hasrun = Task.EXCEPTION + self.error_handler(tsk) + + return Task.EXCEPTION + + def start(self): + """ + Obtains Task instances from the BuildContext instance and adds the ones that need to be executed to + :py:class:`waflib.Runner.Parallel.ready` so that the :py:class:`waflib.Runner.Spawner` consumer thread + has them executed. Obtains the executed Tasks back from :py:class:`waflib.Runner.Parallel.out` + and marks the build as failed by setting the ``stop`` flag. + If only one job is used, then executes the tasks one by one, without consumers. + """ + self.total = self.bld.total() + + while not self.stop: + + self.refill_task_list() + + # consider the next task + tsk = self.get_next_task() + if not tsk: + if self.count: + # tasks may add new ones after they are run + continue + else: + # no tasks to run, no tasks running, time to exit + break + + if tsk.hasrun: + # if the task is marked as "run", just skip it + self.processed += 1 + continue + + if self.stop: # stop immediately after a failure is detected + break + + st = self.task_status(tsk) + if st == Task.RUN_ME: + self._add_task(tsk) + elif st == Task.ASK_LATER: + self.postpone(tsk) + elif st == Task.SKIP_ME: + self.processed += 1 + self.skip(tsk) + self.add_more_tasks(tsk) + elif st == Task.CANCEL_ME: + # A dependency problem has occurred, and the + # build is most likely run with `waf -k` + if Logs.verbose > 1: + self.error.append(tsk) + self.processed += 1 + self.cancel(tsk) + + # self.count represents the tasks that have been made available to the consumer threads + # collect all the tasks after an error else the message may be incomplete + while self.error and self.count: + self.get_out() + + self.ready.put(None) + if not self.stop: + assert not self.count + assert not self.postponed + assert not self.incomplete + + def prio_and_split(self, tasks): + """ + Label input tasks with priority values, and return a pair containing + the tasks that are ready to run and the tasks that are necessarily + waiting for other tasks to complete. + + The priority system is really meant as an optional layer for optimization: + dependency cycles are found quickly, and builds should be more efficient. + A high priority number means that a task is processed first. + + This method can be overridden to disable the priority system:: + + def prio_and_split(self, tasks): + return tasks, [] + + :return: A pair of task lists + :rtype: tuple + """ + # to disable: + #return tasks, [] + for x in tasks: + x.visited = 0 + + reverse = self.revdeps + + groups_done = set() + for x in tasks: + for k in x.run_after: + if isinstance(k, Task.TaskGroup): + if k not in groups_done: + groups_done.add(k) + for j in k.prev: + reverse[j].add(k) + else: + reverse[k].add(x) + + # the priority number is not the tree depth + def visit(n): + if isinstance(n, Task.TaskGroup): + return sum(visit(k) for k in n.next) + + if n.visited == 0: + n.visited = 1 + + if n in reverse: + rev = reverse[n] + n.prio_order = n.tree_weight + len(rev) + sum(visit(k) for k in rev) + else: + n.prio_order = n.tree_weight + + n.visited = 2 + elif n.visited == 1: + raise Errors.WafError('Dependency cycle found!') + return n.prio_order + + for x in tasks: + if x.visited != 0: + # must visit all to detect cycles + continue + try: + visit(x) + except Errors.WafError: + self.debug_cycles(tasks, reverse) + + ready = [] + waiting = [] + for x in tasks: + for k in x.run_after: + if not k.hasrun: + waiting.append(x) + break + else: + ready.append(x) + return (ready, waiting) + + def debug_cycles(self, tasks, reverse): + tmp = {} + for x in tasks: + tmp[x] = 0 + + def visit(n, acc): + if isinstance(n, Task.TaskGroup): + for k in n.next: + visit(k, acc) + return + if tmp[n] == 0: + tmp[n] = 1 + for k in reverse.get(n, []): + visit(k, [n] + acc) + tmp[n] = 2 + elif tmp[n] == 1: + lst = [] + for tsk in acc: + lst.append(repr(tsk)) + if tsk is n: + # exclude prior nodes, we want the minimum cycle + break + raise Errors.WafError('Task dependency cycle in "run_after" constraints: %s' % ''.join(lst)) + for x in tasks: + visit(x, []) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Scripting.py b/ldb-2.0.8/third_party/waf/waflib/Scripting.py new file mode 100644 index 0000000..68dccf2 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Scripting.py @@ -0,0 +1,625 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +"Module called for configuring, compiling and installing targets" + +from __future__ import with_statement + +import os, shlex, shutil, traceback, errno, sys, stat +from waflib import Utils, Configure, Logs, Options, ConfigSet, Context, Errors, Build, Node + +build_dir_override = None + +no_climb_commands = ['configure'] + +default_cmd = "build" + +def waf_entry_point(current_directory, version, wafdir): + """ + This is the main entry point, all Waf execution starts here. + + :param current_directory: absolute path representing the current directory + :type current_directory: string + :param version: version number + :type version: string + :param wafdir: absolute path representing the directory of the waf library + :type wafdir: string + """ + Logs.init_log() + + if Context.WAFVERSION != version: + Logs.error('Waf script %r and library %r do not match (directory %r)', version, Context.WAFVERSION, wafdir) + sys.exit(1) + + # Store current directory before any chdir + Context.waf_dir = wafdir + Context.run_dir = Context.launch_dir = current_directory + start_dir = current_directory + no_climb = os.environ.get('NOCLIMB') + + if len(sys.argv) > 1: + # os.path.join handles absolute paths + # if sys.argv[1] is not an absolute path, then it is relative to the current working directory + potential_wscript = os.path.join(current_directory, sys.argv[1]) + if os.path.basename(potential_wscript) == Context.WSCRIPT_FILE and os.path.isfile(potential_wscript): + # need to explicitly normalize the path, as it may contain extra '/.' + path = os.path.normpath(os.path.dirname(potential_wscript)) + start_dir = os.path.abspath(path) + no_climb = True + sys.argv.pop(1) + + ctx = Context.create_context('options') + (options, commands, env) = ctx.parse_cmd_args(allow_unknown=True) + if options.top: + start_dir = Context.run_dir = Context.top_dir = options.top + no_climb = True + if options.out: + Context.out_dir = options.out + + # if 'configure' is in the commands, do not search any further + if not no_climb: + for k in no_climb_commands: + for y in commands: + if y.startswith(k): + no_climb = True + break + + # try to find a lock file (if the project was configured) + # at the same time, store the first wscript file seen + cur = start_dir + while cur: + try: + lst = os.listdir(cur) + except OSError: + lst = [] + Logs.error('Directory %r is unreadable!', cur) + if Options.lockfile in lst: + env = ConfigSet.ConfigSet() + try: + env.load(os.path.join(cur, Options.lockfile)) + ino = os.stat(cur)[stat.ST_INO] + except EnvironmentError: + pass + else: + # check if the folder was not moved + for x in (env.run_dir, env.top_dir, env.out_dir): + if not x: + continue + if Utils.is_win32: + if cur == x: + load = True + break + else: + # if the filesystem features symlinks, compare the inode numbers + try: + ino2 = os.stat(x)[stat.ST_INO] + except OSError: + pass + else: + if ino == ino2: + load = True + break + else: + Logs.warn('invalid lock file in %s', cur) + load = False + + if load: + Context.run_dir = env.run_dir + Context.top_dir = env.top_dir + Context.out_dir = env.out_dir + break + + if not Context.run_dir: + if Context.WSCRIPT_FILE in lst: + Context.run_dir = cur + + next = os.path.dirname(cur) + if next == cur: + break + cur = next + + if no_climb: + break + + wscript = os.path.normpath(os.path.join(Context.run_dir, Context.WSCRIPT_FILE)) + if not os.path.exists(wscript): + if options.whelp: + Logs.warn('These are the generic options (no wscript/project found)') + ctx.parser.print_help() + sys.exit(0) + Logs.error('Waf: Run from a folder containing a %r file (or try -h for the generic options)', Context.WSCRIPT_FILE) + sys.exit(1) + + try: + os.chdir(Context.run_dir) + except OSError: + Logs.error('Waf: The folder %r is unreadable', Context.run_dir) + sys.exit(1) + + try: + set_main_module(wscript) + except Errors.WafError as e: + Logs.pprint('RED', e.verbose_msg) + Logs.error(str(e)) + sys.exit(1) + except Exception as e: + Logs.error('Waf: The wscript in %r is unreadable', Context.run_dir) + traceback.print_exc(file=sys.stdout) + sys.exit(2) + + if options.profile: + import cProfile, pstats + cProfile.runctx('from waflib import Scripting; Scripting.run_commands()', {}, {}, 'profi.txt') + p = pstats.Stats('profi.txt') + p.sort_stats('time').print_stats(75) # or 'cumulative' + else: + try: + try: + run_commands() + except: + if options.pdb: + import pdb + type, value, tb = sys.exc_info() + traceback.print_exc() + pdb.post_mortem(tb) + else: + raise + except Errors.WafError as e: + if Logs.verbose > 1: + Logs.pprint('RED', e.verbose_msg) + Logs.error(e.msg) + sys.exit(1) + except SystemExit: + raise + except Exception as e: + traceback.print_exc(file=sys.stdout) + sys.exit(2) + except KeyboardInterrupt: + Logs.pprint('RED', 'Interrupted') + sys.exit(68) + +def set_main_module(file_path): + """ + Read the main wscript file into :py:const:`waflib.Context.Context.g_module` and + bind default functions such as ``init``, ``dist``, ``distclean`` if not defined. + Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. + + :param file_path: absolute path representing the top-level wscript file + :type file_path: string + """ + Context.g_module = Context.load_module(file_path) + Context.g_module.root_path = file_path + + # note: to register the module globally, use the following: + # sys.modules['wscript_main'] = g_module + + def set_def(obj): + name = obj.__name__ + if not name in Context.g_module.__dict__: + setattr(Context.g_module, name, obj) + for k in (dist, distclean, distcheck): + set_def(k) + # add dummy init and shutdown functions if they're not defined + if not 'init' in Context.g_module.__dict__: + Context.g_module.init = Utils.nada + if not 'shutdown' in Context.g_module.__dict__: + Context.g_module.shutdown = Utils.nada + if not 'options' in Context.g_module.__dict__: + Context.g_module.options = Utils.nada + +def parse_options(): + """ + Parses the command-line options and initialize the logging system. + Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. + """ + ctx = Context.create_context('options') + ctx.execute() + if not Options.commands: + if isinstance(default_cmd, list): + Options.commands.extend(default_cmd) + else: + Options.commands.append(default_cmd) + if Options.options.whelp: + ctx.parser.print_help() + sys.exit(0) + +def run_command(cmd_name): + """ + Executes a single Waf command. Called by :py:func:`waflib.Scripting.run_commands`. + + :param cmd_name: command to execute, like ``build`` + :type cmd_name: string + """ + ctx = Context.create_context(cmd_name) + ctx.log_timer = Utils.Timer() + ctx.options = Options.options # provided for convenience + ctx.cmd = cmd_name + try: + ctx.execute() + finally: + # Issue 1374 + ctx.finalize() + return ctx + +def run_commands(): + """ + Execute the Waf commands that were given on the command-line, and the other options + Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization, and executed + after :py:func:`waflib.Scripting.parse_options`. + """ + parse_options() + run_command('init') + while Options.commands: + cmd_name = Options.commands.pop(0) + ctx = run_command(cmd_name) + Logs.info('%r finished successfully (%s)', cmd_name, ctx.log_timer) + run_command('shutdown') + +########################################################################################### + +def distclean_dir(dirname): + """ + Distclean function called in the particular case when:: + + top == out + + :param dirname: absolute path of the folder to clean + :type dirname: string + """ + for (root, dirs, files) in os.walk(dirname): + for f in files: + if f.endswith(('.o', '.moc', '.exe')): + fname = os.path.join(root, f) + try: + os.remove(fname) + except OSError: + Logs.warn('Could not remove %r', fname) + + for x in (Context.DBFILE, 'config.log'): + try: + os.remove(x) + except OSError: + pass + + try: + shutil.rmtree(Build.CACHE_DIR) + except OSError: + pass + +def distclean(ctx): + '''removes build folders and data''' + + def remove_and_log(k, fun): + try: + fun(k) + except EnvironmentError as e: + if e.errno != errno.ENOENT: + Logs.warn('Could not remove %r', k) + + # remove waf cache folders on the top-level + if not Options.commands: + for k in os.listdir('.'): + for x in '.waf-2 waf-2 .waf3-2 waf3-2'.split(): + if k.startswith(x): + remove_and_log(k, shutil.rmtree) + + # remove a build folder, if any + cur = '.' + if ctx.options.no_lock_in_top: + cur = ctx.options.out + + try: + lst = os.listdir(cur) + except OSError: + Logs.warn('Could not read %r', cur) + return + + if Options.lockfile in lst: + f = os.path.join(cur, Options.lockfile) + try: + env = ConfigSet.ConfigSet(f) + except EnvironmentError: + Logs.warn('Could not read %r', f) + return + + if not env.out_dir or not env.top_dir: + Logs.warn('Invalid lock file %r', f) + return + + if env.out_dir == env.top_dir: + distclean_dir(env.out_dir) + else: + remove_and_log(env.out_dir, shutil.rmtree) + + env_dirs = [env.out_dir] + if not ctx.options.no_lock_in_top: + env_dirs.append(env.top_dir) + if not ctx.options.no_lock_in_run: + env_dirs.append(env.run_dir) + for k in env_dirs: + p = os.path.join(k, Options.lockfile) + remove_and_log(p, os.remove) + +class Dist(Context.Context): + '''creates an archive containing the project source code''' + cmd = 'dist' + fun = 'dist' + algo = 'tar.bz2' + ext_algo = {} + + def execute(self): + """ + See :py:func:`waflib.Context.Context.execute` + """ + self.recurse([os.path.dirname(Context.g_module.root_path)]) + self.archive() + + def archive(self): + """ + Creates the source archive. + """ + import tarfile + + arch_name = self.get_arch_name() + + try: + self.base_path + except AttributeError: + self.base_path = self.path + + node = self.base_path.make_node(arch_name) + try: + node.delete() + except OSError: + pass + + files = self.get_files() + + if self.algo.startswith('tar.'): + tar = tarfile.open(node.abspath(), 'w:' + self.algo.replace('tar.', '')) + + for x in files: + self.add_tar_file(x, tar) + tar.close() + elif self.algo == 'zip': + import zipfile + zip = zipfile.ZipFile(node.abspath(), 'w', compression=zipfile.ZIP_DEFLATED) + + for x in files: + archive_name = self.get_base_name() + '/' + x.path_from(self.base_path) + zip.write(x.abspath(), archive_name, zipfile.ZIP_DEFLATED) + zip.close() + else: + self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip') + + try: + from hashlib import sha256 + except ImportError: + digest = '' + else: + digest = ' (sha256=%r)' % sha256(node.read(flags='rb')).hexdigest() + + Logs.info('New archive created: %s%s', self.arch_name, digest) + + def get_tar_path(self, node): + """ + Return the path to use for a node in the tar archive, the purpose of this + is to let subclases resolve symbolic links or to change file names + + :return: absolute path + :rtype: string + """ + return node.abspath() + + def add_tar_file(self, x, tar): + """ + Adds a file to the tar archive. Symlinks are not verified. + + :param x: file path + :param tar: tar file object + """ + p = self.get_tar_path(x) + tinfo = tar.gettarinfo(name=p, arcname=self.get_tar_prefix() + '/' + x.path_from(self.base_path)) + tinfo.uid = 0 + tinfo.gid = 0 + tinfo.uname = 'root' + tinfo.gname = 'root' + + if os.path.isfile(p): + with open(p, 'rb') as f: + tar.addfile(tinfo, fileobj=f) + else: + tar.addfile(tinfo) + + def get_tar_prefix(self): + """ + Returns the base path for files added into the archive tar file + + :rtype: string + """ + try: + return self.tar_prefix + except AttributeError: + return self.get_base_name() + + def get_arch_name(self): + """ + Returns the archive file name. + Set the attribute *arch_name* to change the default value:: + + def dist(ctx): + ctx.arch_name = 'ctx.tar.bz2' + + :rtype: string + """ + try: + self.arch_name + except AttributeError: + self.arch_name = self.get_base_name() + '.' + self.ext_algo.get(self.algo, self.algo) + return self.arch_name + + def get_base_name(self): + """ + Returns the default name of the main directory in the archive, which is set to *appname-version*. + Set the attribute *base_name* to change the default value:: + + def dist(ctx): + ctx.base_name = 'files' + + :rtype: string + """ + try: + self.base_name + except AttributeError: + appname = getattr(Context.g_module, Context.APPNAME, 'noname') + version = getattr(Context.g_module, Context.VERSION, '1.0') + self.base_name = appname + '-' + version + return self.base_name + + def get_excl(self): + """ + Returns the patterns to exclude for finding the files in the top-level directory. + Set the attribute *excl* to change the default value:: + + def dist(ctx): + ctx.excl = 'build **/*.o **/*.class' + + :rtype: string + """ + try: + return self.excl + except AttributeError: + self.excl = Node.exclude_regs + ' **/waf-2.* **/.waf-2.* **/waf3-2.* **/.waf3-2.* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' + if Context.out_dir: + nd = self.root.find_node(Context.out_dir) + if nd: + self.excl += ' ' + nd.path_from(self.base_path) + return self.excl + + def get_files(self): + """ + Files to package are searched automatically by :py:func:`waflib.Node.Node.ant_glob`. + Set *files* to prevent this behaviour:: + + def dist(ctx): + ctx.files = ctx.path.find_node('wscript') + + Files are also searched from the directory 'base_path', to change it, set:: + + def dist(ctx): + ctx.base_path = path + + :rtype: list of :py:class:`waflib.Node.Node` + """ + try: + files = self.files + except AttributeError: + files = self.base_path.ant_glob('**/*', excl=self.get_excl()) + return files + +def dist(ctx): + '''makes a tarball for redistributing the sources''' + pass + +class DistCheck(Dist): + """creates an archive with dist, then tries to build it""" + fun = 'distcheck' + cmd = 'distcheck' + + def execute(self): + """ + See :py:func:`waflib.Context.Context.execute` + """ + self.recurse([os.path.dirname(Context.g_module.root_path)]) + self.archive() + self.check() + + def make_distcheck_cmd(self, tmpdir): + cfg = [] + if Options.options.distcheck_args: + cfg = shlex.split(Options.options.distcheck_args) + else: + cfg = [x for x in sys.argv if x.startswith('-')] + cmd = [sys.executable, sys.argv[0], 'configure', 'build', 'install', 'uninstall', '--destdir=' + tmpdir] + cfg + return cmd + + def check(self): + """ + Creates the archive, uncompresses it and tries to build the project + """ + import tempfile, tarfile + + with tarfile.open(self.get_arch_name()) as t: + for x in t: + t.extract(x) + + instdir = tempfile.mkdtemp('.inst', self.get_base_name()) + cmd = self.make_distcheck_cmd(instdir) + ret = Utils.subprocess.Popen(cmd, cwd=self.get_base_name()).wait() + if ret: + raise Errors.WafError('distcheck failed with code %r' % ret) + + if os.path.exists(instdir): + raise Errors.WafError('distcheck succeeded, but files were left in %s' % instdir) + + shutil.rmtree(self.get_base_name()) + + +def distcheck(ctx): + '''checks if the project compiles (tarball from 'dist')''' + pass + +def autoconfigure(execute_method): + """ + Decorator that enables context commands to run *configure* as needed. + """ + def execute(self): + """ + Wraps :py:func:`waflib.Context.Context.execute` on the context class + """ + if not Configure.autoconfig: + return execute_method(self) + + env = ConfigSet.ConfigSet() + do_config = False + try: + env.load(os.path.join(Context.top_dir, Options.lockfile)) + except EnvironmentError: + Logs.warn('Configuring the project') + do_config = True + else: + if env.run_dir != Context.run_dir: + do_config = True + else: + h = 0 + for f in env.files: + try: + h = Utils.h_list((h, Utils.readf(f, 'rb'))) + except EnvironmentError: + do_config = True + break + else: + do_config = h != env.hash + + if do_config: + cmd = env.config_cmd or 'configure' + if Configure.autoconfig == 'clobber': + tmp = Options.options.__dict__ + launch_dir_tmp = Context.launch_dir + if env.options: + Options.options.__dict__ = env.options + Context.launch_dir = env.launch_dir + try: + run_command(cmd) + finally: + Options.options.__dict__ = tmp + Context.launch_dir = launch_dir_tmp + else: + run_command(cmd) + run_command(self.cmd) + else: + return execute_method(self) + return execute +Build.BuildContext.execute = autoconfigure(Build.BuildContext.execute) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Task.py b/ldb-2.0.8/third_party/waf/waflib/Task.py new file mode 100644 index 0000000..cb49a73 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Task.py @@ -0,0 +1,1406 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Tasks represent atomic operations such as processes. +""" + +import os, re, sys, tempfile, traceback +from waflib import Utils, Logs, Errors + +# task states +NOT_RUN = 0 +"""The task was not executed yet""" + +MISSING = 1 +"""The task has been executed but the files have not been created""" + +CRASHED = 2 +"""The task execution returned a non-zero exit status""" + +EXCEPTION = 3 +"""An exception occurred in the task execution""" + +CANCELED = 4 +"""A dependency for the task is missing so it was cancelled""" + +SKIPPED = 8 +"""The task did not have to be executed""" + +SUCCESS = 9 +"""The task was successfully executed""" + +ASK_LATER = -1 +"""The task is not ready to be executed""" + +SKIP_ME = -2 +"""The task does not need to be executed""" + +RUN_ME = -3 +"""The task must be executed""" + +CANCEL_ME = -4 +"""The task cannot be executed because of a dependency problem""" + +COMPILE_TEMPLATE_SHELL = ''' +def f(tsk): + env = tsk.env + gen = tsk.generator + bld = gen.bld + cwdx = tsk.get_cwd() + p = env.get_flat + def to_list(xx): + if isinstance(xx, str): return [xx] + return xx + tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s + return tsk.exec_command(cmd, cwd=cwdx, env=env.env or None) +''' + +COMPILE_TEMPLATE_NOSHELL = ''' +def f(tsk): + env = tsk.env + gen = tsk.generator + bld = gen.bld + cwdx = tsk.get_cwd() + def to_list(xx): + if isinstance(xx, str): return [xx] + return xx + def merge(lst1, lst2): + if lst1 and lst2: + return lst1[:-1] + [lst1[-1] + lst2[0]] + lst2[1:] + return lst1 + lst2 + lst = [] + %s + if '' in lst: + lst = [x for x in lst if x] + tsk.last_cmd = lst + return tsk.exec_command(lst, cwd=cwdx, env=env.env or None) +''' + +COMPILE_TEMPLATE_SIG_VARS = ''' +def f(tsk): + sig = tsk.generator.bld.hash_env_vars(tsk.env, tsk.vars) + tsk.m.update(sig) + env = tsk.env + gen = tsk.generator + bld = gen.bld + cwdx = tsk.get_cwd() + p = env.get_flat + buf = [] + %s + tsk.m.update(repr(buf).encode()) +''' + +classes = {} +""" +The metaclass :py:class:`waflib.Task.store_task_type` stores all class tasks +created by user scripts or Waf tools to this dict. It maps class names to class objects. +""" + +class store_task_type(type): + """ + Metaclass: store the task classes into the dict pointed by the + class attribute 'register' which defaults to :py:const:`waflib.Task.classes`, + + The attribute 'run_str' is compiled into a method 'run' bound to the task class. + """ + def __init__(cls, name, bases, dict): + super(store_task_type, cls).__init__(name, bases, dict) + name = cls.__name__ + + if name != 'evil' and name != 'Task': + if getattr(cls, 'run_str', None): + # if a string is provided, convert it to a method + (f, dvars) = compile_fun(cls.run_str, cls.shell) + cls.hcode = Utils.h_cmd(cls.run_str) + cls.orig_run_str = cls.run_str + # change the name of run_str or it is impossible to subclass with a function + cls.run_str = None + cls.run = f + # process variables + cls.vars = list(set(cls.vars + dvars)) + cls.vars.sort() + if cls.vars: + fun = compile_sig_vars(cls.vars) + if fun: + cls.sig_vars = fun + elif getattr(cls, 'run', None) and not 'hcode' in cls.__dict__: + # getattr(cls, 'hcode') would look in the upper classes + cls.hcode = Utils.h_cmd(cls.run) + + # be creative + getattr(cls, 'register', classes)[name] = cls + +evil = store_task_type('evil', (object,), {}) +"Base class provided to avoid writing a metaclass, so the code can run in python 2.6 and 3.x unmodified" + +class Task(evil): + """ + Task objects represents actions to perform such as commands to execute by calling the `run` method. + + Detecting when to execute a task occurs in the method :py:meth:`waflib.Task.Task.runnable_status`. + + Detecting which tasks to execute is performed through a hash value returned by + :py:meth:`waflib.Task.Task.signature`. The task signature is persistent from build to build. + """ + vars = [] + """ConfigSet variables that should trigger a rebuild (class attribute used for :py:meth:`waflib.Task.Task.sig_vars`)""" + + always_run = False + """Specify whether task instances must always be executed or not (class attribute)""" + + shell = False + """Execute the command with the shell (class attribute)""" + + color = 'GREEN' + """Color for the console display, see :py:const:`waflib.Logs.colors_lst`""" + + ext_in = [] + """File extensions that objects of this task class may use""" + + ext_out = [] + """File extensions that objects of this task class may create""" + + before = [] + """The instances of this class are executed before the instances of classes whose names are in this list""" + + after = [] + """The instances of this class are executed after the instances of classes whose names are in this list""" + + hcode = Utils.SIG_NIL + """String representing an additional hash for the class representation""" + + keep_last_cmd = False + """Whether to keep the last command executed on the instance after execution. + This may be useful for certain extensions but it can a lot of memory. + """ + + weight = 0 + """Optional weight to tune the priority for task instances. + The higher, the earlier. The weight only applies to single task objects.""" + + tree_weight = 0 + """Optional weight to tune the priority of task instances and whole subtrees. + The higher, the earlier.""" + + prio_order = 0 + """Priority order set by the scheduler on instances during the build phase. + You most likely do not need to set it. + """ + + __slots__ = ('hasrun', 'generator', 'env', 'inputs', 'outputs', 'dep_nodes', 'run_after') + + def __init__(self, *k, **kw): + self.hasrun = NOT_RUN + try: + self.generator = kw['generator'] + except KeyError: + self.generator = self + + self.env = kw['env'] + """:py:class:`waflib.ConfigSet.ConfigSet` object (make sure to provide one)""" + + self.inputs = [] + """List of input nodes, which represent the files used by the task instance""" + + self.outputs = [] + """List of output nodes, which represent the files created by the task instance""" + + self.dep_nodes = [] + """List of additional nodes to depend on""" + + self.run_after = set() + """Set of tasks that must be executed before this one""" + + def __lt__(self, other): + return self.priority() > other.priority() + def __le__(self, other): + return self.priority() >= other.priority() + def __gt__(self, other): + return self.priority() < other.priority() + def __ge__(self, other): + return self.priority() <= other.priority() + + def get_cwd(self): + """ + :return: current working directory + :rtype: :py:class:`waflib.Node.Node` + """ + bld = self.generator.bld + ret = getattr(self, 'cwd', None) or getattr(bld, 'cwd', bld.bldnode) + if isinstance(ret, str): + if os.path.isabs(ret): + ret = bld.root.make_node(ret) + else: + ret = self.generator.path.make_node(ret) + return ret + + def quote_flag(self, x): + """ + Surround a process argument by quotes so that a list of arguments can be written to a file + + :param x: flag + :type x: string + :return: quoted flag + :rtype: string + """ + old = x + if '\\' in x: + x = x.replace('\\', '\\\\') + if '"' in x: + x = x.replace('"', '\\"') + if old != x or ' ' in x or '\t' in x or "'" in x: + x = '"%s"' % x + return x + + def priority(self): + """ + Priority of execution; the higher, the earlier + + :return: the priority value + :rtype: a tuple of numeric values + """ + return (self.weight + self.prio_order, - getattr(self.generator, 'tg_idx_count', 0)) + + def split_argfile(self, cmd): + """ + Splits a list of process commands into the executable part and its list of arguments + + :return: a tuple containing the executable first and then the rest of arguments + :rtype: tuple + """ + return ([cmd[0]], [self.quote_flag(x) for x in cmd[1:]]) + + def exec_command(self, cmd, **kw): + """ + Wrapper for :py:meth:`waflib.Context.Context.exec_command`. + This version set the current working directory (``build.variant_dir``), + applies PATH settings (if self.env.PATH is provided), and can run long + commands through a temporary ``@argfile``. + + :param cmd: process command to execute + :type cmd: list of string (best) or string (process will use a shell) + :return: the return code + :rtype: int + + Optional parameters: + + #. cwd: current working directory (Node or string) + #. stdout: set to None to prevent waf from capturing the process standard output + #. stderr: set to None to prevent waf from capturing the process standard error + #. timeout: timeout value (Python 3) + """ + if not 'cwd' in kw: + kw['cwd'] = self.get_cwd() + + if hasattr(self, 'timeout'): + kw['timeout'] = self.timeout + + if self.env.PATH: + env = kw['env'] = dict(kw.get('env') or self.env.env or os.environ) + env['PATH'] = self.env.PATH if isinstance(self.env.PATH, str) else os.pathsep.join(self.env.PATH) + + if hasattr(self, 'stdout'): + kw['stdout'] = self.stdout + if hasattr(self, 'stderr'): + kw['stderr'] = self.stderr + + if not isinstance(cmd, str): + if Utils.is_win32: + # win32 compares the resulting length http://support.microsoft.com/kb/830473 + too_long = sum([len(arg) for arg in cmd]) + len(cmd) > 8192 + else: + # non-win32 counts the amount of arguments (200k) + too_long = len(cmd) > 200000 + + if too_long and getattr(self, 'allow_argsfile', True): + # Shunt arguments to a temporary file if the command is too long. + cmd, args = self.split_argfile(cmd) + try: + (fd, tmp) = tempfile.mkstemp() + os.write(fd, '\r\n'.join(args).encode()) + os.close(fd) + if Logs.verbose: + Logs.debug('argfile: @%r -> %r', tmp, args) + return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw) + finally: + try: + os.remove(tmp) + except OSError: + # anti-virus and indexers can keep files open -_- + pass + return self.generator.bld.exec_command(cmd, **kw) + + def process(self): + """ + Runs the task and handles errors + + :return: 0 or None if everything is fine + :rtype: integer + """ + # remove the task signature immediately before it is executed + # so that the task will be executed again in case of failure + try: + del self.generator.bld.task_sigs[self.uid()] + except KeyError: + pass + + try: + ret = self.run() + except Exception: + self.err_msg = traceback.format_exc() + self.hasrun = EXCEPTION + else: + if ret: + self.err_code = ret + self.hasrun = CRASHED + else: + try: + self.post_run() + except Errors.WafError: + pass + except Exception: + self.err_msg = traceback.format_exc() + self.hasrun = EXCEPTION + else: + self.hasrun = SUCCESS + + if self.hasrun != SUCCESS and self.scan: + # rescan dependencies on next run + try: + del self.generator.bld.imp_sigs[self.uid()] + except KeyError: + pass + + def log_display(self, bld): + "Writes the execution status on the context logger" + if self.generator.bld.progress_bar == 3: + return + + s = self.display() + if s: + if bld.logger: + logger = bld.logger + else: + logger = Logs + + if self.generator.bld.progress_bar == 1: + c1 = Logs.colors.cursor_off + c2 = Logs.colors.cursor_on + logger.info(s, extra={'stream': sys.stderr, 'terminator':'', 'c1': c1, 'c2' : c2}) + else: + logger.info(s, extra={'terminator':'', 'c1': '', 'c2' : ''}) + + def display(self): + """ + Returns an execution status for the console, the progress bar, or the IDE output. + + :rtype: string + """ + col1 = Logs.colors(self.color) + col2 = Logs.colors.NORMAL + master = self.generator.bld.producer + + def cur(): + # the current task position, computed as late as possible + return master.processed - master.ready.qsize() + + if self.generator.bld.progress_bar == 1: + return self.generator.bld.progress_line(cur(), master.total, col1, col2) + + if self.generator.bld.progress_bar == 2: + ela = str(self.generator.bld.timer) + try: + ins = ','.join([n.name for n in self.inputs]) + except AttributeError: + ins = '' + try: + outs = ','.join([n.name for n in self.outputs]) + except AttributeError: + outs = '' + return '|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n' % (master.total, cur(), ins, outs, ela) + + s = str(self) + if not s: + return None + + total = master.total + n = len(str(total)) + fs = '[%%%dd/%%%dd] %%s%%s%%s%%s\n' % (n, n) + kw = self.keyword() + if kw: + kw += ' ' + return fs % (cur(), total, kw, col1, s, col2) + + def hash_constraints(self): + """ + Identifies a task type for all the constraints relevant for the scheduler: precedence, file production + + :return: a hash value + :rtype: string + """ + return (tuple(self.before), tuple(self.after), tuple(self.ext_in), tuple(self.ext_out), self.__class__.__name__, self.hcode) + + def format_error(self): + """ + Returns an error message to display the build failure reasons + + :rtype: string + """ + if Logs.verbose: + msg = ': %r\n%r' % (self, getattr(self, 'last_cmd', '')) + else: + msg = ' (run with -v to display more information)' + name = getattr(self.generator, 'name', '') + if getattr(self, "err_msg", None): + return self.err_msg + elif not self.hasrun: + return 'task in %r was not executed for some reason: %r' % (name, self) + elif self.hasrun == CRASHED: + try: + return ' -> task in %r failed with exit status %r%s' % (name, self.err_code, msg) + except AttributeError: + return ' -> task in %r failed%s' % (name, msg) + elif self.hasrun == MISSING: + return ' -> missing files in %r%s' % (name, msg) + elif self.hasrun == CANCELED: + return ' -> %r canceled because of missing dependencies' % name + else: + return 'invalid status for task in %r: %r' % (name, self.hasrun) + + def colon(self, var1, var2): + """ + Enable scriptlet expressions of the form ${FOO_ST:FOO} + If the first variable (FOO_ST) is empty, then an empty list is returned + + The results will be slightly different if FOO_ST is a list, for example:: + + env.FOO = ['p1', 'p2'] + env.FOO_ST = '-I%s' + # ${FOO_ST:FOO} returns + ['-Ip1', '-Ip2'] + + env.FOO_ST = ['-a', '-b'] + # ${FOO_ST:FOO} returns + ['-a', '-b', 'p1', '-a', '-b', 'p2'] + """ + tmp = self.env[var1] + if not tmp: + return [] + + if isinstance(var2, str): + it = self.env[var2] + else: + it = var2 + if isinstance(tmp, str): + return [tmp % x for x in it] + else: + lst = [] + for y in it: + lst.extend(tmp) + lst.append(y) + return lst + + def __str__(self): + "string to display to the user" + name = self.__class__.__name__ + if self.outputs: + if name.endswith(('lib', 'program')) or not self.inputs: + node = self.outputs[0] + return node.path_from(node.ctx.launch_node()) + if not (self.inputs or self.outputs): + return self.__class__.__name__ + if len(self.inputs) == 1: + node = self.inputs[0] + return node.path_from(node.ctx.launch_node()) + + src_str = ' '.join([a.path_from(a.ctx.launch_node()) for a in self.inputs]) + tgt_str = ' '.join([a.path_from(a.ctx.launch_node()) for a in self.outputs]) + if self.outputs: + sep = ' -> ' + else: + sep = '' + return '%s: %s%s%s' % (self.__class__.__name__, src_str, sep, tgt_str) + + def keyword(self): + "Display keyword used to prettify the console outputs" + name = self.__class__.__name__ + if name.endswith(('lib', 'program')): + return 'Linking' + if len(self.inputs) == 1 and len(self.outputs) == 1: + return 'Compiling' + if not self.inputs: + if self.outputs: + return 'Creating' + else: + return 'Running' + return 'Processing' + + def __repr__(self): + "for debugging purposes" + try: + ins = ",".join([x.name for x in self.inputs]) + outs = ",".join([x.name for x in self.outputs]) + except AttributeError: + ins = ",".join([str(x) for x in self.inputs]) + outs = ",".join([str(x) for x in self.outputs]) + return "".join(['\n\t{task %r: ' % id(self), self.__class__.__name__, " ", ins, " -> ", outs, '}']) + + def uid(self): + """ + Returns an identifier used to determine if tasks are up-to-date. Since the + identifier will be stored between executions, it must be: + + - unique for a task: no two tasks return the same value (for a given build context) + - the same for a given task instance + + By default, the node paths, the class name, and the function are used + as inputs to compute a hash. + + The pointer to the object (python built-in 'id') will change between build executions, + and must be avoided in such hashes. + + :return: hash value + :rtype: string + """ + try: + return self.uid_ + except AttributeError: + m = Utils.md5(self.__class__.__name__) + up = m.update + for x in self.inputs + self.outputs: + up(x.abspath()) + self.uid_ = m.digest() + return self.uid_ + + def set_inputs(self, inp): + """ + Appends the nodes to the *inputs* list + + :param inp: input nodes + :type inp: node or list of nodes + """ + if isinstance(inp, list): + self.inputs += inp + else: + self.inputs.append(inp) + + def set_outputs(self, out): + """ + Appends the nodes to the *outputs* list + + :param out: output nodes + :type out: node or list of nodes + """ + if isinstance(out, list): + self.outputs += out + else: + self.outputs.append(out) + + def set_run_after(self, task): + """ + Run this task only after the given *task*. + + Calling this method from :py:meth:`waflib.Task.Task.runnable_status` may cause + build deadlocks; see :py:meth:`waflib.Tools.fc.fc.runnable_status` for details. + + :param task: task + :type task: :py:class:`waflib.Task.Task` + """ + assert isinstance(task, Task) + self.run_after.add(task) + + def signature(self): + """ + Task signatures are stored between build executions, they are use to track the changes + made to the input nodes (not to the outputs!). The signature hashes data from various sources: + + * explicit dependencies: files listed in the inputs (list of node objects) :py:meth:`waflib.Task.Task.sig_explicit_deps` + * implicit dependencies: list of nodes returned by scanner methods (when present) :py:meth:`waflib.Task.Task.sig_implicit_deps` + * hashed data: variables/values read from task.vars/task.env :py:meth:`waflib.Task.Task.sig_vars` + + If the signature is expected to give a different result, clear the cache kept in ``self.cache_sig``:: + + from waflib import Task + class cls(Task.Task): + def signature(self): + sig = super(Task.Task, self).signature() + delattr(self, 'cache_sig') + return super(Task.Task, self).signature() + + :return: the signature value + :rtype: string or bytes + """ + try: + return self.cache_sig + except AttributeError: + pass + + self.m = Utils.md5(self.hcode) + + # explicit deps + self.sig_explicit_deps() + + # env vars + self.sig_vars() + + # implicit deps / scanner results + if self.scan: + try: + self.sig_implicit_deps() + except Errors.TaskRescan: + return self.signature() + + ret = self.cache_sig = self.m.digest() + return ret + + def runnable_status(self): + """ + Returns the Task status + + :return: a task state in :py:const:`waflib.Task.RUN_ME`, + :py:const:`waflib.Task.SKIP_ME`, :py:const:`waflib.Task.CANCEL_ME` or :py:const:`waflib.Task.ASK_LATER`. + :rtype: int + """ + bld = self.generator.bld + if bld.is_install < 0: + return SKIP_ME + + for t in self.run_after: + if not t.hasrun: + return ASK_LATER + elif t.hasrun < SKIPPED: + # a dependency has an error + return CANCEL_ME + + # first compute the signature + try: + new_sig = self.signature() + except Errors.TaskNotReady: + return ASK_LATER + + # compare the signature to a signature computed previously + key = self.uid() + try: + prev_sig = bld.task_sigs[key] + except KeyError: + Logs.debug('task: task %r must run: it was never run before or the task code changed', self) + return RUN_ME + + if new_sig != prev_sig: + Logs.debug('task: task %r must run: the task signature changed', self) + return RUN_ME + + # compare the signatures of the outputs + for node in self.outputs: + sig = bld.node_sigs.get(node) + if not sig: + Logs.debug('task: task %r must run: an output node has no signature', self) + return RUN_ME + if sig != key: + Logs.debug('task: task %r must run: an output node was produced by another task', self) + return RUN_ME + if not node.exists(): + Logs.debug('task: task %r must run: an output node does not exist', self) + return RUN_ME + + return (self.always_run and RUN_ME) or SKIP_ME + + def post_run(self): + """ + Called after successful execution to record that the task has run by + updating the entry in :py:attr:`waflib.Build.BuildContext.task_sigs`. + """ + bld = self.generator.bld + for node in self.outputs: + if not node.exists(): + self.hasrun = MISSING + self.err_msg = '-> missing file: %r' % node.abspath() + raise Errors.WafError(self.err_msg) + bld.node_sigs[node] = self.uid() # make sure this task produced the files in question + bld.task_sigs[self.uid()] = self.signature() + if not self.keep_last_cmd: + try: + del self.last_cmd + except AttributeError: + pass + + def sig_explicit_deps(self): + """ + Used by :py:meth:`waflib.Task.Task.signature`; it hashes :py:attr:`waflib.Task.Task.inputs` + and :py:attr:`waflib.Task.Task.dep_nodes` signatures. + """ + bld = self.generator.bld + upd = self.m.update + + # the inputs + for x in self.inputs + self.dep_nodes: + upd(x.get_bld_sig()) + + # manual dependencies, they can slow down the builds + if bld.deps_man: + additional_deps = bld.deps_man + for x in self.inputs + self.outputs: + try: + d = additional_deps[x] + except KeyError: + continue + + for v in d: + try: + v = v.get_bld_sig() + except AttributeError: + if hasattr(v, '__call__'): + v = v() # dependency is a function, call it + upd(v) + + def sig_deep_inputs(self): + """ + Enable rebuilds on input files task signatures. Not used by default. + + Example: hashes of output programs can be unchanged after being re-linked, + despite the libraries being different. This method can thus prevent stale unit test + results (waf_unit_test.py). + + Hashing input file timestamps is another possibility for the implementation. + This may cause unnecessary rebuilds when input tasks are frequently executed. + Here is an implementation example:: + + lst = [] + for node in self.inputs + self.dep_nodes: + st = os.stat(node.abspath()) + lst.append(st.st_mtime) + lst.append(st.st_size) + self.m.update(Utils.h_list(lst)) + + The downside of the implementation is that it absolutely requires all build directory + files to be declared within the current build. + """ + bld = self.generator.bld + lst = [bld.task_sigs[bld.node_sigs[node]] for node in (self.inputs + self.dep_nodes) if node.is_bld()] + self.m.update(Utils.h_list(lst)) + + def sig_vars(self): + """ + Used by :py:meth:`waflib.Task.Task.signature`; it hashes :py:attr:`waflib.Task.Task.env` variables/values + When overriding this method, and if scriptlet expressions are used, make sure to follow + the code in :py:meth:`waflib.Task.Task.compile_sig_vars` to enable dependencies on scriptlet results. + + This method may be replaced on subclasses by the metaclass to force dependencies on scriptlet code. + """ + sig = self.generator.bld.hash_env_vars(self.env, self.vars) + self.m.update(sig) + + scan = None + """ + This method, when provided, returns a tuple containing: + + * a list of nodes corresponding to real files + * a list of names for files not found in path_lst + + For example:: + + from waflib.Task import Task + class mytask(Task): + def scan(self, node): + return ([], []) + + The first and second lists in the tuple are stored in :py:attr:`waflib.Build.BuildContext.node_deps` and + :py:attr:`waflib.Build.BuildContext.raw_deps` respectively. + """ + + def sig_implicit_deps(self): + """ + Used by :py:meth:`waflib.Task.Task.signature`; it hashes node signatures + obtained by scanning for dependencies (:py:meth:`waflib.Task.Task.scan`). + + The exception :py:class:`waflib.Errors.TaskRescan` is thrown + when a file has changed. In this case, the method :py:meth:`waflib.Task.Task.signature` is called + once again, and return here to call :py:meth:`waflib.Task.Task.scan` and searching for dependencies. + """ + bld = self.generator.bld + + # get the task signatures from previous runs + key = self.uid() + prev = bld.imp_sigs.get(key, []) + + # for issue #379 + if prev: + try: + if prev == self.compute_sig_implicit_deps(): + return prev + except Errors.TaskNotReady: + raise + except EnvironmentError: + # when a file was renamed, remove the stale nodes (headers in folders without source files) + # this will break the order calculation for headers created during the build in the source directory (should be uncommon) + # the behaviour will differ when top != out + for x in bld.node_deps.get(self.uid(), []): + if not x.is_bld() and not x.exists(): + try: + del x.parent.children[x.name] + except KeyError: + pass + del bld.imp_sigs[key] + raise Errors.TaskRescan('rescan') + + # no previous run or the signature of the dependencies has changed, rescan the dependencies + (bld.node_deps[key], bld.raw_deps[key]) = self.scan() + if Logs.verbose: + Logs.debug('deps: scanner for %s: %r; unresolved: %r', self, bld.node_deps[key], bld.raw_deps[key]) + + # recompute the signature and return it + try: + bld.imp_sigs[key] = self.compute_sig_implicit_deps() + except EnvironmentError: + for k in bld.node_deps.get(self.uid(), []): + if not k.exists(): + Logs.warn('Dependency %r for %r is missing: check the task declaration and the build order!', k, self) + raise + + def compute_sig_implicit_deps(self): + """ + Used by :py:meth:`waflib.Task.Task.sig_implicit_deps` for computing the actual hash of the + :py:class:`waflib.Node.Node` returned by the scanner. + + :return: a hash value for the implicit dependencies + :rtype: string or bytes + """ + upd = self.m.update + self.are_implicit_nodes_ready() + + # scanner returns a node that does not have a signature + # just *ignore* the error and let them figure out from the compiler output + # waf -k behaviour + for k in self.generator.bld.node_deps.get(self.uid(), []): + upd(k.get_bld_sig()) + return self.m.digest() + + def are_implicit_nodes_ready(self): + """ + For each node returned by the scanner, see if there is a task that creates it, + and infer the build order + + This has a low performance impact on null builds (1.86s->1.66s) thanks to caching (28s->1.86s) + """ + bld = self.generator.bld + try: + cache = bld.dct_implicit_nodes + except AttributeError: + bld.dct_implicit_nodes = cache = {} + + # one cache per build group + try: + dct = cache[bld.current_group] + except KeyError: + dct = cache[bld.current_group] = {} + for tsk in bld.cur_tasks: + for x in tsk.outputs: + dct[x] = tsk + + modified = False + for x in bld.node_deps.get(self.uid(), []): + if x in dct: + self.run_after.add(dct[x]) + modified = True + + if modified: + for tsk in self.run_after: + if not tsk.hasrun: + #print "task is not ready..." + raise Errors.TaskNotReady('not ready') +if sys.hexversion > 0x3000000: + def uid(self): + try: + return self.uid_ + except AttributeError: + m = Utils.md5(self.__class__.__name__.encode('latin-1', 'xmlcharrefreplace')) + up = m.update + for x in self.inputs + self.outputs: + up(x.abspath().encode('latin-1', 'xmlcharrefreplace')) + self.uid_ = m.digest() + return self.uid_ + uid.__doc__ = Task.uid.__doc__ + Task.uid = uid + +def is_before(t1, t2): + """ + Returns a non-zero value if task t1 is to be executed before task t2:: + + t1.ext_out = '.h' + t2.ext_in = '.h' + t2.after = ['t1'] + t1.before = ['t2'] + waflib.Task.is_before(t1, t2) # True + + :param t1: Task object + :type t1: :py:class:`waflib.Task.Task` + :param t2: Task object + :type t2: :py:class:`waflib.Task.Task` + """ + to_list = Utils.to_list + for k in to_list(t2.ext_in): + if k in to_list(t1.ext_out): + return 1 + + if t1.__class__.__name__ in to_list(t2.after): + return 1 + + if t2.__class__.__name__ in to_list(t1.before): + return 1 + + return 0 + +def set_file_constraints(tasks): + """ + Updates the ``run_after`` attribute of all tasks based on the task inputs and outputs + + :param tasks: tasks + :type tasks: list of :py:class:`waflib.Task.Task` + """ + ins = Utils.defaultdict(set) + outs = Utils.defaultdict(set) + for x in tasks: + for a in x.inputs: + ins[a].add(x) + for a in x.dep_nodes: + ins[a].add(x) + for a in x.outputs: + outs[a].add(x) + + links = set(ins.keys()).intersection(outs.keys()) + for k in links: + for a in ins[k]: + a.run_after.update(outs[k]) + + +class TaskGroup(object): + """ + Wrap nxm task order constraints into a single object + to prevent the creation of large list/set objects + + This is an optimization + """ + def __init__(self, prev, next): + self.prev = prev + self.next = next + self.done = False + + def get_hasrun(self): + for k in self.prev: + if not k.hasrun: + return NOT_RUN + return SUCCESS + + hasrun = property(get_hasrun, None) + +def set_precedence_constraints(tasks): + """ + Updates the ``run_after`` attribute of all tasks based on the after/before/ext_out/ext_in attributes + + :param tasks: tasks + :type tasks: list of :py:class:`waflib.Task.Task` + """ + cstr_groups = Utils.defaultdict(list) + for x in tasks: + h = x.hash_constraints() + cstr_groups[h].append(x) + + keys = list(cstr_groups.keys()) + maxi = len(keys) + + # this list should be short + for i in range(maxi): + t1 = cstr_groups[keys[i]][0] + for j in range(i + 1, maxi): + t2 = cstr_groups[keys[j]][0] + + # add the constraints based on the comparisons + if is_before(t1, t2): + a = i + b = j + elif is_before(t2, t1): + a = j + b = i + else: + continue + + a = cstr_groups[keys[a]] + b = cstr_groups[keys[b]] + + if len(a) < 2 or len(b) < 2: + for x in b: + x.run_after.update(a) + else: + group = TaskGroup(set(a), set(b)) + for x in b: + x.run_after.add(group) + +def funex(c): + """ + Compiles a scriptlet expression into a Python function + + :param c: function to compile + :type c: string + :return: the function 'f' declared in the input string + :rtype: function + """ + dc = {} + exec(c, dc) + return dc['f'] + +re_cond = re.compile(r'(?P\w+)|(?P\|)|(?P&)') +re_novar = re.compile(r'^(SRC|TGT)\W+.*?$') +reg_act = re.compile(r'(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})', re.M) +def compile_fun_shell(line): + """ + Creates a compiled function to execute a process through a sub-shell + """ + extr = [] + def repl(match): + g = match.group + if g('dollar'): + return "$" + elif g('backslash'): + return '\\\\' + elif g('subst'): + extr.append((g('var'), g('code'))) + return "%s" + return None + line = reg_act.sub(repl, line) or line + dvars = [] + def add_dvar(x): + if x not in dvars: + dvars.append(x) + + def replc(m): + # performs substitutions and populates dvars + if m.group('and'): + return ' and ' + elif m.group('or'): + return ' or ' + else: + x = m.group('var') + add_dvar(x) + return 'env[%r]' % x + + parm = [] + app = parm.append + for (var, meth) in extr: + if var == 'SRC': + if meth: + app('tsk.inputs%s' % meth) + else: + app('" ".join([a.path_from(cwdx) for a in tsk.inputs])') + elif var == 'TGT': + if meth: + app('tsk.outputs%s' % meth) + else: + app('" ".join([a.path_from(cwdx) for a in tsk.outputs])') + elif meth: + if meth.startswith(':'): + add_dvar(var) + m = meth[1:] + if m == 'SRC': + m = '[a.path_from(cwdx) for a in tsk.inputs]' + elif m == 'TGT': + m = '[a.path_from(cwdx) for a in tsk.outputs]' + elif re_novar.match(m): + m = '[tsk.inputs%s]' % m[3:] + elif re_novar.match(m): + m = '[tsk.outputs%s]' % m[3:] + else: + add_dvar(m) + if m[:3] not in ('tsk', 'gen', 'bld'): + m = '%r' % m + app('" ".join(tsk.colon(%r, %s))' % (var, m)) + elif meth.startswith('?'): + # In A?B|C output env.A if one of env.B or env.C is non-empty + expr = re_cond.sub(replc, meth[1:]) + app('p(%r) if (%s) else ""' % (var, expr)) + else: + call = '%s%s' % (var, meth) + add_dvar(call) + app(call) + else: + add_dvar(var) + app("p('%s')" % var) + if parm: + parm = "%% (%s) " % (',\n\t\t'.join(parm)) + else: + parm = '' + + c = COMPILE_TEMPLATE_SHELL % (line, parm) + Logs.debug('action: %s', c.strip().splitlines()) + return (funex(c), dvars) + +reg_act_noshell = re.compile(r"(?P\s+)|(?P\$\{(?P\w+)(?P.*?)\})|(?P([^$ \t\n\r\f\v]|\$\$)+)", re.M) +def compile_fun_noshell(line): + """ + Creates a compiled function to execute a process without a sub-shell + """ + buf = [] + dvars = [] + merge = False + app = buf.append + + def add_dvar(x): + if x not in dvars: + dvars.append(x) + + def replc(m): + # performs substitutions and populates dvars + if m.group('and'): + return ' and ' + elif m.group('or'): + return ' or ' + else: + x = m.group('var') + add_dvar(x) + return 'env[%r]' % x + + for m in reg_act_noshell.finditer(line): + if m.group('space'): + merge = False + continue + elif m.group('text'): + app('[%r]' % m.group('text').replace('$$', '$')) + elif m.group('subst'): + var = m.group('var') + code = m.group('code') + if var == 'SRC': + if code: + app('[tsk.inputs%s]' % code) + else: + app('[a.path_from(cwdx) for a in tsk.inputs]') + elif var == 'TGT': + if code: + app('[tsk.outputs%s]' % code) + else: + app('[a.path_from(cwdx) for a in tsk.outputs]') + elif code: + if code.startswith(':'): + # a composed variable ${FOO:OUT} + add_dvar(var) + m = code[1:] + if m == 'SRC': + m = '[a.path_from(cwdx) for a in tsk.inputs]' + elif m == 'TGT': + m = '[a.path_from(cwdx) for a in tsk.outputs]' + elif re_novar.match(m): + m = '[tsk.inputs%s]' % m[3:] + elif re_novar.match(m): + m = '[tsk.outputs%s]' % m[3:] + else: + add_dvar(m) + if m[:3] not in ('tsk', 'gen', 'bld'): + m = '%r' % m + app('tsk.colon(%r, %s)' % (var, m)) + elif code.startswith('?'): + # In A?B|C output env.A if one of env.B or env.C is non-empty + expr = re_cond.sub(replc, code[1:]) + app('to_list(env[%r] if (%s) else [])' % (var, expr)) + else: + # plain code such as ${tsk.inputs[0].abspath()} + call = '%s%s' % (var, code) + add_dvar(call) + app('to_list(%s)' % call) + else: + # a plain variable such as # a plain variable like ${AR} + app('to_list(env[%r])' % var) + add_dvar(var) + if merge: + tmp = 'merge(%s, %s)' % (buf[-2], buf[-1]) + del buf[-1] + buf[-1] = tmp + merge = True # next turn + + buf = ['lst.extend(%s)' % x for x in buf] + fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf) + Logs.debug('action: %s', fun.strip().splitlines()) + return (funex(fun), dvars) + +def compile_fun(line, shell=False): + """ + Parses a string expression such as '${CC} ${SRC} -o ${TGT}' and returns a pair containing: + + * The function created (compiled) for use as :py:meth:`waflib.Task.Task.run` + * The list of variables that must cause rebuilds when *env* data is modified + + for example:: + + from waflib.Task import compile_fun + compile_fun('cxx', '${CXX} -o ${TGT[0]} ${SRC} -I ${SRC[0].parent.bldpath()}') + + def build(bld): + bld(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"') + + The env variables (CXX, ..) on the task must not hold dicts so as to preserve a consistent order. + The reserved keywords ``TGT`` and ``SRC`` represent the task input and output nodes + + """ + if isinstance(line, str): + if line.find('<') > 0 or line.find('>') > 0 or line.find('&&') > 0: + shell = True + else: + dvars_lst = [] + funs_lst = [] + for x in line: + if isinstance(x, str): + fun, dvars = compile_fun(x, shell) + dvars_lst += dvars + funs_lst.append(fun) + else: + # assume a function to let through + funs_lst.append(x) + def composed_fun(task): + for x in funs_lst: + ret = x(task) + if ret: + return ret + return None + return composed_fun, dvars_lst + if shell: + return compile_fun_shell(line) + else: + return compile_fun_noshell(line) + +def compile_sig_vars(vars): + """ + This method produces a sig_vars method suitable for subclasses that provide + scriptlet code in their run_str code. + If no such method can be created, this method returns None. + + The purpose of the sig_vars method returned is to ensures + that rebuilds occur whenever the contents of the expression changes. + This is the case B below:: + + import time + # case A: regular variables + tg = bld(rule='echo ${FOO}') + tg.env.FOO = '%s' % time.time() + # case B + bld(rule='echo ${gen.foo}', foo='%s' % time.time()) + + :param vars: env variables such as CXXFLAGS or gen.foo + :type vars: list of string + :return: A sig_vars method relevant for dependencies if adequate, else None + :rtype: A function, or None in most cases + """ + buf = [] + for x in sorted(vars): + if x[:3] in ('tsk', 'gen', 'bld'): + buf.append('buf.append(%s)' % x) + if buf: + return funex(COMPILE_TEMPLATE_SIG_VARS % '\n\t'.join(buf)) + return None + +def task_factory(name, func=None, vars=None, color='GREEN', ext_in=[], ext_out=[], before=[], after=[], shell=False, scan=None): + """ + Returns a new task subclass with the function ``run`` compiled from the line given. + + :param func: method run + :type func: string or function + :param vars: list of variables to hash + :type vars: list of string + :param color: color to use + :type color: string + :param shell: when *func* is a string, enable/disable the use of the shell + :type shell: bool + :param scan: method scan + :type scan: function + :rtype: :py:class:`waflib.Task.Task` + """ + + params = { + 'vars': vars or [], # function arguments are static, and this one may be modified by the class + 'color': color, + 'name': name, + 'shell': shell, + 'scan': scan, + } + + if isinstance(func, str) or isinstance(func, tuple): + params['run_str'] = func + else: + params['run'] = func + + cls = type(Task)(name, (Task,), params) + classes[name] = cls + + if ext_in: + cls.ext_in = Utils.to_list(ext_in) + if ext_out: + cls.ext_out = Utils.to_list(ext_out) + if before: + cls.before = Utils.to_list(before) + if after: + cls.after = Utils.to_list(after) + + return cls + +def deep_inputs(cls): + """ + Task class decorator to enable rebuilds on input files task signatures + """ + def sig_explicit_deps(self): + Task.sig_explicit_deps(self) + Task.sig_deep_inputs(self) + cls.sig_explicit_deps = sig_explicit_deps + return cls + +TaskBase = Task +"Provided for compatibility reasons, TaskBase should not be used" + +class TaskSemaphore(object): + """ + Task semaphores provide a simple and efficient way of throttling the amount of + a particular task to run concurrently. The throttling value is capped + by the amount of maximum jobs, so for example, a `TaskSemaphore(10)` + has no effect in a `-j2` build. + + Task semaphores are typically specified on the task class level:: + + class compile(waflib.Task.Task): + semaphore = waflib.Task.TaskSemaphore(2) + run_str = 'touch ${TGT}' + + Task semaphores are meant to be used by the build scheduler in the main + thread, so there are no guarantees of thread safety. + """ + def __init__(self, num): + """ + :param num: maximum value of concurrent tasks + :type num: int + """ + self.num = num + self.locking = set() + self.waiting = set() + + def is_locked(self): + """Returns True if this semaphore cannot be acquired by more tasks""" + return len(self.locking) >= self.num + + def acquire(self, tsk): + """ + Mark the semaphore as used by the given task (not re-entrant). + + :param tsk: task object + :type tsk: :py:class:`waflib.Task.Task` + :raises: :py:class:`IndexError` in case the resource is already acquired + """ + if self.is_locked(): + raise IndexError('Cannot lock more %r' % self.locking) + self.locking.add(tsk) + + def release(self, tsk): + """ + Mark the semaphore as unused by the given task. + + :param tsk: task object + :type tsk: :py:class:`waflib.Task.Task` + :raises: :py:class:`KeyError` in case the resource is not acquired by the task + """ + self.locking.remove(tsk) + diff --git a/ldb-2.0.8/third_party/waf/waflib/TaskGen.py b/ldb-2.0.8/third_party/waf/waflib/TaskGen.py new file mode 100644 index 0000000..f8f92bd --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/TaskGen.py @@ -0,0 +1,917 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Task generators + +The class :py:class:`waflib.TaskGen.task_gen` encapsulates the creation of task objects (low-level code) +The instances can have various parameters, but the creation of task nodes (Task.py) +is deferred. To achieve this, various methods are called from the method "apply" +""" + +import copy, re, os, functools +from waflib import Task, Utils, Logs, Errors, ConfigSet, Node + +feats = Utils.defaultdict(set) +"""remember the methods declaring features""" + +HEADER_EXTS = ['.h', '.hpp', '.hxx', '.hh'] + +class task_gen(object): + """ + Instances of this class create :py:class:`waflib.Task.Task` when + calling the method :py:meth:`waflib.TaskGen.task_gen.post` from the main thread. + A few notes: + + * The methods to call (*self.meths*) can be specified dynamically (removing, adding, ..) + * The 'features' are used to add methods to self.meths and then execute them + * The attribute 'path' is a node representing the location of the task generator + * The tasks created are added to the attribute *tasks* + * The attribute 'idx' is a counter of task generators in the same path + """ + + mappings = Utils.ordered_iter_dict() + """Mappings are global file extension mappings that are retrieved in the order of definition""" + + prec = Utils.defaultdict(set) + """Dict that holds the precedence execution rules for task generator methods""" + + def __init__(self, *k, **kw): + """ + Task generator objects predefine various attributes (source, target) for possible + processing by process_rule (make-like rules) or process_source (extensions, misc methods) + + Tasks are stored on the attribute 'tasks'. They are created by calling methods + listed in ``self.meths`` or referenced in the attribute ``features`` + A topological sort is performed to execute the methods in correct order. + + The extra key/value elements passed in ``kw`` are set as attributes + """ + self.source = [] + self.target = '' + + self.meths = [] + """ + List of method names to execute (internal) + """ + + self.features = [] + """ + List of feature names for bringing new methods in + """ + + self.tasks = [] + """ + Tasks created are added to this list + """ + + if not 'bld' in kw: + # task generators without a build context :-/ + self.env = ConfigSet.ConfigSet() + self.idx = 0 + self.path = None + else: + self.bld = kw['bld'] + self.env = self.bld.env.derive() + self.path = kw.get('path', self.bld.path) # by default, emulate chdir when reading scripts + + # Provide a unique index per folder + # This is part of a measure to prevent output file name collisions + path = self.path.abspath() + try: + self.idx = self.bld.idx[path] = self.bld.idx.get(path, 0) + 1 + except AttributeError: + self.bld.idx = {} + self.idx = self.bld.idx[path] = 1 + + # Record the global task generator count + try: + self.tg_idx_count = self.bld.tg_idx_count = self.bld.tg_idx_count + 1 + except AttributeError: + self.tg_idx_count = self.bld.tg_idx_count = 1 + + for key, val in kw.items(): + setattr(self, key, val) + + def __str__(self): + """Debugging helper""" + return "" % (self.name, self.path.abspath()) + + def __repr__(self): + """Debugging helper""" + lst = [] + for x in self.__dict__: + if x not in ('env', 'bld', 'compiled_tasks', 'tasks'): + lst.append("%s=%s" % (x, repr(getattr(self, x)))) + return "bld(%s) in %s" % (", ".join(lst), self.path.abspath()) + + def get_cwd(self): + """ + Current working directory for the task generator, defaults to the build directory. + This is still used in a few places but it should disappear at some point as the classes + define their own working directory. + + :rtype: :py:class:`waflib.Node.Node` + """ + return self.bld.bldnode + + def get_name(self): + """ + If the attribute ``name`` is not set on the instance, + the name is computed from the target name:: + + def build(bld): + x = bld(name='foo') + x.get_name() # foo + y = bld(target='bar') + y.get_name() # bar + + :rtype: string + :return: name of this task generator + """ + try: + return self._name + except AttributeError: + if isinstance(self.target, list): + lst = [str(x) for x in self.target] + name = self._name = ','.join(lst) + else: + name = self._name = str(self.target) + return name + def set_name(self, name): + self._name = name + + name = property(get_name, set_name) + + def to_list(self, val): + """ + Ensures that a parameter is a list, see :py:func:`waflib.Utils.to_list` + + :type val: string or list of string + :param val: input to return as a list + :rtype: list + """ + if isinstance(val, str): + return val.split() + else: + return val + + def post(self): + """ + Creates tasks for this task generators. The following operations are performed: + + #. The body of this method is called only once and sets the attribute ``posted`` + #. The attribute ``features`` is used to add more methods in ``self.meths`` + #. The methods are sorted by the precedence table ``self.prec`` or `:waflib:attr:waflib.TaskGen.task_gen.prec` + #. The methods are then executed in order + #. The tasks created are added to :py:attr:`waflib.TaskGen.task_gen.tasks` + """ + if getattr(self, 'posted', None): + return False + self.posted = True + + keys = set(self.meths) + keys.update(feats['*']) + + # add the methods listed in the features + self.features = Utils.to_list(self.features) + for x in self.features: + st = feats[x] + if st: + keys.update(st) + elif not x in Task.classes: + Logs.warn('feature %r does not exist - bind at least one method to it?', x) + + # copy the precedence table + prec = {} + prec_tbl = self.prec + for x in prec_tbl: + if x in keys: + prec[x] = prec_tbl[x] + + # elements disconnected + tmp = [] + for a in keys: + for x in prec.values(): + if a in x: + break + else: + tmp.append(a) + + tmp.sort(reverse=True) + + # topological sort + out = [] + while tmp: + e = tmp.pop() + if e in keys: + out.append(e) + try: + nlst = prec[e] + except KeyError: + pass + else: + del prec[e] + for x in nlst: + for y in prec: + if x in prec[y]: + break + else: + tmp.append(x) + tmp.sort(reverse=True) + + if prec: + buf = ['Cycle detected in the method execution:'] + for k, v in prec.items(): + buf.append('- %s after %s' % (k, [x for x in v if x in prec])) + raise Errors.WafError('\n'.join(buf)) + self.meths = out + + # then we run the methods in order + Logs.debug('task_gen: posting %s %d', self, id(self)) + for x in out: + try: + v = getattr(self, x) + except AttributeError: + raise Errors.WafError('%r is not a valid task generator method' % x) + Logs.debug('task_gen: -> %s (%d)', x, id(self)) + v() + + Logs.debug('task_gen: posted %s', self.name) + return True + + def get_hook(self, node): + """ + Returns the ``@extension`` method to call for a Node of a particular extension. + + :param node: Input file to process + :type node: :py:class:`waflib.Tools.Node.Node` + :return: A method able to process the input node by looking at the extension + :rtype: function + """ + name = node.name + for k in self.mappings: + try: + if name.endswith(k): + return self.mappings[k] + except TypeError: + # regexps objects + if k.match(name): + return self.mappings[k] + keys = list(self.mappings.keys()) + raise Errors.WafError("File %r has no mapping in %r (load a waf tool?)" % (node, keys)) + + def create_task(self, name, src=None, tgt=None, **kw): + """ + Creates task instances. + + :param name: task class name + :type name: string + :param src: input nodes + :type src: list of :py:class:`waflib.Tools.Node.Node` + :param tgt: output nodes + :type tgt: list of :py:class:`waflib.Tools.Node.Node` + :return: A task object + :rtype: :py:class:`waflib.Task.Task` + """ + task = Task.classes[name](env=self.env.derive(), generator=self) + if src: + task.set_inputs(src) + if tgt: + task.set_outputs(tgt) + task.__dict__.update(kw) + self.tasks.append(task) + return task + + def clone(self, env): + """ + Makes a copy of a task generator. Once the copy is made, it is necessary to ensure that the + it does not create the same output files as the original, or the same files may + be compiled several times. + + :param env: A configuration set + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :return: A copy + :rtype: :py:class:`waflib.TaskGen.task_gen` + """ + newobj = self.bld() + for x in self.__dict__: + if x in ('env', 'bld'): + continue + elif x in ('path', 'features'): + setattr(newobj, x, getattr(self, x)) + else: + setattr(newobj, x, copy.copy(getattr(self, x))) + + newobj.posted = False + if isinstance(env, str): + newobj.env = self.bld.all_envs[env].derive() + else: + newobj.env = env.derive() + + return newobj + +def declare_chain(name='', rule=None, reentrant=None, color='BLUE', + ext_in=[], ext_out=[], before=[], after=[], decider=None, scan=None, install_path=None, shell=False): + """ + Creates a new mapping and a task class for processing files by extension. + See Tools/flex.py for an example. + + :param name: name for the task class + :type name: string + :param rule: function to execute or string to be compiled in a function + :type rule: string or function + :param reentrant: re-inject the output file in the process (done automatically, set to 0 to disable) + :type reentrant: int + :param color: color for the task output + :type color: string + :param ext_in: execute the task only after the files of such extensions are created + :type ext_in: list of string + :param ext_out: execute the task only before files of such extensions are processed + :type ext_out: list of string + :param before: execute instances of this task before classes of the given names + :type before: list of string + :param after: execute instances of this task after classes of the given names + :type after: list of string + :param decider: if present, function that returns a list of output file extensions (overrides ext_out for output files, but not for the build order) + :type decider: function + :param scan: scanner function for the task + :type scan: function + :param install_path: installation path for the output nodes + :type install_path: string + """ + ext_in = Utils.to_list(ext_in) + ext_out = Utils.to_list(ext_out) + if not name: + name = rule + cls = Task.task_factory(name, rule, color=color, ext_in=ext_in, ext_out=ext_out, before=before, after=after, scan=scan, shell=shell) + + def x_file(self, node): + if ext_in: + _ext_in = ext_in[0] + + tsk = self.create_task(name, node) + cnt = 0 + + ext = decider(self, node) if decider else cls.ext_out + for x in ext: + k = node.change_ext(x, ext_in=_ext_in) + tsk.outputs.append(k) + + if reentrant != None: + if cnt < int(reentrant): + self.source.append(k) + else: + # reinject downstream files into the build + for y in self.mappings: # ~ nfile * nextensions :-/ + if k.name.endswith(y): + self.source.append(k) + break + cnt += 1 + + if install_path: + self.install_task = self.add_install_files(install_to=install_path, install_from=tsk.outputs) + return tsk + + for x in cls.ext_in: + task_gen.mappings[x] = x_file + return x_file + +def taskgen_method(func): + """ + Decorator that registers method as a task generator method. + The function must accept a task generator as first parameter:: + + from waflib.TaskGen import taskgen_method + @taskgen_method + def mymethod(self): + pass + + :param func: task generator method to add + :type func: function + :rtype: function + """ + setattr(task_gen, func.__name__, func) + return func + +def feature(*k): + """ + Decorator that registers a task generator method that will be executed when the + object attribute ``feature`` contains the corresponding key(s):: + + from waflib.Task import feature + @feature('myfeature') + def myfunction(self): + print('that is my feature!') + def build(bld): + bld(features='myfeature') + + :param k: feature names + :type k: list of string + """ + def deco(func): + setattr(task_gen, func.__name__, func) + for name in k: + feats[name].update([func.__name__]) + return func + return deco + +def before_method(*k): + """ + Decorator that registera task generator method which will be executed + before the functions of given name(s):: + + from waflib.TaskGen import feature, before + @feature('myfeature') + @before_method('fun2') + def fun1(self): + print('feature 1!') + @feature('myfeature') + def fun2(self): + print('feature 2!') + def build(bld): + bld(features='myfeature') + + :param k: method names + :type k: list of string + """ + def deco(func): + setattr(task_gen, func.__name__, func) + for fun_name in k: + task_gen.prec[func.__name__].add(fun_name) + return func + return deco +before = before_method + +def after_method(*k): + """ + Decorator that registers a task generator method which will be executed + after the functions of given name(s):: + + from waflib.TaskGen import feature, after + @feature('myfeature') + @after_method('fun2') + def fun1(self): + print('feature 1!') + @feature('myfeature') + def fun2(self): + print('feature 2!') + def build(bld): + bld(features='myfeature') + + :param k: method names + :type k: list of string + """ + def deco(func): + setattr(task_gen, func.__name__, func) + for fun_name in k: + task_gen.prec[fun_name].add(func.__name__) + return func + return deco +after = after_method + +def extension(*k): + """ + Decorator that registers a task generator method which will be invoked during + the processing of source files for the extension given:: + + from waflib import Task + class mytask(Task): + run_str = 'cp ${SRC} ${TGT}' + @extension('.moo') + def create_maa_file(self, node): + self.create_task('mytask', node, node.change_ext('.maa')) + def build(bld): + bld(source='foo.moo') + """ + def deco(func): + setattr(task_gen, func.__name__, func) + for x in k: + task_gen.mappings[x] = func + return func + return deco + +@taskgen_method +def to_nodes(self, lst, path=None): + """ + Flatten the input list of string/nodes/lists into a list of nodes. + + It is used by :py:func:`waflib.TaskGen.process_source` and :py:func:`waflib.TaskGen.process_rule`. + It is designed for source files, for folders, see :py:func:`waflib.Tools.ccroot.to_incnodes`: + + :param lst: input list + :type lst: list of string and nodes + :param path: path from which to search the nodes (by default, :py:attr:`waflib.TaskGen.task_gen.path`) + :type path: :py:class:`waflib.Tools.Node.Node` + :rtype: list of :py:class:`waflib.Tools.Node.Node` + """ + tmp = [] + path = path or self.path + find = path.find_resource + + if isinstance(lst, Node.Node): + lst = [lst] + + for x in Utils.to_list(lst): + if isinstance(x, str): + node = find(x) + elif hasattr(x, 'name'): + node = x + else: + tmp.extend(self.to_nodes(x)) + continue + if not node: + raise Errors.WafError('source not found: %r in %r' % (x, self)) + tmp.append(node) + return tmp + +@feature('*') +def process_source(self): + """ + Processes each element in the attribute ``source`` by extension. + + #. The *source* list is converted through :py:meth:`waflib.TaskGen.to_nodes` to a list of :py:class:`waflib.Node.Node` first. + #. File extensions are mapped to methods having the signature: ``def meth(self, node)`` by :py:meth:`waflib.TaskGen.extension` + #. The method is retrieved through :py:meth:`waflib.TaskGen.task_gen.get_hook` + #. When called, the methods may modify self.source to append more source to process + #. The mappings can map an extension or a filename (see the code below) + """ + self.source = self.to_nodes(getattr(self, 'source', [])) + for node in self.source: + self.get_hook(node)(self, node) + +@feature('*') +@before_method('process_source') +def process_rule(self): + """ + Processes the attribute ``rule``. When present, :py:meth:`waflib.TaskGen.process_source` is disabled:: + + def build(bld): + bld(rule='cp ${SRC} ${TGT}', source='wscript', target='bar.txt') + + Main attributes processed: + + * rule: command to execute, it can be a tuple of strings for multiple commands + * chmod: permissions for the resulting files (integer value such as Utils.O755) + * shell: set to False to execute the command directly (default is True to use a shell) + * scan: scanner function + * vars: list of variables to trigger rebuilds, such as CFLAGS + * cls_str: string to display when executing the task + * cls_keyword: label to display when executing the task + * cache_rule: by default, try to re-use similar classes, set to False to disable + * source: list of Node or string objects representing the source files required by this task + * target: list of Node or string objects representing the files that this task creates + * cwd: current working directory (Node or string) + * stdout: standard output, set to None to prevent waf from capturing the text + * stderr: standard error, set to None to prevent waf from capturing the text + * timeout: timeout for command execution (Python 3) + * always: whether to always run the command (False by default) + * deep_inputs: whether the task must depend on the input file tasks too (False by default) + """ + if not getattr(self, 'rule', None): + return + + # create the task class + name = str(getattr(self, 'name', None) or self.target or getattr(self.rule, '__name__', self.rule)) + + # or we can put the class in a cache for performance reasons + try: + cache = self.bld.cache_rule_attr + except AttributeError: + cache = self.bld.cache_rule_attr = {} + + chmod = getattr(self, 'chmod', None) + shell = getattr(self, 'shell', True) + color = getattr(self, 'color', 'BLUE') + scan = getattr(self, 'scan', None) + _vars = getattr(self, 'vars', []) + cls_str = getattr(self, 'cls_str', None) + cls_keyword = getattr(self, 'cls_keyword', None) + use_cache = getattr(self, 'cache_rule', 'True') + deep_inputs = getattr(self, 'deep_inputs', False) + + scan_val = has_deps = hasattr(self, 'deps') + if scan: + scan_val = id(scan) + + key = Utils.h_list((name, self.rule, chmod, shell, color, cls_str, cls_keyword, scan_val, _vars, deep_inputs)) + + cls = None + if use_cache: + try: + cls = cache[key] + except KeyError: + pass + if not cls: + rule = self.rule + if chmod is not None: + def chmod_fun(tsk): + for x in tsk.outputs: + os.chmod(x.abspath(), tsk.generator.chmod) + if isinstance(rule, tuple): + rule = list(rule) + rule.append(chmod_fun) + rule = tuple(rule) + else: + rule = (rule, chmod_fun) + + cls = Task.task_factory(name, rule, _vars, shell=shell, color=color) + + if cls_str: + setattr(cls, '__str__', self.cls_str) + + if cls_keyword: + setattr(cls, 'keyword', self.cls_keyword) + + if deep_inputs: + Task.deep_inputs(cls) + + if scan: + cls.scan = self.scan + elif has_deps: + def scan(self): + nodes = [] + for x in self.generator.to_list(getattr(self.generator, 'deps', None)): + node = self.generator.path.find_resource(x) + if not node: + self.generator.bld.fatal('Could not find %r (was it declared?)' % x) + nodes.append(node) + return [nodes, []] + cls.scan = scan + + if use_cache: + cache[key] = cls + + # now create one instance + tsk = self.create_task(name) + + for x in ('after', 'before', 'ext_in', 'ext_out'): + setattr(tsk, x, getattr(self, x, [])) + + if hasattr(self, 'stdout'): + tsk.stdout = self.stdout + + if hasattr(self, 'stderr'): + tsk.stderr = self.stderr + + if getattr(self, 'timeout', None): + tsk.timeout = self.timeout + + if getattr(self, 'always', None): + tsk.always_run = True + + if getattr(self, 'target', None): + if isinstance(self.target, str): + self.target = self.target.split() + if not isinstance(self.target, list): + self.target = [self.target] + for x in self.target: + if isinstance(x, str): + tsk.outputs.append(self.path.find_or_declare(x)) + else: + x.parent.mkdir() # if a node was given, create the required folders + tsk.outputs.append(x) + if getattr(self, 'install_path', None): + self.install_task = self.add_install_files(install_to=self.install_path, + install_from=tsk.outputs, chmod=getattr(self, 'chmod', Utils.O644)) + + if getattr(self, 'source', None): + tsk.inputs = self.to_nodes(self.source) + # bypass the execution of process_source by setting the source to an empty list + self.source = [] + + if getattr(self, 'cwd', None): + tsk.cwd = self.cwd + + if isinstance(tsk.run, functools.partial): + # Python documentation says: "partial objects defined in classes + # behave like static methods and do not transform into bound + # methods during instance attribute look-up." + tsk.run = functools.partial(tsk.run, tsk) + +@feature('seq') +def sequence_order(self): + """ + Adds a strict sequential constraint between the tasks generated by task generators. + It works because task generators are posted in order. + It will not post objects which belong to other folders. + + Example:: + + bld(features='javac seq') + bld(features='jar seq') + + To start a new sequence, set the attribute seq_start, for example:: + + obj = bld(features='seq') + obj.seq_start = True + + Note that the method is executed in last position. This is more an + example than a widely-used solution. + """ + if self.meths and self.meths[-1] != 'sequence_order': + self.meths.append('sequence_order') + return + + if getattr(self, 'seq_start', None): + return + + # all the tasks previously declared must be run before these + if getattr(self.bld, 'prev', None): + self.bld.prev.post() + for x in self.bld.prev.tasks: + for y in self.tasks: + y.set_run_after(x) + + self.bld.prev = self + + +re_m4 = re.compile(r'@(\w+)@', re.M) + +class subst_pc(Task.Task): + """ + Creates *.pc* files from *.pc.in*. The task is executed whenever an input variable used + in the substitution changes. + """ + + def force_permissions(self): + "Private for the time being, we will probably refactor this into run_str=[run1,chmod]" + if getattr(self.generator, 'chmod', None): + for x in self.outputs: + os.chmod(x.abspath(), self.generator.chmod) + + def run(self): + "Substitutes variables in a .in file" + + if getattr(self.generator, 'is_copy', None): + for i, x in enumerate(self.outputs): + x.write(self.inputs[i].read('rb'), 'wb') + stat = os.stat(self.inputs[i].abspath()) # Preserve mtime of the copy + os.utime(self.outputs[i].abspath(), (stat.st_atime, stat.st_mtime)) + self.force_permissions() + return None + + if getattr(self.generator, 'fun', None): + ret = self.generator.fun(self) + if not ret: + self.force_permissions() + return ret + + code = self.inputs[0].read(encoding=getattr(self.generator, 'encoding', 'latin-1')) + if getattr(self.generator, 'subst_fun', None): + code = self.generator.subst_fun(self, code) + if code is not None: + self.outputs[0].write(code, encoding=getattr(self.generator, 'encoding', 'latin-1')) + self.force_permissions() + return None + + # replace all % by %% to prevent errors by % signs + code = code.replace('%', '%%') + + # extract the vars foo into lst and replace @foo@ by %(foo)s + lst = [] + def repl(match): + g = match.group + if g(1): + lst.append(g(1)) + return "%%(%s)s" % g(1) + return '' + code = getattr(self.generator, 're_m4', re_m4).sub(repl, code) + + try: + d = self.generator.dct + except AttributeError: + d = {} + for x in lst: + tmp = getattr(self.generator, x, '') or self.env[x] or self.env[x.upper()] + try: + tmp = ''.join(tmp) + except TypeError: + tmp = str(tmp) + d[x] = tmp + + code = code % d + self.outputs[0].write(code, encoding=getattr(self.generator, 'encoding', 'latin-1')) + self.generator.bld.raw_deps[self.uid()] = lst + + # make sure the signature is updated + try: + delattr(self, 'cache_sig') + except AttributeError: + pass + + self.force_permissions() + + def sig_vars(self): + """ + Compute a hash (signature) of the variables used in the substitution + """ + bld = self.generator.bld + env = self.env + upd = self.m.update + + if getattr(self.generator, 'fun', None): + upd(Utils.h_fun(self.generator.fun).encode()) + if getattr(self.generator, 'subst_fun', None): + upd(Utils.h_fun(self.generator.subst_fun).encode()) + + # raw_deps: persistent custom values returned by the scanner + vars = self.generator.bld.raw_deps.get(self.uid(), []) + + # hash both env vars and task generator attributes + act_sig = bld.hash_env_vars(env, vars) + upd(act_sig) + + lst = [getattr(self.generator, x, '') for x in vars] + upd(Utils.h_list(lst)) + + return self.m.digest() + +@extension('.pc.in') +def add_pcfile(self, node): + """ + Processes *.pc.in* files to *.pc*. Installs the results to ``${PREFIX}/lib/pkgconfig/`` by default + + def build(bld): + bld(source='foo.pc.in', install_path='${LIBDIR}/pkgconfig/') + """ + tsk = self.create_task('subst_pc', node, node.change_ext('.pc', '.pc.in')) + self.install_task = self.add_install_files( + install_to=getattr(self, 'install_path', '${LIBDIR}/pkgconfig/'), install_from=tsk.outputs) + +class subst(subst_pc): + pass + +@feature('subst') +@before_method('process_source', 'process_rule') +def process_subst(self): + """ + Defines a transformation that substitutes the contents of *source* files to *target* files:: + + def build(bld): + bld( + features='subst', + source='foo.c.in', + target='foo.c', + install_path='${LIBDIR}/pkgconfig', + VAR = 'val' + ) + + The input files are supposed to contain macros of the form *@VAR@*, where *VAR* is an argument + of the task generator object. + + This method overrides the processing by :py:meth:`waflib.TaskGen.process_source`. + """ + + src = Utils.to_list(getattr(self, 'source', [])) + if isinstance(src, Node.Node): + src = [src] + tgt = Utils.to_list(getattr(self, 'target', [])) + if isinstance(tgt, Node.Node): + tgt = [tgt] + if len(src) != len(tgt): + raise Errors.WafError('invalid number of source/target for %r' % self) + + for x, y in zip(src, tgt): + if not x or not y: + raise Errors.WafError('null source or target for %r' % self) + a, b = None, None + + if isinstance(x, str) and isinstance(y, str) and x == y: + a = self.path.find_node(x) + b = self.path.get_bld().make_node(y) + if not os.path.isfile(b.abspath()): + b.parent.mkdir() + else: + if isinstance(x, str): + a = self.path.find_resource(x) + elif isinstance(x, Node.Node): + a = x + if isinstance(y, str): + b = self.path.find_or_declare(y) + elif isinstance(y, Node.Node): + b = y + + if not a: + raise Errors.WafError('could not find %r for %r' % (x, self)) + + tsk = self.create_task('subst', a, b) + for k in ('after', 'before', 'ext_in', 'ext_out'): + val = getattr(self, k, None) + if val: + setattr(tsk, k, val) + + # paranoid safety measure for the general case foo.in->foo.h with ambiguous dependencies + for xt in HEADER_EXTS: + if b.name.endswith(xt): + tsk.ext_out = tsk.ext_out + ['.h'] + break + + inst_to = getattr(self, 'install_path', None) + if inst_to: + self.install_task = self.add_install_files(install_to=inst_to, + install_from=b, chmod=getattr(self, 'chmod', Utils.O644)) + + self.source = [] + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/__init__.py b/ldb-2.0.8/third_party/waf/waflib/Tools/__init__.py new file mode 100644 index 0000000..079df35 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/ar.py b/ldb-2.0.8/third_party/waf/waflib/Tools/ar.py new file mode 100644 index 0000000..b39b645 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/ar.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) +# Ralf Habacker, 2006 (rh) + +""" +The **ar** program creates static libraries. This tool is almost always loaded +from others (C, C++, D, etc) for static library support. +""" + +from waflib.Configure import conf + +@conf +def find_ar(conf): + """Configuration helper used by C/C++ tools to enable the support for static libraries""" + conf.load('ar') + +def configure(conf): + """Finds the ar program and sets the default flags in ``conf.env.ARFLAGS``""" + conf.find_program('ar', var='AR') + conf.add_os_flags('ARFLAGS') + if not conf.env.ARFLAGS: + conf.env.ARFLAGS = ['rcs'] + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/asm.py b/ldb-2.0.8/third_party/waf/waflib/Tools/asm.py new file mode 100644 index 0000000..a57e83b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/asm.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2008-2018 (ita) + +""" +Assembly support, used by tools such as gas and nasm + +To declare targets using assembly:: + + def configure(conf): + conf.load('gcc gas') + + def build(bld): + bld( + features='c cstlib asm', + source = 'test.S', + target = 'asmtest') + + bld( + features='asm asmprogram', + source = 'test.S', + target = 'asmtest') + +Support for pure asm programs and libraries should also work:: + + def configure(conf): + conf.load('nasm') + conf.find_program('ld', 'ASLINK') + + def build(bld): + bld( + features='asm asmprogram', + source = 'test.S', + target = 'asmtest') +""" + +import re +from waflib import Errors, Logs, Task +from waflib.Tools.ccroot import link_task, stlink_task +from waflib.TaskGen import extension +from waflib.Tools import c_preproc + +re_lines = re.compile( + '^[ \t]*(?:%)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef)[ \t]*(.*)\r*$', + re.IGNORECASE | re.MULTILINE) + +class asm_parser(c_preproc.c_parser): + def filter_comments(self, node): + code = node.read() + code = c_preproc.re_nl.sub('', code) + code = c_preproc.re_cpp.sub(c_preproc.repl, code) + return re_lines.findall(code) + +class asm(Task.Task): + """ + Compiles asm files by gas/nasm/yasm/... + """ + color = 'BLUE' + run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' + + def scan(self): + if self.env.ASM_NAME == 'gas': + return c_preproc.scan(self) + Logs.warn('There is no dependency scanner for Nasm!') + return [[], []] + elif self.env.ASM_NAME == 'nasm': + Logs.warn('The Nasm dependency scanner is incomplete!') + + try: + incn = self.generator.includes_nodes + except AttributeError: + raise Errors.WafError('%r is missing the "asm" feature' % self.generator) + + if c_preproc.go_absolute: + nodepaths = incn + else: + nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] + + tmp = asm_parser(nodepaths) + tmp.start(self.inputs[0], self.env) + return (tmp.nodes, tmp.names) + +@extension('.s', '.S', '.asm', '.ASM', '.spp', '.SPP') +def asm_hook(self, node): + """ + Binds the asm extension to the asm task + + :param node: input file + :type node: :py:class:`waflib.Node.Node` + """ + return self.create_compiled_task('asm', node) + +class asmprogram(link_task): + "Links object files into a c program" + run_str = '${ASLINK} ${ASLINKFLAGS} ${ASLNK_TGT_F}${TGT} ${ASLNK_SRC_F}${SRC}' + ext_out = ['.bin'] + inst_to = '${BINDIR}' + +class asmshlib(asmprogram): + "Links object files into a c shared library" + inst_to = '${LIBDIR}' + +class asmstlib(stlink_task): + "Links object files into a c static library" + pass # do not remove + +def configure(conf): + conf.env.ASMPATH_ST = '-I%s' diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/bison.py b/ldb-2.0.8/third_party/waf/waflib/Tools/bison.py new file mode 100644 index 0000000..eef56dc --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/bison.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# encoding: utf-8 +# John O'Meara, 2006 +# Thomas Nagy 2009-2018 (ita) + +""" +The **bison** program is a code generator which creates C or C++ files. +The generated files are compiled into object files. +""" + +from waflib import Task +from waflib.TaskGen import extension + +class bison(Task.Task): + """Compiles bison files""" + color = 'BLUE' + run_str = '${BISON} ${BISONFLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}' + ext_out = ['.h'] # just to make sure + +@extension('.y', '.yc', '.yy') +def big_bison(self, node): + """ + Creates a bison task, which must be executed from the directory of the output file. + """ + has_h = '-d' in self.env.BISONFLAGS + + outs = [] + if node.name.endswith('.yc'): + outs.append(node.change_ext('.tab.cc')) + if has_h: + outs.append(node.change_ext('.tab.hh')) + else: + outs.append(node.change_ext('.tab.c')) + if has_h: + outs.append(node.change_ext('.tab.h')) + + tsk = self.create_task('bison', node, outs) + tsk.cwd = node.parent.get_bld() + + # and the c/cxx file must be compiled too + self.source.append(outs[0]) + +def configure(conf): + """ + Detects the *bison* program + """ + conf.find_program('bison', var='BISON') + conf.env.BISONFLAGS = ['-d'] + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/c.py b/ldb-2.0.8/third_party/waf/waflib/Tools/c.py new file mode 100644 index 0000000..effd6b6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/c.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +"Base for c programs/libraries" + +from waflib import TaskGen, Task +from waflib.Tools import c_preproc +from waflib.Tools.ccroot import link_task, stlink_task + +@TaskGen.extension('.c') +def c_hook(self, node): + "Binds the c file extensions create :py:class:`waflib.Tools.c.c` instances" + if not self.env.CC and self.env.CXX: + return self.create_compiled_task('cxx', node) + return self.create_compiled_task('c', node) + +class c(Task.Task): + "Compiles C files into object files" + run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' + vars = ['CCDEPS'] # unused variable to depend on, just in case + ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] + scan = c_preproc.scan + +class cprogram(link_task): + "Links object files into c programs" + run_str = '${LINK_CC} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' + ext_out = ['.bin'] + vars = ['LINKDEPS'] + inst_to = '${BINDIR}' + +class cshlib(cprogram): + "Links object files into c shared libraries" + inst_to = '${LIBDIR}' + +class cstlib(stlink_task): + "Links object files into a c static libraries" + pass # do not remove + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/c_aliases.py b/ldb-2.0.8/third_party/waf/waflib/Tools/c_aliases.py new file mode 100644 index 0000000..985e048 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/c_aliases.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2015 (ita) + +"base for all c/c++ programs and libraries" + +from waflib import Utils, Errors +from waflib.Configure import conf + +def get_extensions(lst): + """ + Returns the file extensions for the list of files given as input + + :param lst: files to process + :list lst: list of string or :py:class:`waflib.Node.Node` + :return: list of file extensions + :rtype: list of string + """ + ret = [] + for x in Utils.to_list(lst): + if not isinstance(x, str): + x = x.name + ret.append(x[x.rfind('.') + 1:]) + return ret + +def sniff_features(**kw): + """ + Computes and returns the features required for a task generator by + looking at the file extensions. This aimed for C/C++ mainly:: + + snif_features(source=['foo.c', 'foo.cxx'], type='shlib') + # returns ['cxx', 'c', 'cxxshlib', 'cshlib'] + + :param source: source files to process + :type source: list of string or :py:class:`waflib.Node.Node` + :param type: object type in *program*, *shlib* or *stlib* + :type type: string + :return: the list of features for a task generator processing the source files + :rtype: list of string + """ + exts = get_extensions(kw['source']) + typ = kw['typ'] + feats = [] + + # watch the order, cxx will have the precedence + for x in 'cxx cpp c++ cc C'.split(): + if x in exts: + feats.append('cxx') + break + if 'c' in exts or 'vala' in exts or 'gs' in exts: + feats.append('c') + + if 's' in exts or 'S' in exts: + feats.append('asm') + + for x in 'f f90 F F90 for FOR'.split(): + if x in exts: + feats.append('fc') + break + + if 'd' in exts: + feats.append('d') + + if 'java' in exts: + feats.append('java') + return 'java' + + if typ in ('program', 'shlib', 'stlib'): + will_link = False + for x in feats: + if x in ('cxx', 'd', 'fc', 'c', 'asm'): + feats.append(x + typ) + will_link = True + if not will_link and not kw.get('features', []): + raise Errors.WafError('Cannot link from %r, try passing eg: features="c cprogram"?' % kw) + return feats + +def set_features(kw, typ): + """ + Inserts data in the input dict *kw* based on existing data and on the type of target + required (typ). + + :param kw: task generator parameters + :type kw: dict + :param typ: type of target + :type typ: string + """ + kw['typ'] = typ + kw['features'] = Utils.to_list(kw.get('features', [])) + Utils.to_list(sniff_features(**kw)) + +@conf +def program(bld, *k, **kw): + """ + Alias for creating programs by looking at the file extensions:: + + def build(bld): + bld.program(source='foo.c', target='app') + # equivalent to: + # bld(features='c cprogram', source='foo.c', target='app') + + """ + set_features(kw, 'program') + return bld(*k, **kw) + +@conf +def shlib(bld, *k, **kw): + """ + Alias for creating shared libraries by looking at the file extensions:: + + def build(bld): + bld.shlib(source='foo.c', target='app') + # equivalent to: + # bld(features='c cshlib', source='foo.c', target='app') + + """ + set_features(kw, 'shlib') + return bld(*k, **kw) + +@conf +def stlib(bld, *k, **kw): + """ + Alias for creating static libraries by looking at the file extensions:: + + def build(bld): + bld.stlib(source='foo.cpp', target='app') + # equivalent to: + # bld(features='cxx cxxstlib', source='foo.cpp', target='app') + + """ + set_features(kw, 'stlib') + return bld(*k, **kw) + +@conf +def objects(bld, *k, **kw): + """ + Alias for creating object files by looking at the file extensions:: + + def build(bld): + bld.objects(source='foo.c', target='app') + # equivalent to: + # bld(features='c', source='foo.c', target='app') + + """ + set_features(kw, 'objects') + return bld(*k, **kw) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/c_config.py b/ldb-2.0.8/third_party/waf/waflib/Tools/c_config.py new file mode 100644 index 0000000..80580cc --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/c_config.py @@ -0,0 +1,1352 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +C/C++/D configuration helpers +""" + +from __future__ import with_statement + +import os, re, shlex +from waflib import Build, Utils, Task, Options, Logs, Errors, Runner +from waflib.TaskGen import after_method, feature +from waflib.Configure import conf + +WAF_CONFIG_H = 'config.h' +"""default name for the config.h file""" + +DEFKEYS = 'define_key' +INCKEYS = 'include_key' + +SNIP_EMPTY_PROGRAM = ''' +int main(int argc, char **argv) { + (void)argc; (void)argv; + return 0; +} +''' + +MACRO_TO_DESTOS = { +'__linux__' : 'linux', +'__GNU__' : 'gnu', # hurd +'__FreeBSD__' : 'freebsd', +'__NetBSD__' : 'netbsd', +'__OpenBSD__' : 'openbsd', +'__sun' : 'sunos', +'__hpux' : 'hpux', +'__sgi' : 'irix', +'_AIX' : 'aix', +'__CYGWIN__' : 'cygwin', +'__MSYS__' : 'cygwin', +'_UWIN' : 'uwin', +'_WIN64' : 'win32', +'_WIN32' : 'win32', +# Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file. +'__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin', +'__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone +'__QNX__' : 'qnx', +'__native_client__' : 'nacl' # google native client platform +} + +MACRO_TO_DEST_CPU = { +'__x86_64__' : 'x86_64', +'__amd64__' : 'x86_64', +'__i386__' : 'x86', +'__ia64__' : 'ia', +'__mips__' : 'mips', +'__sparc__' : 'sparc', +'__alpha__' : 'alpha', +'__aarch64__' : 'aarch64', +'__thumb__' : 'thumb', +'__arm__' : 'arm', +'__hppa__' : 'hppa', +'__powerpc__' : 'powerpc', +'__ppc__' : 'powerpc', +'__convex__' : 'convex', +'__m68k__' : 'm68k', +'__s390x__' : 's390x', +'__s390__' : 's390', +'__sh__' : 'sh', +'__xtensa__' : 'xtensa', +} + +@conf +def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=None): + """ + Parses flags from the input lines, and adds them to the relevant use variables:: + + def configure(conf): + conf.parse_flags('-O3', 'FOO') + # conf.env.CXXFLAGS_FOO = ['-O3'] + # conf.env.CFLAGS_FOO = ['-O3'] + + :param line: flags + :type line: string + :param uselib_store: where to add the flags + :type uselib_store: string + :param env: config set or conf.env by default + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + """ + + assert(isinstance(line, str)) + + env = env or self.env + + # Issue 811 and 1371 + if posix is None: + posix = True + if '\\' in line: + posix = ('\\ ' in line) or ('\\\\' in line) + + lex = shlex.shlex(line, posix=posix) + lex.whitespace_split = True + lex.commenters = '' + lst = list(lex) + + # append_unique is not always possible + # for example, apple flags may require both -arch i386 and -arch ppc + uselib = uselib_store + def app(var, val): + env.append_value('%s_%s' % (var, uselib), val) + def appu(var, val): + env.append_unique('%s_%s' % (var, uselib), val) + static = False + while lst: + x = lst.pop(0) + st = x[:2] + ot = x[2:] + + if st == '-I' or st == '/I': + if not ot: + ot = lst.pop(0) + appu('INCLUDES', ot) + elif st == '-i': + tmp = [x, lst.pop(0)] + app('CFLAGS', tmp) + app('CXXFLAGS', tmp) + elif st == '-D' or (env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but.. + if not ot: + ot = lst.pop(0) + app('DEFINES', ot) + elif st == '-l': + if not ot: + ot = lst.pop(0) + prefix = 'STLIB' if (force_static or static) else 'LIB' + app(prefix, ot) + elif st == '-L': + if not ot: + ot = lst.pop(0) + prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH' + appu(prefix, ot) + elif x.startswith('/LIBPATH:'): + prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH' + appu(prefix, x.replace('/LIBPATH:', '')) + elif x.startswith('-std='): + prefix = 'CXXFLAGS' if '++' in x else 'CFLAGS' + app(prefix, x) + elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie'): + app('CFLAGS', x) + app('CXXFLAGS', x) + app('LINKFLAGS', x) + elif x == '-framework': + appu('FRAMEWORK', lst.pop(0)) + elif x.startswith('-F'): + appu('FRAMEWORKPATH', x[2:]) + elif x == '-Wl,-rpath' or x == '-Wl,-R': + app('RPATH', lst.pop(0).lstrip('-Wl,')) + elif x.startswith('-Wl,-R,'): + app('RPATH', x[7:]) + elif x.startswith('-Wl,-R'): + app('RPATH', x[6:]) + elif x.startswith('-Wl,-rpath,'): + app('RPATH', x[11:]) + elif x == '-Wl,-Bstatic' or x == '-Bstatic': + static = True + elif x == '-Wl,-Bdynamic' or x == '-Bdynamic': + static = False + elif x.startswith('-Wl') or x in ('-rdynamic', '-pie'): + app('LINKFLAGS', x) + elif x.startswith(('-m', '-f', '-dynamic', '-O', '-g')): + # Adding the -W option breaks python builds on Openindiana + app('CFLAGS', x) + app('CXXFLAGS', x) + elif x.startswith('-bundle'): + app('LINKFLAGS', x) + elif x.startswith(('-undefined', '-Xlinker')): + arg = lst.pop(0) + app('LINKFLAGS', [x, arg]) + elif x.startswith(('-arch', '-isysroot')): + tmp = [x, lst.pop(0)] + app('CFLAGS', tmp) + app('CXXFLAGS', tmp) + app('LINKFLAGS', tmp) + elif x.endswith(('.a', '.so', '.dylib', '.lib')): + appu('LINKFLAGS', x) # not cool, #762 + else: + self.to_log('Unhandled flag %r' % x) + +@conf +def validate_cfg(self, kw): + """ + Searches for the program *pkg-config* if missing, and validates the + parameters to pass to :py:func:`waflib.Tools.c_config.exec_cfg`. + + :param path: the **-config program to use** (default is *pkg-config*) + :type path: list of string + :param msg: message to display to describe the test executed + :type msg: string + :param okmsg: message to display when the test is successful + :type okmsg: string + :param errmsg: message to display in case of error + :type errmsg: string + """ + if not 'path' in kw: + if not self.env.PKGCONFIG: + self.find_program('pkg-config', var='PKGCONFIG') + kw['path'] = self.env.PKGCONFIG + + # verify that exactly one action is requested + s = ('atleast_pkgconfig_version' in kw) + ('modversion' in kw) + ('package' in kw) + if s != 1: + raise ValueError('exactly one of atleast_pkgconfig_version, modversion and package must be set') + if not 'msg' in kw: + if 'atleast_pkgconfig_version' in kw: + kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version'] + elif 'modversion' in kw: + kw['msg'] = 'Checking for %r version' % kw['modversion'] + else: + kw['msg'] = 'Checking for %r' %(kw['package']) + + # let the modversion check set the okmsg to the detected version + if not 'okmsg' in kw and not 'modversion' in kw: + kw['okmsg'] = 'yes' + if not 'errmsg' in kw: + kw['errmsg'] = 'not found' + + # pkg-config version + if 'atleast_pkgconfig_version' in kw: + pass + elif 'modversion' in kw: + if not 'uselib_store' in kw: + kw['uselib_store'] = kw['modversion'] + if not 'define_name' in kw: + kw['define_name'] = '%s_VERSION' % Utils.quote_define_name(kw['uselib_store']) + else: + if not 'uselib_store' in kw: + kw['uselib_store'] = Utils.to_list(kw['package'])[0].upper() + if not 'define_name' in kw: + kw['define_name'] = self.have_define(kw['uselib_store']) + +@conf +def exec_cfg(self, kw): + """ + Executes ``pkg-config`` or other ``-config`` applications to collect configuration flags: + + * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return + * if modversion is given, then return the module version + * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable + + :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests) + :type atleast_pkgconfig_version: string + :param package: package name, for example *gtk+-2.0* + :type package: string + :param uselib_store: if the test is successful, define HAVE\\_*name*. It is also used to define *conf.env.FLAGS_name* variables. + :type uselib_store: string + :param modversion: if provided, return the version of the given module and define *name*\\_VERSION + :type modversion: string + :param args: arguments to give to *package* when retrieving flags + :type args: list of string + :param variables: return the values of particular variables + :type variables: list of string + :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES) + :type define_variable: dict(string: string) + """ + + path = Utils.to_list(kw['path']) + env = self.env.env or None + if kw.get('pkg_config_path'): + if not env: + env = dict(self.environ) + env['PKG_CONFIG_PATH'] = kw['pkg_config_path'] + + def define_it(): + define_name = kw['define_name'] + # by default, add HAVE_X to the config.h, else provide DEFINES_X for use=X + if kw.get('global_define', 1): + self.define(define_name, 1, False) + else: + self.env.append_unique('DEFINES_%s' % kw['uselib_store'], "%s=1" % define_name) + + if kw.get('add_have_to_env', 1): + self.env[define_name] = 1 + + # pkg-config version + if 'atleast_pkgconfig_version' in kw: + cmd = path + ['--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']] + self.cmd_and_log(cmd, env=env) + return + + # single version for a module + if 'modversion' in kw: + version = self.cmd_and_log(path + ['--modversion', kw['modversion']], env=env).strip() + if not 'okmsg' in kw: + kw['okmsg'] = version + self.define(kw['define_name'], version) + return version + + lst = [] + path + + defi = kw.get('define_variable') + if not defi: + defi = self.env.PKG_CONFIG_DEFINES or {} + for key, val in defi.items(): + lst.append('--define-variable=%s=%s' % (key, val)) + + static = kw.get('force_static', False) + if 'args' in kw: + args = Utils.to_list(kw['args']) + if '--static' in args or '--static-libs' in args: + static = True + lst += args + + # tools like pkgconf expect the package argument after the -- ones -_- + lst.extend(Utils.to_list(kw['package'])) + + # retrieving variables of a module + if 'variables' in kw: + v_env = kw.get('env', self.env) + vars = Utils.to_list(kw['variables']) + for v in vars: + val = self.cmd_and_log(lst + ['--variable=' + v], env=env).strip() + var = '%s_%s' % (kw['uselib_store'], v) + v_env[var] = val + return + + # so we assume the command-line will output flags to be parsed afterwards + ret = self.cmd_and_log(lst, env=env) + + define_it() + self.parse_flags(ret, kw['uselib_store'], kw.get('env', self.env), force_static=static, posix=kw.get('posix')) + return ret + +@conf +def check_cfg(self, *k, **kw): + """ + Checks for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc). + This wraps internal calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg` + + A few examples:: + + def configure(conf): + conf.load('compiler_c') + conf.check_cfg(package='glib-2.0', args='--libs --cflags') + conf.check_cfg(package='pango') + conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs']) + conf.check_cfg(package='pango', + args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'], + msg="Checking for 'pango 0.1.0'") + conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL') + conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', + package='', uselib_store='OPEN_MPI', mandatory=False) + # variables + conf.check_cfg(package='gtk+-2.0', variables=['includedir', 'prefix'], uselib_store='FOO') + print(conf.env.FOO_includedir) + """ + self.validate_cfg(kw) + if 'msg' in kw: + self.start_msg(kw['msg'], **kw) + ret = None + try: + ret = self.exec_cfg(kw) + except self.errors.WafError as e: + if 'errmsg' in kw: + self.end_msg(kw['errmsg'], 'YELLOW', **kw) + if Logs.verbose > 1: + self.to_log('Command failure: %s' % e) + self.fatal('The configuration failed') + else: + if not ret: + ret = True + kw['success'] = ret + if 'okmsg' in kw: + self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) + + return ret + +def build_fun(bld): + """ + Build function that is used for running configuration tests with ``conf.check()`` + """ + if bld.kw['compile_filename']: + node = bld.srcnode.make_node(bld.kw['compile_filename']) + node.write(bld.kw['code']) + + o = bld(features=bld.kw['features'], source=bld.kw['compile_filename'], target='testprog') + + for k, v in bld.kw.items(): + setattr(o, k, v) + + if not bld.kw.get('quiet'): + bld.conf.to_log("==>\n%s\n<==" % bld.kw['code']) + +@conf +def validate_c(self, kw): + """ + Pre-checks the parameters that will be given to :py:func:`waflib.Configure.run_build` + + :param compiler: c or cxx (tries to guess what is best) + :type compiler: string + :param type: cprogram, cshlib, cstlib - not required if *features are given directly* + :type type: binary to create + :param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib`` + :type feature: list of string + :param fragment: provide a piece of code for the test (default is to let the system create one) + :type fragment: string + :param uselib_store: define variables after the test is executed (IMPORTANT!) + :type uselib_store: string + :param use: parameters to use for building (just like the normal *use* keyword) + :type use: list of string + :param define_name: define to set when the check is over + :type define_name: string + :param execute: execute the resulting binary + :type execute: bool + :param define_ret: if execute is set to True, use the execution output in both the define and the return value + :type define_ret: bool + :param header_name: check for a particular header + :type header_name: string + :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers + :type auto_add_header_name: bool + """ + for x in ('type_name', 'field_name', 'function_name'): + if x in kw: + Logs.warn('Invalid argument %r in test' % x) + + if not 'build_fun' in kw: + kw['build_fun'] = build_fun + + if not 'env' in kw: + kw['env'] = self.env.derive() + env = kw['env'] + + if not 'compiler' in kw and not 'features' in kw: + kw['compiler'] = 'c' + if env.CXX_NAME and Task.classes.get('cxx'): + kw['compiler'] = 'cxx' + if not self.env.CXX: + self.fatal('a c++ compiler is required') + else: + if not self.env.CC: + self.fatal('a c compiler is required') + + if not 'compile_mode' in kw: + kw['compile_mode'] = 'c' + if 'cxx' in Utils.to_list(kw.get('features', [])) or kw.get('compiler') == 'cxx': + kw['compile_mode'] = 'cxx' + + if not 'type' in kw: + kw['type'] = 'cprogram' + + if not 'features' in kw: + if not 'header_name' in kw or kw.get('link_header_test', True): + kw['features'] = [kw['compile_mode'], kw['type']] # "c ccprogram" + else: + kw['features'] = [kw['compile_mode']] + else: + kw['features'] = Utils.to_list(kw['features']) + + if not 'compile_filename' in kw: + kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '') + + def to_header(dct): + if 'header_name' in dct: + dct = Utils.to_list(dct['header_name']) + return ''.join(['#include <%s>\n' % x for x in dct]) + return '' + + if 'framework_name' in kw: + # OSX, not sure this is used anywhere + fwkname = kw['framework_name'] + if not 'uselib_store' in kw: + kw['uselib_store'] = fwkname.upper() + if not kw.get('no_header'): + fwk = '%s/%s.h' % (fwkname, fwkname) + if kw.get('remove_dot_h'): + fwk = fwk[:-2] + val = kw.get('header_name', []) + kw['header_name'] = Utils.to_list(val) + [fwk] + kw['msg'] = 'Checking for framework %s' % fwkname + kw['framework'] = fwkname + + elif 'header_name' in kw: + if not 'msg' in kw: + kw['msg'] = 'Checking for header %s' % kw['header_name'] + + l = Utils.to_list(kw['header_name']) + assert len(l), 'list of headers in header_name is empty' + + kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM + if not 'uselib_store' in kw: + kw['uselib_store'] = l[0].upper() + if not 'define_name' in kw: + kw['define_name'] = self.have_define(l[0]) + + if 'lib' in kw: + if not 'msg' in kw: + kw['msg'] = 'Checking for library %s' % kw['lib'] + if not 'uselib_store' in kw: + kw['uselib_store'] = kw['lib'].upper() + + if 'stlib' in kw: + if not 'msg' in kw: + kw['msg'] = 'Checking for static library %s' % kw['stlib'] + if not 'uselib_store' in kw: + kw['uselib_store'] = kw['stlib'].upper() + + if 'fragment' in kw: + # an additional code fragment may be provided to replace the predefined code + # in custom headers + kw['code'] = kw['fragment'] + if not 'msg' in kw: + kw['msg'] = 'Checking for code snippet' + if not 'errmsg' in kw: + kw['errmsg'] = 'no' + + for (flagsname,flagstype) in (('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')): + if flagsname in kw: + if not 'msg' in kw: + kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname]) + if not 'errmsg' in kw: + kw['errmsg'] = 'no' + + if not 'execute' in kw: + kw['execute'] = False + if kw['execute']: + kw['features'].append('test_exec') + kw['chmod'] = Utils.O755 + + if not 'errmsg' in kw: + kw['errmsg'] = 'not found' + + if not 'okmsg' in kw: + kw['okmsg'] = 'yes' + + if not 'code' in kw: + kw['code'] = SNIP_EMPTY_PROGRAM + + # if there are headers to append automatically to the next tests + if self.env[INCKEYS]: + kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code'] + + # in case defines lead to very long command-lines + if kw.get('merge_config_header') or env.merge_config_header: + kw['code'] = '%s\n\n%s' % (self.get_config_header(), kw['code']) + env.DEFINES = [] # modify the copy + + if not kw.get('success'): + kw['success'] = None + + if 'define_name' in kw: + self.undefine(kw['define_name']) + if not 'msg' in kw: + self.fatal('missing "msg" in conf.check(...)') + +@conf +def post_check(self, *k, **kw): + """ + Sets the variables after a test executed in + :py:func:`waflib.Tools.c_config.check` was run successfully + """ + is_success = 0 + if kw['execute']: + if kw['success'] is not None: + if kw.get('define_ret'): + is_success = kw['success'] + else: + is_success = (kw['success'] == 0) + else: + is_success = (kw['success'] == 0) + + if kw.get('define_name'): + comment = kw.get('comment', '') + define_name = kw['define_name'] + if kw['execute'] and kw.get('define_ret') and isinstance(is_success, str): + if kw.get('global_define', 1): + self.define(define_name, is_success, quote=kw.get('quote', 1), comment=comment) + else: + if kw.get('quote', 1): + succ = '"%s"' % is_success + else: + succ = int(is_success) + val = '%s=%s' % (define_name, succ) + var = 'DEFINES_%s' % kw['uselib_store'] + self.env.append_value(var, val) + else: + if kw.get('global_define', 1): + self.define_cond(define_name, is_success, comment=comment) + else: + var = 'DEFINES_%s' % kw['uselib_store'] + self.env.append_value(var, '%s=%s' % (define_name, int(is_success))) + + # define conf.env.HAVE_X to 1 + if kw.get('add_have_to_env', 1): + if kw.get('uselib_store'): + self.env[self.have_define(kw['uselib_store'])] = 1 + elif kw['execute'] and kw.get('define_ret'): + self.env[define_name] = is_success + else: + self.env[define_name] = int(is_success) + + if 'header_name' in kw: + if kw.get('auto_add_header_name'): + self.env.append_value(INCKEYS, Utils.to_list(kw['header_name'])) + + if is_success and 'uselib_store' in kw: + from waflib.Tools import ccroot + # See get_uselib_vars in ccroot.py + _vars = set() + for x in kw['features']: + if x in ccroot.USELIB_VARS: + _vars |= ccroot.USELIB_VARS[x] + + for k in _vars: + x = k.lower() + if x in kw: + self.env.append_value(k + '_' + kw['uselib_store'], kw[x]) + return is_success + +@conf +def check(self, *k, **kw): + """ + Performs a configuration test by calling :py:func:`waflib.Configure.run_build`. + For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`. + To force a specific compiler, pass ``compiler='c'`` or ``compiler='cxx'`` to the list of arguments + + Besides build targets, complete builds can be given through a build function. All files will + be written to a temporary directory:: + + def build(bld): + lib_node = bld.srcnode.make_node('libdir/liblc1.c') + lib_node.parent.mkdir() + lib_node.write('#include \\nint lib_func(void) { FILE *f = fopen("foo", "r");}\\n', 'w') + bld(features='c cshlib', source=[lib_node], linkflags=conf.env.EXTRA_LDFLAGS, target='liblc') + conf.check(build_fun=build, msg=msg) + """ + self.validate_c(kw) + self.start_msg(kw['msg'], **kw) + ret = None + try: + ret = self.run_build(*k, **kw) + except self.errors.ConfigurationError: + self.end_msg(kw['errmsg'], 'YELLOW', **kw) + if Logs.verbose > 1: + raise + else: + self.fatal('The configuration failed') + else: + kw['success'] = ret + + ret = self.post_check(*k, **kw) + if not ret: + self.end_msg(kw['errmsg'], 'YELLOW', **kw) + self.fatal('The configuration failed %r' % ret) + else: + self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) + return ret + +class test_exec(Task.Task): + """ + A task that runs programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`. + """ + color = 'PINK' + def run(self): + cmd = [self.inputs[0].abspath()] + getattr(self.generator, 'test_args', []) + if getattr(self.generator, 'rpath', None): + if getattr(self.generator, 'define_ret', False): + self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd) + else: + self.generator.bld.retval = self.generator.bld.exec_command(cmd) + else: + env = self.env.env or {} + env.update(dict(os.environ)) + for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'): + env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '') + if getattr(self.generator, 'define_ret', False): + self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd, env=env) + else: + self.generator.bld.retval = self.generator.bld.exec_command(cmd, env=env) + +@feature('test_exec') +@after_method('apply_link') +def test_exec_fun(self): + """ + The feature **test_exec** is used to create a task that will to execute the binary + created (link task output) during the build. The exit status will be set + on the build context, so only one program may have the feature *test_exec*. + This is used by configuration tests:: + + def configure(conf): + conf.check(execute=True) + """ + self.create_task('test_exec', self.link_task.outputs[0]) + +@conf +def check_cxx(self, *k, **kw): + """ + Runs a test with a task generator of the form:: + + conf.check(features='cxx cxxprogram', ...) + """ + kw['compiler'] = 'cxx' + return self.check(*k, **kw) + +@conf +def check_cc(self, *k, **kw): + """ + Runs a test with a task generator of the form:: + + conf.check(features='c cprogram', ...) + """ + kw['compiler'] = 'c' + return self.check(*k, **kw) + +@conf +def set_define_comment(self, key, comment): + """ + Sets a comment that will appear in the configuration header + + :type key: string + :type comment: string + """ + coms = self.env.DEFINE_COMMENTS + if not coms: + coms = self.env.DEFINE_COMMENTS = {} + coms[key] = comment or '' + +@conf +def get_define_comment(self, key): + """ + Returns the comment associated to a define + + :type key: string + """ + coms = self.env.DEFINE_COMMENTS or {} + return coms.get(key, '') + +@conf +def define(self, key, val, quote=True, comment=''): + """ + Stores a single define and its state into ``conf.env.DEFINES``. The value is cast to an integer (0/1). + + :param key: define name + :type key: string + :param val: value + :type val: int or string + :param quote: enclose strings in quotes (yes by default) + :type quote: bool + """ + assert isinstance(key, str) + if not key: + return + if val is True: + val = 1 + elif val in (False, None): + val = 0 + + if isinstance(val, int) or isinstance(val, float): + s = '%s=%s' + else: + s = quote and '%s="%s"' or '%s=%s' + app = s % (key, str(val)) + + ban = key + '=' + lst = self.env.DEFINES + for x in lst: + if x.startswith(ban): + lst[lst.index(x)] = app + break + else: + self.env.append_value('DEFINES', app) + + self.env.append_unique(DEFKEYS, key) + self.set_define_comment(key, comment) + +@conf +def undefine(self, key, comment=''): + """ + Removes a global define from ``conf.env.DEFINES`` + + :param key: define name + :type key: string + """ + assert isinstance(key, str) + if not key: + return + ban = key + '=' + lst = [x for x in self.env.DEFINES if not x.startswith(ban)] + self.env.DEFINES = lst + self.env.append_unique(DEFKEYS, key) + self.set_define_comment(key, comment) + +@conf +def define_cond(self, key, val, comment=''): + """ + Conditionally defines a name:: + + def configure(conf): + conf.define_cond('A', True) + # equivalent to: + # if val: conf.define('A', 1) + # else: conf.undefine('A') + + :param key: define name + :type key: string + :param val: value + :type val: int or string + """ + assert isinstance(key, str) + if not key: + return + if val: + self.define(key, 1, comment=comment) + else: + self.undefine(key, comment=comment) + +@conf +def is_defined(self, key): + """ + Indicates whether a particular define is globally set in ``conf.env.DEFINES``. + + :param key: define name + :type key: string + :return: True if the define is set + :rtype: bool + """ + assert key and isinstance(key, str) + + ban = key + '=' + for x in self.env.DEFINES: + if x.startswith(ban): + return True + return False + +@conf +def get_define(self, key): + """ + Returns the value of an existing define, or None if not found + + :param key: define name + :type key: string + :rtype: string + """ + assert key and isinstance(key, str) + + ban = key + '=' + for x in self.env.DEFINES: + if x.startswith(ban): + return x[len(ban):] + return None + +@conf +def have_define(self, key): + """ + Returns a variable suitable for command-line or header use by removing invalid characters + and prefixing it with ``HAVE_`` + + :param key: define name + :type key: string + :return: the input key prefixed by *HAVE_* and substitute any invalid characters. + :rtype: string + """ + return (self.env.HAVE_PAT or 'HAVE_%s') % Utils.quote_define_name(key) + +@conf +def write_config_header(self, configfile='', guard='', top=False, defines=True, headers=False, remove=True, define_prefix=''): + """ + Writes a configuration header containing defines and includes:: + + def configure(cnf): + cnf.define('A', 1) + cnf.write_config_header('config.h') + + This function only adds include guards (if necessary), consult + :py:func:`waflib.Tools.c_config.get_config_header` for details on the body. + + :param configfile: path to the file to create (relative or absolute) + :type configfile: string + :param guard: include guard name to add, by default it is computed from the file name + :type guard: string + :param top: write the configuration header from the build directory (default is from the current path) + :type top: bool + :param defines: add the defines (yes by default) + :type defines: bool + :param headers: add #include in the file + :type headers: bool + :param remove: remove the defines after they are added (yes by default, works like in autoconf) + :type remove: bool + :type define_prefix: string + :param define_prefix: prefix all the defines in the file with a particular prefix + """ + if not configfile: + configfile = WAF_CONFIG_H + waf_guard = guard or 'W_%s_WAF' % Utils.quote_define_name(configfile) + + node = top and self.bldnode or self.path.get_bld() + node = node.make_node(configfile) + node.parent.mkdir() + + lst = ['/* WARNING! All changes made to this file will be lost! */\n'] + lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard)) + lst.append(self.get_config_header(defines, headers, define_prefix=define_prefix)) + lst.append('\n#endif /* %s */\n' % waf_guard) + + node.write('\n'.join(lst)) + + # config files must not be removed on "waf clean" + self.env.append_unique(Build.CFG_FILES, [node.abspath()]) + + if remove: + for key in self.env[DEFKEYS]: + self.undefine(key) + self.env[DEFKEYS] = [] + +@conf +def get_config_header(self, defines=True, headers=False, define_prefix=''): + """ + Creates the contents of a ``config.h`` file from the defines and includes + set in conf.env.define_key / conf.env.include_key. No include guards are added. + + A prelude will be added from the variable env.WAF_CONFIG_H_PRELUDE if provided. This + can be used to insert complex macros or include guards:: + + def configure(conf): + conf.env.WAF_CONFIG_H_PRELUDE = '#include \\n' + conf.write_config_header('config.h') + + :param defines: write the defines values + :type defines: bool + :param headers: write include entries for each element in self.env.INCKEYS + :type headers: bool + :type define_prefix: string + :param define_prefix: prefix all the defines with a particular prefix + :return: the contents of a ``config.h`` file + :rtype: string + """ + lst = [] + + if self.env.WAF_CONFIG_H_PRELUDE: + lst.append(self.env.WAF_CONFIG_H_PRELUDE) + + if headers: + for x in self.env[INCKEYS]: + lst.append('#include <%s>' % x) + + if defines: + tbl = {} + for k in self.env.DEFINES: + a, _, b = k.partition('=') + tbl[a] = b + + for k in self.env[DEFKEYS]: + caption = self.get_define_comment(k) + if caption: + caption = ' /* %s */' % caption + try: + txt = '#define %s%s %s%s' % (define_prefix, k, tbl[k], caption) + except KeyError: + txt = '/* #undef %s%s */%s' % (define_prefix, k, caption) + lst.append(txt) + return "\n".join(lst) + +@conf +def cc_add_flags(conf): + """ + Adds CFLAGS / CPPFLAGS from os.environ to conf.env + """ + conf.add_os_flags('CPPFLAGS', dup=False) + conf.add_os_flags('CFLAGS', dup=False) + +@conf +def cxx_add_flags(conf): + """ + Adds CXXFLAGS / CPPFLAGS from os.environ to conf.env + """ + conf.add_os_flags('CPPFLAGS', dup=False) + conf.add_os_flags('CXXFLAGS', dup=False) + +@conf +def link_add_flags(conf): + """ + Adds LINKFLAGS / LDFLAGS from os.environ to conf.env + """ + conf.add_os_flags('LINKFLAGS', dup=False) + conf.add_os_flags('LDFLAGS', dup=False) + +@conf +def cc_load_tools(conf): + """ + Loads the Waf c extensions + """ + if not conf.env.DEST_OS: + conf.env.DEST_OS = Utils.unversioned_sys_platform() + conf.load('c') + +@conf +def cxx_load_tools(conf): + """ + Loads the Waf c++ extensions + """ + if not conf.env.DEST_OS: + conf.env.DEST_OS = Utils.unversioned_sys_platform() + conf.load('cxx') + +@conf +def get_cc_version(conf, cc, gcc=False, icc=False, clang=False): + """ + Runs the preprocessor to determine the gcc/icc/clang version + + The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env* + + :raise: :py:class:`waflib.Errors.ConfigurationError` + """ + cmd = cc + ['-dM', '-E', '-'] + env = conf.env.env or None + try: + out, err = conf.cmd_and_log(cmd, output=0, input='\n'.encode(), env=env) + except Errors.WafError: + conf.fatal('Could not determine the compiler version %r' % cmd) + + if gcc: + if out.find('__INTEL_COMPILER') >= 0: + conf.fatal('The intel compiler pretends to be gcc') + if out.find('__GNUC__') < 0 and out.find('__clang__') < 0: + conf.fatal('Could not determine the compiler type') + + if icc and out.find('__INTEL_COMPILER') < 0: + conf.fatal('Not icc/icpc') + + if clang and out.find('__clang__') < 0: + conf.fatal('Not clang/clang++') + if not clang and out.find('__clang__') >= 0: + conf.fatal('Could not find gcc/g++ (only Clang), if renamed try eg: CC=gcc48 CXX=g++48 waf configure') + + k = {} + if icc or gcc or clang: + out = out.splitlines() + for line in out: + lst = shlex.split(line) + if len(lst)>2: + key = lst[1] + val = lst[2] + k[key] = val + + def isD(var): + return var in k + + # Some documentation is available at http://predef.sourceforge.net + # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns. + if not conf.env.DEST_OS: + conf.env.DEST_OS = '' + for i in MACRO_TO_DESTOS: + if isD(i): + conf.env.DEST_OS = MACRO_TO_DESTOS[i] + break + else: + if isD('__APPLE__') and isD('__MACH__'): + conf.env.DEST_OS = 'darwin' + elif isD('__unix__'): # unix must be tested last as it's a generic fallback + conf.env.DEST_OS = 'generic' + + if isD('__ELF__'): + conf.env.DEST_BINFMT = 'elf' + elif isD('__WINNT__') or isD('__CYGWIN__') or isD('_WIN32'): + conf.env.DEST_BINFMT = 'pe' + if not conf.env.IMPLIBDIR: + conf.env.IMPLIBDIR = conf.env.LIBDIR # for .lib or .dll.a files + conf.env.LIBDIR = conf.env.BINDIR + elif isD('__APPLE__'): + conf.env.DEST_BINFMT = 'mac-o' + + if not conf.env.DEST_BINFMT: + # Infer the binary format from the os name. + conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS) + + for i in MACRO_TO_DEST_CPU: + if isD(i): + conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i] + break + + Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')])) + if icc: + ver = k['__INTEL_COMPILER'] + conf.env.CC_VERSION = (ver[:-2], ver[-2], ver[-1]) + else: + if isD('__clang__') and isD('__clang_major__'): + conf.env.CC_VERSION = (k['__clang_major__'], k['__clang_minor__'], k['__clang_patchlevel__']) + else: + # older clang versions and gcc + conf.env.CC_VERSION = (k['__GNUC__'], k['__GNUC_MINOR__'], k.get('__GNUC_PATCHLEVEL__', '0')) + return k + +@conf +def get_xlc_version(conf, cc): + """ + Returns the Aix compiler version + + :raise: :py:class:`waflib.Errors.ConfigurationError` + """ + cmd = cc + ['-qversion'] + try: + out, err = conf.cmd_and_log(cmd, output=0) + except Errors.WafError: + conf.fatal('Could not find xlc %r' % cmd) + + # the intention is to catch the 8.0 in "IBM XL C/C++ Enterprise Edition V8.0 for AIX..." + for v in (r"IBM XL C/C\+\+.* V(?P\d*)\.(?P\d*)",): + version_re = re.compile(v, re.I).search + match = version_re(out or err) + if match: + k = match.groupdict() + conf.env.CC_VERSION = (k['major'], k['minor']) + break + else: + conf.fatal('Could not determine the XLC version.') + +@conf +def get_suncc_version(conf, cc): + """ + Returns the Sun compiler version + + :raise: :py:class:`waflib.Errors.ConfigurationError` + """ + cmd = cc + ['-V'] + try: + out, err = conf.cmd_and_log(cmd, output=0) + except Errors.WafError as e: + # Older versions of the compiler exit with non-zero status when reporting their version + if not (hasattr(e, 'returncode') and hasattr(e, 'stdout') and hasattr(e, 'stderr')): + conf.fatal('Could not find suncc %r' % cmd) + out = e.stdout + err = e.stderr + + version = (out or err) + version = version.splitlines()[0] + + # cc: Sun C 5.10 SunOS_i386 2009/06/03 + # cc: Studio 12.5 Sun C++ 5.14 SunOS_sparc Beta 2015/11/17 + # cc: WorkShop Compilers 5.0 98/12/15 C 5.0 + version_re = re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P\d*)\.(?P\d*)', re.I).search + match = version_re(version) + if match: + k = match.groupdict() + conf.env.CC_VERSION = (k['major'], k['minor']) + else: + conf.fatal('Could not determine the suncc version.') + +# ============ the --as-needed flag should added during the configuration, not at runtime ========= + +@conf +def add_as_needed(self): + """ + Adds ``--as-needed`` to the *LINKFLAGS* + On some platforms, it is a default flag. In some cases (e.g., in NS-3) it is necessary to explicitly disable this feature with `-Wl,--no-as-needed` flag. + """ + if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME): + self.env.append_unique('LINKFLAGS', '-Wl,--as-needed') + +# ============ parallel configuration + +class cfgtask(Task.Task): + """ + A task that executes build configuration tests (calls conf.check) + + Make sure to use locks if concurrent access to the same conf.env data is necessary. + """ + def __init__(self, *k, **kw): + Task.Task.__init__(self, *k, **kw) + self.run_after = set() + + def display(self): + return '' + + def runnable_status(self): + for x in self.run_after: + if not x.hasrun: + return Task.ASK_LATER + return Task.RUN_ME + + def uid(self): + return Utils.SIG_NIL + + def signature(self): + return Utils.SIG_NIL + + def run(self): + conf = self.conf + bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath()) + bld.env = conf.env + bld.init_dirs() + bld.in_msg = 1 # suppress top-level start_msg + bld.logger = self.logger + bld.multicheck_task = self + args = self.args + try: + if 'func' in args: + bld.test(build_fun=args['func'], + msg=args.get('msg', ''), + okmsg=args.get('okmsg', ''), + errmsg=args.get('errmsg', ''), + ) + else: + args['multicheck_mandatory'] = args.get('mandatory', True) + args['mandatory'] = True + try: + bld.check(**args) + finally: + args['mandatory'] = args['multicheck_mandatory'] + except Exception: + return 1 + + def process(self): + Task.Task.process(self) + if 'msg' in self.args: + with self.generator.bld.multicheck_lock: + self.conf.start_msg(self.args['msg']) + if self.hasrun == Task.NOT_RUN: + self.conf.end_msg('test cancelled', 'YELLOW') + elif self.hasrun != Task.SUCCESS: + self.conf.end_msg(self.args.get('errmsg', 'no'), 'YELLOW') + else: + self.conf.end_msg(self.args.get('okmsg', 'yes'), 'GREEN') + +@conf +def multicheck(self, *k, **kw): + """ + Runs configuration tests in parallel; results are printed sequentially at the end of the build + but each test must provide its own msg value to display a line:: + + def test_build(ctx): + ctx.in_msg = True # suppress console outputs + ctx.check_large_file(mandatory=False) + + conf.multicheck( + {'header_name':'stdio.h', 'msg':'... stdio', 'uselib_store':'STDIO', 'global_define':False}, + {'header_name':'xyztabcd.h', 'msg':'... optional xyztabcd.h', 'mandatory': False}, + {'header_name':'stdlib.h', 'msg':'... stdlib', 'okmsg': 'aye', 'errmsg': 'nope'}, + {'func': test_build, 'msg':'... testing an arbitrary build function', 'okmsg':'ok'}, + msg = 'Checking for headers in parallel', + mandatory = True, # mandatory tests raise an error at the end + run_all_tests = True, # try running all tests + ) + + The configuration tests may modify the values in conf.env in any order, and the define + values can affect configuration tests being executed. It is hence recommended + to provide `uselib_store` values with `global_define=False` to prevent such issues. + """ + self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k)), **kw) + + # Force a copy so that threads append to the same list at least + # no order is guaranteed, but the values should not disappear at least + for var in ('DEFINES', DEFKEYS): + self.env.append_value(var, []) + self.env.DEFINE_COMMENTS = self.env.DEFINE_COMMENTS or {} + + # define a task object that will execute our tests + class par(object): + def __init__(self): + self.keep = False + self.task_sigs = {} + self.progress_bar = 0 + def total(self): + return len(tasks) + def to_log(self, *k, **kw): + return + + bld = par() + bld.keep = kw.get('run_all_tests', True) + bld.imp_sigs = {} + tasks = [] + + id_to_task = {} + for dct in k: + x = Task.classes['cfgtask'](bld=bld, env=None) + tasks.append(x) + x.args = dct + x.bld = bld + x.conf = self + x.args = dct + + # bind a logger that will keep the info in memory + x.logger = Logs.make_mem_logger(str(id(x)), self.logger) + + if 'id' in dct: + id_to_task[dct['id']] = x + + # second pass to set dependencies with after_test/before_test + for x in tasks: + for key in Utils.to_list(x.args.get('before_tests', [])): + tsk = id_to_task[key] + if not tsk: + raise ValueError('No test named %r' % key) + tsk.run_after.add(x) + for key in Utils.to_list(x.args.get('after_tests', [])): + tsk = id_to_task[key] + if not tsk: + raise ValueError('No test named %r' % key) + x.run_after.add(tsk) + + def it(): + yield tasks + while 1: + yield [] + bld.producer = p = Runner.Parallel(bld, Options.options.jobs) + bld.multicheck_lock = Utils.threading.Lock() + p.biter = it() + + self.end_msg('started') + p.start() + + # flush the logs in order into the config.log + for x in tasks: + x.logger.memhandler.flush() + + self.start_msg('-> processing test results') + if p.error: + for x in p.error: + if getattr(x, 'err_msg', None): + self.to_log(x.err_msg) + self.end_msg('fail', color='RED') + raise Errors.WafError('There is an error in the library, read config.log for more information') + + failure_count = 0 + for x in tasks: + if x.hasrun not in (Task.SUCCESS, Task.NOT_RUN): + failure_count += 1 + + if failure_count: + self.end_msg(kw.get('errmsg', '%s test failed' % failure_count), color='YELLOW', **kw) + else: + self.end_msg('all ok', **kw) + + for x in tasks: + if x.hasrun != Task.SUCCESS: + if x.args.get('mandatory', True): + self.fatal(kw.get('fatalmsg') or 'One of the tests has failed, read config.log for more information') + +@conf +def check_gcc_o_space(self, mode='c'): + if int(self.env.CC_VERSION[0]) > 4: + # this is for old compilers + return + self.env.stash() + if mode == 'c': + self.env.CCLNK_TGT_F = ['-o', ''] + elif mode == 'cxx': + self.env.CXXLNK_TGT_F = ['-o', ''] + features = '%s %sshlib' % (mode, mode) + try: + self.check(msg='Checking if the -o link must be split from arguments', fragment=SNIP_EMPTY_PROGRAM, features=features) + except self.errors.ConfigurationError: + self.env.revert() + else: + self.env.commit() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/c_osx.py b/ldb-2.0.8/third_party/waf/waflib/Tools/c_osx.py new file mode 100644 index 0000000..f70b128 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/c_osx.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy 2008-2018 (ita) + +""" +MacOSX related tools +""" + +import os, shutil, platform +from waflib import Task, Utils +from waflib.TaskGen import taskgen_method, feature, after_method, before_method + +app_info = ''' + + + + + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Waf + CFBundleSignature + ???? + NOTE + THIS IS A GENERATED FILE, DO NOT MODIFY + CFBundleExecutable + {app_name} + + +''' +""" +plist template +""" + +@feature('c', 'cxx') +def set_macosx_deployment_target(self): + """ + see WAF issue 285 and also and also http://trac.macports.org/ticket/17059 + """ + if self.env.MACOSX_DEPLOYMENT_TARGET: + os.environ['MACOSX_DEPLOYMENT_TARGET'] = self.env.MACOSX_DEPLOYMENT_TARGET + elif 'MACOSX_DEPLOYMENT_TARGET' not in os.environ: + if Utils.unversioned_sys_platform() == 'darwin': + os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2]) + +@taskgen_method +def create_bundle_dirs(self, name, out): + """ + Creates bundle folders, used by :py:func:`create_task_macplist` and :py:func:`create_task_macapp` + """ + dir = out.parent.find_or_declare(name) + dir.mkdir() + macos = dir.find_or_declare(['Contents', 'MacOS']) + macos.mkdir() + return dir + +def bundle_name_for_output(out): + name = out.name + k = name.rfind('.') + if k >= 0: + name = name[:k] + '.app' + else: + name = name + '.app' + return name + +@feature('cprogram', 'cxxprogram') +@after_method('apply_link') +def create_task_macapp(self): + """ + To compile an executable into a Mac application (a .app), set its *mac_app* attribute:: + + def build(bld): + bld.shlib(source='a.c', target='foo', mac_app=True) + + To force *all* executables to be transformed into Mac applications:: + + def build(bld): + bld.env.MACAPP = True + bld.shlib(source='a.c', target='foo') + """ + if self.env.MACAPP or getattr(self, 'mac_app', False): + out = self.link_task.outputs[0] + + name = bundle_name_for_output(out) + dir = self.create_bundle_dirs(name, out) + + n1 = dir.find_or_declare(['Contents', 'MacOS', out.name]) + + self.apptask = self.create_task('macapp', self.link_task.outputs, n1) + inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/MacOS/' % name + self.add_install_files(install_to=inst_to, install_from=n1, chmod=Utils.O755) + + if getattr(self, 'mac_files', None): + # this only accepts files; they will be installed as seen from mac_files_root + mac_files_root = getattr(self, 'mac_files_root', None) + if isinstance(mac_files_root, str): + mac_files_root = self.path.find_node(mac_files_root) + if not mac_files_root: + self.bld.fatal('Invalid mac_files_root %r' % self.mac_files_root) + res_dir = n1.parent.parent.make_node('Resources') + inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Resources' % name + for node in self.to_nodes(self.mac_files): + relpath = node.path_from(mac_files_root or node.parent) + self.create_task('macapp', node, res_dir.make_node(relpath)) + self.add_install_as(install_to=os.path.join(inst_to, relpath), install_from=node) + + if getattr(self.bld, 'is_install', None): + # disable regular binary installation + self.install_task.hasrun = Task.SKIP_ME + +@feature('cprogram', 'cxxprogram') +@after_method('apply_link') +def create_task_macplist(self): + """ + Creates a :py:class:`waflib.Tools.c_osx.macplist` instance. + """ + if self.env.MACAPP or getattr(self, 'mac_app', False): + out = self.link_task.outputs[0] + + name = bundle_name_for_output(out) + + dir = self.create_bundle_dirs(name, out) + n1 = dir.find_or_declare(['Contents', 'Info.plist']) + self.plisttask = plisttask = self.create_task('macplist', [], n1) + plisttask.context = { + 'app_name': self.link_task.outputs[0].name, + 'env': self.env + } + + plist_ctx = getattr(self, 'plist_context', None) + if (plist_ctx): + plisttask.context.update(plist_ctx) + + if getattr(self, 'mac_plist', False): + node = self.path.find_resource(self.mac_plist) + if node: + plisttask.inputs.append(node) + else: + plisttask.code = self.mac_plist + else: + plisttask.code = app_info + + inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/' % name + self.add_install_files(install_to=inst_to, install_from=n1) + +@feature('cshlib', 'cxxshlib') +@before_method('apply_link', 'propagate_uselib_vars') +def apply_bundle(self): + """ + To make a bundled shared library (a ``.bundle``), set the *mac_bundle* attribute:: + + def build(bld): + bld.shlib(source='a.c', target='foo', mac_bundle = True) + + To force *all* executables to be transformed into bundles:: + + def build(bld): + bld.env.MACBUNDLE = True + bld.shlib(source='a.c', target='foo') + """ + if self.env.MACBUNDLE or getattr(self, 'mac_bundle', False): + self.env.LINKFLAGS_cshlib = self.env.LINKFLAGS_cxxshlib = [] # disable the '-dynamiclib' flag + self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN + use = self.use = self.to_list(getattr(self, 'use', [])) + if not 'MACBUNDLE' in use: + use.append('MACBUNDLE') + +app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources'] + +class macapp(Task.Task): + """ + Creates mac applications + """ + color = 'PINK' + def run(self): + self.outputs[0].parent.mkdir() + shutil.copy2(self.inputs[0].srcpath(), self.outputs[0].abspath()) + +class macplist(Task.Task): + """ + Creates plist files + """ + color = 'PINK' + ext_in = ['.bin'] + def run(self): + if getattr(self, 'code', None): + txt = self.code + else: + txt = self.inputs[0].read() + context = getattr(self, 'context', {}) + txt = txt.format(**context) + self.outputs[0].write(txt) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/c_preproc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/c_preproc.py new file mode 100644 index 0000000..68e5f5a --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/c_preproc.py @@ -0,0 +1,1091 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +""" +C/C++ preprocessor for finding dependencies + +Reasons for using the Waf preprocessor by default + +#. Some c/c++ extensions (Qt) require a custom preprocessor for obtaining the dependencies (.moc files) +#. Not all compilers provide .d files for obtaining the dependencies (portability) +#. A naive file scanner will not catch the constructs such as "#include foo()" +#. A naive file scanner will catch unnecessary dependencies (change an unused header -> recompile everything) + +Regarding the speed concerns: + +* the preprocessing is performed only when files must be compiled +* the macros are evaluated only for #if/#elif/#include +* system headers are not scanned by default + +Now if you do not want the Waf preprocessor, the tool +gccdeps* uses the .d files produced +during the compilation to track the dependencies (useful when used with the boost libraries). +It only works with gcc >= 4.4 though. + +A dumb preprocessor is also available in the tool *c_dumbpreproc* +""" +# TODO: more varargs, pragma once + +import re, string, traceback +from waflib import Logs, Utils, Errors + +class PreprocError(Errors.WafError): + pass + +FILE_CACHE_SIZE = 100000 +LINE_CACHE_SIZE = 100000 + +POPFILE = '-' +"Constant representing a special token used in :py:meth:`waflib.Tools.c_preproc.c_parser.start` iteration to switch to a header read previously" + +recursion_limit = 150 +"Limit on the amount of files to read in the dependency scanner" + +go_absolute = False +"Set to True to track headers on files in /usr/include, else absolute paths are ignored (but it becomes very slow)" + +standard_includes = ['/usr/local/include', '/usr/include'] +if Utils.is_win32: + standard_includes = [] + +use_trigraphs = 0 +"""Apply trigraph rules (False by default)""" + +# obsolete, do not use +strict_quotes = 0 + +g_optrans = { +'not':'!', +'not_eq':'!', +'and':'&&', +'and_eq':'&=', +'or':'||', +'or_eq':'|=', +'xor':'^', +'xor_eq':'^=', +'bitand':'&', +'bitor':'|', +'compl':'~', +} +"""Operators such as and/or/xor for c++. Set an empty dict to disable.""" + +# ignore #warning and #error +re_lines = re.compile( + '^[ \t]*(?:#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$', + re.IGNORECASE | re.MULTILINE) +"""Match #include lines""" + +re_mac = re.compile(r"^[a-zA-Z_]\w*") +"""Match macro definitions""" + +re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') +"""Match macro functions""" + +re_pragma_once = re.compile(r'^\s*once\s*', re.IGNORECASE) +"""Match #pragma once statements""" + +re_nl = re.compile('\\\\\r*\n', re.MULTILINE) +"""Match newlines""" + +re_cpp = re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) +"""Filter C/C++ comments""" + +trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')] +"""Trigraph definitions""" + +chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39} +"""Escape characters""" + +NUM = 'i' +"""Number token""" + +OP = 'O' +"""Operator token""" + +IDENT = 'T' +"""Identifier token""" + +STR = 's' +"""String token""" + +CHAR = 'c' +"""Character token""" + +tok_types = [NUM, STR, IDENT, OP] +"""Token types""" + +exp_types = [ + r"""0[xX](?P[a-fA-F0-9]+)(?P[uUlL]*)|L*?'(?P(\\.|[^\\'])+)'|(?P\d+)[Ee](?P[+-]*?\d+)(?P[fFlL]*)|(?P\d*\.\d+)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P\d+\.\d*)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P0*)(?P\d+)(?P[uUlL]*)""", + r'L?"([^"\\]|\\.)*"', + r'[a-zA-Z_]\w*', + r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]', +] +"""Expression types""" + +re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M) +"""Match expressions into tokens""" + +accepted = 'a' +"""Parser state is *accepted*""" + +ignored = 'i' +"""Parser state is *ignored*, for example preprocessor lines in an #if 0 block""" + +undefined = 'u' +"""Parser state is *undefined* at the moment""" + +skipped = 's' +"""Parser state is *skipped*, for example preprocessor lines in a #elif 0 block""" + +def repl(m): + """Replace function used with :py:attr:`waflib.Tools.c_preproc.re_cpp`""" + s = m.group() + if s[0] == '/': + return ' ' + return s + +prec = {} +""" +Operator precedence rules required for parsing expressions of the form:: + + #if 1 && 2 != 0 +""" +ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ','] +for x, syms in enumerate(ops): + for u in syms.split(): + prec[u] = x + +def reduce_nums(val_1, val_2, val_op): + """ + Apply arithmetic rules to compute a result + + :param val1: input parameter + :type val1: int or string + :param val2: input parameter + :type val2: int or string + :param val_op: C operator in *+*, */*, *-*, etc + :type val_op: string + :rtype: int + """ + #print val_1, val_2, val_op + + # now perform the operation, make certain a and b are numeric + try: + a = 0 + val_1 + except TypeError: + a = int(val_1) + try: + b = 0 + val_2 + except TypeError: + b = int(val_2) + + d = val_op + if d == '%': + c = a % b + elif d=='+': + c = a + b + elif d=='-': + c = a - b + elif d=='*': + c = a * b + elif d=='/': + c = a / b + elif d=='^': + c = a ^ b + elif d=='==': + c = int(a == b) + elif d=='|' or d == 'bitor': + c = a | b + elif d=='||' or d == 'or' : + c = int(a or b) + elif d=='&' or d == 'bitand': + c = a & b + elif d=='&&' or d == 'and': + c = int(a and b) + elif d=='!=' or d == 'not_eq': + c = int(a != b) + elif d=='^' or d == 'xor': + c = int(a^b) + elif d=='<=': + c = int(a <= b) + elif d=='<': + c = int(a < b) + elif d=='>': + c = int(a > b) + elif d=='>=': + c = int(a >= b) + elif d=='<<': + c = a << b + elif d=='>>': + c = a >> b + else: + c = 0 + return c + +def get_num(lst): + """ + Try to obtain a number from a list of tokens. The token types are defined in :py:attr:`waflib.Tools.ccroot.tok_types`. + + :param lst: list of preprocessor tokens + :type lst: list of tuple (tokentype, value) + :return: a pair containing the number and the rest of the list + :rtype: tuple(value, list) + """ + if not lst: + raise PreprocError('empty list for get_num') + (p, v) = lst[0] + if p == OP: + if v == '(': + count_par = 1 + i = 1 + while i < len(lst): + (p, v) = lst[i] + + if p == OP: + if v == ')': + count_par -= 1 + if count_par == 0: + break + elif v == '(': + count_par += 1 + i += 1 + else: + raise PreprocError('rparen expected %r' % lst) + + (num, _) = get_term(lst[1:i]) + return (num, lst[i+1:]) + + elif v == '+': + return get_num(lst[1:]) + elif v == '-': + num, lst = get_num(lst[1:]) + return (reduce_nums('-1', num, '*'), lst) + elif v == '!': + num, lst = get_num(lst[1:]) + return (int(not int(num)), lst) + elif v == '~': + num, lst = get_num(lst[1:]) + return (~ int(num), lst) + else: + raise PreprocError('Invalid op token %r for get_num' % lst) + elif p == NUM: + return v, lst[1:] + elif p == IDENT: + # all macros should have been replaced, remaining identifiers eval to 0 + return 0, lst[1:] + else: + raise PreprocError('Invalid token %r for get_num' % lst) + +def get_term(lst): + """ + Evaluate an expression recursively, for example:: + + 1+1+1 -> 2+1 -> 3 + + :param lst: list of tokens + :type lst: list of tuple(token, value) + :return: the value and the remaining tokens + :rtype: value, list + """ + + if not lst: + raise PreprocError('empty list for get_term') + num, lst = get_num(lst) + if not lst: + return (num, []) + (p, v) = lst[0] + if p == OP: + if v == ',': + # skip + return get_term(lst[1:]) + elif v == '?': + count_par = 0 + i = 1 + while i < len(lst): + (p, v) = lst[i] + + if p == OP: + if v == ')': + count_par -= 1 + elif v == '(': + count_par += 1 + elif v == ':': + if count_par == 0: + break + i += 1 + else: + raise PreprocError('rparen expected %r' % lst) + + if int(num): + return get_term(lst[1:i]) + else: + return get_term(lst[i+1:]) + + else: + num2, lst = get_num(lst[1:]) + + if not lst: + # no more tokens to process + num2 = reduce_nums(num, num2, v) + return get_term([(NUM, num2)] + lst) + + # operator precedence + p2, v2 = lst[0] + if p2 != OP: + raise PreprocError('op expected %r' % lst) + + if prec[v2] >= prec[v]: + num2 = reduce_nums(num, num2, v) + return get_term([(NUM, num2)] + lst) + else: + num3, lst = get_num(lst[1:]) + num3 = reduce_nums(num2, num3, v2) + return get_term([(NUM, num), (p, v), (NUM, num3)] + lst) + + + raise PreprocError('cannot reduce %r' % lst) + +def reduce_eval(lst): + """ + Take a list of tokens and output true or false for #if/#elif conditions. + + :param lst: a list of tokens + :type lst: list of tuple(token, value) + :return: a token + :rtype: tuple(NUM, int) + """ + num, lst = get_term(lst) + return (NUM, num) + +def stringize(lst): + """ + Merge a list of tokens into a string + + :param lst: a list of tokens + :type lst: list of tuple(token, value) + :rtype: string + """ + lst = [str(v2) for (p2, v2) in lst] + return "".join(lst) + +def paste_tokens(t1, t2): + """ + Token pasting works between identifiers, particular operators, and identifiers and numbers:: + + a ## b -> ab + > ## = -> >= + a ## 2 -> a2 + + :param t1: token + :type t1: tuple(type, value) + :param t2: token + :type t2: tuple(type, value) + """ + p1 = None + if t1[0] == OP and t2[0] == OP: + p1 = OP + elif t1[0] == IDENT and (t2[0] == IDENT or t2[0] == NUM): + p1 = IDENT + elif t1[0] == NUM and t2[0] == NUM: + p1 = NUM + if not p1: + raise PreprocError('tokens do not make a valid paste %r and %r' % (t1, t2)) + return (p1, t1[1] + t2[1]) + +def reduce_tokens(lst, defs, ban=[]): + """ + Replace the tokens in lst, using the macros provided in defs, and a list of macros that cannot be re-applied + + :param lst: list of tokens + :type lst: list of tuple(token, value) + :param defs: macro definitions + :type defs: dict + :param ban: macros that cannot be substituted (recursion is not allowed) + :type ban: list of string + :return: the new list of tokens + :rtype: value, list + """ + + i = 0 + while i < len(lst): + (p, v) = lst[i] + + if p == IDENT and v == "defined": + del lst[i] + if i < len(lst): + (p2, v2) = lst[i] + if p2 == IDENT: + if v2 in defs: + lst[i] = (NUM, 1) + else: + lst[i] = (NUM, 0) + elif p2 == OP and v2 == '(': + del lst[i] + (p2, v2) = lst[i] + del lst[i] # remove the ident, and change the ) for the value + if v2 in defs: + lst[i] = (NUM, 1) + else: + lst[i] = (NUM, 0) + else: + raise PreprocError('Invalid define expression %r' % lst) + + elif p == IDENT and v in defs: + + if isinstance(defs[v], str): + a, b = extract_macro(defs[v]) + defs[v] = b + macro_def = defs[v] + to_add = macro_def[1] + + if isinstance(macro_def[0], list): + # macro without arguments + del lst[i] + accu = to_add[:] + reduce_tokens(accu, defs, ban+[v]) + for tmp in accu: + lst.insert(i, tmp) + i += 1 + else: + # collect the arguments for the funcall + + args = [] + del lst[i] + + if i >= len(lst): + raise PreprocError('expected ( after %r (got nothing)' % v) + + (p2, v2) = lst[i] + if p2 != OP or v2 != '(': + raise PreprocError('expected ( after %r' % v) + + del lst[i] + + one_param = [] + count_paren = 0 + while i < len(lst): + p2, v2 = lst[i] + + del lst[i] + if p2 == OP and count_paren == 0: + if v2 == '(': + one_param.append((p2, v2)) + count_paren += 1 + elif v2 == ')': + if one_param: + args.append(one_param) + break + elif v2 == ',': + if not one_param: + raise PreprocError('empty param in funcall %r' % v) + args.append(one_param) + one_param = [] + else: + one_param.append((p2, v2)) + else: + one_param.append((p2, v2)) + if v2 == '(': + count_paren += 1 + elif v2 == ')': + count_paren -= 1 + else: + raise PreprocError('malformed macro') + + # substitute the arguments within the define expression + accu = [] + arg_table = macro_def[0] + j = 0 + while j < len(to_add): + (p2, v2) = to_add[j] + + if p2 == OP and v2 == '#': + # stringize is for arguments only + if j+1 < len(to_add) and to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: + toks = args[arg_table[to_add[j+1][1]]] + accu.append((STR, stringize(toks))) + j += 1 + else: + accu.append((p2, v2)) + elif p2 == OP and v2 == '##': + # token pasting, how can man invent such a complicated system? + if accu and j+1 < len(to_add): + # we have at least two tokens + + t1 = accu[-1] + + if to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: + toks = args[arg_table[to_add[j+1][1]]] + + if toks: + accu[-1] = paste_tokens(t1, toks[0]) #(IDENT, accu[-1][1] + toks[0][1]) + accu.extend(toks[1:]) + else: + # error, case "a##" + accu.append((p2, v2)) + accu.extend(toks) + elif to_add[j+1][0] == IDENT and to_add[j+1][1] == '__VA_ARGS__': + # first collect the tokens + va_toks = [] + st = len(macro_def[0]) + pt = len(args) + for x in args[pt-st+1:]: + va_toks.extend(x) + va_toks.append((OP, ',')) + if va_toks: + va_toks.pop() # extra comma + if len(accu)>1: + (p3, v3) = accu[-1] + (p4, v4) = accu[-2] + if v3 == '##': + # remove the token paste + accu.pop() + if v4 == ',' and pt < st: + # remove the comma + accu.pop() + accu += va_toks + else: + accu[-1] = paste_tokens(t1, to_add[j+1]) + + j += 1 + else: + # Invalid paste, case "##a" or "b##" + accu.append((p2, v2)) + + elif p2 == IDENT and v2 in arg_table: + toks = args[arg_table[v2]] + reduce_tokens(toks, defs, ban+[v]) + accu.extend(toks) + else: + accu.append((p2, v2)) + + j += 1 + + + reduce_tokens(accu, defs, ban+[v]) + + for x in range(len(accu)-1, -1, -1): + lst.insert(i, accu[x]) + + i += 1 + + +def eval_macro(lst, defs): + """ + Reduce the tokens by :py:func:`waflib.Tools.c_preproc.reduce_tokens` and try to return a 0/1 result by :py:func:`waflib.Tools.c_preproc.reduce_eval`. + + :param lst: list of tokens + :type lst: list of tuple(token, value) + :param defs: macro definitions + :type defs: dict + :rtype: int + """ + reduce_tokens(lst, defs, []) + if not lst: + raise PreprocError('missing tokens to evaluate') + + if lst: + p, v = lst[0] + if p == IDENT and v not in defs: + raise PreprocError('missing macro %r' % lst) + + p, v = reduce_eval(lst) + return int(v) != 0 + +def extract_macro(txt): + """ + Process a macro definition of the form:: + #define f(x, y) x * y + + into a function or a simple macro without arguments + + :param txt: expression to exact a macro definition from + :type txt: string + :return: a tuple containing the name, the list of arguments and the replacement + :rtype: tuple(string, [list, list]) + """ + t = tokenize(txt) + if re_fun.search(txt): + p, name = t[0] + + p, v = t[1] + if p != OP: + raise PreprocError('expected (') + + i = 1 + pindex = 0 + params = {} + prev = '(' + + while 1: + i += 1 + p, v = t[i] + + if prev == '(': + if p == IDENT: + params[v] = pindex + pindex += 1 + prev = p + elif p == OP and v == ')': + break + else: + raise PreprocError('unexpected token (3)') + elif prev == IDENT: + if p == OP and v == ',': + prev = v + elif p == OP and v == ')': + break + else: + raise PreprocError('comma or ... expected') + elif prev == ',': + if p == IDENT: + params[v] = pindex + pindex += 1 + prev = p + elif p == OP and v == '...': + raise PreprocError('not implemented (1)') + else: + raise PreprocError('comma or ... expected (2)') + elif prev == '...': + raise PreprocError('not implemented (2)') + else: + raise PreprocError('unexpected else') + + #~ print (name, [params, t[i+1:]]) + return (name, [params, t[i+1:]]) + else: + (p, v) = t[0] + if len(t) > 1: + return (v, [[], t[1:]]) + else: + # empty define, assign an empty token + return (v, [[], [('T','')]]) + +re_include = re.compile(r'^\s*(<(?:.*)>|"(?:.*)")') +def extract_include(txt, defs): + """ + Process a line in the form:: + + #include foo + + :param txt: include line to process + :type txt: string + :param defs: macro definitions + :type defs: dict + :return: the file name + :rtype: string + """ + m = re_include.search(txt) + if m: + txt = m.group(1) + return txt[0], txt[1:-1] + + # perform preprocessing and look at the result, it must match an include + toks = tokenize(txt) + reduce_tokens(toks, defs, ['waf_include']) + + if not toks: + raise PreprocError('could not parse include %r' % txt) + + if len(toks) == 1: + if toks[0][0] == STR: + return '"', toks[0][1] + else: + if toks[0][1] == '<' and toks[-1][1] == '>': + ret = '<', stringize(toks).lstrip('<').rstrip('>') + return ret + + raise PreprocError('could not parse include %r' % txt) + +def parse_char(txt): + """ + Parse a c character + + :param txt: character to parse + :type txt: string + :return: a character literal + :rtype: string + """ + + if not txt: + raise PreprocError('attempted to parse a null char') + if txt[0] != '\\': + return ord(txt) + c = txt[1] + if c == 'x': + if len(txt) == 4 and txt[3] in string.hexdigits: + return int(txt[2:], 16) + return int(txt[2:], 16) + elif c.isdigit(): + if c == '0' and len(txt)==2: + return 0 + for i in 3, 2, 1: + if len(txt) > i and txt[1:1+i].isdigit(): + return (1+i, int(txt[1:1+i], 8)) + else: + try: + return chr_esc[c] + except KeyError: + raise PreprocError('could not parse char literal %r' % txt) + +def tokenize(s): + """ + Convert a string into a list of tokens (shlex.split does not apply to c/c++/d) + + :param s: input to tokenize + :type s: string + :return: a list of tokens + :rtype: list of tuple(token, value) + """ + return tokenize_private(s)[:] # force a copy of the results + +def tokenize_private(s): + ret = [] + for match in re_clexer.finditer(s): + m = match.group + for name in tok_types: + v = m(name) + if v: + if name == IDENT: + if v in g_optrans: + name = OP + elif v.lower() == "true": + v = 1 + name = NUM + elif v.lower() == "false": + v = 0 + name = NUM + elif name == NUM: + if m('oct'): + v = int(v, 8) + elif m('hex'): + v = int(m('hex'), 16) + elif m('n0'): + v = m('n0') + else: + v = m('char') + if v: + v = parse_char(v) + else: + v = m('n2') or m('n4') + elif name == OP: + if v == '%:': + v = '#' + elif v == '%:%:': + v = '##' + elif name == STR: + # remove the quotes around the string + v = v[1:-1] + ret.append((name, v)) + break + return ret + +def format_defines(lst): + ret = [] + for y in lst: + if y: + pos = y.find('=') + if pos == -1: + # "-DFOO" should give "#define FOO 1" + ret.append(y) + elif pos > 0: + # all others are assumed to be -DX=Y + ret.append('%s %s' % (y[:pos], y[pos+1:])) + else: + raise ValueError('Invalid define expression %r' % y) + return ret + +class c_parser(object): + """ + Used by :py:func:`waflib.Tools.c_preproc.scan` to parse c/h files. Note that by default, + only project headers are parsed. + """ + def __init__(self, nodepaths=None, defines=None): + self.lines = [] + """list of lines read""" + + if defines is None: + self.defs = {} + else: + self.defs = dict(defines) # make a copy + self.state = [] + + self.count_files = 0 + self.currentnode_stack = [] + + self.nodepaths = nodepaths or [] + """Include paths""" + + self.nodes = [] + """List of :py:class:`waflib.Node.Node` found so far""" + + self.names = [] + """List of file names that could not be matched by any file""" + + self.curfile = '' + """Current file""" + + self.ban_includes = set() + """Includes that must not be read (#pragma once)""" + + self.listed = set() + """Include nodes/names already listed to avoid duplicates in self.nodes/self.names""" + + def cached_find_resource(self, node, filename): + """ + Find a file from the input directory + + :param node: directory + :type node: :py:class:`waflib.Node.Node` + :param filename: header to find + :type filename: string + :return: the node if found, or None + :rtype: :py:class:`waflib.Node.Node` + """ + try: + cache = node.ctx.preproc_cache_node + except AttributeError: + cache = node.ctx.preproc_cache_node = Utils.lru_cache(FILE_CACHE_SIZE) + + key = (node, filename) + try: + return cache[key] + except KeyError: + ret = node.find_resource(filename) + if ret: + if getattr(ret, 'children', None): + ret = None + elif ret.is_child_of(node.ctx.bldnode): + tmp = node.ctx.srcnode.search_node(ret.path_from(node.ctx.bldnode)) + if tmp and getattr(tmp, 'children', None): + ret = None + cache[key] = ret + return ret + + def tryfind(self, filename, kind='"', env=None): + """ + Try to obtain a node from the filename based from the include paths. Will add + the node found to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` or the file name to + :py:attr:`waflib.Tools.c_preproc.c_parser.names` if no corresponding file is found. Called by + :py:attr:`waflib.Tools.c_preproc.c_parser.start`. + + :param filename: header to find + :type filename: string + :return: the node if found + :rtype: :py:class:`waflib.Node.Node` + """ + if filename.endswith('.moc'): + # we could let the qt4 module use a subclass, but then the function "scan" below must be duplicated + # in the qt4 and in the qt5 classes. So we have two lines here and it is sufficient. + self.names.append(filename) + return None + + self.curfile = filename + + found = None + if kind == '"': + if env.MSVC_VERSION: + for n in reversed(self.currentnode_stack): + found = self.cached_find_resource(n, filename) + if found: + break + else: + found = self.cached_find_resource(self.currentnode_stack[-1], filename) + + if not found: + for n in self.nodepaths: + found = self.cached_find_resource(n, filename) + if found: + break + + listed = self.listed + if found and not found in self.ban_includes: + if found not in listed: + listed.add(found) + self.nodes.append(found) + self.addlines(found) + else: + if filename not in listed: + listed.add(filename) + self.names.append(filename) + return found + + def filter_comments(self, node): + """ + Filter the comments from a c/h file, and return the preprocessor lines. + The regexps :py:attr:`waflib.Tools.c_preproc.re_cpp`, :py:attr:`waflib.Tools.c_preproc.re_nl` and :py:attr:`waflib.Tools.c_preproc.re_lines` are used internally. + + :return: the preprocessor directives as a list of (keyword, line) + :rtype: a list of string pairs + """ + # return a list of tuples : keyword, line + code = node.read() + if use_trigraphs: + for (a, b) in trig_def: + code = code.split(a).join(b) + code = re_nl.sub('', code) + code = re_cpp.sub(repl, code) + return re_lines.findall(code) + + def parse_lines(self, node): + try: + cache = node.ctx.preproc_cache_lines + except AttributeError: + cache = node.ctx.preproc_cache_lines = Utils.lru_cache(LINE_CACHE_SIZE) + try: + return cache[node] + except KeyError: + cache[node] = lines = self.filter_comments(node) + lines.append((POPFILE, '')) + lines.reverse() + return lines + + def addlines(self, node): + """ + Add the lines from a header in the list of preprocessor lines to parse + + :param node: header + :type node: :py:class:`waflib.Node.Node` + """ + + self.currentnode_stack.append(node.parent) + + self.count_files += 1 + if self.count_files > recursion_limit: + # issue #812 + raise PreprocError('recursion limit exceeded') + + if Logs.verbose: + Logs.debug('preproc: reading file %r', node) + try: + lines = self.parse_lines(node) + except EnvironmentError: + raise PreprocError('could not read the file %r' % node) + except Exception: + if Logs.verbose > 0: + Logs.error('parsing %r failed %s', node, traceback.format_exc()) + else: + self.lines.extend(lines) + + def start(self, node, env): + """ + Preprocess a source file to obtain the dependencies, which are accumulated to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` + and :py:attr:`waflib.Tools.c_preproc.c_parser.names`. + + :param node: source file + :type node: :py:class:`waflib.Node.Node` + :param env: config set containing additional defines to take into account + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + """ + Logs.debug('preproc: scanning %s (in %s)', node.name, node.parent.name) + + self.current_file = node + self.addlines(node) + + # macros may be defined on the command-line, so they must be parsed as if they were part of the file + if env.DEFINES: + lst = format_defines(env.DEFINES) + lst.reverse() + self.lines.extend([('define', x) for x in lst]) + + while self.lines: + (token, line) = self.lines.pop() + if token == POPFILE: + self.count_files -= 1 + self.currentnode_stack.pop() + continue + + try: + state = self.state + + # make certain we define the state if we are about to enter in an if block + if token[:2] == 'if': + state.append(undefined) + elif token == 'endif': + state.pop() + + # skip lines when in a dead 'if' branch, wait for the endif + if token[0] != 'e': + if skipped in self.state or ignored in self.state: + continue + + if token == 'if': + ret = eval_macro(tokenize(line), self.defs) + if ret: + state[-1] = accepted + else: + state[-1] = ignored + elif token == 'ifdef': + m = re_mac.match(line) + if m and m.group() in self.defs: + state[-1] = accepted + else: + state[-1] = ignored + elif token == 'ifndef': + m = re_mac.match(line) + if m and m.group() in self.defs: + state[-1] = ignored + else: + state[-1] = accepted + elif token == 'include' or token == 'import': + (kind, inc) = extract_include(line, self.defs) + self.current_file = self.tryfind(inc, kind, env) + if token == 'import': + self.ban_includes.add(self.current_file) + elif token == 'elif': + if state[-1] == accepted: + state[-1] = skipped + elif state[-1] == ignored: + if eval_macro(tokenize(line), self.defs): + state[-1] = accepted + elif token == 'else': + if state[-1] == accepted: + state[-1] = skipped + elif state[-1] == ignored: + state[-1] = accepted + elif token == 'define': + try: + self.defs[self.define_name(line)] = line + except AttributeError: + raise PreprocError('Invalid define line %r' % line) + elif token == 'undef': + m = re_mac.match(line) + if m and m.group() in self.defs: + self.defs.__delitem__(m.group()) + #print "undef %s" % name + elif token == 'pragma': + if re_pragma_once.match(line.lower()): + self.ban_includes.add(self.current_file) + except Exception as e: + if Logs.verbose: + Logs.debug('preproc: line parsing failed (%s): %s %s', e, line, traceback.format_exc()) + + def define_name(self, line): + """ + :param line: define line + :type line: string + :rtype: string + :return: the define name + """ + return re_mac.match(line).group() + +def scan(task): + """ + Get the dependencies using a c/c++ preprocessor, this is required for finding dependencies of the kind:: + + #include some_macro() + + This function is bound as a task method on :py:class:`waflib.Tools.c.c` and :py:class:`waflib.Tools.cxx.cxx` for example + """ + try: + incn = task.generator.includes_nodes + except AttributeError: + raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": ' % task.generator) + + if go_absolute: + nodepaths = incn + [task.generator.bld.root.find_dir(x) for x in standard_includes] + else: + nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] + + tmp = c_parser(nodepaths) + tmp.start(task.inputs[0], task.env) + return (tmp.nodes, tmp.names) diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/c_tests.py b/ldb-2.0.8/third_party/waf/waflib/Tools/c_tests.py new file mode 100644 index 0000000..7a4094f --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/c_tests.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2016-2018 (ita) + +""" +Various configuration tests. +""" + +from waflib import Task +from waflib.Configure import conf +from waflib.TaskGen import feature, before_method, after_method + +LIB_CODE = ''' +#ifdef _MSC_VER +#define testEXPORT __declspec(dllexport) +#else +#define testEXPORT +#endif +testEXPORT int lib_func(void) { return 9; } +''' + +MAIN_CODE = ''' +#ifdef _MSC_VER +#define testEXPORT __declspec(dllimport) +#else +#define testEXPORT +#endif +testEXPORT int lib_func(void); +int main(int argc, char **argv) { + (void)argc; (void)argv; + return !(lib_func() == 9); +} +''' + +@feature('link_lib_test') +@before_method('process_source') +def link_lib_test_fun(self): + """ + The configuration test :py:func:`waflib.Configure.run_build` declares a unique task generator, + so we need to create other task generators from here to check if the linker is able to link libraries. + """ + def write_test_file(task): + task.outputs[0].write(task.generator.code) + + rpath = [] + if getattr(self, 'add_rpath', False): + rpath = [self.bld.path.get_bld().abspath()] + + mode = self.mode + m = '%s %s' % (mode, mode) + ex = self.test_exec and 'test_exec' or '' + bld = self.bld + bld(rule=write_test_file, target='test.' + mode, code=LIB_CODE) + bld(rule=write_test_file, target='main.' + mode, code=MAIN_CODE) + bld(features='%sshlib' % m, source='test.' + mode, target='test') + bld(features='%sprogram %s' % (m, ex), source='main.' + mode, target='app', use='test', rpath=rpath) + +@conf +def check_library(self, mode=None, test_exec=True): + """ + Checks if libraries can be linked with the current linker. Uses :py:func:`waflib.Tools.c_tests.link_lib_test_fun`. + + :param mode: c or cxx or d + :type mode: string + """ + if not mode: + mode = 'c' + if self.env.CXX: + mode = 'cxx' + self.check( + compile_filename = [], + features = 'link_lib_test', + msg = 'Checking for libraries', + mode = mode, + test_exec = test_exec) + +######################################################################################## + +INLINE_CODE = ''' +typedef int foo_t; +static %s foo_t static_foo () {return 0; } +%s foo_t foo () { + return 0; +} +''' +INLINE_VALUES = ['inline', '__inline__', '__inline'] + +@conf +def check_inline(self, **kw): + """ + Checks for the right value for inline macro. + Define INLINE_MACRO to 1 if the define is found. + If the inline macro is not 'inline', add a define to the ``config.h`` (#define inline __inline__) + + :param define_name: define INLINE_MACRO by default to 1 if the macro is defined + :type define_name: string + :param features: by default *c* or *cxx* depending on the compiler present + :type features: list of string + """ + self.start_msg('Checking for inline') + + if not 'define_name' in kw: + kw['define_name'] = 'INLINE_MACRO' + if not 'features' in kw: + if self.env.CXX: + kw['features'] = ['cxx'] + else: + kw['features'] = ['c'] + + for x in INLINE_VALUES: + kw['fragment'] = INLINE_CODE % (x, x) + + try: + self.check(**kw) + except self.errors.ConfigurationError: + continue + else: + self.end_msg(x) + if x != 'inline': + self.define('inline', x, quote=False) + return x + self.fatal('could not use inline functions') + +######################################################################################## + +LARGE_FRAGMENT = '''#include +int main(int argc, char **argv) { + (void)argc; (void)argv; + return !(sizeof(off_t) >= 8); +} +''' + +@conf +def check_large_file(self, **kw): + """ + Checks for large file support and define the macro HAVE_LARGEFILE + The test is skipped on win32 systems (DEST_BINFMT == pe). + + :param define_name: define to set, by default *HAVE_LARGEFILE* + :type define_name: string + :param execute: execute the test (yes by default) + :type execute: bool + """ + if not 'define_name' in kw: + kw['define_name'] = 'HAVE_LARGEFILE' + if not 'execute' in kw: + kw['execute'] = True + + if not 'features' in kw: + if self.env.CXX: + kw['features'] = ['cxx', 'cxxprogram'] + else: + kw['features'] = ['c', 'cprogram'] + + kw['fragment'] = LARGE_FRAGMENT + + kw['msg'] = 'Checking for large file support' + ret = True + try: + if self.env.DEST_BINFMT != 'pe': + ret = self.check(**kw) + except self.errors.ConfigurationError: + pass + else: + if ret: + return True + + kw['msg'] = 'Checking for -D_FILE_OFFSET_BITS=64' + kw['defines'] = ['_FILE_OFFSET_BITS=64'] + try: + ret = self.check(**kw) + except self.errors.ConfigurationError: + pass + else: + self.define('_FILE_OFFSET_BITS', 64) + return ret + + self.fatal('There is no support for large files') + +######################################################################################## + +ENDIAN_FRAGMENT = ''' +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; +} +short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; +} +extern int foo; +''' + +class grep_for_endianness(Task.Task): + """ + Task that reads a binary and tries to determine the endianness + """ + color = 'PINK' + def run(self): + txt = self.inputs[0].read(flags='rb').decode('latin-1') + if txt.find('LiTTleEnDian') > -1: + self.generator.tmp.append('little') + elif txt.find('BIGenDianSyS') > -1: + self.generator.tmp.append('big') + else: + return -1 + +@feature('grep_for_endianness') +@after_method('process_source') +def grep_for_endianness_fun(self): + """ + Used by the endianness configuration test + """ + self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0]) + +@conf +def check_endianness(self): + """ + Executes a configuration test to determine the endianness + """ + tmp = [] + def check_msg(self): + return tmp[0] + self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', + msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, + okmsg=check_msg, confcache=None) + return tmp[0] + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/ccroot.py b/ldb-2.0.8/third_party/waf/waflib/Tools/ccroot.py new file mode 100644 index 0000000..579d5b2 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/ccroot.py @@ -0,0 +1,791 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Classes and methods shared by tools providing support for C-like language such +as C/C++/D/Assembly/Go (this support module is almost never used alone). +""" + +import os, re +from waflib import Task, Utils, Node, Errors, Logs +from waflib.TaskGen import after_method, before_method, feature, taskgen_method, extension +from waflib.Tools import c_aliases, c_preproc, c_config, c_osx, c_tests +from waflib.Configure import conf + +SYSTEM_LIB_PATHS = ['/usr/lib64', '/usr/lib', '/usr/local/lib64', '/usr/local/lib'] + +USELIB_VARS = Utils.defaultdict(set) +""" +Mapping for features to :py:class:`waflib.ConfigSet.ConfigSet` variables. See :py:func:`waflib.Tools.ccroot.propagate_uselib_vars`. +""" + +USELIB_VARS['c'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CCDEPS', 'CFLAGS', 'ARCH']) +USELIB_VARS['cxx'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CXXDEPS', 'CXXFLAGS', 'ARCH']) +USELIB_VARS['d'] = set(['INCLUDES', 'DFLAGS']) +USELIB_VARS['includes'] = set(['INCLUDES', 'FRAMEWORKPATH', 'ARCH']) + +USELIB_VARS['cprogram'] = USELIB_VARS['cxxprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH', 'LDFLAGS']) +USELIB_VARS['cshlib'] = USELIB_VARS['cxxshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH', 'LDFLAGS']) +USELIB_VARS['cstlib'] = USELIB_VARS['cxxstlib'] = set(['ARFLAGS', 'LINKDEPS']) + +USELIB_VARS['dprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) +USELIB_VARS['dshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) +USELIB_VARS['dstlib'] = set(['ARFLAGS', 'LINKDEPS']) + +USELIB_VARS['asm'] = set(['ASFLAGS']) + +# ================================================================================================= + +@taskgen_method +def create_compiled_task(self, name, node): + """ + Create the compilation task: c, cxx, asm, etc. The output node is created automatically (object file with a typical **.o** extension). + The task is appended to the list *compiled_tasks* which is then used by :py:func:`waflib.Tools.ccroot.apply_link` + + :param name: name of the task class + :type name: string + :param node: the file to compile + :type node: :py:class:`waflib.Node.Node` + :return: The task created + :rtype: :py:class:`waflib.Task.Task` + """ + out = '%s.%d.o' % (node.name, self.idx) + task = self.create_task(name, node, node.parent.find_or_declare(out)) + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks = [task] + return task + +@taskgen_method +def to_incnodes(self, inlst): + """ + Task generator method provided to convert a list of string/nodes into a list of includes folders. + + The paths are assumed to be relative to the task generator path, except if they begin by **#** + in which case they are searched from the top-level directory (``bld.srcnode``). + The folders are simply assumed to be existing. + + The node objects in the list are returned in the output list. The strings are converted + into node objects if possible. The node is searched from the source directory, and if a match is found, + the equivalent build directory is created and added to the returned list too. When a folder cannot be found, it is ignored. + + :param inlst: list of folders + :type inlst: space-delimited string or a list of string/nodes + :rtype: list of :py:class:`waflib.Node.Node` + :return: list of include folders as nodes + """ + lst = [] + seen = set() + for x in self.to_list(inlst): + if x in seen or not x: + continue + seen.add(x) + + # with a real lot of targets, it is sometimes interesting to cache the results below + if isinstance(x, Node.Node): + lst.append(x) + else: + if os.path.isabs(x): + lst.append(self.bld.root.make_node(x) or x) + else: + if x[0] == '#': + p = self.bld.bldnode.make_node(x[1:]) + v = self.bld.srcnode.make_node(x[1:]) + else: + p = self.path.get_bld().make_node(x) + v = self.path.make_node(x) + if p.is_child_of(self.bld.bldnode): + p.mkdir() + lst.append(p) + lst.append(v) + return lst + +@feature('c', 'cxx', 'd', 'asm', 'fc', 'includes') +@after_method('propagate_uselib_vars', 'process_source') +def apply_incpaths(self): + """ + Task generator method that processes the attribute *includes*:: + + tg = bld(features='includes', includes='.') + + The folders only need to be relative to the current directory, the equivalent build directory is + added automatically (for headers created in the build directory). This enables using a build directory + or not (``top == out``). + + This method will add a list of nodes read by :py:func:`waflib.Tools.ccroot.to_incnodes` in ``tg.env.INCPATHS``, + and the list of include paths in ``tg.env.INCLUDES``. + """ + + lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env.INCLUDES) + self.includes_nodes = lst + cwd = self.get_cwd() + self.env.INCPATHS = [x.path_from(cwd) for x in lst] + +class link_task(Task.Task): + """ + Base class for all link tasks. A task generator is supposed to have at most one link task bound in the attribute *link_task*. See :py:func:`waflib.Tools.ccroot.apply_link`. + + .. inheritance-diagram:: waflib.Tools.ccroot.stlink_task waflib.Tools.c.cprogram waflib.Tools.c.cshlib waflib.Tools.cxx.cxxstlib waflib.Tools.cxx.cxxprogram waflib.Tools.cxx.cxxshlib waflib.Tools.d.dprogram waflib.Tools.d.dshlib waflib.Tools.d.dstlib waflib.Tools.ccroot.fake_shlib waflib.Tools.ccroot.fake_stlib waflib.Tools.asm.asmprogram waflib.Tools.asm.asmshlib waflib.Tools.asm.asmstlib + """ + color = 'YELLOW' + + weight = 3 + """Try to process link tasks as early as possible""" + + inst_to = None + """Default installation path for the link task outputs, or None to disable""" + + chmod = Utils.O755 + """Default installation mode for the link task outputs""" + + def add_target(self, target): + """ + Process the *target* attribute to add the platform-specific prefix/suffix such as *.so* or *.exe*. + The settings are retrieved from ``env.clsname_PATTERN`` + """ + if isinstance(target, str): + base = self.generator.path + if target.startswith('#'): + # for those who like flat structures + target = target[1:] + base = self.generator.bld.bldnode + + pattern = self.env[self.__class__.__name__ + '_PATTERN'] + if not pattern: + pattern = '%s' + folder, name = os.path.split(target) + + if self.__class__.__name__.find('shlib') > 0 and getattr(self.generator, 'vnum', None): + nums = self.generator.vnum.split('.') + if self.env.DEST_BINFMT == 'pe': + # include the version in the dll file name, + # the import lib file name stays unversioned. + name = name + '-' + nums[0] + elif self.env.DEST_OS == 'openbsd': + pattern = '%s.%s' % (pattern, nums[0]) + if len(nums) >= 2: + pattern += '.%s' % nums[1] + + if folder: + tmp = folder + os.sep + pattern % name + else: + tmp = pattern % name + target = base.find_or_declare(tmp) + self.set_outputs(target) + + def exec_command(self, *k, **kw): + ret = super(link_task, self).exec_command(*k, **kw) + if not ret and self.env.DO_MANIFEST: + ret = self.exec_mf() + return ret + + def exec_mf(self): + """ + Create manifest files for VS-like compilers (msvc, ifort, ...) + """ + if not self.env.MT: + return 0 + + manifest = None + for out_node in self.outputs: + if out_node.name.endswith('.manifest'): + manifest = out_node.abspath() + break + else: + # Should never get here. If we do, it means the manifest file was + # never added to the outputs list, thus we don't have a manifest file + # to embed, so we just return. + return 0 + + # embedding mode. Different for EXE's and DLL's. + # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx + mode = '' + for x in Utils.to_list(self.generator.features): + if x in ('cprogram', 'cxxprogram', 'fcprogram', 'fcprogram_test'): + mode = 1 + elif x in ('cshlib', 'cxxshlib', 'fcshlib'): + mode = 2 + + Logs.debug('msvc: embedding manifest in mode %r', mode) + + lst = [] + self.env.MT + lst.extend(Utils.to_list(self.env.MTFLAGS)) + lst.extend(['-manifest', manifest]) + lst.append('-outputresource:%s;%s' % (self.outputs[0].abspath(), mode)) + + return super(link_task, self).exec_command(lst) + +class stlink_task(link_task): + """ + Base for static link tasks, which use *ar* most of the time. + The target is always removed before being written. + """ + run_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' + + chmod = Utils.O644 + """Default installation mode for the static libraries""" + +def rm_tgt(cls): + old = cls.run + def wrap(self): + try: + os.remove(self.outputs[0].abspath()) + except OSError: + pass + return old(self) + setattr(cls, 'run', wrap) +rm_tgt(stlink_task) + +@feature('skip_stlib_link_deps') +@before_method('process_use') +def apply_skip_stlib_link_deps(self): + """ + This enables an optimization in the :py:func:wafilb.Tools.ccroot.processes_use: method that skips dependency and + link flag optimizations for targets that generate static libraries (via the :py:class:Tools.ccroot.stlink_task task). + The actual behavior is implemented in :py:func:wafilb.Tools.ccroot.processes_use: method so this feature only tells waf + to enable the new behavior. + """ + self.env.SKIP_STLIB_LINK_DEPS = True + +@feature('c', 'cxx', 'd', 'fc', 'asm') +@after_method('process_source') +def apply_link(self): + """ + Collect the tasks stored in ``compiled_tasks`` (created by :py:func:`waflib.Tools.ccroot.create_compiled_task`), and + use the outputs for a new instance of :py:class:`waflib.Tools.ccroot.link_task`. The class to use is the first link task + matching a name from the attribute *features*, for example:: + + def build(bld): + tg = bld(features='cxx cxxprogram cprogram', source='main.c', target='app') + + will create the task ``tg.link_task`` as a new instance of :py:class:`waflib.Tools.cxx.cxxprogram` + """ + + for x in self.features: + if x == 'cprogram' and 'cxx' in self.features: # limited compat + x = 'cxxprogram' + elif x == 'cshlib' and 'cxx' in self.features: + x = 'cxxshlib' + + if x in Task.classes: + if issubclass(Task.classes[x], link_task): + link = x + break + else: + return + + objs = [t.outputs[0] for t in getattr(self, 'compiled_tasks', [])] + self.link_task = self.create_task(link, objs) + self.link_task.add_target(self.target) + + # remember that the install paths are given by the task generators + try: + inst_to = self.install_path + except AttributeError: + inst_to = self.link_task.inst_to + if inst_to: + # install a copy of the node list we have at this moment (implib not added) + self.install_task = self.add_install_files( + install_to=inst_to, install_from=self.link_task.outputs[:], + chmod=self.link_task.chmod, task=self.link_task) + +@taskgen_method +def use_rec(self, name, **kw): + """ + Processes the ``use`` keyword recursively. This method is kind of private and only meant to be used from ``process_use`` + """ + + if name in self.tmp_use_not or name in self.tmp_use_seen: + return + + try: + y = self.bld.get_tgen_by_name(name) + except Errors.WafError: + self.uselib.append(name) + self.tmp_use_not.add(name) + return + + self.tmp_use_seen.append(name) + y.post() + + # bind temporary attributes on the task generator + y.tmp_use_objects = objects = kw.get('objects', True) + y.tmp_use_stlib = stlib = kw.get('stlib', True) + try: + link_task = y.link_task + except AttributeError: + y.tmp_use_var = '' + else: + objects = False + if not isinstance(link_task, stlink_task): + stlib = False + y.tmp_use_var = 'LIB' + else: + y.tmp_use_var = 'STLIB' + + p = self.tmp_use_prec + for x in self.to_list(getattr(y, 'use', [])): + if self.env["STLIB_" + x]: + continue + try: + p[x].append(name) + except KeyError: + p[x] = [name] + self.use_rec(x, objects=objects, stlib=stlib) + +@feature('c', 'cxx', 'd', 'use', 'fc') +@before_method('apply_incpaths', 'propagate_uselib_vars') +@after_method('apply_link', 'process_source') +def process_use(self): + """ + Process the ``use`` attribute which contains a list of task generator names:: + + def build(bld): + bld.shlib(source='a.c', target='lib1') + bld.program(source='main.c', target='app', use='lib1') + + See :py:func:`waflib.Tools.ccroot.use_rec`. + """ + + use_not = self.tmp_use_not = set() + self.tmp_use_seen = [] # we would like an ordered set + use_prec = self.tmp_use_prec = {} + self.uselib = self.to_list(getattr(self, 'uselib', [])) + self.includes = self.to_list(getattr(self, 'includes', [])) + names = self.to_list(getattr(self, 'use', [])) + + for x in names: + self.use_rec(x) + + for x in use_not: + if x in use_prec: + del use_prec[x] + + # topological sort + out = self.tmp_use_sorted = [] + tmp = [] + for x in self.tmp_use_seen: + for k in use_prec.values(): + if x in k: + break + else: + tmp.append(x) + + while tmp: + e = tmp.pop() + out.append(e) + try: + nlst = use_prec[e] + except KeyError: + pass + else: + del use_prec[e] + for x in nlst: + for y in use_prec: + if x in use_prec[y]: + break + else: + tmp.append(x) + if use_prec: + raise Errors.WafError('Cycle detected in the use processing %r' % use_prec) + out.reverse() + + link_task = getattr(self, 'link_task', None) + for x in out: + y = self.bld.get_tgen_by_name(x) + var = y.tmp_use_var + if var and link_task: + if self.env.SKIP_STLIB_LINK_DEPS and isinstance(link_task, stlink_task): + # If the skip_stlib_link_deps feature is enabled then we should + # avoid adding lib deps to the stlink_task instance. + pass + elif var == 'LIB' or y.tmp_use_stlib or x in names: + self.env.append_value(var, [y.target[y.target.rfind(os.sep) + 1:]]) + self.link_task.dep_nodes.extend(y.link_task.outputs) + tmp_path = y.link_task.outputs[0].parent.path_from(self.get_cwd()) + self.env.append_unique(var + 'PATH', [tmp_path]) + else: + if y.tmp_use_objects: + self.add_objects_from_tgen(y) + + if getattr(y, 'export_includes', None): + # self.includes may come from a global variable #2035 + self.includes = self.includes + y.to_incnodes(y.export_includes) + + if getattr(y, 'export_defines', None): + self.env.append_value('DEFINES', self.to_list(y.export_defines)) + + + # and finally, add the use variables (no recursion needed) + for x in names: + try: + y = self.bld.get_tgen_by_name(x) + except Errors.WafError: + if not self.env['STLIB_' + x] and not x in self.uselib: + self.uselib.append(x) + else: + for k in self.to_list(getattr(y, 'use', [])): + if not self.env['STLIB_' + k] and not k in self.uselib: + self.uselib.append(k) + +@taskgen_method +def accept_node_to_link(self, node): + """ + PRIVATE INTERNAL USE ONLY + """ + return not node.name.endswith('.pdb') + +@taskgen_method +def add_objects_from_tgen(self, tg): + """ + Add the objects from the depending compiled tasks as link task inputs. + + Some objects are filtered: for instance, .pdb files are added + to the compiled tasks but not to the link tasks (to avoid errors) + PRIVATE INTERNAL USE ONLY + """ + try: + link_task = self.link_task + except AttributeError: + pass + else: + for tsk in getattr(tg, 'compiled_tasks', []): + for x in tsk.outputs: + if self.accept_node_to_link(x): + link_task.inputs.append(x) + +@taskgen_method +def get_uselib_vars(self): + """ + :return: the *uselib* variables associated to the *features* attribute (see :py:attr:`waflib.Tools.ccroot.USELIB_VARS`) + :rtype: list of string + """ + _vars = set() + for x in self.features: + if x in USELIB_VARS: + _vars |= USELIB_VARS[x] + return _vars + +@feature('c', 'cxx', 'd', 'fc', 'javac', 'cs', 'uselib', 'asm') +@after_method('process_use') +def propagate_uselib_vars(self): + """ + Process uselib variables for adding flags. For example, the following target:: + + def build(bld): + bld.env.AFLAGS_aaa = ['bar'] + from waflib.Tools.ccroot import USELIB_VARS + USELIB_VARS['aaa'] = ['AFLAGS'] + + tg = bld(features='aaa', aflags='test') + + The *aflags* attribute will be processed and this method will set:: + + tg.env.AFLAGS = ['bar', 'test'] + """ + _vars = self.get_uselib_vars() + env = self.env + app = env.append_value + feature_uselib = self.features + self.to_list(getattr(self, 'uselib', [])) + for var in _vars: + y = var.lower() + val = getattr(self, y, []) + if val: + app(var, self.to_list(val)) + + for x in feature_uselib: + val = env['%s_%s' % (var, x)] + if val: + app(var, val) + +# ============ the code above must not know anything about import libs ========== + +@feature('cshlib', 'cxxshlib', 'fcshlib') +@after_method('apply_link') +def apply_implib(self): + """ + Handle dlls and their import libs on Windows-like systems. + + A ``.dll.a`` file called *import library* is generated. + It must be installed as it is required for linking the library. + """ + if not self.env.DEST_BINFMT == 'pe': + return + + dll = self.link_task.outputs[0] + if isinstance(self.target, Node.Node): + name = self.target.name + else: + name = os.path.split(self.target)[1] + implib = self.env.implib_PATTERN % name + implib = dll.parent.find_or_declare(implib) + self.env.append_value('LINKFLAGS', self.env.IMPLIB_ST % implib.bldpath()) + self.link_task.outputs.append(implib) + + if getattr(self, 'defs', None) and self.env.DEST_BINFMT == 'pe': + node = self.path.find_resource(self.defs) + if not node: + raise Errors.WafError('invalid def file %r' % self.defs) + if self.env.def_PATTERN: + self.env.append_value('LINKFLAGS', self.env.def_PATTERN % node.path_from(self.get_cwd())) + self.link_task.dep_nodes.append(node) + else: + # gcc for windows takes *.def file as input without any special flag + self.link_task.inputs.append(node) + + # where to put the import library + if getattr(self, 'install_task', None): + try: + # user has given a specific installation path for the import library + inst_to = self.install_path_implib + except AttributeError: + try: + # user has given an installation path for the main library, put the import library in it + inst_to = self.install_path + except AttributeError: + # else, put the library in BINDIR and the import library in LIBDIR + inst_to = '${IMPLIBDIR}' + self.install_task.install_to = '${BINDIR}' + if not self.env.IMPLIBDIR: + self.env.IMPLIBDIR = self.env.LIBDIR + self.implib_install_task = self.add_install_files(install_to=inst_to, install_from=implib, + chmod=self.link_task.chmod, task=self.link_task) + +# ============ the code above must not know anything about vnum processing on unix platforms ========= + +re_vnum = re.compile('^([1-9]\\d*|0)([.]([1-9]\\d*|0)){0,2}?$') +@feature('cshlib', 'cxxshlib', 'dshlib', 'fcshlib', 'vnum') +@after_method('apply_link', 'propagate_uselib_vars') +def apply_vnum(self): + """ + Enforce version numbering on shared libraries. The valid version numbers must have either zero or two dots:: + + def build(bld): + bld.shlib(source='a.c', target='foo', vnum='14.15.16') + + In this example on Linux platform, ``libfoo.so`` is installed as ``libfoo.so.14.15.16``, and the following symbolic links are created: + + * ``libfoo.so → libfoo.so.14.15.16`` + * ``libfoo.so.14 → libfoo.so.14.15.16`` + + By default, the library will be assigned SONAME ``libfoo.so.14``, effectively declaring ABI compatibility between all minor and patch releases for the major version of the library. When necessary, the compatibility can be explicitly defined using `cnum` parameter: + + def build(bld): + bld.shlib(source='a.c', target='foo', vnum='14.15.16', cnum='14.15') + + In this case, the assigned SONAME will be ``libfoo.so.14.15`` with ABI compatibility only between path releases for a specific major and minor version of the library. + + On OS X platform, install-name parameter will follow the above logic for SONAME with exception that it also specifies an absolute path (based on install_path) of the library. + """ + if not getattr(self, 'vnum', '') or os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'): + return + + link = self.link_task + if not re_vnum.match(self.vnum): + raise Errors.WafError('Invalid vnum %r for target %r' % (self.vnum, getattr(self, 'name', self))) + nums = self.vnum.split('.') + node = link.outputs[0] + + cnum = getattr(self, 'cnum', str(nums[0])) + cnums = cnum.split('.') + if len(cnums)>len(nums) or nums[0:len(cnums)] != cnums: + raise Errors.WafError('invalid compatibility version %s' % cnum) + + libname = node.name + if libname.endswith('.dylib'): + name3 = libname.replace('.dylib', '.%s.dylib' % self.vnum) + name2 = libname.replace('.dylib', '.%s.dylib' % cnum) + else: + name3 = libname + '.' + self.vnum + name2 = libname + '.' + cnum + + # add the so name for the ld linker - to disable, just unset env.SONAME_ST + if self.env.SONAME_ST: + v = self.env.SONAME_ST % name2 + self.env.append_value('LINKFLAGS', v.split()) + + # the following task is just to enable execution from the build dir :-/ + if self.env.DEST_OS != 'openbsd': + outs = [node.parent.make_node(name3)] + if name2 != name3: + outs.append(node.parent.make_node(name2)) + self.create_task('vnum', node, outs) + + if getattr(self, 'install_task', None): + self.install_task.hasrun = Task.SKIPPED + self.install_task.no_errcheck_out = True + path = self.install_task.install_to + if self.env.DEST_OS == 'openbsd': + libname = self.link_task.outputs[0].name + t1 = self.add_install_as(install_to='%s/%s' % (path, libname), install_from=node, chmod=self.link_task.chmod) + self.vnum_install_task = (t1,) + else: + t1 = self.add_install_as(install_to=path + os.sep + name3, install_from=node, chmod=self.link_task.chmod) + t3 = self.add_symlink_as(install_to=path + os.sep + libname, install_from=name3) + if name2 != name3: + t2 = self.add_symlink_as(install_to=path + os.sep + name2, install_from=name3) + self.vnum_install_task = (t1, t2, t3) + else: + self.vnum_install_task = (t1, t3) + + if '-dynamiclib' in self.env.LINKFLAGS: + # this requires after(propagate_uselib_vars) + try: + inst_to = self.install_path + except AttributeError: + inst_to = self.link_task.inst_to + if inst_to: + p = Utils.subst_vars(inst_to, self.env) + path = os.path.join(p, name2) + self.env.append_value('LINKFLAGS', ['-install_name', path]) + self.env.append_value('LINKFLAGS', '-Wl,-compatibility_version,%s' % cnum) + self.env.append_value('LINKFLAGS', '-Wl,-current_version,%s' % self.vnum) + +class vnum(Task.Task): + """ + Create the symbolic links for a versioned shared library. Instances are created by :py:func:`waflib.Tools.ccroot.apply_vnum` + """ + color = 'CYAN' + ext_in = ['.bin'] + def keyword(self): + return 'Symlinking' + def run(self): + for x in self.outputs: + path = x.abspath() + try: + os.remove(path) + except OSError: + pass + + try: + os.symlink(self.inputs[0].name, path) + except OSError: + return 1 + +class fake_shlib(link_task): + """ + Task used for reading a system library and adding the dependency on it + """ + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + return Task.SKIP_ME + +class fake_stlib(stlink_task): + """ + Task used for reading a system library and adding the dependency on it + """ + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + return Task.SKIP_ME + +@conf +def read_shlib(self, name, paths=[], export_includes=[], export_defines=[]): + """ + Read a system shared library, enabling its use as a local library. Will trigger a rebuild if the file changes:: + + def build(bld): + bld.read_shlib('m') + bld.program(source='main.c', use='m') + """ + return self(name=name, features='fake_lib', lib_paths=paths, lib_type='shlib', export_includes=export_includes, export_defines=export_defines) + +@conf +def read_stlib(self, name, paths=[], export_includes=[], export_defines=[]): + """ + Read a system static library, enabling a use as a local library. Will trigger a rebuild if the file changes. + """ + return self(name=name, features='fake_lib', lib_paths=paths, lib_type='stlib', export_includes=export_includes, export_defines=export_defines) + +lib_patterns = { + 'shlib' : ['lib%s.so', '%s.so', 'lib%s.dylib', 'lib%s.dll', '%s.dll'], + 'stlib' : ['lib%s.a', '%s.a', 'lib%s.dll', '%s.dll', 'lib%s.lib', '%s.lib'], +} + +@feature('fake_lib') +def process_lib(self): + """ + Find the location of a foreign library. Used by :py:class:`waflib.Tools.ccroot.read_shlib` and :py:class:`waflib.Tools.ccroot.read_stlib`. + """ + node = None + + names = [x % self.name for x in lib_patterns[self.lib_type]] + for x in self.lib_paths + [self.path] + SYSTEM_LIB_PATHS: + if not isinstance(x, Node.Node): + x = self.bld.root.find_node(x) or self.path.find_node(x) + if not x: + continue + + for y in names: + node = x.find_node(y) + if node: + try: + Utils.h_file(node.abspath()) + except EnvironmentError: + raise ValueError('Could not read %r' % y) + break + else: + continue + break + else: + raise Errors.WafError('could not find library %r' % self.name) + self.link_task = self.create_task('fake_%s' % self.lib_type, [], [node]) + self.target = self.name + + +class fake_o(Task.Task): + def runnable_status(self): + return Task.SKIP_ME + +@extension('.o', '.obj') +def add_those_o_files(self, node): + tsk = self.create_task('fake_o', [], node) + try: + self.compiled_tasks.append(tsk) + except AttributeError: + self.compiled_tasks = [tsk] + +@feature('fake_obj') +@before_method('process_source') +def process_objs(self): + """ + Puts object files in the task generator outputs + """ + for node in self.to_nodes(self.source): + self.add_those_o_files(node) + self.source = [] + +@conf +def read_object(self, obj): + """ + Read an object file, enabling injection in libs/programs. Will trigger a rebuild if the file changes. + + :param obj: object file path, as string or Node + """ + if not isinstance(obj, self.path.__class__): + obj = self.path.find_resource(obj) + return self(features='fake_obj', source=obj, name=obj.name) + +@feature('cxxprogram', 'cprogram') +@after_method('apply_link', 'process_use') +def set_full_paths_hpux(self): + """ + On hp-ux, extend the libpaths and static library paths to absolute paths + """ + if self.env.DEST_OS != 'hp-ux': + return + base = self.bld.bldnode.abspath() + for var in ['LIBPATH', 'STLIBPATH']: + lst = [] + for x in self.env[var]: + if x.startswith('/'): + lst.append(x) + else: + lst.append(os.path.normpath(os.path.join(base, x))) + self.env[var] = lst + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/clang.py b/ldb-2.0.8/third_party/waf/waflib/Tools/clang.py new file mode 100644 index 0000000..3828e39 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/clang.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Krzysztof Kosiński 2014 + +""" +Detect the Clang C compiler +""" + +from waflib.Tools import ccroot, ar, gcc +from waflib.Configure import conf + +@conf +def find_clang(conf): + """ + Finds the program clang and executes it to ensure it really is clang + """ + cc = conf.find_program('clang', var='CC') + conf.get_cc_version(cc, clang=True) + conf.env.CC_NAME = 'clang' + +def configure(conf): + conf.find_clang() + conf.find_program(['llvm-ar', 'ar'], var='AR') + conf.find_ar() + conf.gcc_common_flags() + conf.gcc_modifier_platform() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/clangxx.py b/ldb-2.0.8/third_party/waf/waflib/Tools/clangxx.py new file mode 100644 index 0000000..152013c --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/clangxx.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy 2009-2018 (ita) + +""" +Detect the Clang++ C++ compiler +""" + +from waflib.Tools import ccroot, ar, gxx +from waflib.Configure import conf + +@conf +def find_clangxx(conf): + """ + Finds the program clang++, and executes it to ensure it really is clang++ + """ + cxx = conf.find_program('clang++', var='CXX') + conf.get_cc_version(cxx, clang=True) + conf.env.CXX_NAME = 'clang' + +def configure(conf): + conf.find_clangxx() + conf.find_program(['llvm-ar', 'ar'], var='AR') + conf.find_ar() + conf.gxx_common_flags() + conf.gxx_modifier_platform() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_c.py b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_c.py new file mode 100644 index 0000000..2dba3f8 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_c.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Matthias Jahn jahn dôt matthias ât freenet dôt de, 2007 (pmarat) + +""" +Try to detect a C compiler from the list of supported compilers (gcc, msvc, etc):: + + def options(opt): + opt.load('compiler_c') + def configure(cnf): + cnf.load('compiler_c') + def build(bld): + bld.program(source='main.c', target='app') + +The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_c.c_compiler`. To register +a new C compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: + + from waflib.Tools.compiler_c import c_compiler + c_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] + + def options(opt): + opt.load('compiler_c') + def configure(cnf): + cnf.load('compiler_c') + def build(bld): + bld.program(source='main.c', target='app') + +Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: + + $ CC=clang waf configure +""" + +import re +from waflib.Tools import ccroot +from waflib import Utils +from waflib.Logs import debug + +c_compiler = { +'win32': ['msvc', 'gcc', 'clang'], +'cygwin': ['gcc'], +'darwin': ['clang', 'gcc'], +'aix': ['xlc', 'gcc', 'clang'], +'linux': ['gcc', 'clang', 'icc'], +'sunos': ['suncc', 'gcc'], +'irix': ['gcc', 'irixcc'], +'hpux': ['gcc'], +'osf1V': ['gcc'], +'gnu': ['gcc', 'clang'], +'java': ['gcc', 'msvc', 'clang', 'icc'], +'default':['clang', 'gcc'], +} +""" +Dict mapping platform names to Waf tools finding specific C compilers:: + + from waflib.Tools.compiler_c import c_compiler + c_compiler['linux'] = ['gcc', 'icc', 'suncc'] +""" + +def default_compilers(): + build_platform = Utils.unversioned_sys_platform() + possible_compiler_list = c_compiler.get(build_platform, c_compiler['default']) + return ' '.join(possible_compiler_list) + +def configure(conf): + """ + Detects a suitable C compiler + + :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found + """ + try: + test_for_compiler = conf.options.check_c_compiler or default_compilers() + except AttributeError: + conf.fatal("Add options(opt): opt.load('compiler_c')") + + for compiler in re.split('[ ,]+', test_for_compiler): + conf.env.stash() + conf.start_msg('Checking for %r (C compiler)' % compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError as e: + conf.env.revert() + conf.end_msg(False) + debug('compiler_c: %r', e) + else: + if conf.env.CC: + conf.end_msg(conf.env.get_flat('CC')) + conf.env.COMPILER_CC = compiler + conf.env.commit() + break + conf.env.revert() + conf.end_msg(False) + else: + conf.fatal('could not configure a C compiler!') + +def options(opt): + """ + This is how to provide compiler preferences on the command-line:: + + $ waf configure --check-c-compiler=gcc + """ + test_for_compiler = default_compilers() + opt.load_special_tools('c_*.py', ban=['c_dumbpreproc.py']) + cc_compiler_opts = opt.add_option_group('Configuration options') + cc_compiler_opts.add_option('--check-c-compiler', default=None, + help='list of C compilers to try [%s]' % test_for_compiler, + dest="check_c_compiler") + + for x in test_for_compiler.split(): + opt.load('%s' % x) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_cxx.py b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_cxx.py new file mode 100644 index 0000000..1af65a2 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_cxx.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Matthias Jahn jahn dôt matthias ât freenet dôt de 2007 (pmarat) + +""" +Try to detect a C++ compiler from the list of supported compilers (g++, msvc, etc):: + + def options(opt): + opt.load('compiler_cxx') + def configure(cnf): + cnf.load('compiler_cxx') + def build(bld): + bld.program(source='main.cpp', target='app') + +The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_cxx.cxx_compiler`. To register +a new C++ compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: + + from waflib.Tools.compiler_cxx import cxx_compiler + cxx_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] + + def options(opt): + opt.load('compiler_cxx') + def configure(cnf): + cnf.load('compiler_cxx') + def build(bld): + bld.program(source='main.c', target='app') + +Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: + + $ CXX=clang waf configure +""" + + +import re +from waflib.Tools import ccroot +from waflib import Utils +from waflib.Logs import debug + +cxx_compiler = { +'win32': ['msvc', 'g++', 'clang++'], +'cygwin': ['g++'], +'darwin': ['clang++', 'g++'], +'aix': ['xlc++', 'g++', 'clang++'], +'linux': ['g++', 'clang++', 'icpc'], +'sunos': ['sunc++', 'g++'], +'irix': ['g++'], +'hpux': ['g++'], +'osf1V': ['g++'], +'gnu': ['g++', 'clang++'], +'java': ['g++', 'msvc', 'clang++', 'icpc'], +'default': ['clang++', 'g++'] +} +""" +Dict mapping the platform names to Waf tools finding specific C++ compilers:: + + from waflib.Tools.compiler_cxx import cxx_compiler + cxx_compiler['linux'] = ['gxx', 'icpc', 'suncxx'] +""" + +def default_compilers(): + build_platform = Utils.unversioned_sys_platform() + possible_compiler_list = cxx_compiler.get(build_platform, cxx_compiler['default']) + return ' '.join(possible_compiler_list) + +def configure(conf): + """ + Detects a suitable C++ compiler + + :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found + """ + try: + test_for_compiler = conf.options.check_cxx_compiler or default_compilers() + except AttributeError: + conf.fatal("Add options(opt): opt.load('compiler_cxx')") + + for compiler in re.split('[ ,]+', test_for_compiler): + conf.env.stash() + conf.start_msg('Checking for %r (C++ compiler)' % compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError as e: + conf.env.revert() + conf.end_msg(False) + debug('compiler_cxx: %r', e) + else: + if conf.env.CXX: + conf.end_msg(conf.env.get_flat('CXX')) + conf.env.COMPILER_CXX = compiler + conf.env.commit() + break + conf.env.revert() + conf.end_msg(False) + else: + conf.fatal('could not configure a C++ compiler!') + +def options(opt): + """ + This is how to provide compiler preferences on the command-line:: + + $ waf configure --check-cxx-compiler=gxx + """ + test_for_compiler = default_compilers() + opt.load_special_tools('cxx_*.py') + cxx_compiler_opts = opt.add_option_group('Configuration options') + cxx_compiler_opts.add_option('--check-cxx-compiler', default=None, + help='list of C++ compilers to try [%s]' % test_for_compiler, + dest="check_cxx_compiler") + + for x in test_for_compiler.split(): + opt.load('%s' % x) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_d.py b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_d.py new file mode 100644 index 0000000..43bb1f6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_d.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Carlos Rafael Giani, 2007 (dv) +# Thomas Nagy, 2016-2018 (ita) + +""" +Try to detect a D compiler from the list of supported compilers:: + + def options(opt): + opt.load('compiler_d') + def configure(cnf): + cnf.load('compiler_d') + def build(bld): + bld.program(source='main.d', target='app') + +Only three D compilers are really present at the moment: + +* gdc +* dmd, the ldc compiler having a very similar command-line interface +* ldc2 +""" + +import re +from waflib import Utils, Logs + +d_compiler = { +'default' : ['gdc', 'dmd', 'ldc2'] +} +""" +Dict mapping the platform names to lists of names of D compilers to try, in order of preference:: + + from waflib.Tools.compiler_d import d_compiler + d_compiler['default'] = ['gdc', 'dmd', 'ldc2'] +""" + +def default_compilers(): + build_platform = Utils.unversioned_sys_platform() + possible_compiler_list = d_compiler.get(build_platform, d_compiler['default']) + return ' '.join(possible_compiler_list) + +def configure(conf): + """ + Detects a suitable D compiler + + :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found + """ + try: + test_for_compiler = conf.options.check_d_compiler or default_compilers() + except AttributeError: + conf.fatal("Add options(opt): opt.load('compiler_d')") + + for compiler in re.split('[ ,]+', test_for_compiler): + conf.env.stash() + conf.start_msg('Checking for %r (D compiler)' % compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError as e: + conf.env.revert() + conf.end_msg(False) + Logs.debug('compiler_d: %r', e) + else: + if conf.env.D: + conf.end_msg(conf.env.get_flat('D')) + conf.env.COMPILER_D = compiler + conf.env.commit() + break + conf.env.revert() + conf.end_msg(False) + else: + conf.fatal('could not configure a D compiler!') + +def options(opt): + """ + This is how to provide compiler preferences on the command-line:: + + $ waf configure --check-d-compiler=dmd + """ + test_for_compiler = default_compilers() + d_compiler_opts = opt.add_option_group('Configuration options') + d_compiler_opts.add_option('--check-d-compiler', default=None, + help='list of D compilers to try [%s]' % test_for_compiler, dest='check_d_compiler') + + for x in test_for_compiler.split(): + opt.load('%s' % x) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_fc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_fc.py new file mode 100644 index 0000000..96b58e7 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/compiler_fc.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import re +from waflib import Utils, Logs +from waflib.Tools import fc + +fc_compiler = { + 'win32' : ['gfortran','ifort'], + 'darwin' : ['gfortran', 'g95', 'ifort'], + 'linux' : ['gfortran', 'g95', 'ifort'], + 'java' : ['gfortran', 'g95', 'ifort'], + 'default': ['gfortran'], + 'aix' : ['gfortran'] +} +""" +Dict mapping the platform names to lists of names of Fortran compilers to try, in order of preference:: + + from waflib.Tools.compiler_c import c_compiler + c_compiler['linux'] = ['gfortran', 'g95', 'ifort'] +""" + +def default_compilers(): + build_platform = Utils.unversioned_sys_platform() + possible_compiler_list = fc_compiler.get(build_platform, fc_compiler['default']) + return ' '.join(possible_compiler_list) + +def configure(conf): + """ + Detects a suitable Fortran compiler + + :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found + """ + try: + test_for_compiler = conf.options.check_fortran_compiler or default_compilers() + except AttributeError: + conf.fatal("Add options(opt): opt.load('compiler_fc')") + for compiler in re.split('[ ,]+', test_for_compiler): + conf.env.stash() + conf.start_msg('Checking for %r (Fortran compiler)' % compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError as e: + conf.env.revert() + conf.end_msg(False) + Logs.debug('compiler_fortran: %r', e) + else: + if conf.env.FC: + conf.end_msg(conf.env.get_flat('FC')) + conf.env.COMPILER_FORTRAN = compiler + conf.env.commit() + break + conf.env.revert() + conf.end_msg(False) + else: + conf.fatal('could not configure a Fortran compiler!') + +def options(opt): + """ + This is how to provide compiler preferences on the command-line:: + + $ waf configure --check-fortran-compiler=ifort + """ + test_for_compiler = default_compilers() + opt.load_special_tools('fc_*.py') + fortran_compiler_opts = opt.add_option_group('Configuration options') + fortran_compiler_opts.add_option('--check-fortran-compiler', default=None, + help='list of Fortran compiler to try [%s]' % test_for_compiler, + dest="check_fortran_compiler") + + for x in test_for_compiler.split(): + opt.load('%s' % x) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/cs.py b/ldb-2.0.8/third_party/waf/waflib/Tools/cs.py new file mode 100644 index 0000000..aecca6d --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/cs.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +""" +C# support. A simple example:: + + def configure(conf): + conf.load('cs') + def build(bld): + bld(features='cs', source='main.cs', gen='foo') + +Note that the configuration may compile C# snippets:: + + FRAG = ''' + namespace Moo { + public class Test { public static int Main(string[] args) { return 0; } } + }''' + def configure(conf): + conf.check(features='cs', fragment=FRAG, compile_filename='test.cs', gen='test.exe', + bintype='exe', csflags=['-pkg:gtk-sharp-2.0'], msg='Checking for Gtksharp support') +""" + +from waflib import Utils, Task, Options, Errors +from waflib.TaskGen import before_method, after_method, feature +from waflib.Tools import ccroot +from waflib.Configure import conf + +ccroot.USELIB_VARS['cs'] = set(['CSFLAGS', 'ASSEMBLIES', 'RESOURCES']) +ccroot.lib_patterns['csshlib'] = ['%s'] + +@feature('cs') +@before_method('process_source') +def apply_cs(self): + """ + Create a C# task bound to the attribute *cs_task*. There can be only one C# task by task generator. + """ + cs_nodes = [] + no_nodes = [] + for x in self.to_nodes(self.source): + if x.name.endswith('.cs'): + cs_nodes.append(x) + else: + no_nodes.append(x) + self.source = no_nodes + + bintype = getattr(self, 'bintype', self.gen.endswith('.dll') and 'library' or 'exe') + self.cs_task = tsk = self.create_task('mcs', cs_nodes, self.path.find_or_declare(self.gen)) + tsk.env.CSTYPE = '/target:%s' % bintype + tsk.env.OUT = '/out:%s' % tsk.outputs[0].abspath() + self.env.append_value('CSFLAGS', '/platform:%s' % getattr(self, 'platform', 'anycpu')) + + inst_to = getattr(self, 'install_path', bintype=='exe' and '${BINDIR}' or '${LIBDIR}') + if inst_to: + # note: we are making a copy, so the files added to cs_task.outputs won't be installed automatically + mod = getattr(self, 'chmod', bintype=='exe' and Utils.O755 or Utils.O644) + self.install_task = self.add_install_files(install_to=inst_to, install_from=self.cs_task.outputs[:], chmod=mod) + +@feature('cs') +@after_method('apply_cs') +def use_cs(self): + """ + C# applications honor the **use** keyword:: + + def build(bld): + bld(features='cs', source='My.cs', bintype='library', gen='my.dll', name='mylib') + bld(features='cs', source='Hi.cs', includes='.', bintype='exe', gen='hi.exe', use='mylib', name='hi') + """ + names = self.to_list(getattr(self, 'use', [])) + get = self.bld.get_tgen_by_name + for x in names: + try: + y = get(x) + except Errors.WafError: + self.env.append_value('CSFLAGS', '/reference:%s' % x) + continue + y.post() + + tsk = getattr(y, 'cs_task', None) or getattr(y, 'link_task', None) + if not tsk: + self.bld.fatal('cs task has no link task for use %r' % self) + self.cs_task.dep_nodes.extend(tsk.outputs) # dependency + self.cs_task.set_run_after(tsk) # order (redundant, the order is inferred from the nodes inputs/outputs) + self.env.append_value('CSFLAGS', '/reference:%s' % tsk.outputs[0].abspath()) + +@feature('cs') +@after_method('apply_cs', 'use_cs') +def debug_cs(self): + """ + The C# targets may create .mdb or .pdb files:: + + def build(bld): + bld(features='cs', source='My.cs', bintype='library', gen='my.dll', csdebug='full') + # csdebug is a value in (True, 'full', 'pdbonly') + """ + csdebug = getattr(self, 'csdebug', self.env.CSDEBUG) + if not csdebug: + return + + node = self.cs_task.outputs[0] + if self.env.CS_NAME == 'mono': + out = node.parent.find_or_declare(node.name + '.mdb') + else: + out = node.change_ext('.pdb') + self.cs_task.outputs.append(out) + + if getattr(self, 'install_task', None): + self.pdb_install_task = self.add_install_files( + install_to=self.install_task.install_to, install_from=out) + + if csdebug == 'pdbonly': + val = ['/debug+', '/debug:pdbonly'] + elif csdebug == 'full': + val = ['/debug+', '/debug:full'] + else: + val = ['/debug-'] + self.env.append_value('CSFLAGS', val) + +@feature('cs') +@after_method('debug_cs') +def doc_cs(self): + """ + The C# targets may create .xml documentation files:: + + def build(bld): + bld(features='cs', source='My.cs', bintype='library', gen='my.dll', csdoc=True) + # csdoc is a boolean value + """ + csdoc = getattr(self, 'csdoc', self.env.CSDOC) + if not csdoc: + return + + node = self.cs_task.outputs[0] + out = node.change_ext('.xml') + self.cs_task.outputs.append(out) + + if getattr(self, 'install_task', None): + self.doc_install_task = self.add_install_files( + install_to=self.install_task.install_to, install_from=out) + + self.env.append_value('CSFLAGS', '/doc:%s' % out.abspath()) + +class mcs(Task.Task): + """ + Compile C# files + """ + color = 'YELLOW' + run_str = '${MCS} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' + + def split_argfile(self, cmd): + inline = [cmd[0]] + infile = [] + for x in cmd[1:]: + # csc doesn't want /noconfig in @file + if x.lower() == '/noconfig': + inline.append(x) + else: + infile.append(self.quote_flag(x)) + return (inline, infile) + +def configure(conf): + """ + Find a C# compiler, set the variable MCS for the compiler and CS_NAME (mono or csc) + """ + csc = getattr(Options.options, 'cscbinary', None) + if csc: + conf.env.MCS = csc + conf.find_program(['csc', 'mcs', 'gmcs'], var='MCS') + conf.env.ASS_ST = '/r:%s' + conf.env.RES_ST = '/resource:%s' + + conf.env.CS_NAME = 'csc' + if str(conf.env.MCS).lower().find('mcs') > -1: + conf.env.CS_NAME = 'mono' + +def options(opt): + """ + Add a command-line option for the configuration:: + + $ waf configure --with-csc-binary=/foo/bar/mcs + """ + opt.add_option('--with-csc-binary', type='string', dest='cscbinary') + +class fake_csshlib(Task.Task): + """ + Task used for reading a foreign .net assembly and adding the dependency on it + """ + color = 'YELLOW' + inst_to = None + + def runnable_status(self): + return Task.SKIP_ME + +@conf +def read_csshlib(self, name, paths=[]): + """ + Read a foreign .net assembly for the *use* system:: + + def build(bld): + bld.read_csshlib('ManagedLibrary.dll', paths=[bld.env.mylibrarypath]) + bld(features='cs', source='Hi.cs', bintype='exe', gen='hi.exe', use='ManagedLibrary.dll') + + :param name: Name of the library + :type name: string + :param paths: Folders in which the library may be found + :type paths: list of string + :return: A task generator having the feature *fake_lib* which will call :py:func:`waflib.Tools.ccroot.process_lib` + :rtype: :py:class:`waflib.TaskGen.task_gen` + """ + return self(name=name, features='fake_lib', lib_paths=paths, lib_type='csshlib') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/cxx.py b/ldb-2.0.8/third_party/waf/waflib/Tools/cxx.py new file mode 100644 index 0000000..194fad7 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/cxx.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +"Base for c++ programs and libraries" + +from waflib import TaskGen, Task +from waflib.Tools import c_preproc +from waflib.Tools.ccroot import link_task, stlink_task + +@TaskGen.extension('.cpp','.cc','.cxx','.C','.c++') +def cxx_hook(self, node): + "Binds c++ file extensions to create :py:class:`waflib.Tools.cxx.cxx` instances" + return self.create_compiled_task('cxx', node) + +if not '.c' in TaskGen.task_gen.mappings: + TaskGen.task_gen.mappings['.c'] = TaskGen.task_gen.mappings['.cpp'] + +class cxx(Task.Task): + "Compiles C++ files into object files" + run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' + vars = ['CXXDEPS'] # unused variable to depend on, just in case + ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] + scan = c_preproc.scan + +class cxxprogram(link_task): + "Links object files into c++ programs" + run_str = '${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' + vars = ['LINKDEPS'] + ext_out = ['.bin'] + inst_to = '${BINDIR}' + +class cxxshlib(cxxprogram): + "Links object files into c++ shared libraries" + inst_to = '${LIBDIR}' + +class cxxstlib(stlink_task): + "Links object files into c++ static libraries" + pass # do not remove + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/d.py b/ldb-2.0.8/third_party/waf/waflib/Tools/d.py new file mode 100644 index 0000000..e4cf73b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/d.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Carlos Rafael Giani, 2007 (dv) +# Thomas Nagy, 2007-2018 (ita) + +from waflib import Utils, Task, Errors +from waflib.TaskGen import taskgen_method, feature, extension +from waflib.Tools import d_scan, d_config +from waflib.Tools.ccroot import link_task, stlink_task + +class d(Task.Task): + "Compile a d file into an object file" + color = 'GREEN' + run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_SRC_F:SRC} ${D_TGT_F:TGT}' + scan = d_scan.scan + +class d_with_header(d): + "Compile a d file and generate a header" + run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_HDR_F:tgt.outputs[1].bldpath()} ${D_SRC_F:SRC} ${D_TGT_F:tgt.outputs[0].bldpath()}' + +class d_header(Task.Task): + "Compile d headers" + color = 'BLUE' + run_str = '${D} ${D_HEADER} ${SRC}' + +class dprogram(link_task): + "Link object files into a d program" + run_str = '${D_LINKER} ${LINKFLAGS} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F:TGT} ${RPATH_ST:RPATH} ${DSTLIB_MARKER} ${DSTLIBPATH_ST:STLIBPATH} ${DSTLIB_ST:STLIB} ${DSHLIB_MARKER} ${DLIBPATH_ST:LIBPATH} ${DSHLIB_ST:LIB}' + inst_to = '${BINDIR}' + +class dshlib(dprogram): + "Link object files into a d shared library" + inst_to = '${LIBDIR}' + +class dstlib(stlink_task): + "Link object files into a d static library" + pass # do not remove + +@extension('.d', '.di', '.D') +def d_hook(self, node): + """ + Compile *D* files. To get .di files as well as .o files, set the following:: + + def build(bld): + bld.program(source='foo.d', target='app', generate_headers=True) + + """ + ext = Utils.destos_to_binfmt(self.env.DEST_OS) == 'pe' and 'obj' or 'o' + out = '%s.%d.%s' % (node.name, self.idx, ext) + def create_compiled_task(self, name, node): + task = self.create_task(name, node, node.parent.find_or_declare(out)) + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks = [task] + return task + + if getattr(self, 'generate_headers', None): + tsk = create_compiled_task(self, 'd_with_header', node) + tsk.outputs.append(node.change_ext(self.env.DHEADER_ext)) + else: + tsk = create_compiled_task(self, 'd', node) + return tsk + +@taskgen_method +def generate_header(self, filename): + """ + See feature request #104:: + + def build(bld): + tg = bld.program(source='foo.d', target='app') + tg.generate_header('blah.d') + # is equivalent to: + #tg = bld.program(source='foo.d', target='app', header_lst='blah.d') + + :param filename: header to create + :type filename: string + """ + try: + self.header_lst.append([filename, self.install_path]) + except AttributeError: + self.header_lst = [[filename, self.install_path]] + +@feature('d') +def process_header(self): + """ + Process the attribute 'header_lst' to create the d header compilation tasks:: + + def build(bld): + bld.program(source='foo.d', target='app', header_lst='blah.d') + """ + for i in getattr(self, 'header_lst', []): + node = self.path.find_resource(i[0]) + if not node: + raise Errors.WafError('file %r not found on d obj' % i[0]) + self.create_task('d_header', node, node.change_ext('.di')) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/d_config.py b/ldb-2.0.8/third_party/waf/waflib/Tools/d_config.py new file mode 100644 index 0000000..6637556 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/d_config.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2016-2018 (ita) + +from waflib import Utils +from waflib.Configure import conf + +@conf +def d_platform_flags(self): + """ + Sets the extensions dll/so for d programs and libraries + """ + v = self.env + if not v.DEST_OS: + v.DEST_OS = Utils.unversioned_sys_platform() + binfmt = Utils.destos_to_binfmt(self.env.DEST_OS) + if binfmt == 'pe': + v.dprogram_PATTERN = '%s.exe' + v.dshlib_PATTERN = 'lib%s.dll' + v.dstlib_PATTERN = 'lib%s.a' + elif binfmt == 'mac-o': + v.dprogram_PATTERN = '%s' + v.dshlib_PATTERN = 'lib%s.dylib' + v.dstlib_PATTERN = 'lib%s.a' + else: + v.dprogram_PATTERN = '%s' + v.dshlib_PATTERN = 'lib%s.so' + v.dstlib_PATTERN = 'lib%s.a' + +DLIB = ''' +version(D_Version2) { + import std.stdio; + int main() { + writefln("phobos2"); + return 0; + } +} else { + version(Tango) { + import tango.stdc.stdio; + int main() { + printf("tango"); + return 0; + } + } else { + import std.stdio; + int main() { + writefln("phobos1"); + return 0; + } + } +} +''' +"""Detection string for the D standard library""" + +@conf +def check_dlibrary(self, execute=True): + """ + Detects the kind of standard library that comes with the compiler, + and sets conf.env.DLIBRARY to tango, phobos1 or phobos2 + """ + ret = self.check_cc(features='d dprogram', fragment=DLIB, compile_filename='test.d', execute=execute, define_ret=True) + if execute: + self.env.DLIBRARY = ret.strip() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/d_scan.py b/ldb-2.0.8/third_party/waf/waflib/Tools/d_scan.py new file mode 100644 index 0000000..4e807a6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/d_scan.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2016-2018 (ita) + +""" +Provide a scanner for finding dependencies on d files +""" + +import re +from waflib import Utils + +def filter_comments(filename): + """ + :param filename: d file name + :type filename: string + :rtype: list + :return: a list of characters + """ + txt = Utils.readf(filename) + i = 0 + buf = [] + max = len(txt) + begin = 0 + while i < max: + c = txt[i] + if c == '"' or c == "'": # skip a string or character literal + buf.append(txt[begin:i]) + delim = c + i += 1 + while i < max: + c = txt[i] + if c == delim: + break + elif c == '\\': # skip the character following backslash + i += 1 + i += 1 + i += 1 + begin = i + elif c == '/': # try to replace a comment with whitespace + buf.append(txt[begin:i]) + i += 1 + if i == max: + break + c = txt[i] + if c == '+': # eat nesting /+ +/ comment + i += 1 + nesting = 1 + c = None + while i < max: + prev = c + c = txt[i] + if prev == '/' and c == '+': + nesting += 1 + c = None + elif prev == '+' and c == '/': + nesting -= 1 + if nesting == 0: + break + c = None + i += 1 + elif c == '*': # eat /* */ comment + i += 1 + c = None + while i < max: + prev = c + c = txt[i] + if prev == '*' and c == '/': + break + i += 1 + elif c == '/': # eat // comment + i += 1 + while i < max and txt[i] != '\n': + i += 1 + else: # no comment + begin = i - 1 + continue + i += 1 + begin = i + buf.append(' ') + else: + i += 1 + buf.append(txt[begin:]) + return buf + +class d_parser(object): + """ + Parser for d files + """ + def __init__(self, env, incpaths): + #self.code = '' + #self.module = '' + #self.imports = [] + + self.allnames = [] + + self.re_module = re.compile(r"module\s+([^;]+)") + self.re_import = re.compile(r"import\s+([^;]+)") + self.re_import_bindings = re.compile("([^:]+):(.*)") + self.re_import_alias = re.compile("[^=]+=(.+)") + + self.env = env + + self.nodes = [] + self.names = [] + + self.incpaths = incpaths + + def tryfind(self, filename): + """ + Search file a file matching an module/import directive + + :param filename: file to read + :type filename: string + """ + found = 0 + for n in self.incpaths: + found = n.find_resource(filename.replace('.', '/') + '.d') + if found: + self.nodes.append(found) + self.waiting.append(found) + break + if not found: + if not filename in self.names: + self.names.append(filename) + + def get_strings(self, code): + """ + :param code: d code to parse + :type code: string + :return: the modules that the code uses + :rtype: a list of match objects + """ + #self.imports = [] + self.module = '' + lst = [] + + # get the module name (if present) + + mod_name = self.re_module.search(code) + if mod_name: + self.module = re.sub(r'\s+', '', mod_name.group(1)) # strip all whitespaces + + # go through the code, have a look at all import occurrences + + # first, lets look at anything beginning with "import" and ending with ";" + import_iterator = self.re_import.finditer(code) + if import_iterator: + for import_match in import_iterator: + import_match_str = re.sub(r'\s+', '', import_match.group(1)) # strip all whitespaces + + # does this end with an import bindings declaration? + # (import bindings always terminate the list of imports) + bindings_match = self.re_import_bindings.match(import_match_str) + if bindings_match: + import_match_str = bindings_match.group(1) + # if so, extract the part before the ":" (since the module declaration(s) is/are located there) + + # split the matching string into a bunch of strings, separated by a comma + matches = import_match_str.split(',') + + for match in matches: + alias_match = self.re_import_alias.match(match) + if alias_match: + # is this an alias declaration? (alias = module name) if so, extract the module name + match = alias_match.group(1) + + lst.append(match) + return lst + + def start(self, node): + """ + The parsing starts here + + :param node: input file + :type node: :py:class:`waflib.Node.Node` + """ + self.waiting = [node] + # while the stack is not empty, add the dependencies + while self.waiting: + nd = self.waiting.pop(0) + self.iter(nd) + + def iter(self, node): + """ + Find all the modules that a file depends on, uses :py:meth:`waflib.Tools.d_scan.d_parser.tryfind` to process dependent files + + :param node: input file + :type node: :py:class:`waflib.Node.Node` + """ + path = node.abspath() # obtain the absolute path + code = "".join(filter_comments(path)) # read the file and filter the comments + names = self.get_strings(code) # obtain the import strings + for x in names: + # optimization + if x in self.allnames: + continue + self.allnames.append(x) + + # for each name, see if it is like a node or not + self.tryfind(x) + +def scan(self): + "look for .d/.di used by a d file" + env = self.env + gruik = d_parser(env, self.generator.includes_nodes) + node = self.inputs[0] + gruik.start(node) + nodes = gruik.nodes + names = gruik.names + return (nodes, names) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/dbus.py b/ldb-2.0.8/third_party/waf/waflib/Tools/dbus.py new file mode 100644 index 0000000..d520f1c --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/dbus.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Ali Sabil, 2007 + +""" +Compiles dbus files with **dbus-binding-tool** + +Typical usage:: + + def options(opt): + opt.load('compiler_c dbus') + def configure(conf): + conf.load('compiler_c dbus') + def build(bld): + tg = bld.program( + includes = '.', + source = bld.path.ant_glob('*.c'), + target = 'gnome-hello') + tg.add_dbus_file('test.xml', 'test_prefix', 'glib-server') +""" + +from waflib import Task, Errors +from waflib.TaskGen import taskgen_method, before_method + +@taskgen_method +def add_dbus_file(self, filename, prefix, mode): + """ + Adds a dbus file to the list of dbus files to process. Store them in the attribute *dbus_lst*. + + :param filename: xml file to compile + :type filename: string + :param prefix: dbus binding tool prefix (--prefix=prefix) + :type prefix: string + :param mode: dbus binding tool mode (--mode=mode) + :type mode: string + """ + if not hasattr(self, 'dbus_lst'): + self.dbus_lst = [] + if not 'process_dbus' in self.meths: + self.meths.append('process_dbus') + self.dbus_lst.append([filename, prefix, mode]) + +@before_method('process_source') +def process_dbus(self): + """ + Processes the dbus files stored in the attribute *dbus_lst* to create :py:class:`waflib.Tools.dbus.dbus_binding_tool` instances. + """ + for filename, prefix, mode in getattr(self, 'dbus_lst', []): + node = self.path.find_resource(filename) + if not node: + raise Errors.WafError('file not found ' + filename) + tsk = self.create_task('dbus_binding_tool', node, node.change_ext('.h')) + tsk.env.DBUS_BINDING_TOOL_PREFIX = prefix + tsk.env.DBUS_BINDING_TOOL_MODE = mode + +class dbus_binding_tool(Task.Task): + """ + Compiles a dbus file + """ + color = 'BLUE' + ext_out = ['.h'] + run_str = '${DBUS_BINDING_TOOL} --prefix=${DBUS_BINDING_TOOL_PREFIX} --mode=${DBUS_BINDING_TOOL_MODE} --output=${TGT} ${SRC}' + shell = True # temporary workaround for #795 + +def configure(conf): + """ + Detects the program dbus-binding-tool and sets ``conf.env.DBUS_BINDING_TOOL`` + """ + conf.find_program('dbus-binding-tool', var='DBUS_BINDING_TOOL') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/dmd.py b/ldb-2.0.8/third_party/waf/waflib/Tools/dmd.py new file mode 100644 index 0000000..8917ca1 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/dmd.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Carlos Rafael Giani, 2007 (dv) +# Thomas Nagy, 2008-2018 (ita) + +import sys +from waflib.Tools import ar, d +from waflib.Configure import conf + +@conf +def find_dmd(conf): + """ + Finds the program *dmd*, *dmd2*, or *ldc* and set the variable *D* + """ + conf.find_program(['dmd', 'dmd2', 'ldc'], var='D') + + # make sure that we're dealing with dmd1, dmd2, or ldc(1) + out = conf.cmd_and_log(conf.env.D + ['--help']) + if out.find("D Compiler v") == -1: + out = conf.cmd_and_log(conf.env.D + ['-version']) + if out.find("based on DMD v1.") == -1: + conf.fatal("detected compiler is not dmd/ldc") + +@conf +def common_flags_ldc(conf): + """ + Sets the D flags required by *ldc* + """ + v = conf.env + v.DFLAGS = ['-d-version=Posix'] + v.LINKFLAGS = [] + v.DFLAGS_dshlib = ['-relocation-model=pic'] + +@conf +def common_flags_dmd(conf): + """ + Set the flags required by *dmd* or *dmd2* + """ + v = conf.env + + v.D_SRC_F = ['-c'] + v.D_TGT_F = '-of%s' + + v.D_LINKER = v.D + v.DLNK_SRC_F = '' + v.DLNK_TGT_F = '-of%s' + v.DINC_ST = '-I%s' + + v.DSHLIB_MARKER = v.DSTLIB_MARKER = '' + v.DSTLIB_ST = v.DSHLIB_ST = '-L-l%s' + v.DSTLIBPATH_ST = v.DLIBPATH_ST = '-L-L%s' + + v.LINKFLAGS_dprogram= ['-quiet'] + + v.DFLAGS_dshlib = ['-fPIC'] + v.LINKFLAGS_dshlib = ['-L-shared'] + + v.DHEADER_ext = '.di' + v.DFLAGS_d_with_header = ['-H', '-Hf'] + v.D_HDR_F = '%s' + +def configure(conf): + """ + Configuration for *dmd*, *dmd2*, and *ldc* + """ + conf.find_dmd() + + if sys.platform == 'win32': + out = conf.cmd_and_log(conf.env.D + ['--help']) + if out.find('D Compiler v2.') > -1: + conf.fatal('dmd2 on Windows is not supported, use gdc or ldc2 instead') + + conf.load('ar') + conf.load('d') + conf.common_flags_dmd() + conf.d_platform_flags() + + if str(conf.env.D).find('ldc') > -1: + conf.common_flags_ldc() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/errcheck.py b/ldb-2.0.8/third_party/waf/waflib/Tools/errcheck.py new file mode 100644 index 0000000..de8d75a --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/errcheck.py @@ -0,0 +1,237 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011 (ita) + +""" +Common mistakes highlighting. + +There is a performance impact, so this tool is only loaded when running ``waf -v`` +""" + +typos = { +'feature':'features', +'sources':'source', +'targets':'target', +'include':'includes', +'export_include':'export_includes', +'define':'defines', +'importpath':'includes', +'installpath':'install_path', +'iscopy':'is_copy', +'uses':'use', +} + +meths_typos = ['__call__', 'program', 'shlib', 'stlib', 'objects'] + +import sys +from waflib import Logs, Build, Node, Task, TaskGen, ConfigSet, Errors, Utils +from waflib.Tools import ccroot + +def check_same_targets(self): + mp = Utils.defaultdict(list) + uids = {} + + def check_task(tsk): + if not isinstance(tsk, Task.Task): + return + if hasattr(tsk, 'no_errcheck_out'): + return + + for node in tsk.outputs: + mp[node].append(tsk) + try: + uids[tsk.uid()].append(tsk) + except KeyError: + uids[tsk.uid()] = [tsk] + + for g in self.groups: + for tg in g: + try: + for tsk in tg.tasks: + check_task(tsk) + except AttributeError: + # raised if not a task generator, which should be uncommon + check_task(tg) + + dupe = False + for (k, v) in mp.items(): + if len(v) > 1: + dupe = True + msg = '* Node %r is created more than once%s. The task generators are:' % (k, Logs.verbose == 1 and " (full message on 'waf -v -v')" or "") + Logs.error(msg) + for x in v: + if Logs.verbose > 1: + Logs.error(' %d. %r', 1 + v.index(x), x.generator) + else: + Logs.error(' %d. %r in %r', 1 + v.index(x), x.generator.name, getattr(x.generator, 'path', None)) + Logs.error('If you think that this is an error, set no_errcheck_out on the task instance') + + if not dupe: + for (k, v) in uids.items(): + if len(v) > 1: + Logs.error('* Several tasks use the same identifier. Please check the information on\n https://waf.io/apidocs/Task.html?highlight=uid#waflib.Task.Task.uid') + tg_details = tsk.generator.name + if Logs.verbose > 2: + tg_details = tsk.generator + for tsk in v: + Logs.error(' - object %r (%r) defined in %r', tsk.__class__.__name__, tsk, tg_details) + +def check_invalid_constraints(self): + feat = set() + for x in list(TaskGen.feats.values()): + feat.union(set(x)) + for (x, y) in TaskGen.task_gen.prec.items(): + feat.add(x) + feat.union(set(y)) + ext = set() + for x in TaskGen.task_gen.mappings.values(): + ext.add(x.__name__) + invalid = ext & feat + if invalid: + Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method', list(invalid)) + + # the build scripts have been read, so we can check for invalid after/before attributes on task classes + for cls in list(Task.classes.values()): + if sys.hexversion > 0x3000000 and issubclass(cls, Task.Task) and isinstance(cls.hcode, str): + raise Errors.WafError('Class %r has hcode value %r of type , expecting (use Utils.h_cmd() ?)' % (cls, cls.hcode)) + + for x in ('before', 'after'): + for y in Utils.to_list(getattr(cls, x, [])): + if not Task.classes.get(y): + Logs.error('Erroneous order constraint %r=%r on task class %r', x, y, cls.__name__) + if getattr(cls, 'rule', None): + Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")', cls.__name__) + +def replace(m): + """ + Replaces existing BuildContext methods to verify parameter names, + for example ``bld(source=)`` has no ending *s* + """ + oldcall = getattr(Build.BuildContext, m) + def call(self, *k, **kw): + ret = oldcall(self, *k, **kw) + for x in typos: + if x in kw: + if x == 'iscopy' and 'subst' in getattr(self, 'features', ''): + continue + Logs.error('Fix the typo %r -> %r on %r', x, typos[x], ret) + return ret + setattr(Build.BuildContext, m, call) + +def enhance_lib(): + """ + Modifies existing classes and methods to enable error verification + """ + for m in meths_typos: + replace(m) + + # catch '..' in ant_glob patterns + def ant_glob(self, *k, **kw): + if k: + lst = Utils.to_list(k[0]) + for pat in lst: + sp = pat.split('/') + if '..' in sp: + Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'", k[0]) + if '.' in sp: + Logs.error("In ant_glob pattern %r: '.' means 'one dot', not 'current directory'", k[0]) + return self.old_ant_glob(*k, **kw) + Node.Node.old_ant_glob = Node.Node.ant_glob + Node.Node.ant_glob = ant_glob + + # catch ant_glob on build folders + def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True, quiet=False): + if remove: + try: + if self.is_child_of(self.ctx.bldnode) and not quiet: + quiet = True + Logs.error('Calling ant_glob on build folders (%r) is dangerous: add quiet=True / remove=False', self) + except AttributeError: + pass + return self.old_ant_iter(accept, maxdepth, pats, dir, src, remove, quiet) + Node.Node.old_ant_iter = Node.Node.ant_iter + Node.Node.ant_iter = ant_iter + + # catch conflicting ext_in/ext_out/before/after declarations + old = Task.is_before + def is_before(t1, t2): + ret = old(t1, t2) + if ret and old(t2, t1): + Logs.error('Contradictory order constraints in classes %r %r', t1, t2) + return ret + Task.is_before = is_before + + # check for bld(feature='cshlib') where no 'c' is given - this can be either a mistake or on purpose + # so we only issue a warning + def check_err_features(self): + lst = self.to_list(self.features) + if 'shlib' in lst: + Logs.error('feature shlib -> cshlib, dshlib or cxxshlib') + for x in ('c', 'cxx', 'd', 'fc'): + if not x in lst and lst and lst[0] in [x+y for y in ('program', 'shlib', 'stlib')]: + Logs.error('%r features is probably missing %r', self, x) + TaskGen.feature('*')(check_err_features) + + # check for erroneous order constraints + def check_err_order(self): + if not hasattr(self, 'rule') and not 'subst' in Utils.to_list(self.features): + for x in ('before', 'after', 'ext_in', 'ext_out'): + if hasattr(self, x): + Logs.warn('Erroneous order constraint %r on non-rule based task generator %r', x, self) + else: + for x in ('before', 'after'): + for y in self.to_list(getattr(self, x, [])): + if not Task.classes.get(y): + Logs.error('Erroneous order constraint %s=%r on %r (no such class)', x, y, self) + TaskGen.feature('*')(check_err_order) + + # check for @extension used with @feature/@before_method/@after_method + def check_compile(self): + check_invalid_constraints(self) + try: + ret = self.orig_compile() + finally: + check_same_targets(self) + return ret + Build.BuildContext.orig_compile = Build.BuildContext.compile + Build.BuildContext.compile = check_compile + + # check for invalid build groups #914 + def use_rec(self, name, **kw): + try: + y = self.bld.get_tgen_by_name(name) + except Errors.WafError: + pass + else: + idx = self.bld.get_group_idx(self) + odx = self.bld.get_group_idx(y) + if odx > idx: + msg = "Invalid 'use' across build groups:" + if Logs.verbose > 1: + msg += '\n target %r\n uses:\n %r' % (self, y) + else: + msg += " %r uses %r (try 'waf -v -v' for the full error)" % (self.name, name) + raise Errors.WafError(msg) + self.orig_use_rec(name, **kw) + TaskGen.task_gen.orig_use_rec = TaskGen.task_gen.use_rec + TaskGen.task_gen.use_rec = use_rec + + # check for env.append + def _getattr(self, name, default=None): + if name == 'append' or name == 'add': + raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique') + elif name == 'prepend': + raise Errors.WafError('env.prepend does not exist: use env.prepend_value') + if name in self.__slots__: + return super(ConfigSet.ConfigSet, self).__getattr__(name, default) + else: + return self[name] + ConfigSet.ConfigSet.__getattr__ = _getattr + + +def options(opt): + """ + Error verification can be enabled by default (not just on ``waf -v``) by adding to the user script options + """ + enhance_lib() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/fc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/fc.py new file mode 100644 index 0000000..fd4d39c --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/fc.py @@ -0,0 +1,203 @@ +#! /usr/bin/env python +# encoding: utf-8 +# DC 2008 +# Thomas Nagy 2016-2018 (ita) + +""" +Fortran support +""" + +from waflib import Utils, Task, Errors +from waflib.Tools import ccroot, fc_config, fc_scan +from waflib.TaskGen import extension +from waflib.Configure import conf + +ccroot.USELIB_VARS['fc'] = set(['FCFLAGS', 'DEFINES', 'INCLUDES', 'FCPPFLAGS']) +ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) +ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) +ccroot.USELIB_VARS['fcstlib'] = set(['ARFLAGS', 'LINKDEPS']) + +@extension('.f','.F','.f90','.F90','.for','.FOR','.f95','.F95','.f03','.F03','.f08','.F08') +def fc_hook(self, node): + "Binds the Fortran file extensions create :py:class:`waflib.Tools.fc.fc` instances" + return self.create_compiled_task('fc', node) + +@conf +def modfile(conf, name): + """ + Turns a module name into the right module file name. + Defaults to all lower case. + """ + if name.find(':') >= 0: + # Depending on a submodule! + separator = conf.env.FC_SUBMOD_SEPARATOR or '@' + # Ancestors of the submodule will be prefixed to the + # submodule name, separated by a colon. + modpath = name.split(':') + # Only the ancestor (actual) module and the submodule name + # will be used for the filename. + modname = modpath[0] + separator + modpath[-1] + suffix = conf.env.FC_SUBMOD_SUFFIX or '.smod' + else: + modname = name + suffix = '.mod' + + return {'lower' :modname.lower() + suffix.lower(), + 'lower.MOD' :modname.lower() + suffix.upper(), + 'UPPER.mod' :modname.upper() + suffix.lower(), + 'UPPER' :modname.upper() + suffix.upper()}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] + +def get_fortran_tasks(tsk): + """ + Obtains all fortran tasks from the same build group. Those tasks must not have + the attribute 'nomod' or 'mod_fortran_done' + + :return: a list of :py:class:`waflib.Tools.fc.fc` instances + """ + bld = tsk.generator.bld + tasks = bld.get_tasks_group(bld.get_group_idx(tsk.generator)) + return [x for x in tasks if isinstance(x, fc) and not getattr(x, 'nomod', None) and not getattr(x, 'mod_fortran_done', None)] + +class fc(Task.Task): + """ + Fortran tasks can only run when all fortran tasks in a current task group are ready to be executed + This may cause a deadlock if some fortran task is waiting for something that cannot happen (circular dependency) + Should this ever happen, set the 'nomod=True' on those tasks instances to break the loop + """ + color = 'GREEN' + run_str = '${FC} ${FCFLAGS} ${FCINCPATH_ST:INCPATHS} ${FCDEFINES_ST:DEFINES} ${_FCMODOUTFLAGS} ${FC_TGT_F}${TGT[0].abspath()} ${FC_SRC_F}${SRC[0].abspath()} ${FCPPFLAGS}' + vars = ["FORTRANMODPATHFLAG"] + + def scan(self): + """Fortran dependency scanner""" + tmp = fc_scan.fortran_parser(self.generator.includes_nodes) + tmp.task = self + tmp.start(self.inputs[0]) + return (tmp.nodes, tmp.names) + + def runnable_status(self): + """ + Sets the mod file outputs and the dependencies on the mod files over all Fortran tasks + executed by the main thread so there are no concurrency issues + """ + if getattr(self, 'mod_fortran_done', None): + return super(fc, self).runnable_status() + + # now, if we reach this part it is because this fortran task is the first in the list + bld = self.generator.bld + + # obtain the fortran tasks + lst = get_fortran_tasks(self) + + # disable this method for other tasks + for tsk in lst: + tsk.mod_fortran_done = True + + # wait for all the .f tasks to be ready for execution + # and ensure that the scanners are called at least once + for tsk in lst: + ret = tsk.runnable_status() + if ret == Task.ASK_LATER: + # we have to wait for one of the other fortran tasks to be ready + # this may deadlock if there are dependencies between fortran tasks + # but this should not happen (we are setting them here!) + for x in lst: + x.mod_fortran_done = None + + return Task.ASK_LATER + + ins = Utils.defaultdict(set) + outs = Utils.defaultdict(set) + + # the .mod files to create + for tsk in lst: + key = tsk.uid() + for x in bld.raw_deps[key]: + if x.startswith('MOD@'): + name = bld.modfile(x.replace('MOD@', '')) + node = bld.srcnode.find_or_declare(name) + tsk.set_outputs(node) + outs[node].add(tsk) + + # the .mod files to use + for tsk in lst: + key = tsk.uid() + for x in bld.raw_deps[key]: + if x.startswith('USE@'): + name = bld.modfile(x.replace('USE@', '')) + node = bld.srcnode.find_resource(name) + if node and node not in tsk.outputs: + if not node in bld.node_deps[key]: + bld.node_deps[key].append(node) + ins[node].add(tsk) + + # if the intersection matches, set the order + for k in ins.keys(): + for a in ins[k]: + a.run_after.update(outs[k]) + for x in outs[k]: + self.generator.bld.producer.revdeps[x].add(a) + + # the scanner cannot output nodes, so we have to set them + # ourselves as task.dep_nodes (additional input nodes) + tmp = [] + for t in outs[k]: + tmp.extend(t.outputs) + a.dep_nodes.extend(tmp) + a.dep_nodes.sort(key=lambda x: x.abspath()) + + # the task objects have changed: clear the signature cache + for tsk in lst: + try: + delattr(tsk, 'cache_sig') + except AttributeError: + pass + + return super(fc, self).runnable_status() + +class fcprogram(ccroot.link_task): + """Links Fortran programs""" + color = 'YELLOW' + run_str = '${FC} ${LINKFLAGS} ${FCLNK_SRC_F}${SRC} ${FCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FCSTLIB_MARKER} ${FCSTLIBPATH_ST:STLIBPATH} ${FCSTLIB_ST:STLIB} ${FCSHLIB_MARKER} ${FCLIBPATH_ST:LIBPATH} ${FCLIB_ST:LIB} ${LDFLAGS}' + inst_to = '${BINDIR}' + +class fcshlib(fcprogram): + """Links Fortran libraries""" + inst_to = '${LIBDIR}' + +class fcstlib(ccroot.stlink_task): + """Links Fortran static libraries (uses ar by default)""" + pass # do not remove the pass statement + +class fcprogram_test(fcprogram): + """Custom link task to obtain compiler outputs for Fortran configuration tests""" + + def runnable_status(self): + """This task is always executed""" + ret = super(fcprogram_test, self).runnable_status() + if ret == Task.SKIP_ME: + ret = Task.RUN_ME + return ret + + def exec_command(self, cmd, **kw): + """Stores the compiler std our/err onto the build context, to bld.out + bld.err""" + bld = self.generator.bld + + kw['shell'] = isinstance(cmd, str) + kw['stdout'] = kw['stderr'] = Utils.subprocess.PIPE + kw['cwd'] = self.get_cwd() + bld.out = bld.err = '' + + bld.to_log('command: %s\n' % cmd) + + kw['output'] = 0 + try: + (bld.out, bld.err) = bld.cmd_and_log(cmd, **kw) + except Errors.WafError: + return -1 + + if bld.out: + bld.to_log('out: %s\n' % bld.out) + if bld.err: + bld.to_log('err: %s\n' % bld.err) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/fc_config.py b/ldb-2.0.8/third_party/waf/waflib/Tools/fc_config.py new file mode 100644 index 0000000..dc5e5c9 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/fc_config.py @@ -0,0 +1,488 @@ +#! /usr/bin/env python +# encoding: utf-8 +# DC 2008 +# Thomas Nagy 2016-2018 (ita) + +""" +Fortran configuration helpers +""" + +import re, os, sys, shlex +from waflib.Configure import conf +from waflib.TaskGen import feature, before_method + +FC_FRAGMENT = ' program main\n end program main\n' +FC_FRAGMENT2 = ' PROGRAM MAIN\n END\n' # what's the actual difference between these? + +@conf +def fc_flags(conf): + """ + Defines common fortran configuration flags and file extensions + """ + v = conf.env + + v.FC_SRC_F = [] + v.FC_TGT_F = ['-c', '-o'] + v.FCINCPATH_ST = '-I%s' + v.FCDEFINES_ST = '-D%s' + + if not v.LINK_FC: + v.LINK_FC = v.FC + + v.FCLNK_SRC_F = [] + v.FCLNK_TGT_F = ['-o'] + + v.FCFLAGS_fcshlib = ['-fpic'] + v.LINKFLAGS_fcshlib = ['-shared'] + v.fcshlib_PATTERN = 'lib%s.so' + + v.fcstlib_PATTERN = 'lib%s.a' + + v.FCLIB_ST = '-l%s' + v.FCLIBPATH_ST = '-L%s' + v.FCSTLIB_ST = '-l%s' + v.FCSTLIBPATH_ST = '-L%s' + v.FCSTLIB_MARKER = '-Wl,-Bstatic' + v.FCSHLIB_MARKER = '-Wl,-Bdynamic' + + v.SONAME_ST = '-Wl,-h,%s' + +@conf +def fc_add_flags(conf): + """ + Adds FCFLAGS / LDFLAGS / LINKFLAGS from os.environ to conf.env + """ + conf.add_os_flags('FCPPFLAGS', dup=False) + conf.add_os_flags('FCFLAGS', dup=False) + conf.add_os_flags('LINKFLAGS', dup=False) + conf.add_os_flags('LDFLAGS', dup=False) + +@conf +def check_fortran(self, *k, **kw): + """ + Compiles a Fortran program to ensure that the settings are correct + """ + self.check_cc( + fragment = FC_FRAGMENT, + compile_filename = 'test.f', + features = 'fc fcprogram', + msg = 'Compiling a simple fortran app') + +@conf +def check_fc(self, *k, **kw): + """ + Same as :py:func:`waflib.Tools.c_config.check` but defaults to the *Fortran* programming language + (this overrides the C defaults in :py:func:`waflib.Tools.c_config.validate_c`) + """ + kw['compiler'] = 'fc' + if not 'compile_mode' in kw: + kw['compile_mode'] = 'fc' + if not 'type' in kw: + kw['type'] = 'fcprogram' + if not 'compile_filename' in kw: + kw['compile_filename'] = 'test.f90' + if not 'code' in kw: + kw['code'] = FC_FRAGMENT + return self.check(*k, **kw) + +# ------------------------------------------------------------------------ +# --- These are the default platform modifiers, refactored here for +# convenience. gfortran and g95 have much overlap. +# ------------------------------------------------------------------------ + +@conf +def fortran_modifier_darwin(conf): + """ + Defines Fortran flags and extensions for OSX systems + """ + v = conf.env + v.FCFLAGS_fcshlib = ['-fPIC'] + v.LINKFLAGS_fcshlib = ['-dynamiclib'] + v.fcshlib_PATTERN = 'lib%s.dylib' + v.FRAMEWORKPATH_ST = '-F%s' + v.FRAMEWORK_ST = ['-framework'] + + v.LINKFLAGS_fcstlib = [] + + v.FCSHLIB_MARKER = '' + v.FCSTLIB_MARKER = '' + v.SONAME_ST = '' + +@conf +def fortran_modifier_win32(conf): + """ + Defines Fortran flags for Windows platforms + """ + v = conf.env + v.fcprogram_PATTERN = v.fcprogram_test_PATTERN = '%s.exe' + + v.fcshlib_PATTERN = '%s.dll' + v.implib_PATTERN = '%s.dll.a' + v.IMPLIB_ST = '-Wl,--out-implib,%s' + + v.FCFLAGS_fcshlib = [] + + # Auto-import is enabled by default even without this option, + # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages + # that the linker emits otherwise. + v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) + +@conf +def fortran_modifier_cygwin(conf): + """ + Defines Fortran flags for use on cygwin + """ + fortran_modifier_win32(conf) + v = conf.env + v.fcshlib_PATTERN = 'cyg%s.dll' + v.append_value('LINKFLAGS_fcshlib', ['-Wl,--enable-auto-image-base']) + v.FCFLAGS_fcshlib = [] + +# ------------------------------------------------------------------------ + +@conf +def check_fortran_dummy_main(self, *k, **kw): + """ + Determines if a main function is needed by compiling a code snippet with + the C compiler and linking it with the Fortran compiler (useful on unix-like systems) + """ + if not self.env.CC: + self.fatal('A c compiler is required for check_fortran_dummy_main') + + lst = ['MAIN__', '__MAIN', '_MAIN', 'MAIN_', 'MAIN'] + lst.extend([m.lower() for m in lst]) + lst.append('') + + self.start_msg('Detecting whether we need a dummy main') + for main in lst: + kw['fortran_main'] = main + try: + self.check_cc( + fragment = 'int %s() { return 0; }\n' % (main or 'test'), + features = 'c fcprogram', + mandatory = True + ) + if not main: + self.env.FC_MAIN = -1 + self.end_msg('no') + else: + self.env.FC_MAIN = main + self.end_msg('yes %s' % main) + break + except self.errors.ConfigurationError: + pass + else: + self.end_msg('not found') + self.fatal('could not detect whether fortran requires a dummy main, see the config.log') + +# ------------------------------------------------------------------------ + +GCC_DRIVER_LINE = re.compile('^Driving:') +POSIX_STATIC_EXT = re.compile(r'\S+\.a') +POSIX_LIB_FLAGS = re.compile(r'-l\S+') + +@conf +def is_link_verbose(self, txt): + """Returns True if 'useful' link options can be found in txt""" + assert isinstance(txt, str) + for line in txt.splitlines(): + if not GCC_DRIVER_LINE.search(line): + if POSIX_STATIC_EXT.search(line) or POSIX_LIB_FLAGS.search(line): + return True + return False + +@conf +def check_fortran_verbose_flag(self, *k, **kw): + """ + Checks what kind of verbose (-v) flag works, then sets it to env.FC_VERBOSE_FLAG + """ + self.start_msg('fortran link verbose flag') + for x in ('-v', '--verbose', '-verbose', '-V'): + try: + self.check_cc( + features = 'fc fcprogram_test', + fragment = FC_FRAGMENT2, + compile_filename = 'test.f', + linkflags = [x], + mandatory=True) + except self.errors.ConfigurationError: + pass + else: + # output is on stderr or stdout (for xlf) + if self.is_link_verbose(self.test_bld.err) or self.is_link_verbose(self.test_bld.out): + self.end_msg(x) + break + else: + self.end_msg('failure') + self.fatal('Could not obtain the fortran link verbose flag (see config.log)') + + self.env.FC_VERBOSE_FLAG = x + return x + +# ------------------------------------------------------------------------ + +# linkflags which match those are ignored +LINKFLAGS_IGNORED = [r'-lang*', r'-lcrt[a-zA-Z0-9\.]*\.o', r'-lc$', r'-lSystem', r'-libmil', r'-LIST:*', r'-LNO:*'] +if os.name == 'nt': + LINKFLAGS_IGNORED.extend([r'-lfrt*', r'-luser32', r'-lkernel32', r'-ladvapi32', r'-lmsvcrt', r'-lshell32', r'-lmingw', r'-lmoldname']) +else: + LINKFLAGS_IGNORED.append(r'-lgcc*') +RLINKFLAGS_IGNORED = [re.compile(f) for f in LINKFLAGS_IGNORED] + +def _match_ignore(line): + """Returns True if the line should be ignored (Fortran verbose flag test)""" + for i in RLINKFLAGS_IGNORED: + if i.match(line): + return True + return False + +def parse_fortran_link(lines): + """Given the output of verbose link of Fortran compiler, this returns a + list of flags necessary for linking using the standard linker.""" + final_flags = [] + for line in lines: + if not GCC_DRIVER_LINE.match(line): + _parse_flink_line(line, final_flags) + return final_flags + +SPACE_OPTS = re.compile('^-[LRuYz]$') +NOSPACE_OPTS = re.compile('^-[RL]') + +def _parse_flink_token(lexer, token, tmp_flags): + # Here we go (convention for wildcard is shell, not regex !) + # 1 TODO: we first get some root .a libraries + # 2 TODO: take everything starting by -bI:* + # 3 Ignore the following flags: -lang* | -lcrt*.o | -lc | + # -lgcc* | -lSystem | -libmil | -LANG:=* | -LIST:* | -LNO:*) + # 4 take into account -lkernel32 + # 5 For options of the kind -[[LRuYz]], as they take one argument + # after, the actual option is the next token + # 6 For -YP,*: take and replace by -Larg where arg is the old + # argument + # 7 For -[lLR]*: take + + # step 3 + if _match_ignore(token): + pass + # step 4 + elif token.startswith('-lkernel32') and sys.platform == 'cygwin': + tmp_flags.append(token) + # step 5 + elif SPACE_OPTS.match(token): + t = lexer.get_token() + if t.startswith('P,'): + t = t[2:] + for opt in t.split(os.pathsep): + tmp_flags.append('-L%s' % opt) + # step 6 + elif NOSPACE_OPTS.match(token): + tmp_flags.append(token) + # step 7 + elif POSIX_LIB_FLAGS.match(token): + tmp_flags.append(token) + else: + # ignore anything not explicitly taken into account + pass + + t = lexer.get_token() + return t + +def _parse_flink_line(line, final_flags): + """private""" + lexer = shlex.shlex(line, posix = True) + lexer.whitespace_split = True + + t = lexer.get_token() + tmp_flags = [] + while t: + t = _parse_flink_token(lexer, t, tmp_flags) + + final_flags.extend(tmp_flags) + return final_flags + +@conf +def check_fortran_clib(self, autoadd=True, *k, **kw): + """ + Obtains the flags for linking with the C library + if this check works, add uselib='CLIB' to your task generators + """ + if not self.env.FC_VERBOSE_FLAG: + self.fatal('env.FC_VERBOSE_FLAG is not set: execute check_fortran_verbose_flag?') + + self.start_msg('Getting fortran runtime link flags') + try: + self.check_cc( + fragment = FC_FRAGMENT2, + compile_filename = 'test.f', + features = 'fc fcprogram_test', + linkflags = [self.env.FC_VERBOSE_FLAG] + ) + except Exception: + self.end_msg(False) + if kw.get('mandatory', True): + conf.fatal('Could not find the c library flags') + else: + out = self.test_bld.err + flags = parse_fortran_link(out.splitlines()) + self.end_msg('ok (%s)' % ' '.join(flags)) + self.env.LINKFLAGS_CLIB = flags + return flags + return [] + +def getoutput(conf, cmd, stdin=False): + """ + Obtains Fortran command outputs + """ + from waflib import Errors + if conf.env.env: + env = conf.env.env + else: + env = dict(os.environ) + env['LANG'] = 'C' + input = stdin and '\n'.encode() or None + try: + out, err = conf.cmd_and_log(cmd, env=env, output=0, input=input) + except Errors.WafError as e: + # An WafError might indicate an error code during the command + # execution, in this case we still obtain the stderr and stdout, + # which we can use to find the version string. + if not (hasattr(e, 'stderr') and hasattr(e, 'stdout')): + raise e + else: + # Ignore the return code and return the original + # stdout and stderr. + out = e.stdout + err = e.stderr + except Exception: + conf.fatal('could not determine the compiler version %r' % cmd) + return (out, err) + +# ------------------------------------------------------------------------ + +ROUTINES_CODE = """\ + subroutine foobar() + return + end + subroutine foo_bar() + return + end +""" + +MAIN_CODE = """ +void %(dummy_func_nounder)s(void); +void %(dummy_func_under)s(void); +int %(main_func_name)s() { + %(dummy_func_nounder)s(); + %(dummy_func_under)s(); + return 0; +} +""" + +@feature('link_main_routines_func') +@before_method('process_source') +def link_main_routines_tg_method(self): + """ + The configuration test declares a unique task generator, + so we create other task generators from there for fortran link tests + """ + def write_test_file(task): + task.outputs[0].write(task.generator.code) + bld = self.bld + bld(rule=write_test_file, target='main.c', code=MAIN_CODE % self.__dict__) + bld(rule=write_test_file, target='test.f', code=ROUTINES_CODE) + bld(features='fc fcstlib', source='test.f', target='test') + bld(features='c fcprogram', source='main.c', target='app', use='test') + +def mangling_schemes(): + """ + Generate triplets for use with mangle_name + (used in check_fortran_mangling) + the order is tuned for gfortan + """ + for u in ('_', ''): + for du in ('', '_'): + for c in ("lower", "upper"): + yield (u, du, c) + +def mangle_name(u, du, c, name): + """Mangle a name from a triplet (used in check_fortran_mangling)""" + return getattr(name, c)() + u + (name.find('_') != -1 and du or '') + +@conf +def check_fortran_mangling(self, *k, **kw): + """ + Detect the mangling scheme, sets FORTRAN_MANGLING to the triplet found + + This test will compile a fortran static library, then link a c app against it + """ + if not self.env.CC: + self.fatal('A c compiler is required for link_main_routines') + if not self.env.FC: + self.fatal('A fortran compiler is required for link_main_routines') + if not self.env.FC_MAIN: + self.fatal('Checking for mangling requires self.env.FC_MAIN (execute "check_fortran_dummy_main" first?)') + + self.start_msg('Getting fortran mangling scheme') + for (u, du, c) in mangling_schemes(): + try: + self.check_cc( + compile_filename = [], + features = 'link_main_routines_func', + msg = 'nomsg', + errmsg = 'nomsg', + dummy_func_nounder = mangle_name(u, du, c, 'foobar'), + dummy_func_under = mangle_name(u, du, c, 'foo_bar'), + main_func_name = self.env.FC_MAIN + ) + except self.errors.ConfigurationError: + pass + else: + self.end_msg("ok ('%s', '%s', '%s-case')" % (u, du, c)) + self.env.FORTRAN_MANGLING = (u, du, c) + break + else: + self.end_msg(False) + self.fatal('mangler not found') + return (u, du, c) + +@feature('pyext') +@before_method('propagate_uselib_vars', 'apply_link') +def set_lib_pat(self): + """Sets the Fortran flags for linking with Python""" + self.env.fcshlib_PATTERN = self.env.pyext_PATTERN + +@conf +def detect_openmp(self): + """ + Detects openmp flags and sets the OPENMP ``FCFLAGS``/``LINKFLAGS`` + """ + for x in ('-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp'): + try: + self.check_fc( + msg = 'Checking for OpenMP flag %s' % x, + fragment = 'program main\n call omp_get_num_threads()\nend program main', + fcflags = x, + linkflags = x, + uselib_store = 'OPENMP' + ) + except self.errors.ConfigurationError: + pass + else: + break + else: + self.fatal('Could not find OpenMP') + +@conf +def check_gfortran_o_space(self): + if self.env.FC_NAME != 'GFORTRAN' or int(self.env.FC_VERSION[0]) > 4: + # This is for old compilers and only for gfortran. + # No idea how other implementations handle this. Be safe and bail out. + return + self.env.stash() + self.env.FCLNK_TGT_F = ['-o', ''] + try: + self.check_fc(msg='Checking if the -o link must be split from arguments', fragment=FC_FRAGMENT, features='fc fcshlib') + except self.errors.ConfigurationError: + self.env.revert() + else: + self.env.commit() diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/fc_scan.py b/ldb-2.0.8/third_party/waf/waflib/Tools/fc_scan.py new file mode 100644 index 0000000..0824c92 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/fc_scan.py @@ -0,0 +1,120 @@ +#! /usr/bin/env python +# encoding: utf-8 +# DC 2008 +# Thomas Nagy 2016-2018 (ita) + +import re + +INC_REGEX = r"""(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" +USE_REGEX = r"""(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" +MOD_REGEX = r"""(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)""" +SMD_REGEX = r"""(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)""" + +re_inc = re.compile(INC_REGEX, re.I) +re_use = re.compile(USE_REGEX, re.I) +re_mod = re.compile(MOD_REGEX, re.I) +re_smd = re.compile(SMD_REGEX, re.I) + +class fortran_parser(object): + """ + This parser returns: + + * the nodes corresponding to the module names to produce + * the nodes corresponding to the include files used + * the module names used by the fortran files + """ + def __init__(self, incpaths): + self.seen = [] + """Files already parsed""" + + self.nodes = [] + """List of :py:class:`waflib.Node.Node` representing the dependencies to return""" + + self.names = [] + """List of module names to return""" + + self.incpaths = incpaths + """List of :py:class:`waflib.Node.Node` representing the include paths""" + + def find_deps(self, node): + """ + Parses a Fortran file to obtain the dependencies used/provided + + :param node: fortran file to read + :type node: :py:class:`waflib.Node.Node` + :return: lists representing the includes, the modules used, and the modules created by a fortran file + :rtype: tuple of list of strings + """ + txt = node.read() + incs = [] + uses = [] + mods = [] + for line in txt.splitlines(): + # line by line regexp search? optimize? + m = re_inc.search(line) + if m: + incs.append(m.group(1)) + m = re_use.search(line) + if m: + uses.append(m.group(1)) + m = re_mod.search(line) + if m: + mods.append(m.group(1)) + m = re_smd.search(line) + if m: + uses.append(m.group(1)) + mods.append('{0}:{1}'.format(m.group(1),m.group(2))) + return (incs, uses, mods) + + def start(self, node): + """ + Start parsing. Use the stack ``self.waiting`` to hold nodes to iterate on + + :param node: fortran file + :type node: :py:class:`waflib.Node.Node` + """ + self.waiting = [node] + while self.waiting: + nd = self.waiting.pop(0) + self.iter(nd) + + def iter(self, node): + """ + Processes a single file during dependency parsing. Extracts files used + modules used and modules provided. + """ + incs, uses, mods = self.find_deps(node) + for x in incs: + if x in self.seen: + continue + self.seen.append(x) + self.tryfind_header(x) + + for x in uses: + name = "USE@%s" % x + if not name in self.names: + self.names.append(name) + + for x in mods: + name = "MOD@%s" % x + if not name in self.names: + self.names.append(name) + + def tryfind_header(self, filename): + """ + Adds an include file to the list of nodes to process + + :param filename: file name + :type filename: string + """ + found = None + for n in self.incpaths: + found = n.find_resource(filename) + if found: + self.nodes.append(found) + self.waiting.append(found) + break + if not found: + if not filename in self.names: + self.names.append(filename) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/flex.py b/ldb-2.0.8/third_party/waf/waflib/Tools/flex.py new file mode 100644 index 0000000..2256657 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/flex.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# encoding: utf-8 +# John O'Meara, 2006 +# Thomas Nagy, 2006-2018 (ita) + +""" +The **flex** program is a code generator which creates C or C++ files. +The generated files are compiled into object files. +""" + +import os, re +from waflib import Task, TaskGen +from waflib.Tools import ccroot + +def decide_ext(self, node): + if 'cxx' in self.features: + return ['.lex.cc'] + return ['.lex.c'] + +def flexfun(tsk): + env = tsk.env + bld = tsk.generator.bld + wd = bld.variant_dir + def to_list(xx): + if isinstance(xx, str): + return [xx] + return xx + tsk.last_cmd = lst = [] + lst.extend(to_list(env.FLEX)) + lst.extend(to_list(env.FLEXFLAGS)) + inputs = [a.path_from(tsk.get_cwd()) for a in tsk.inputs] + if env.FLEX_MSYS: + inputs = [x.replace(os.sep, '/') for x in inputs] + lst.extend(inputs) + lst = [x for x in lst if x] + txt = bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) + tsk.outputs[0].write(txt.replace('\r\n', '\n').replace('\r', '\n')) # issue #1207 + +TaskGen.declare_chain( + name = 'flex', + rule = flexfun, # issue #854 + ext_in = '.l', + decider = decide_ext, +) + +# To support the following: +# bld(features='c', flexflags='-P/foo') +Task.classes['flex'].vars = ['FLEXFLAGS', 'FLEX'] +ccroot.USELIB_VARS['c'].add('FLEXFLAGS') +ccroot.USELIB_VARS['cxx'].add('FLEXFLAGS') + +def configure(conf): + """ + Detect the *flex* program + """ + conf.find_program('flex', var='FLEX') + conf.env.FLEXFLAGS = ['-t'] + + if re.search (r"\\msys\\[0-9.]+\\bin\\flex.exe$", conf.env.FLEX[0]): + # this is the flex shipped with MSYS + conf.env.FLEX_MSYS = True + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/g95.py b/ldb-2.0.8/third_party/waf/waflib/Tools/g95.py new file mode 100644 index 0000000..f69ba4f --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/g95.py @@ -0,0 +1,66 @@ +#! /usr/bin/env python +# encoding: utf-8 +# KWS 2010 +# Thomas Nagy 2016-2018 (ita) + +import re +from waflib import Utils +from waflib.Tools import fc, fc_config, fc_scan, ar +from waflib.Configure import conf + +@conf +def find_g95(conf): + fc = conf.find_program('g95', var='FC') + conf.get_g95_version(fc) + conf.env.FC_NAME = 'G95' + +@conf +def g95_flags(conf): + v = conf.env + v.FCFLAGS_fcshlib = ['-fPIC'] + v.FORTRANMODFLAG = ['-fmod=', ''] # template for module path + v.FCFLAGS_DEBUG = ['-Werror'] # why not + +@conf +def g95_modifier_win32(conf): + fc_config.fortran_modifier_win32(conf) + +@conf +def g95_modifier_cygwin(conf): + fc_config.fortran_modifier_cygwin(conf) + +@conf +def g95_modifier_darwin(conf): + fc_config.fortran_modifier_darwin(conf) + +@conf +def g95_modifier_platform(conf): + dest_os = conf.env.DEST_OS or Utils.unversioned_sys_platform() + g95_modifier_func = getattr(conf, 'g95_modifier_' + dest_os, None) + if g95_modifier_func: + g95_modifier_func() + +@conf +def get_g95_version(conf, fc): + """get the compiler version""" + + version_re = re.compile(r"g95\s*(?P\d*)\.(?P\d*)").search + cmd = fc + ['--version'] + out, err = fc_config.getoutput(conf, cmd, stdin=False) + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('cannot determine g95 version') + k = match.groupdict() + conf.env.FC_VERSION = (k['major'], k['minor']) + +def configure(conf): + conf.find_g95() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.g95_flags() + conf.g95_modifier_platform() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/gas.py b/ldb-2.0.8/third_party/waf/waflib/Tools/gas.py new file mode 100644 index 0000000..4a8745a --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/gas.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2008-2018 (ita) + +"Detect as/gas/gcc for compiling assembly files" + +import waflib.Tools.asm # - leave this +from waflib.Tools import ar + +def configure(conf): + """ + Find the programs gas/as/gcc and set the variable *AS* + """ + conf.find_program(['gas', 'gcc'], var='AS') + conf.env.AS_TGT_F = ['-c', '-o'] + conf.env.ASLNK_TGT_F = ['-o'] + conf.find_ar() + conf.load('asm') + conf.env.ASM_NAME = 'gas' diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/gcc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/gcc.py new file mode 100644 index 0000000..acdd473 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/gcc.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) +# Ralf Habacker, 2006 (rh) +# Yinon Ehrlich, 2009 + +""" +gcc/llvm detection. +""" + +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +@conf +def find_gcc(conf): + """ + Find the program gcc, and if present, try to detect its version number + """ + cc = conf.find_program(['gcc', 'cc'], var='CC') + conf.get_cc_version(cc, gcc=True) + conf.env.CC_NAME = 'gcc' + +@conf +def gcc_common_flags(conf): + """ + Common flags for gcc on nearly all platforms + """ + v = conf.env + + v.CC_SRC_F = [] + v.CC_TGT_F = ['-c', '-o'] + + if not v.LINK_CC: + v.LINK_CC = v.CC + + v.CCLNK_SRC_F = [] + v.CCLNK_TGT_F = ['-o'] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + v.RPATH_ST = '-Wl,-rpath,%s' + + v.SONAME_ST = '-Wl,-h,%s' + v.SHLIB_MARKER = '-Wl,-Bdynamic' + v.STLIB_MARKER = '-Wl,-Bstatic' + + v.cprogram_PATTERN = '%s' + + v.CFLAGS_cshlib = ['-fPIC'] + v.LINKFLAGS_cshlib = ['-shared'] + v.cshlib_PATTERN = 'lib%s.so' + + v.LINKFLAGS_cstlib = ['-Wl,-Bstatic'] + v.cstlib_PATTERN = 'lib%s.a' + + v.LINKFLAGS_MACBUNDLE = ['-bundle', '-undefined', 'dynamic_lookup'] + v.CFLAGS_MACBUNDLE = ['-fPIC'] + v.macbundle_PATTERN = '%s.bundle' + +@conf +def gcc_modifier_win32(conf): + """Configuration flags for executing gcc on Windows""" + v = conf.env + v.cprogram_PATTERN = '%s.exe' + + v.cshlib_PATTERN = '%s.dll' + v.implib_PATTERN = '%s.dll.a' + v.IMPLIB_ST = '-Wl,--out-implib,%s' + + v.CFLAGS_cshlib = [] + + # Auto-import is enabled by default even without this option, + # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages + # that the linker emits otherwise. + v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) + +@conf +def gcc_modifier_cygwin(conf): + """Configuration flags for executing gcc on Cygwin""" + gcc_modifier_win32(conf) + v = conf.env + v.cshlib_PATTERN = 'cyg%s.dll' + v.append_value('LINKFLAGS_cshlib', ['-Wl,--enable-auto-image-base']) + v.CFLAGS_cshlib = [] + +@conf +def gcc_modifier_darwin(conf): + """Configuration flags for executing gcc on MacOS""" + v = conf.env + v.CFLAGS_cshlib = ['-fPIC'] + v.LINKFLAGS_cshlib = ['-dynamiclib'] + v.cshlib_PATTERN = 'lib%s.dylib' + v.FRAMEWORKPATH_ST = '-F%s' + v.FRAMEWORK_ST = ['-framework'] + v.ARCH_ST = ['-arch'] + + v.LINKFLAGS_cstlib = [] + + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + v.SONAME_ST = [] + +@conf +def gcc_modifier_aix(conf): + """Configuration flags for executing gcc on AIX""" + v = conf.env + v.LINKFLAGS_cprogram = ['-Wl,-brtl'] + v.LINKFLAGS_cshlib = ['-shared','-Wl,-brtl,-bexpfull'] + v.SHLIB_MARKER = [] + +@conf +def gcc_modifier_hpux(conf): + v = conf.env + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + v.CFLAGS_cshlib = ['-fPIC','-DPIC'] + v.cshlib_PATTERN = 'lib%s.sl' + +@conf +def gcc_modifier_openbsd(conf): + conf.env.SONAME_ST = [] + +@conf +def gcc_modifier_osf1V(conf): + v = conf.env + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + v.SONAME_ST = [] + +@conf +def gcc_modifier_platform(conf): + """Execute platform-specific functions based on *gcc_modifier_+NAME*""" + # * set configurations specific for a platform. + # * the destination platform is detected automatically by looking at the macros the compiler predefines, + # and if it's not recognised, it fallbacks to sys.platform. + gcc_modifier_func = getattr(conf, 'gcc_modifier_' + conf.env.DEST_OS, None) + if gcc_modifier_func: + gcc_modifier_func() + +def configure(conf): + """ + Configuration for gcc + """ + conf.find_gcc() + conf.find_ar() + conf.gcc_common_flags() + conf.gcc_modifier_platform() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + conf.check_gcc_o_space() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/gdc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/gdc.py new file mode 100644 index 0000000..d89a66d --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/gdc.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Carlos Rafael Giani, 2007 (dv) + +from waflib.Tools import ar, d +from waflib.Configure import conf + +@conf +def find_gdc(conf): + """ + Finds the program gdc and set the variable *D* + """ + conf.find_program('gdc', var='D') + + out = conf.cmd_and_log(conf.env.D + ['--version']) + if out.find("gdc") == -1: + conf.fatal("detected compiler is not gdc") + +@conf +def common_flags_gdc(conf): + """ + Sets the flags required by *gdc* + """ + v = conf.env + + v.DFLAGS = [] + + v.D_SRC_F = ['-c'] + v.D_TGT_F = '-o%s' + + v.D_LINKER = v.D + v.DLNK_SRC_F = '' + v.DLNK_TGT_F = '-o%s' + v.DINC_ST = '-I%s' + + v.DSHLIB_MARKER = v.DSTLIB_MARKER = '' + v.DSTLIB_ST = v.DSHLIB_ST = '-l%s' + v.DSTLIBPATH_ST = v.DLIBPATH_ST = '-L%s' + + v.LINKFLAGS_dshlib = ['-shared'] + + v.DHEADER_ext = '.di' + v.DFLAGS_d_with_header = '-fintfc' + v.D_HDR_F = '-fintfc-file=%s' + +def configure(conf): + """ + Configuration for gdc + """ + conf.find_gdc() + conf.load('ar') + conf.load('d') + conf.common_flags_gdc() + conf.d_platform_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/gfortran.py b/ldb-2.0.8/third_party/waf/waflib/Tools/gfortran.py new file mode 100644 index 0000000..1050667 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/gfortran.py @@ -0,0 +1,93 @@ +#! /usr/bin/env python +# encoding: utf-8 +# DC 2008 +# Thomas Nagy 2016-2018 (ita) + +import re +from waflib import Utils +from waflib.Tools import fc, fc_config, fc_scan, ar +from waflib.Configure import conf + +@conf +def find_gfortran(conf): + """Find the gfortran program (will look in the environment variable 'FC')""" + fc = conf.find_program(['gfortran','g77'], var='FC') + # (fallback to g77 for systems, where no gfortran is available) + conf.get_gfortran_version(fc) + conf.env.FC_NAME = 'GFORTRAN' + +@conf +def gfortran_flags(conf): + v = conf.env + v.FCFLAGS_fcshlib = ['-fPIC'] + v.FORTRANMODFLAG = ['-J', ''] # template for module path + v.FCFLAGS_DEBUG = ['-Werror'] # why not + +@conf +def gfortran_modifier_win32(conf): + fc_config.fortran_modifier_win32(conf) + +@conf +def gfortran_modifier_cygwin(conf): + fc_config.fortran_modifier_cygwin(conf) + +@conf +def gfortran_modifier_darwin(conf): + fc_config.fortran_modifier_darwin(conf) + +@conf +def gfortran_modifier_platform(conf): + dest_os = conf.env.DEST_OS or Utils.unversioned_sys_platform() + gfortran_modifier_func = getattr(conf, 'gfortran_modifier_' + dest_os, None) + if gfortran_modifier_func: + gfortran_modifier_func() + +@conf +def get_gfortran_version(conf, fc): + """Get the compiler version""" + + # ensure this is actually gfortran, not an imposter. + version_re = re.compile(r"GNU\s*Fortran", re.I).search + cmd = fc + ['--version'] + out, err = fc_config.getoutput(conf, cmd, stdin=False) + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('Could not determine the compiler type') + + # --- now get more detailed info -- see c_config.get_cc_version + cmd = fc + ['-dM', '-E', '-'] + out, err = fc_config.getoutput(conf, cmd, stdin=True) + + if out.find('__GNUC__') < 0: + conf.fatal('Could not determine the compiler type') + + k = {} + out = out.splitlines() + import shlex + + for line in out: + lst = shlex.split(line) + if len(lst)>2: + key = lst[1] + val = lst[2] + k[key] = val + + def isD(var): + return var in k + + def isT(var): + return var in k and k[var] != '0' + + conf.env.FC_VERSION = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) + +def configure(conf): + conf.find_gfortran() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.gfortran_flags() + conf.gfortran_modifier_platform() + conf.check_gfortran_o_space() diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/glib2.py b/ldb-2.0.8/third_party/waf/waflib/Tools/glib2.py new file mode 100644 index 0000000..949fe37 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/glib2.py @@ -0,0 +1,489 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +""" +Support for GLib2 tools: + +* marshal +* enums +* gsettings +* gresource +""" + +import os +import functools +from waflib import Context, Task, Utils, Options, Errors, Logs +from waflib.TaskGen import taskgen_method, before_method, feature, extension +from waflib.Configure import conf + +################## marshal files + +@taskgen_method +def add_marshal_file(self, filename, prefix): + """ + Adds a file to the list of marshal files to process. Store them in the attribute *marshal_list*. + + :param filename: xml file to compile + :type filename: string + :param prefix: marshal prefix (--prefix=prefix) + :type prefix: string + """ + if not hasattr(self, 'marshal_list'): + self.marshal_list = [] + self.meths.append('process_marshal') + self.marshal_list.append((filename, prefix)) + +@before_method('process_source') +def process_marshal(self): + """ + Processes the marshal files stored in the attribute *marshal_list* to create :py:class:`waflib.Tools.glib2.glib_genmarshal` instances. + Adds the c file created to the list of source to process. + """ + for f, prefix in getattr(self, 'marshal_list', []): + node = self.path.find_resource(f) + + if not node: + raise Errors.WafError('file not found %r' % f) + + h_node = node.change_ext('.h') + c_node = node.change_ext('.c') + + task = self.create_task('glib_genmarshal', node, [h_node, c_node]) + task.env.GLIB_GENMARSHAL_PREFIX = prefix + self.source = self.to_nodes(getattr(self, 'source', [])) + self.source.append(c_node) + +class glib_genmarshal(Task.Task): + vars = ['GLIB_GENMARSHAL_PREFIX', 'GLIB_GENMARSHAL'] + color = 'BLUE' + ext_out = ['.h'] + def run(self): + bld = self.generator.bld + + get = self.env.get_flat + cmd1 = "%s %s --prefix=%s --header > %s" % ( + get('GLIB_GENMARSHAL'), + self.inputs[0].srcpath(), + get('GLIB_GENMARSHAL_PREFIX'), + self.outputs[0].abspath() + ) + + ret = bld.exec_command(cmd1) + if ret: + return ret + + #print self.outputs[1].abspath() + c = '''#include "%s"\n''' % self.outputs[0].name + self.outputs[1].write(c) + + cmd2 = "%s %s --prefix=%s --body >> %s" % ( + get('GLIB_GENMARSHAL'), + self.inputs[0].srcpath(), + get('GLIB_GENMARSHAL_PREFIX'), + self.outputs[1].abspath() + ) + return bld.exec_command(cmd2) + +########################## glib-mkenums + +@taskgen_method +def add_enums_from_template(self, source='', target='', template='', comments=''): + """ + Adds a file to the list of enum files to process. Stores them in the attribute *enums_list*. + + :param source: enum file to process + :type source: string + :param target: target file + :type target: string + :param template: template file + :type template: string + :param comments: comments + :type comments: string + """ + if not hasattr(self, 'enums_list'): + self.enums_list = [] + self.meths.append('process_enums') + self.enums_list.append({'source': source, + 'target': target, + 'template': template, + 'file-head': '', + 'file-prod': '', + 'file-tail': '', + 'enum-prod': '', + 'value-head': '', + 'value-prod': '', + 'value-tail': '', + 'comments': comments}) + +@taskgen_method +def add_enums(self, source='', target='', + file_head='', file_prod='', file_tail='', enum_prod='', + value_head='', value_prod='', value_tail='', comments=''): + """ + Adds a file to the list of enum files to process. Stores them in the attribute *enums_list*. + + :param source: enum file to process + :type source: string + :param target: target file + :type target: string + :param file_head: unused + :param file_prod: unused + :param file_tail: unused + :param enum_prod: unused + :param value_head: unused + :param value_prod: unused + :param value_tail: unused + :param comments: comments + :type comments: string + """ + if not hasattr(self, 'enums_list'): + self.enums_list = [] + self.meths.append('process_enums') + self.enums_list.append({'source': source, + 'template': '', + 'target': target, + 'file-head': file_head, + 'file-prod': file_prod, + 'file-tail': file_tail, + 'enum-prod': enum_prod, + 'value-head': value_head, + 'value-prod': value_prod, + 'value-tail': value_tail, + 'comments': comments}) + +@before_method('process_source') +def process_enums(self): + """ + Processes the enum files stored in the attribute *enum_list* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. + """ + for enum in getattr(self, 'enums_list', []): + task = self.create_task('glib_mkenums') + env = task.env + + inputs = [] + + # process the source + source_list = self.to_list(enum['source']) + if not source_list: + raise Errors.WafError('missing source ' + str(enum)) + source_list = [self.path.find_resource(k) for k in source_list] + inputs += source_list + env.GLIB_MKENUMS_SOURCE = [k.abspath() for k in source_list] + + # find the target + if not enum['target']: + raise Errors.WafError('missing target ' + str(enum)) + tgt_node = self.path.find_or_declare(enum['target']) + if tgt_node.name.endswith('.c'): + self.source.append(tgt_node) + env.GLIB_MKENUMS_TARGET = tgt_node.abspath() + + + options = [] + + if enum['template']: # template, if provided + template_node = self.path.find_resource(enum['template']) + options.append('--template %s' % (template_node.abspath())) + inputs.append(template_node) + params = {'file-head' : '--fhead', + 'file-prod' : '--fprod', + 'file-tail' : '--ftail', + 'enum-prod' : '--eprod', + 'value-head' : '--vhead', + 'value-prod' : '--vprod', + 'value-tail' : '--vtail', + 'comments': '--comments'} + for param, option in params.items(): + if enum[param]: + options.append('%s %r' % (option, enum[param])) + + env.GLIB_MKENUMS_OPTIONS = ' '.join(options) + + # update the task instance + task.set_inputs(inputs) + task.set_outputs(tgt_node) + +class glib_mkenums(Task.Task): + """ + Processes enum files + """ + run_str = '${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}' + color = 'PINK' + ext_out = ['.h'] + +######################################### gsettings + +@taskgen_method +def add_settings_schemas(self, filename_list): + """ + Adds settings files to process to *settings_schema_files* + + :param filename_list: files + :type filename_list: list of string + """ + if not hasattr(self, 'settings_schema_files'): + self.settings_schema_files = [] + + if not isinstance(filename_list, list): + filename_list = [filename_list] + + self.settings_schema_files.extend(filename_list) + +@taskgen_method +def add_settings_enums(self, namespace, filename_list): + """ + Called only once by task generator to set the enums namespace. + + :param namespace: namespace + :type namespace: string + :param filename_list: enum files to process + :type filename_list: file list + """ + if hasattr(self, 'settings_enum_namespace'): + raise Errors.WafError("Tried to add gsettings enums to %r more than once" % self.name) + self.settings_enum_namespace = namespace + + if not isinstance(filename_list, list): + filename_list = [filename_list] + self.settings_enum_files = filename_list + +@feature('glib2') +def process_settings(self): + """ + Processes the schema files in *settings_schema_files* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. The + same files are validated through :py:class:`waflib.Tools.glib2.glib_validate_schema` tasks. + + """ + enums_tgt_node = [] + install_files = [] + + settings_schema_files = getattr(self, 'settings_schema_files', []) + if settings_schema_files and not self.env.GLIB_COMPILE_SCHEMAS: + raise Errors.WafError ("Unable to process GSettings schemas - glib-compile-schemas was not found during configure") + + # 1. process gsettings_enum_files (generate .enums.xml) + # + if hasattr(self, 'settings_enum_files'): + enums_task = self.create_task('glib_mkenums') + + source_list = self.settings_enum_files + source_list = [self.path.find_resource(k) for k in source_list] + enums_task.set_inputs(source_list) + enums_task.env.GLIB_MKENUMS_SOURCE = [k.abspath() for k in source_list] + + target = self.settings_enum_namespace + '.enums.xml' + tgt_node = self.path.find_or_declare(target) + enums_task.set_outputs(tgt_node) + enums_task.env.GLIB_MKENUMS_TARGET = tgt_node.abspath() + enums_tgt_node = [tgt_node] + + install_files.append(tgt_node) + + options = '--comments "" --fhead "" --vhead " <@type@ id=\\"%s.@EnumName@\\">" --vprod " " --vtail " " --ftail "" ' % (self.settings_enum_namespace) + enums_task.env.GLIB_MKENUMS_OPTIONS = options + + # 2. process gsettings_schema_files (validate .gschema.xml files) + # + for schema in settings_schema_files: + schema_task = self.create_task ('glib_validate_schema') + + schema_node = self.path.find_resource(schema) + if not schema_node: + raise Errors.WafError("Cannot find the schema file %r" % schema) + install_files.append(schema_node) + source_list = enums_tgt_node + [schema_node] + + schema_task.set_inputs (source_list) + schema_task.env.GLIB_COMPILE_SCHEMAS_OPTIONS = [("--schema-file=" + k.abspath()) for k in source_list] + + target_node = schema_node.change_ext('.xml.valid') + schema_task.set_outputs (target_node) + schema_task.env.GLIB_VALIDATE_SCHEMA_OUTPUT = target_node.abspath() + + # 3. schemas install task + def compile_schemas_callback(bld): + if not bld.is_install: + return + compile_schemas = Utils.to_list(bld.env.GLIB_COMPILE_SCHEMAS) + destdir = Options.options.destdir + paths = bld._compile_schemas_registered + if destdir: + paths = (os.path.join(destdir, path.lstrip(os.sep)) for path in paths) + for path in paths: + Logs.pprint('YELLOW', 'Updating GSettings schema cache %r' % path) + if self.bld.exec_command(compile_schemas + [path]): + Logs.warn('Could not update GSettings schema cache %r' % path) + + if self.bld.is_install: + schemadir = self.env.GSETTINGSSCHEMADIR + if not schemadir: + raise Errors.WafError ('GSETTINGSSCHEMADIR not defined (should have been set up automatically during configure)') + + if install_files: + self.add_install_files(install_to=schemadir, install_from=install_files) + registered_schemas = getattr(self.bld, '_compile_schemas_registered', None) + if not registered_schemas: + registered_schemas = self.bld._compile_schemas_registered = set() + self.bld.add_post_fun(compile_schemas_callback) + registered_schemas.add(schemadir) + +class glib_validate_schema(Task.Task): + """ + Validates schema files + """ + run_str = 'rm -f ${GLIB_VALIDATE_SCHEMA_OUTPUT} && ${GLIB_COMPILE_SCHEMAS} --dry-run ${GLIB_COMPILE_SCHEMAS_OPTIONS} && touch ${GLIB_VALIDATE_SCHEMA_OUTPUT}' + color = 'PINK' + +################## gresource + +@extension('.gresource.xml') +def process_gresource_source(self, node): + """ + Creates tasks that turn ``.gresource.xml`` files to C code + """ + if not self.env.GLIB_COMPILE_RESOURCES: + raise Errors.WafError ("Unable to process GResource file - glib-compile-resources was not found during configure") + + if 'gresource' in self.features: + return + + h_node = node.change_ext('_xml.h') + c_node = node.change_ext('_xml.c') + self.create_task('glib_gresource_source', node, [h_node, c_node]) + self.source.append(c_node) + +@feature('gresource') +def process_gresource_bundle(self): + """ + Creates tasks to turn ``.gresource`` files from ``.gresource.xml`` files:: + + def build(bld): + bld( + features='gresource', + source=['resources1.gresource.xml', 'resources2.gresource.xml'], + install_path='${LIBDIR}/${PACKAGE}' + ) + + :param source: XML files to process + :type source: list of string + :param install_path: installation path + :type install_path: string + """ + for i in self.to_list(self.source): + node = self.path.find_resource(i) + + task = self.create_task('glib_gresource_bundle', node, node.change_ext('')) + inst_to = getattr(self, 'install_path', None) + if inst_to: + self.add_install_files(install_to=inst_to, install_from=task.outputs) + +class glib_gresource_base(Task.Task): + """ + Base class for gresource based tasks + """ + color = 'BLUE' + base_cmd = '${GLIB_COMPILE_RESOURCES} --sourcedir=${SRC[0].parent.srcpath()} --sourcedir=${SRC[0].bld_dir()}' + + def scan(self): + """ + Scans gresource dependencies through ``glib-compile-resources --generate-dependencies command`` + """ + bld = self.generator.bld + kw = {} + kw['cwd'] = self.get_cwd() + kw['quiet'] = Context.BOTH + + cmd = Utils.subst_vars('${GLIB_COMPILE_RESOURCES} --sourcedir=%s --sourcedir=%s --generate-dependencies %s' % ( + self.inputs[0].parent.srcpath(), + self.inputs[0].bld_dir(), + self.inputs[0].bldpath() + ), self.env) + + output = bld.cmd_and_log(cmd, **kw) + + nodes = [] + names = [] + for dep in output.splitlines(): + if dep: + node = bld.bldnode.find_node(dep) + if node: + nodes.append(node) + else: + names.append(dep) + + return (nodes, names) + +class glib_gresource_source(glib_gresource_base): + """ + Task to generate C source code (.h and .c files) from a gresource.xml file + """ + vars = ['GLIB_COMPILE_RESOURCES'] + fun_h = Task.compile_fun_shell(glib_gresource_base.base_cmd + ' --target=${TGT[0].abspath()} --generate-header ${SRC}') + fun_c = Task.compile_fun_shell(glib_gresource_base.base_cmd + ' --target=${TGT[1].abspath()} --generate-source ${SRC}') + ext_out = ['.h'] + + def run(self): + return self.fun_h[0](self) or self.fun_c[0](self) + +class glib_gresource_bundle(glib_gresource_base): + """ + Task to generate a .gresource binary file from a gresource.xml file + """ + run_str = glib_gresource_base.base_cmd + ' --target=${TGT} ${SRC}' + shell = True # temporary workaround for #795 + +@conf +def find_glib_genmarshal(conf): + conf.find_program('glib-genmarshal', var='GLIB_GENMARSHAL') + +@conf +def find_glib_mkenums(conf): + if not conf.env.PERL: + conf.find_program('perl', var='PERL') + conf.find_program('glib-mkenums', interpreter='PERL', var='GLIB_MKENUMS') + +@conf +def find_glib_compile_schemas(conf): + # when cross-compiling, gsettings.m4 locates the program with the following: + # pkg-config --variable glib_compile_schemas gio-2.0 + conf.find_program('glib-compile-schemas', var='GLIB_COMPILE_SCHEMAS') + + def getstr(varname): + return getattr(Options.options, varname, getattr(conf.env,varname, '')) + + gsettingsschemadir = getstr('GSETTINGSSCHEMADIR') + if not gsettingsschemadir: + datadir = getstr('DATADIR') + if not datadir: + prefix = conf.env.PREFIX + datadir = os.path.join(prefix, 'share') + gsettingsschemadir = os.path.join(datadir, 'glib-2.0', 'schemas') + + conf.env.GSETTINGSSCHEMADIR = gsettingsschemadir + +@conf +def find_glib_compile_resources(conf): + conf.find_program('glib-compile-resources', var='GLIB_COMPILE_RESOURCES') + +def configure(conf): + """ + Finds the following programs: + + * *glib-genmarshal* and set *GLIB_GENMARSHAL* + * *glib-mkenums* and set *GLIB_MKENUMS* + * *glib-compile-schemas* and set *GLIB_COMPILE_SCHEMAS* (not mandatory) + * *glib-compile-resources* and set *GLIB_COMPILE_RESOURCES* (not mandatory) + """ + conf.find_glib_genmarshal() + conf.find_glib_mkenums() + conf.find_glib_compile_schemas(mandatory=False) + conf.find_glib_compile_resources(mandatory=False) + +def options(opt): + """ + Adds the ``--gsettingsschemadir`` command-line option + """ + gr = opt.add_option_group('Installation directories') + gr.add_option('--gsettingsschemadir', help='GSettings schema location [DATADIR/glib-2.0/schemas]', default='', dest='GSETTINGSSCHEMADIR') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/gnu_dirs.py b/ldb-2.0.8/third_party/waf/waflib/Tools/gnu_dirs.py new file mode 100644 index 0000000..2847071 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/gnu_dirs.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Ali Sabil, 2007 + +""" +Sets various standard variables such as INCLUDEDIR. SBINDIR and others. To use this module just call:: + + opt.load('gnu_dirs') + +and:: + + conf.load('gnu_dirs') + +Add options for the standard GNU directories, this tool will add the options +found in autotools, and will update the environment with the following +installation variables: + +============== ========================================= ======================= +Variable Description Default Value +============== ========================================= ======================= +PREFIX installation prefix /usr/local +EXEC_PREFIX installation prefix for binaries PREFIX +BINDIR user commands EXEC_PREFIX/bin +SBINDIR system binaries EXEC_PREFIX/sbin +LIBEXECDIR program-specific binaries EXEC_PREFIX/libexec +SYSCONFDIR host-specific configuration PREFIX/etc +SHAREDSTATEDIR architecture-independent variable data PREFIX/com +LOCALSTATEDIR variable data PREFIX/var +LIBDIR object code libraries EXEC_PREFIX/lib +INCLUDEDIR header files PREFIX/include +OLDINCLUDEDIR header files for non-GCC compilers /usr/include +DATAROOTDIR architecture-independent data root PREFIX/share +DATADIR architecture-independent data DATAROOTDIR +INFODIR GNU "info" documentation DATAROOTDIR/info +LOCALEDIR locale-dependent data DATAROOTDIR/locale +MANDIR manual pages DATAROOTDIR/man +DOCDIR documentation root DATAROOTDIR/doc/APPNAME +HTMLDIR HTML documentation DOCDIR +DVIDIR DVI documentation DOCDIR +PDFDIR PDF documentation DOCDIR +PSDIR PostScript documentation DOCDIR +============== ========================================= ======================= +""" + +import os, re +from waflib import Utils, Options, Context + +gnuopts = ''' +bindir, user commands, ${EXEC_PREFIX}/bin +sbindir, system binaries, ${EXEC_PREFIX}/sbin +libexecdir, program-specific binaries, ${EXEC_PREFIX}/libexec +sysconfdir, host-specific configuration, ${PREFIX}/etc +sharedstatedir, architecture-independent variable data, ${PREFIX}/com +localstatedir, variable data, ${PREFIX}/var +libdir, object code libraries, ${EXEC_PREFIX}/lib%s +includedir, header files, ${PREFIX}/include +oldincludedir, header files for non-GCC compilers, /usr/include +datarootdir, architecture-independent data root, ${PREFIX}/share +datadir, architecture-independent data, ${DATAROOTDIR} +infodir, GNU "info" documentation, ${DATAROOTDIR}/info +localedir, locale-dependent data, ${DATAROOTDIR}/locale +mandir, manual pages, ${DATAROOTDIR}/man +docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} +htmldir, HTML documentation, ${DOCDIR} +dvidir, DVI documentation, ${DOCDIR} +pdfdir, PDF documentation, ${DOCDIR} +psdir, PostScript documentation, ${DOCDIR} +''' % Utils.lib64() + +_options = [x.split(', ') for x in gnuopts.splitlines() if x] + +def configure(conf): + """ + Reads the command-line options to set lots of variables in *conf.env*. The variables + BINDIR and LIBDIR will be overwritten. + """ + def get_param(varname, default): + return getattr(Options.options, varname, '') or default + + env = conf.env + env.LIBDIR = env.BINDIR = [] + env.EXEC_PREFIX = get_param('EXEC_PREFIX', env.PREFIX) + env.PACKAGE = getattr(Context.g_module, 'APPNAME', None) or env.PACKAGE + + complete = False + iter = 0 + while not complete and iter < len(_options) + 1: + iter += 1 + complete = True + for name, help, default in _options: + name = name.upper() + if not env[name]: + try: + env[name] = Utils.subst_vars(get_param(name, default).replace('/', os.sep), env) + except TypeError: + complete = False + + if not complete: + lst = [x for x, _, _ in _options if not env[x.upper()]] + raise conf.errors.WafError('Variable substitution failure %r' % lst) + +def options(opt): + """ + Adds lots of command-line options, for example:: + + --exec-prefix: EXEC_PREFIX + """ + inst_dir = opt.add_option_group('Installation prefix', +'By default, "waf install" will put the files in\ + "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\ + than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"') + + for k in ('--prefix', '--destdir'): + option = opt.parser.get_option(k) + if option: + opt.parser.remove_option(k) + inst_dir.add_option(option) + + inst_dir.add_option('--exec-prefix', + help = 'installation prefix for binaries [PREFIX]', + default = '', + dest = 'EXEC_PREFIX') + + dirs_options = opt.add_option_group('Installation directories') + + for name, help, default in _options: + option_name = '--' + name + str_default = default + str_help = '%s [%s]' % (help, re.sub(r'\$\{([^}]+)\}', r'\1', str_default)) + dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/gxx.py b/ldb-2.0.8/third_party/waf/waflib/Tools/gxx.py new file mode 100644 index 0000000..22c5d26 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/gxx.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) +# Ralf Habacker, 2006 (rh) +# Yinon Ehrlich, 2009 + +""" +g++/llvm detection. +""" + +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +@conf +def find_gxx(conf): + """ + Finds the program g++, and if present, try to detect its version number + """ + cxx = conf.find_program(['g++', 'c++'], var='CXX') + conf.get_cc_version(cxx, gcc=True) + conf.env.CXX_NAME = 'gcc' + +@conf +def gxx_common_flags(conf): + """ + Common flags for g++ on nearly all platforms + """ + v = conf.env + + v.CXX_SRC_F = [] + v.CXX_TGT_F = ['-c', '-o'] + + if not v.LINK_CXX: + v.LINK_CXX = v.CXX + + v.CXXLNK_SRC_F = [] + v.CXXLNK_TGT_F = ['-o'] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + v.RPATH_ST = '-Wl,-rpath,%s' + + v.SONAME_ST = '-Wl,-h,%s' + v.SHLIB_MARKER = '-Wl,-Bdynamic' + v.STLIB_MARKER = '-Wl,-Bstatic' + + v.cxxprogram_PATTERN = '%s' + + v.CXXFLAGS_cxxshlib = ['-fPIC'] + v.LINKFLAGS_cxxshlib = ['-shared'] + v.cxxshlib_PATTERN = 'lib%s.so' + + v.LINKFLAGS_cxxstlib = ['-Wl,-Bstatic'] + v.cxxstlib_PATTERN = 'lib%s.a' + + v.LINKFLAGS_MACBUNDLE = ['-bundle', '-undefined', 'dynamic_lookup'] + v.CXXFLAGS_MACBUNDLE = ['-fPIC'] + v.macbundle_PATTERN = '%s.bundle' + +@conf +def gxx_modifier_win32(conf): + """Configuration flags for executing gcc on Windows""" + v = conf.env + v.cxxprogram_PATTERN = '%s.exe' + + v.cxxshlib_PATTERN = '%s.dll' + v.implib_PATTERN = '%s.dll.a' + v.IMPLIB_ST = '-Wl,--out-implib,%s' + + v.CXXFLAGS_cxxshlib = [] + + # Auto-import is enabled by default even without this option, + # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages + # that the linker emits otherwise. + v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) + +@conf +def gxx_modifier_cygwin(conf): + """Configuration flags for executing g++ on Cygwin""" + gxx_modifier_win32(conf) + v = conf.env + v.cxxshlib_PATTERN = 'cyg%s.dll' + v.append_value('LINKFLAGS_cxxshlib', ['-Wl,--enable-auto-image-base']) + v.CXXFLAGS_cxxshlib = [] + +@conf +def gxx_modifier_darwin(conf): + """Configuration flags for executing g++ on MacOS""" + v = conf.env + v.CXXFLAGS_cxxshlib = ['-fPIC'] + v.LINKFLAGS_cxxshlib = ['-dynamiclib'] + v.cxxshlib_PATTERN = 'lib%s.dylib' + v.FRAMEWORKPATH_ST = '-F%s' + v.FRAMEWORK_ST = ['-framework'] + v.ARCH_ST = ['-arch'] + + v.LINKFLAGS_cxxstlib = [] + + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + v.SONAME_ST = [] + +@conf +def gxx_modifier_aix(conf): + """Configuration flags for executing g++ on AIX""" + v = conf.env + v.LINKFLAGS_cxxprogram= ['-Wl,-brtl'] + + v.LINKFLAGS_cxxshlib = ['-shared', '-Wl,-brtl,-bexpfull'] + v.SHLIB_MARKER = [] + +@conf +def gxx_modifier_hpux(conf): + v = conf.env + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + v.CFLAGS_cxxshlib = ['-fPIC','-DPIC'] + v.cxxshlib_PATTERN = 'lib%s.sl' + +@conf +def gxx_modifier_openbsd(conf): + conf.env.SONAME_ST = [] + +@conf +def gcc_modifier_osf1V(conf): + v = conf.env + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + v.SONAME_ST = [] + +@conf +def gxx_modifier_platform(conf): + """Execute platform-specific functions based on *gxx_modifier_+NAME*""" + # * set configurations specific for a platform. + # * the destination platform is detected automatically by looking at the macros the compiler predefines, + # and if it's not recognised, it fallbacks to sys.platform. + gxx_modifier_func = getattr(conf, 'gxx_modifier_' + conf.env.DEST_OS, None) + if gxx_modifier_func: + gxx_modifier_func() + +def configure(conf): + """ + Configuration for g++ + """ + conf.find_gxx() + conf.find_ar() + conf.gxx_common_flags() + conf.gxx_modifier_platform() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() + conf.check_gcc_o_space('cxx') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/icc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/icc.py new file mode 100644 index 0000000..b6492c8 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/icc.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Stian Selnes 2008 +# Thomas Nagy 2009-2018 (ita) + +""" +Detects the Intel C compiler +""" + +import sys +from waflib.Tools import ccroot, ar, gcc +from waflib.Configure import conf + +@conf +def find_icc(conf): + """ + Finds the program icc and execute it to ensure it really is icc + """ + cc = conf.find_program(['icc', 'ICL'], var='CC') + conf.get_cc_version(cc, icc=True) + conf.env.CC_NAME = 'icc' + +def configure(conf): + conf.find_icc() + conf.find_ar() + conf.gcc_common_flags() + conf.gcc_modifier_platform() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/icpc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/icpc.py new file mode 100644 index 0000000..8a6cc6c --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/icpc.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy 2009-2018 (ita) + +""" +Detects the Intel C++ compiler +""" + +import sys +from waflib.Tools import ccroot, ar, gxx +from waflib.Configure import conf + +@conf +def find_icpc(conf): + """ + Finds the program icpc, and execute it to ensure it really is icpc + """ + cxx = conf.find_program('icpc', var='CXX') + conf.get_cc_version(cxx, icc=True) + conf.env.CXX_NAME = 'icc' + +def configure(conf): + conf.find_icpc() + conf.find_ar() + conf.gxx_common_flags() + conf.gxx_modifier_platform() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/ifort.py b/ldb-2.0.8/third_party/waf/waflib/Tools/ifort.py new file mode 100644 index 0000000..17d3052 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/ifort.py @@ -0,0 +1,413 @@ +#! /usr/bin/env python +# encoding: utf-8 +# DC 2008 +# Thomas Nagy 2016-2018 (ita) + +import os, re, traceback +from waflib import Utils, Logs, Errors +from waflib.Tools import fc, fc_config, fc_scan, ar, ccroot +from waflib.Configure import conf +from waflib.TaskGen import after_method, feature + +@conf +def find_ifort(conf): + fc = conf.find_program('ifort', var='FC') + conf.get_ifort_version(fc) + conf.env.FC_NAME = 'IFORT' + +@conf +def ifort_modifier_win32(self): + v = self.env + v.IFORT_WIN32 = True + v.FCSTLIB_MARKER = '' + v.FCSHLIB_MARKER = '' + + v.FCLIB_ST = v.FCSTLIB_ST = '%s.lib' + v.FCLIBPATH_ST = v.STLIBPATH_ST = '/LIBPATH:%s' + v.FCINCPATH_ST = '/I%s' + v.FCDEFINES_ST = '/D%s' + + v.fcprogram_PATTERN = v.fcprogram_test_PATTERN = '%s.exe' + v.fcshlib_PATTERN = '%s.dll' + v.fcstlib_PATTERN = v.implib_PATTERN = '%s.lib' + + v.FCLNK_TGT_F = '/out:' + v.FC_TGT_F = ['/c', '/o', ''] + v.FCFLAGS_fcshlib = '' + v.LINKFLAGS_fcshlib = '/DLL' + v.AR_TGT_F = '/out:' + v.IMPLIB_ST = '/IMPLIB:%s' + + v.append_value('LINKFLAGS', '/subsystem:console') + if v.IFORT_MANIFEST: + v.append_value('LINKFLAGS', ['/MANIFEST']) + +@conf +def ifort_modifier_darwin(conf): + fc_config.fortran_modifier_darwin(conf) + +@conf +def ifort_modifier_platform(conf): + dest_os = conf.env.DEST_OS or Utils.unversioned_sys_platform() + ifort_modifier_func = getattr(conf, 'ifort_modifier_' + dest_os, None) + if ifort_modifier_func: + ifort_modifier_func() + +@conf +def get_ifort_version(conf, fc): + """ + Detects the compiler version and sets ``conf.env.FC_VERSION`` + """ + version_re = re.compile(r"\bIntel\b.*\bVersion\s*(?P\d*)\.(?P\d*)",re.I).search + if Utils.is_win32: + cmd = fc + else: + cmd = fc + ['-logo'] + + out, err = fc_config.getoutput(conf, cmd, stdin=False) + match = version_re(out) or version_re(err) + if not match: + conf.fatal('cannot determine ifort version.') + k = match.groupdict() + conf.env.FC_VERSION = (k['major'], k['minor']) + +def configure(conf): + """ + Detects the Intel Fortran compilers + """ + if Utils.is_win32: + compiler, version, path, includes, libdirs, arch = conf.detect_ifort() + v = conf.env + v.DEST_CPU = arch + v.PATH = path + v.INCLUDES = includes + v.LIBPATH = libdirs + v.MSVC_COMPILER = compiler + try: + v.MSVC_VERSION = float(version) + except ValueError: + v.MSVC_VERSION = float(version[:-3]) + + conf.find_ifort_win32() + conf.ifort_modifier_win32() + else: + conf.find_ifort() + conf.find_program('xiar', var='AR') + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.ifort_modifier_platform() + + +all_ifort_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] +"""List of icl platforms""" + +@conf +def gather_ifort_versions(conf, versions): + """ + List compiler versions by looking up registry keys + """ + version_pattern = re.compile(r'^...?.?\....?.?') + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\Fortran') + except OSError: + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\Fortran') + except OSError: + return + index = 0 + while 1: + try: + version = Utils.winreg.EnumKey(all_versions, index) + except OSError: + break + index += 1 + if not version_pattern.match(version): + continue + targets = {} + for target,arch in all_ifort_platforms: + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target + try: + Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) + icl_version=Utils.winreg.OpenKey(all_versions,version) + path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') + except OSError: + pass + else: + batch_file=os.path.join(path,'bin','ifortvars.bat') + if os.path.isfile(batch_file): + targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) + + for target,arch in all_ifort_platforms: + try: + icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) + path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') + except OSError: + continue + else: + batch_file=os.path.join(path,'bin','ifortvars.bat') + if os.path.isfile(batch_file): + targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) + major = version[0:2] + versions['intel ' + major] = targets + +@conf +def setup_ifort(conf, versiondict): + """ + Checks installed compilers and targets and returns the first combination from the user's + options, env, or the global supported lists that checks. + + :param versiondict: dict(platform -> dict(architecture -> configuration)) + :type versiondict: dict(string -> dict(string -> target_compiler) + :return: the compiler, revision, path, include dirs, library paths and target architecture + :rtype: tuple of strings + """ + platforms = Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_ifort_platforms] + desired_versions = conf.env.MSVC_VERSIONS or list(reversed(list(versiondict.keys()))) + for version in desired_versions: + try: + targets = versiondict[version] + except KeyError: + continue + for arch in platforms: + try: + cfg = targets[arch] + except KeyError: + continue + cfg.evaluate() + if cfg.is_valid: + compiler,revision = version.rsplit(' ', 1) + return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu + conf.fatal('ifort: Impossible to find a valid architecture for building %r - %r' % (desired_versions, list(versiondict.keys()))) + +@conf +def get_ifort_version_win32(conf, compiler, version, target, vcvars): + # FIXME hack + try: + conf.msvc_cnt += 1 + except AttributeError: + conf.msvc_cnt = 1 + batfile = conf.bldnode.make_node('waf-print-msvc-%d.bat' % conf.msvc_cnt) + batfile.write("""@echo off +set INCLUDE= +set LIB= +call "%s" %s +echo PATH=%%PATH%% +echo INCLUDE=%%INCLUDE%% +echo LIB=%%LIB%%;%%LIBPATH%% +""" % (vcvars,target)) + sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()]) + batfile.delete() + lines = sout.splitlines() + + if not lines[0]: + lines.pop(0) + + MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None + for line in lines: + if line.startswith('PATH='): + path = line[5:] + MSVC_PATH = path.split(';') + elif line.startswith('INCLUDE='): + MSVC_INCDIR = [i for i in line[8:].split(';') if i] + elif line.startswith('LIB='): + MSVC_LIBDIR = [i for i in line[4:].split(';') if i] + if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR): + conf.fatal('ifort: Could not find a valid architecture for building (get_ifort_version_win32)') + + # Check if the compiler is usable at all. + # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run. + env = dict(os.environ) + env.update(PATH = path) + compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) + fc = conf.find_program(compiler_name, path_list=MSVC_PATH) + + # delete CL if exists. because it could contain parameters which can change cl's behaviour rather catastrophically. + if 'CL' in env: + del(env['CL']) + + try: + conf.cmd_and_log(fc + ['/help'], env=env) + except UnicodeError: + st = traceback.format_exc() + if conf.logger: + conf.logger.error(st) + conf.fatal('ifort: Unicode error - check the code page?') + except Exception as e: + Logs.debug('ifort: get_ifort_version: %r %r %r -> failure %s', compiler, version, target, str(e)) + conf.fatal('ifort: cannot run the compiler in get_ifort_version (run with -v to display errors)') + else: + Logs.debug('ifort: get_ifort_version: %r %r %r -> OK', compiler, version, target) + finally: + conf.env[compiler_name] = '' + + return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) + +class target_compiler(object): + """ + Wraps a compiler configuration; call evaluate() to determine + whether the configuration is usable. + """ + def __init__(self, ctx, compiler, cpu, version, bat_target, bat, callback=None): + """ + :param ctx: configuration context to use to eventually get the version environment + :param compiler: compiler name + :param cpu: target cpu + :param version: compiler version number + :param bat_target: ? + :param bat: path to the batch file to run + :param callback: optional function to take the realized environment variables tup and map it (e.g. to combine other constant paths) + """ + self.conf = ctx + self.name = None + self.is_valid = False + self.is_done = False + + self.compiler = compiler + self.cpu = cpu + self.version = version + self.bat_target = bat_target + self.bat = bat + self.callback = callback + + def evaluate(self): + if self.is_done: + return + self.is_done = True + try: + vs = self.conf.get_ifort_version_win32(self.compiler, self.version, self.bat_target, self.bat) + except Errors.ConfigurationError: + self.is_valid = False + return + if self.callback: + vs = self.callback(self, vs) + self.is_valid = True + (self.bindirs, self.incdirs, self.libdirs) = vs + + def __str__(self): + return str((self.bindirs, self.incdirs, self.libdirs)) + + def __repr__(self): + return repr((self.bindirs, self.incdirs, self.libdirs)) + +@conf +def detect_ifort(self): + return self.setup_ifort(self.get_ifort_versions(False)) + +@conf +def get_ifort_versions(self, eval_and_save=True): + """ + :return: platforms to compiler configurations + :rtype: dict + """ + dct = {} + self.gather_ifort_versions(dct) + return dct + +def _get_prog_names(self, compiler): + if compiler=='intel': + compiler_name = 'ifort' + linker_name = 'XILINK' + lib_name = 'XILIB' + else: + # assumes CL.exe + compiler_name = 'CL' + linker_name = 'LINK' + lib_name = 'LIB' + return compiler_name, linker_name, lib_name + +@conf +def find_ifort_win32(conf): + # the autodetection is supposed to be performed before entering in this method + v = conf.env + path = v.PATH + compiler = v.MSVC_COMPILER + version = v.MSVC_VERSION + + compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) + v.IFORT_MANIFEST = (compiler == 'intel' and version >= 11) + + # compiler + fc = conf.find_program(compiler_name, var='FC', path_list=path) + + # before setting anything, check if the compiler is really intel fortran + env = dict(conf.environ) + if path: + env.update(PATH = ';'.join(path)) + if not conf.cmd_and_log(fc + ['/nologo', '/help'], env=env): + conf.fatal('not intel fortran compiler could not be identified') + + v.FC_NAME = 'IFORT' + + if not v.LINK_FC: + conf.find_program(linker_name, var='LINK_FC', path_list=path, mandatory=True) + + if not v.AR: + conf.find_program(lib_name, path_list=path, var='AR', mandatory=True) + v.ARFLAGS = ['/nologo'] + + # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later + if v.IFORT_MANIFEST: + conf.find_program('MT', path_list=path, var='MT') + v.MTFLAGS = ['/nologo'] + + try: + conf.load('winres') + except Errors.WafError: + Logs.warn('Resource compiler not found. Compiling resource file is disabled') + +####################################################################################################### +##### conf above, build below + +@after_method('apply_link') +@feature('fc') +def apply_flags_ifort(self): + """ + Adds additional flags implied by msvc, such as subsystems and pdb files:: + + def build(bld): + bld.stlib(source='main.c', target='bar', subsystem='gruik') + """ + if not self.env.IFORT_WIN32 or not getattr(self, 'link_task', None): + return + + is_static = isinstance(self.link_task, ccroot.stlink_task) + + subsystem = getattr(self, 'subsystem', '') + if subsystem: + subsystem = '/subsystem:%s' % subsystem + flags = is_static and 'ARFLAGS' or 'LINKFLAGS' + self.env.append_value(flags, subsystem) + + if not is_static: + for f in self.env.LINKFLAGS: + d = f.lower() + if d[1:] == 'debug': + pdbnode = self.link_task.outputs[0].change_ext('.pdb') + self.link_task.outputs.append(pdbnode) + + if getattr(self, 'install_task', None): + self.pdb_install_task = self.add_install_files(install_to=self.install_task.install_to, install_from=pdbnode) + + break + +@feature('fcprogram', 'fcshlib', 'fcprogram_test') +@after_method('apply_link') +def apply_manifest_ifort(self): + """ + Enables manifest embedding in Fortran DLLs when using ifort on Windows + See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx + """ + if self.env.IFORT_WIN32 and getattr(self, 'link_task', None): + # it seems ifort.exe cannot be called for linking + self.link_task.env.FC = self.env.LINK_FC + + if self.env.IFORT_WIN32 and self.env.IFORT_MANIFEST and getattr(self, 'link_task', None): + out_node = self.link_task.outputs[0] + man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') + self.link_task.outputs.append(man_node) + self.env.DO_MANIFEST = True + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/intltool.py b/ldb-2.0.8/third_party/waf/waflib/Tools/intltool.py new file mode 100644 index 0000000..af95ba8 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/intltool.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +""" +Support for translation tools such as msgfmt and intltool + +Usage:: + + def configure(conf): + conf.load('gnu_dirs intltool') + + def build(bld): + # process the .po files into .gmo files, and install them in LOCALEDIR + bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") + + # process an input file, substituting the translations from the po dir + bld( + features = "intltool_in", + podir = "../po", + style = "desktop", + flags = ["-u"], + source = 'kupfer.desktop.in', + install_path = "${DATADIR}/applications", + ) + +Usage of the :py:mod:`waflib.Tools.gnu_dirs` is recommended, but not obligatory. +""" + +from __future__ import with_statement + +import os, re +from waflib import Context, Task, Utils, Logs +import waflib.Tools.ccroot +from waflib.TaskGen import feature, before_method, taskgen_method +from waflib.Logs import error +from waflib.Configure import conf + +_style_flags = { + 'ba': '-b', + 'desktop': '-d', + 'keys': '-k', + 'quoted': '--quoted-style', + 'quotedxml': '--quotedxml-style', + 'rfc822deb': '-r', + 'schemas': '-s', + 'xml': '-x', +} + +@taskgen_method +def ensure_localedir(self): + """ + Expands LOCALEDIR from DATAROOTDIR/locale if possible, or falls back to PREFIX/share/locale + """ + # use the tool gnu_dirs to provide options to define this + if not self.env.LOCALEDIR: + if self.env.DATAROOTDIR: + self.env.LOCALEDIR = os.path.join(self.env.DATAROOTDIR, 'locale') + else: + self.env.LOCALEDIR = os.path.join(self.env.PREFIX, 'share', 'locale') + +@before_method('process_source') +@feature('intltool_in') +def apply_intltool_in_f(self): + """ + Creates tasks to translate files by intltool-merge:: + + def build(bld): + bld( + features = "intltool_in", + podir = "../po", + style = "desktop", + flags = ["-u"], + source = 'kupfer.desktop.in', + install_path = "${DATADIR}/applications", + ) + + :param podir: location of the .po files + :type podir: string + :param source: source files to process + :type source: list of string + :param style: the intltool-merge mode of operation, can be one of the following values: + ``ba``, ``desktop``, ``keys``, ``quoted``, ``quotedxml``, ``rfc822deb``, ``schemas`` and ``xml``. + See the ``intltool-merge`` man page for more information about supported modes of operation. + :type style: string + :param flags: compilation flags ("-quc" by default) + :type flags: list of string + :param install_path: installation path + :type install_path: string + """ + try: + self.meths.remove('process_source') + except ValueError: + pass + + self.ensure_localedir() + + podir = getattr(self, 'podir', '.') + podirnode = self.path.find_dir(podir) + if not podirnode: + error("could not find the podir %r" % podir) + return + + cache = getattr(self, 'intlcache', '.intlcache') + self.env.INTLCACHE = [os.path.join(str(self.path.get_bld()), podir, cache)] + self.env.INTLPODIR = podirnode.bldpath() + self.env.append_value('INTLFLAGS', getattr(self, 'flags', self.env.INTLFLAGS_DEFAULT)) + + if '-c' in self.env.INTLFLAGS: + self.bld.fatal('Redundant -c flag in intltool task %r' % self) + + style = getattr(self, 'style', None) + if style: + try: + style_flag = _style_flags[style] + except KeyError: + self.bld.fatal('intltool_in style "%s" is not valid' % style) + + self.env.append_unique('INTLFLAGS', [style_flag]) + + for i in self.to_list(self.source): + node = self.path.find_resource(i) + + task = self.create_task('intltool', node, node.change_ext('')) + inst = getattr(self, 'install_path', None) + if inst: + self.add_install_files(install_to=inst, install_from=task.outputs) + +@feature('intltool_po') +def apply_intltool_po(self): + """ + Creates tasks to process po files:: + + def build(bld): + bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") + + The relevant task generator arguments are: + + :param podir: directory of the .po files + :type podir: string + :param appname: name of the application + :type appname: string + :param install_path: installation directory + :type install_path: string + + The file LINGUAS must be present in the directory pointed by *podir* and list the translation files to process. + """ + try: + self.meths.remove('process_source') + except ValueError: + pass + + self.ensure_localedir() + + appname = getattr(self, 'appname', getattr(Context.g_module, Context.APPNAME, 'set_your_app_name')) + podir = getattr(self, 'podir', '.') + inst = getattr(self, 'install_path', '${LOCALEDIR}') + + linguas = self.path.find_node(os.path.join(podir, 'LINGUAS')) + if linguas: + # scan LINGUAS file for locales to process + with open(linguas.abspath()) as f: + langs = [] + for line in f.readlines(): + # ignore lines containing comments + if not line.startswith('#'): + langs += line.split() + re_linguas = re.compile('[-a-zA-Z_@.]+') + for lang in langs: + # Make sure that we only process lines which contain locales + if re_linguas.match(lang): + node = self.path.find_resource(os.path.join(podir, re_linguas.match(lang).group() + '.po')) + task = self.create_task('po', node, node.change_ext('.mo')) + + if inst: + filename = task.outputs[0].name + (langname, ext) = os.path.splitext(filename) + inst_file = inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo' + self.add_install_as(install_to=inst_file, install_from=task.outputs[0], + chmod=getattr(self, 'chmod', Utils.O644)) + + else: + Logs.pprint('RED', "Error no LINGUAS file found in po directory") + +class po(Task.Task): + """ + Compiles .po files into .gmo files + """ + run_str = '${MSGFMT} -o ${TGT} ${SRC}' + color = 'BLUE' + +class intltool(Task.Task): + """ + Calls intltool-merge to update translation files + """ + run_str = '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE_ST:INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}' + color = 'BLUE' + +@conf +def find_msgfmt(conf): + """ + Detects msgfmt and sets the ``MSGFMT`` variable + """ + conf.find_program('msgfmt', var='MSGFMT') + +@conf +def find_intltool_merge(conf): + """ + Detects intltool-merge + """ + if not conf.env.PERL: + conf.find_program('perl', var='PERL') + conf.env.INTLCACHE_ST = '--cache=%s' + conf.env.INTLFLAGS_DEFAULT = ['-q', '-u'] + conf.find_program('intltool-merge', interpreter='PERL', var='INTLTOOL') + +def configure(conf): + """ + Detects the program *msgfmt* and set *conf.env.MSGFMT*. + Detects the program *intltool-merge* and set *conf.env.INTLTOOL*. + It is possible to set INTLTOOL in the environment, but it must not have spaces in it:: + + $ INTLTOOL="/path/to/the program/intltool" waf configure + + If a C/C++ compiler is present, execute a compilation test to find the header *locale.h*. + """ + conf.find_msgfmt() + conf.find_intltool_merge() + if conf.env.CC or conf.env.CXX: + conf.check(header_name='locale.h') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/irixcc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/irixcc.py new file mode 100644 index 0000000..c3ae1ac --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/irixcc.py @@ -0,0 +1,66 @@ +#! /usr/bin/env python +# encoding: utf-8 +# imported from samba + +""" +Compiler definition for irix/MIPSpro cc compiler +""" + +from waflib import Errors +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +@conf +def find_irixcc(conf): + v = conf.env + cc = None + if v.CC: + cc = v.CC + elif 'CC' in conf.environ: + cc = conf.environ['CC'] + if not cc: + cc = conf.find_program('cc', var='CC') + if not cc: + conf.fatal('irixcc was not found') + + try: + conf.cmd_and_log(cc + ['-version']) + except Errors.WafError: + conf.fatal('%r -version could not be executed' % cc) + + v.CC = cc + v.CC_NAME = 'irix' + +@conf +def irixcc_common_flags(conf): + v = conf.env + + v.CC_SRC_F = '' + v.CC_TGT_F = ['-c', '-o'] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + if not v.LINK_CC: + v.LINK_CC = v.CC + + v.CCLNK_SRC_F = '' + v.CCLNK_TGT_F = ['-o'] + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + + v.cprogram_PATTERN = '%s' + v.cshlib_PATTERN = 'lib%s.so' + v.cstlib_PATTERN = 'lib%s.a' + +def configure(conf): + conf.find_irixcc() + conf.find_cpp() + conf.find_ar() + conf.irixcc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/javaw.py b/ldb-2.0.8/third_party/waf/waflib/Tools/javaw.py new file mode 100644 index 0000000..ceb08c2 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/javaw.py @@ -0,0 +1,593 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +""" +Java support + +Javac is one of the few compilers that behaves very badly: + +#. it outputs files where it wants to (-d is only for the package root) + +#. it recompiles files silently behind your back + +#. it outputs an undefined amount of files (inner classes) + +Remember that the compilation can be performed using Jython[1] rather than regular Python. Instead of +running one of the following commands:: + + ./waf configure + python waf configure + +You would have to run:: + + java -jar /path/to/jython.jar waf configure + +[1] http://www.jython.org/ + +Usage +===== + +Load the "java" tool. + +def configure(conf): + conf.load('java') + +Java tools will be autodetected and eventually, if present, the quite +standard JAVA_HOME environment variable will be used. The also standard +CLASSPATH variable is used for library searching. + +In configuration phase checks can be done on the system environment, for +example to check if a class is known in the classpath:: + + conf.check_java_class('java.io.FileOutputStream') + +or if the system supports JNI applications building:: + + conf.check_jni_headers() + + +The java tool supports compiling java code, creating jar files and +creating javadoc documentation. This can be either done separately or +together in a single definition. For example to manage them separately:: + + bld(features = 'javac', + srcdir = 'src', + compat = '1.7', + use = 'animals', + name = 'cats-src', + ) + + bld(features = 'jar', + basedir = '.', + destfile = '../cats.jar', + name = 'cats', + use = 'cats-src' + ) + + +Or together by defining all the needed attributes:: + + bld(features = 'javac jar javadoc', + srcdir = 'src/', # folder containing the sources to compile + outdir = 'src', # folder where to output the classes (in the build directory) + compat = '1.6', # java compatibility version number + classpath = ['.', '..'], + + # jar + basedir = 'src', # folder containing the classes and other files to package (must match outdir) + destfile = 'foo.jar', # do not put the destfile in the folder of the java classes! + use = 'NNN', + jaropts = ['-C', 'default/src/', '.'], # can be used to give files + manifest = 'src/Manifest.mf', # Manifest file to include + + # javadoc + javadoc_package = ['com.meow' , 'com.meow.truc.bar', 'com.meow.truc.foo'], + javadoc_output = 'javadoc', + ) + +External jar dependencies can be mapped to a standard waf "use" dependency by +setting an environment variable with a CLASSPATH prefix in the configuration, +for example:: + + conf.env.CLASSPATH_NNN = ['aaaa.jar', 'bbbb.jar'] + +and then NNN can be freely used in rules as:: + + use = 'NNN', + +In the java tool the dependencies via use are not transitive by default, as +this necessity depends on the code. To enable recursive dependency scanning +use on a specific rule: + + recurse_use = True + +Or build-wise by setting RECURSE_JAVA: + + bld.env.RECURSE_JAVA = True + +Unit tests can be integrated in the waf unit test environment using the javatest extra. +""" + +import os, shutil +from waflib import Task, Utils, Errors, Node +from waflib.Configure import conf +from waflib.TaskGen import feature, before_method, after_method, taskgen_method + +from waflib.Tools import ccroot +ccroot.USELIB_VARS['javac'] = set(['CLASSPATH', 'JAVACFLAGS']) + +SOURCE_RE = '**/*.java' +JAR_RE = '**/*' + +class_check_source = ''' +public class Test { + public static void main(String[] argv) { + Class lib; + if (argv.length < 1) { + System.err.println("Missing argument"); + System.exit(77); + } + try { + lib = Class.forName(argv[0]); + } catch (ClassNotFoundException e) { + System.err.println("ClassNotFoundException"); + System.exit(1); + } + lib = null; + System.exit(0); + } +} +''' + +@feature('javac') +@before_method('process_source') +def apply_java(self): + """ + Create a javac task for compiling *.java files*. There can be + only one javac task by task generator. + """ + Utils.def_attrs(self, jarname='', classpath='', + sourcepath='.', srcdir='.', + jar_mf_attributes={}, jar_mf_classpath=[]) + + outdir = getattr(self, 'outdir', None) + if outdir: + if not isinstance(outdir, Node.Node): + outdir = self.path.get_bld().make_node(self.outdir) + else: + outdir = self.path.get_bld() + outdir.mkdir() + self.outdir = outdir + self.env.OUTDIR = outdir.abspath() + + self.javac_task = tsk = self.create_task('javac') + tmp = [] + + srcdir = getattr(self, 'srcdir', '') + if isinstance(srcdir, Node.Node): + srcdir = [srcdir] + for x in Utils.to_list(srcdir): + if isinstance(x, Node.Node): + y = x + else: + y = self.path.find_dir(x) + if not y: + self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) + tmp.append(y) + + tsk.srcdir = tmp + + if getattr(self, 'compat', None): + tsk.env.append_value('JAVACFLAGS', ['-source', str(self.compat)]) + + if hasattr(self, 'sourcepath'): + fold = [isinstance(x, Node.Node) and x or self.path.find_dir(x) for x in self.to_list(self.sourcepath)] + names = os.pathsep.join([x.srcpath() for x in fold]) + else: + names = [x.srcpath() for x in tsk.srcdir] + + if names: + tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) + + +@taskgen_method +def java_use_rec(self, name, **kw): + """ + Processes recursively the *use* attribute for each referred java compilation + """ + if name in self.tmp_use_seen: + return + + self.tmp_use_seen.append(name) + + try: + y = self.bld.get_tgen_by_name(name) + except Errors.WafError: + self.uselib.append(name) + return + else: + y.post() + # Add generated JAR name for CLASSPATH. Task ordering (set_run_after) + # is already guaranteed by ordering done between the single tasks + if hasattr(y, 'jar_task'): + self.use_lst.append(y.jar_task.outputs[0].abspath()) + else: + if hasattr(y,'outdir'): + self.use_lst.append(y.outdir.abspath()) + else: + self.use_lst.append(y.path.get_bld().abspath()) + + for x in self.to_list(getattr(y, 'use', [])): + self.java_use_rec(x) + +@feature('javac') +@before_method('propagate_uselib_vars') +@after_method('apply_java') +def use_javac_files(self): + """ + Processes the *use* attribute referring to other java compilations + """ + self.use_lst = [] + self.tmp_use_seen = [] + self.uselib = self.to_list(getattr(self, 'uselib', [])) + names = self.to_list(getattr(self, 'use', [])) + get = self.bld.get_tgen_by_name + for x in names: + try: + tg = get(x) + except Errors.WafError: + self.uselib.append(x) + else: + tg.post() + if hasattr(tg, 'jar_task'): + self.use_lst.append(tg.jar_task.outputs[0].abspath()) + self.javac_task.set_run_after(tg.jar_task) + self.javac_task.dep_nodes.extend(tg.jar_task.outputs) + else: + if hasattr(tg, 'outdir'): + base_node = tg.outdir + else: + base_node = tg.path.get_bld() + + self.use_lst.append(base_node.abspath()) + self.javac_task.dep_nodes.extend([x for x in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) + + for tsk in tg.tasks: + self.javac_task.set_run_after(tsk) + + # If recurse use scan is enabled recursively add use attribute for each used one + if getattr(self, 'recurse_use', False) or self.bld.env.RECURSE_JAVA: + self.java_use_rec(x) + + self.env.append_value('CLASSPATH', self.use_lst) + +@feature('javac') +@after_method('apply_java', 'propagate_uselib_vars', 'use_javac_files') +def set_classpath(self): + """ + Sets the CLASSPATH value on the *javac* task previously created. + """ + if getattr(self, 'classpath', None): + self.env.append_unique('CLASSPATH', getattr(self, 'classpath', [])) + for x in self.tasks: + x.env.CLASSPATH = os.pathsep.join(self.env.CLASSPATH) + os.pathsep + +@feature('jar') +@after_method('apply_java', 'use_javac_files') +@before_method('process_source') +def jar_files(self): + """ + Creates a jar task (one maximum per task generator) + """ + destfile = getattr(self, 'destfile', 'test.jar') + jaropts = getattr(self, 'jaropts', []) + manifest = getattr(self, 'manifest', None) + + basedir = getattr(self, 'basedir', None) + if basedir: + if not isinstance(self.basedir, Node.Node): + basedir = self.path.get_bld().make_node(basedir) + else: + basedir = self.path.get_bld() + if not basedir: + self.bld.fatal('Could not find the basedir %r for %r' % (self.basedir, self)) + + self.jar_task = tsk = self.create_task('jar_create') + if manifest: + jarcreate = getattr(self, 'jarcreate', 'cfm') + if not isinstance(manifest,Node.Node): + node = self.path.find_resource(manifest) + else: + node = manifest + if not node: + self.bld.fatal('invalid manifest file %r for %r' % (manifest, self)) + tsk.dep_nodes.append(node) + jaropts.insert(0, node.abspath()) + else: + jarcreate = getattr(self, 'jarcreate', 'cf') + if not isinstance(destfile, Node.Node): + destfile = self.path.find_or_declare(destfile) + if not destfile: + self.bld.fatal('invalid destfile %r for %r' % (destfile, self)) + tsk.set_outputs(destfile) + tsk.basedir = basedir + + jaropts.append('-C') + jaropts.append(basedir.bldpath()) + jaropts.append('.') + + tsk.env.JAROPTS = jaropts + tsk.env.JARCREATE = jarcreate + + if getattr(self, 'javac_task', None): + tsk.set_run_after(self.javac_task) + +@feature('jar') +@after_method('jar_files') +def use_jar_files(self): + """ + Processes the *use* attribute to set the build order on the + tasks created by another task generator. + """ + self.uselib = self.to_list(getattr(self, 'uselib', [])) + names = self.to_list(getattr(self, 'use', [])) + get = self.bld.get_tgen_by_name + for x in names: + try: + y = get(x) + except Errors.WafError: + self.uselib.append(x) + else: + y.post() + self.jar_task.run_after.update(y.tasks) + +class JTask(Task.Task): + """ + Base class for java and jar tasks; provides functionality to run long commands + """ + def split_argfile(self, cmd): + inline = [cmd[0]] + infile = [] + for x in cmd[1:]: + # jar and javac do not want -J flags in @file + if x.startswith('-J'): + inline.append(x) + else: + infile.append(self.quote_flag(x)) + return (inline, infile) + +class jar_create(JTask): + """ + Creates a jar file + """ + color = 'GREEN' + run_str = '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}' + + def runnable_status(self): + """ + Wait for dependent tasks to be executed, then read the + files to update the list of inputs. + """ + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + if not self.inputs: + try: + self.inputs = [x for x in self.basedir.ant_glob(JAR_RE, remove=False, quiet=True) if id(x) != id(self.outputs[0])] + except Exception: + raise Errors.WafError('Could not find the basedir %r for %r' % (self.basedir, self)) + return super(jar_create, self).runnable_status() + +class javac(JTask): + """ + Compiles java files + """ + color = 'BLUE' + run_str = '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}' + vars = ['CLASSPATH', 'JAVACFLAGS', 'JAVAC', 'OUTDIR'] + """ + The javac task will be executed again if the variables CLASSPATH, JAVACFLAGS, JAVAC or OUTDIR change. + """ + def uid(self): + """Identify java tasks by input&output folder""" + lst = [self.__class__.__name__, self.generator.outdir.abspath()] + for x in self.srcdir: + lst.append(x.abspath()) + return Utils.h_list(lst) + + def runnable_status(self): + """ + Waits for dependent tasks to be complete, then read the file system to find the input nodes. + """ + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + + if not self.inputs: + self.inputs = [] + for x in self.srcdir: + if x.exists(): + self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False, quiet=True)) + return super(javac, self).runnable_status() + + def post_run(self): + """ + List class files created + """ + for node in self.generator.outdir.ant_glob('**/*.class', quiet=True): + self.generator.bld.node_sigs[node] = self.uid() + self.generator.bld.task_sigs[self.uid()] = self.cache_sig + +@feature('javadoc') +@after_method('process_rule') +def create_javadoc(self): + """ + Creates a javadoc task (feature 'javadoc') + """ + tsk = self.create_task('javadoc') + tsk.classpath = getattr(self, 'classpath', []) + self.javadoc_package = Utils.to_list(self.javadoc_package) + if not isinstance(self.javadoc_output, Node.Node): + self.javadoc_output = self.bld.path.find_or_declare(self.javadoc_output) + +class javadoc(Task.Task): + """ + Builds java documentation + """ + color = 'BLUE' + + def __str__(self): + return '%s: %s -> %s\n' % (self.__class__.__name__, self.generator.srcdir, self.generator.javadoc_output) + + def run(self): + env = self.env + bld = self.generator.bld + wd = bld.bldnode + + #add src node + bld node (for generated java code) + srcpath = self.generator.path.abspath() + os.sep + self.generator.srcdir + srcpath += os.pathsep + srcpath += self.generator.path.get_bld().abspath() + os.sep + self.generator.srcdir + + classpath = env.CLASSPATH + classpath += os.pathsep + classpath += os.pathsep.join(self.classpath) + classpath = "".join(classpath) + + self.last_cmd = lst = [] + lst.extend(Utils.to_list(env.JAVADOC)) + lst.extend(['-d', self.generator.javadoc_output.abspath()]) + lst.extend(['-sourcepath', srcpath]) + lst.extend(['-classpath', classpath]) + lst.extend(['-subpackages']) + lst.extend(self.generator.javadoc_package) + lst = [x for x in lst if x] + + self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) + + def post_run(self): + nodes = self.generator.javadoc_output.ant_glob('**', quiet=True) + for node in nodes: + self.generator.bld.node_sigs[node] = self.uid() + self.generator.bld.task_sigs[self.uid()] = self.cache_sig + +def configure(self): + """ + Detects the javac, java and jar programs + """ + # If JAVA_PATH is set, we prepend it to the path list + java_path = self.environ['PATH'].split(os.pathsep) + v = self.env + + if 'JAVA_HOME' in self.environ: + java_path = [os.path.join(self.environ['JAVA_HOME'], 'bin')] + java_path + self.env.JAVA_HOME = [self.environ['JAVA_HOME']] + + for x in 'javac java jar javadoc'.split(): + self.find_program(x, var=x.upper(), path_list=java_path, mandatory=(x not in ('javadoc'))) + + if 'CLASSPATH' in self.environ: + v.CLASSPATH = self.environ['CLASSPATH'] + + if not v.JAR: + self.fatal('jar is required for making java packages') + if not v.JAVAC: + self.fatal('javac is required for compiling java classes') + + v.JARCREATE = 'cf' # can use cvf + v.JAVACFLAGS = [] + +@conf +def check_java_class(self, classname, with_classpath=None): + """ + Checks if the specified java class exists + + :param classname: class to check, like java.util.HashMap + :type classname: string + :param with_classpath: additional classpath to give + :type with_classpath: string + """ + javatestdir = '.waf-javatest' + + classpath = javatestdir + if self.env.CLASSPATH: + classpath += os.pathsep + self.env.CLASSPATH + if isinstance(with_classpath, str): + classpath += os.pathsep + with_classpath + + shutil.rmtree(javatestdir, True) + os.mkdir(javatestdir) + + Utils.writef(os.path.join(javatestdir, 'Test.java'), class_check_source) + + # Compile the source + self.exec_command(self.env.JAVAC + [os.path.join(javatestdir, 'Test.java')], shell=False) + + # Try to run the app + cmd = self.env.JAVA + ['-cp', classpath, 'Test', classname] + self.to_log("%s\n" % str(cmd)) + found = self.exec_command(cmd, shell=False) + + self.msg('Checking for java class %s' % classname, not found) + + shutil.rmtree(javatestdir, True) + + return found + +@conf +def check_jni_headers(conf): + """ + Checks for jni headers and libraries. On success the conf.env variables xxx_JAVA are added for use in C/C++ targets:: + + def options(opt): + opt.load('compiler_c') + + def configure(conf): + conf.load('compiler_c java') + conf.check_jni_headers() + + def build(bld): + bld.shlib(source='a.c', target='app', use='JAVA') + """ + if not conf.env.CC_NAME and not conf.env.CXX_NAME: + conf.fatal('load a compiler first (gcc, g++, ..)') + + if not conf.env.JAVA_HOME: + conf.fatal('set JAVA_HOME in the system environment') + + # jni requires the jvm + javaHome = conf.env.JAVA_HOME[0] + + dir = conf.root.find_dir(conf.env.JAVA_HOME[0] + '/include') + if dir is None: + dir = conf.root.find_dir(conf.env.JAVA_HOME[0] + '/../Headers') # think different?! + if dir is None: + conf.fatal('JAVA_HOME does not seem to be set properly') + + f = dir.ant_glob('**/(jni|jni_md).h') + incDirs = [x.parent.abspath() for x in f] + + dir = conf.root.find_dir(conf.env.JAVA_HOME[0]) + f = dir.ant_glob('**/*jvm.(so|dll|dylib)') + libDirs = [x.parent.abspath() for x in f] or [javaHome] + + # On windows, we need both the .dll and .lib to link. On my JDK, they are + # in different directories... + f = dir.ant_glob('**/*jvm.(lib)') + if f: + libDirs = [[x, y.parent.abspath()] for x in libDirs for y in f] + + if conf.env.DEST_OS == 'freebsd': + conf.env.append_unique('LINKFLAGS_JAVA', '-pthread') + for d in libDirs: + try: + conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm', + libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA') + except Exception: + pass + else: + break + else: + conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/ldc2.py b/ldb-2.0.8/third_party/waf/waflib/Tools/ldc2.py new file mode 100644 index 0000000..a51c344 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/ldc2.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Alex Rønne Petersen, 2012 (alexrp/Zor) + +from waflib.Tools import ar, d +from waflib.Configure import conf + +@conf +def find_ldc2(conf): + """ + Finds the program *ldc2* and set the variable *D* + """ + conf.find_program(['ldc2'], var='D') + + out = conf.cmd_and_log(conf.env.D + ['-version']) + if out.find("based on DMD v2.") == -1: + conf.fatal("detected compiler is not ldc2") + +@conf +def common_flags_ldc2(conf): + """ + Sets the D flags required by *ldc2* + """ + v = conf.env + + v.D_SRC_F = ['-c'] + v.D_TGT_F = '-of%s' + + v.D_LINKER = v.D + v.DLNK_SRC_F = '' + v.DLNK_TGT_F = '-of%s' + v.DINC_ST = '-I%s' + + v.DSHLIB_MARKER = v.DSTLIB_MARKER = '' + v.DSTLIB_ST = v.DSHLIB_ST = '-L-l%s' + v.DSTLIBPATH_ST = v.DLIBPATH_ST = '-L-L%s' + + v.LINKFLAGS_dshlib = ['-L-shared'] + + v.DHEADER_ext = '.di' + v.DFLAGS_d_with_header = ['-H', '-Hf'] + v.D_HDR_F = '%s' + + v.LINKFLAGS = [] + v.DFLAGS_dshlib = ['-relocation-model=pic'] + +def configure(conf): + """ + Configuration for *ldc2* + """ + conf.find_ldc2() + conf.load('ar') + conf.load('d') + conf.common_flags_ldc2() + conf.d_platform_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/lua.py b/ldb-2.0.8/third_party/waf/waflib/Tools/lua.py new file mode 100644 index 0000000..15a333a --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/lua.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Sebastian Schlingmann, 2008 +# Thomas Nagy, 2008-2018 (ita) + +""" +Lua support. + +Compile *.lua* files into *.luac*:: + + def configure(conf): + conf.load('lua') + conf.env.LUADIR = '/usr/local/share/myapp/scripts/' + def build(bld): + bld(source='foo.lua') +""" + +from waflib.TaskGen import extension +from waflib import Task + +@extension('.lua') +def add_lua(self, node): + tsk = self.create_task('luac', node, node.change_ext('.luac')) + inst_to = getattr(self, 'install_path', self.env.LUADIR and '${LUADIR}' or None) + if inst_to: + self.add_install_files(install_to=inst_to, install_from=tsk.outputs) + return tsk + +class luac(Task.Task): + run_str = '${LUAC} -s -o ${TGT} ${SRC}' + color = 'PINK' + +def configure(conf): + """ + Detect the luac compiler and set *conf.env.LUAC* + """ + conf.find_program('luac', var='LUAC') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/md5_tstamp.py b/ldb-2.0.8/third_party/waf/waflib/Tools/md5_tstamp.py new file mode 100644 index 0000000..d1569fa --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/md5_tstamp.py @@ -0,0 +1,41 @@ +#! /usr/bin/env python +# encoding: utf-8 + +""" +Re-calculate md5 hashes of files only when the file time have changed:: + + def options(opt): + opt.load('md5_tstamp') + +The hashes can also reflect either the file contents (STRONGEST=True) or the +file time and file size. + +The performance benefits of this module are usually insignificant. +""" + +import os, stat +from waflib import Utils, Build, Node + +STRONGEST = True + +Build.SAVED_ATTRS.append('hashes_md5_tstamp') +def h_file(self): + filename = self.abspath() + st = os.stat(filename) + + cache = self.ctx.hashes_md5_tstamp + if filename in cache and cache[filename][0] == st.st_mtime: + return cache[filename][1] + + if STRONGEST: + ret = Utils.h_file(filename) + else: + if stat.S_ISDIR(st[stat.ST_MODE]): + raise IOError('Not a file') + ret = Utils.md5(str((st.st_mtime, st.st_size)).encode()).digest() + + cache[filename] = (st.st_mtime, ret) + return ret +h_file.__doc__ = Node.Node.h_file.__doc__ +Node.Node.h_file = h_file + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/msvc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/msvc.py new file mode 100644 index 0000000..f169c7f --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/msvc.py @@ -0,0 +1,1020 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Carlos Rafael Giani, 2006 (dv) +# Tamas Pal, 2007 (folti) +# Nicolas Mercier, 2009 +# Matt Clarkson, 2012 + +""" +Microsoft Visual C++/Intel C++ compiler support + +If you get detection problems, first try any of the following:: + + chcp 65001 + set PYTHONIOENCODING=... + set PYTHONLEGACYWINDOWSSTDIO=1 + +Usage:: + + $ waf configure --msvc_version="msvc 10.0,msvc 9.0" --msvc_target="x64" + +or:: + + def configure(conf): + conf.env.MSVC_VERSIONS = ['msvc 10.0', 'msvc 9.0', 'msvc 8.0', 'msvc 7.1', 'msvc 7.0', 'msvc 6.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0'] + conf.env.MSVC_TARGETS = ['x64'] + conf.load('msvc') + +or:: + + def configure(conf): + conf.load('msvc', funs='no_autodetect') + conf.check_lib_msvc('gdi32') + conf.check_libs_msvc('kernel32 user32') + def build(bld): + tg = bld.program(source='main.c', target='app', use='KERNEL32 USER32 GDI32') + +Platforms and targets will be tested in the order they appear; +the first good configuration will be used. + +To force testing all the configurations that are not used, use the ``--no-msvc-lazy`` option +or set ``conf.env.MSVC_LAZY_AUTODETECT=False``. + +Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64, x86_arm, amd64_x86, amd64_arm + +Compilers supported: + +* msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 15 (Visual Studio 2017) +* wsdk => Windows SDK, versions 6.0, 6.1, 7.0, 7.1, 8.0 +* icl => Intel compiler, versions 9, 10, 11, 13 +* winphone => Visual Studio to target Windows Phone 8 native (version 8.0 for now) +* Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i) +* PocketPC => Compiler/SDK for PocketPC devices (armv4/v4i) + +To use WAF in a VS2008 Make file project (see http://code.google.com/p/waf/issues/detail?id=894) +You may consider to set the environment variable "VS_UNICODE_OUTPUT" to nothing before calling waf. +So in your project settings use something like 'cmd.exe /C "set VS_UNICODE_OUTPUT=& set PYTHONUNBUFFERED=true & waf build"'. +cmd.exe /C "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf configure" +Setting PYTHONUNBUFFERED gives the unbuffered output. +""" + +import os, sys, re, traceback +from waflib import Utils, Logs, Options, Errors +from waflib.TaskGen import after_method, feature + +from waflib.Configure import conf +from waflib.Tools import ccroot, c, cxx, ar + +g_msvc_systemlibs = ''' +aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet +cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs +credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d +ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp +faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid +gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop +kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi +mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree +msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm +netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp +odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 +osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu +ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm +rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 +shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 +traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg +version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm +wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp +'''.split() +"""importlibs provided by MSVC/Platform SDK. Do NOT search them""" + +all_msvc_platforms = [ ('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'), + ('x86_amd64', 'amd64'), ('x86_ia64', 'ia64'), ('x86_arm', 'arm'), ('x86_arm64', 'arm64'), + ('amd64_x86', 'x86'), ('amd64_arm', 'arm'), ('amd64_arm64', 'arm64') ] +"""List of msvc platforms""" + +all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ] +"""List of wince platforms""" + +all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] +"""List of icl platforms""" + +def options(opt): + opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='') + opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') + opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy') + +@conf +def setup_msvc(conf, versiondict): + """ + Checks installed compilers and targets and returns the first combination from the user's + options, env, or the global supported lists that checks. + + :param versiondict: dict(platform -> dict(architecture -> configuration)) + :type versiondict: dict(string -> dict(string -> target_compiler) + :return: the compiler, revision, path, include dirs, library paths and target architecture + :rtype: tuple of strings + """ + platforms = getattr(Options.options, 'msvc_targets', '').split(',') + if platforms == ['']: + platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] + desired_versions = getattr(Options.options, 'msvc_version', '').split(',') + if desired_versions == ['']: + desired_versions = conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys()))) + + # Override lazy detection by evaluating after the fact. + lazy_detect = getattr(Options.options, 'msvc_lazy', True) + if conf.env.MSVC_LAZY_AUTODETECT is False: + lazy_detect = False + + if not lazy_detect: + for val in versiondict.values(): + for arch in list(val.keys()): + cfg = val[arch] + cfg.evaluate() + if not cfg.is_valid: + del val[arch] + conf.env.MSVC_INSTALLED_VERSIONS = versiondict + + for version in desired_versions: + Logs.debug('msvc: detecting %r - %r', version, desired_versions) + try: + targets = versiondict[version] + except KeyError: + continue + + seen = set() + for arch in platforms: + if arch in seen: + continue + else: + seen.add(arch) + try: + cfg = targets[arch] + except KeyError: + continue + + cfg.evaluate() + if cfg.is_valid: + compiler,revision = version.rsplit(' ', 1) + return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu + conf.fatal('msvc: Impossible to find a valid architecture for building %r - %r' % (desired_versions, list(versiondict.keys()))) + +@conf +def get_msvc_version(conf, compiler, version, target, vcvars): + """ + Checks that an installed compiler actually runs and uses vcvars to obtain the + environment needed by the compiler. + + :param compiler: compiler type, for looking up the executable name + :param version: compiler version, for debugging only + :param target: target architecture + :param vcvars: batch file to run to check the environment + :return: the location of the compiler executable, the location of include dirs, and the library paths + :rtype: tuple of strings + """ + Logs.debug('msvc: get_msvc_version: %r %r %r', compiler, version, target) + + try: + conf.msvc_cnt += 1 + except AttributeError: + conf.msvc_cnt = 1 + batfile = conf.bldnode.make_node('waf-print-msvc-%d.bat' % conf.msvc_cnt) + batfile.write("""@echo off +set INCLUDE= +set LIB= +call "%s" %s +echo PATH=%%PATH%% +echo INCLUDE=%%INCLUDE%% +echo LIB=%%LIB%%;%%LIBPATH%% +""" % (vcvars,target)) + sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()]) + lines = sout.splitlines() + + if not lines[0]: + lines.pop(0) + + MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None + for line in lines: + if line.startswith('PATH='): + path = line[5:] + MSVC_PATH = path.split(';') + elif line.startswith('INCLUDE='): + MSVC_INCDIR = [i for i in line[8:].split(';') if i] + elif line.startswith('LIB='): + MSVC_LIBDIR = [i for i in line[4:].split(';') if i] + if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR): + conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)') + + # Check if the compiler is usable at all. + # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run. + env = dict(os.environ) + env.update(PATH = path) + compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) + cxx = conf.find_program(compiler_name, path_list=MSVC_PATH) + + # delete CL if exists. because it could contain parameters which can change cl's behaviour rather catastrophically. + if 'CL' in env: + del(env['CL']) + + try: + conf.cmd_and_log(cxx + ['/help'], env=env) + except UnicodeError: + st = traceback.format_exc() + if conf.logger: + conf.logger.error(st) + conf.fatal('msvc: Unicode error - check the code page?') + except Exception as e: + Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s', compiler, version, target, str(e)) + conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)') + else: + Logs.debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target) + finally: + conf.env[compiler_name] = '' + + return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) + +def gather_wince_supported_platforms(): + """ + Checks SmartPhones SDKs + + :param versions: list to modify + :type versions: list + """ + supported_wince_platforms = [] + try: + ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') + except OSError: + try: + ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') + except OSError: + ce_sdk = '' + if not ce_sdk: + return supported_wince_platforms + + index = 0 + while 1: + try: + sdk_device = Utils.winreg.EnumKey(ce_sdk, index) + sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device) + except OSError: + break + index += 1 + try: + path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir') + except OSError: + try: + path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation') + except OSError: + continue + path,xml = os.path.split(path) + path = str(path) + path,device = os.path.split(path) + if not device: + path,device = os.path.split(path) + platforms = [] + for arch,compiler in all_wince_platforms: + if os.path.isdir(os.path.join(path, device, 'Lib', arch)): + platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch))) + if platforms: + supported_wince_platforms.append((device, platforms)) + return supported_wince_platforms + +def gather_msvc_detected_versions(): + #Detected MSVC versions! + version_pattern = re.compile(r'^(\d\d?\.\d\d?)(Exp)?$') + detected_versions = [] + for vcver,vcvar in (('VCExpress','Exp'), ('VisualStudio','')): + prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) + except OSError: + prefix = 'SOFTWARE\\Microsoft\\' + vcver + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) + except OSError: + continue + + index = 0 + while 1: + try: + version = Utils.winreg.EnumKey(all_versions, index) + except OSError: + break + index += 1 + match = version_pattern.match(version) + if match: + versionnumber = float(match.group(1)) + else: + continue + detected_versions.append((versionnumber, version+vcvar, prefix+'\\'+version)) + def fun(tup): + return tup[0] + + detected_versions.sort(key = fun) + return detected_versions + +class target_compiler(object): + """ + Wrap a compiler configuration; call evaluate() to determine + whether the configuration is usable. + """ + def __init__(self, ctx, compiler, cpu, version, bat_target, bat, callback=None): + """ + :param ctx: configuration context to use to eventually get the version environment + :param compiler: compiler name + :param cpu: target cpu + :param version: compiler version number + :param bat_target: ? + :param bat: path to the batch file to run + """ + self.conf = ctx + self.name = None + self.is_valid = False + self.is_done = False + + self.compiler = compiler + self.cpu = cpu + self.version = version + self.bat_target = bat_target + self.bat = bat + self.callback = callback + + def evaluate(self): + if self.is_done: + return + self.is_done = True + try: + vs = self.conf.get_msvc_version(self.compiler, self.version, self.bat_target, self.bat) + except Errors.ConfigurationError: + self.is_valid = False + return + if self.callback: + vs = self.callback(self, vs) + self.is_valid = True + (self.bindirs, self.incdirs, self.libdirs) = vs + + def __str__(self): + return str((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) + + def __repr__(self): + return repr((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) + +@conf +def gather_wsdk_versions(conf, versions): + """ + Use winreg to add the msvc versions to the input list + + :param versions: list to modify + :type versions: list + """ + version_pattern = re.compile(r'^v..?.?\...?.?') + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') + except OSError: + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') + except OSError: + return + index = 0 + while 1: + try: + version = Utils.winreg.EnumKey(all_versions, index) + except OSError: + break + index += 1 + if not version_pattern.match(version): + continue + try: + msvc_version = Utils.winreg.OpenKey(all_versions, version) + path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') + except OSError: + continue + if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): + targets = {} + for target,arch in all_msvc_platforms: + targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')) + versions['wsdk ' + version[1:]] = targets + +@conf +def gather_msvc_targets(conf, versions, version, vc_path): + #Looking for normal MSVC compilers! + targets = {} + + if os.path.isfile(os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat')): + for target,realtarget in all_msvc_platforms[::-1]: + targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat')) + elif os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')): + for target,realtarget in all_msvc_platforms[::-1]: + targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'vcvarsall.bat')) + elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')): + targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')) + elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')): + targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat')) + if targets: + versions['msvc %s' % version] = targets + +@conf +def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms): + #Looking for Win CE compilers! + for device,platforms in supported_platforms: + targets = {} + for platform,compiler,include,lib in platforms: + winCEpath = os.path.join(vc_path, 'ce') + if not os.path.isdir(winCEpath): + continue + + if os.path.isdir(os.path.join(winCEpath, 'lib', platform)): + bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)] + incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include] + libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib] + def combine_common(obj, compiler_env): + # TODO this is likely broken, remove in waf 2.1 + (common_bindirs,_1,_2) = compiler_env + return (bindirs + common_bindirs, incdirs, libdirs) + targets[platform] = target_compiler(conf, 'msvc', platform, version, 'x86', vsvars, combine_common) + if targets: + versions[device + ' ' + version] = targets + +@conf +def gather_winphone_targets(conf, versions, version, vc_path, vsvars): + #Looking for WinPhone compilers + targets = {} + for target,realtarget in all_msvc_platforms[::-1]: + targets[target] = target_compiler(conf, 'winphone', realtarget, version, target, vsvars) + if targets: + versions['winphone ' + version] = targets + +@conf +def gather_vswhere_versions(conf, versions): + try: + import json + except ImportError: + Logs.error('Visual Studio 2017 detection requires Python 2.6') + return + + prg_path = os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files (x86)')) + + vswhere = os.path.join(prg_path, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe') + args = [vswhere, '-products', '*', '-legacy', '-format', 'json'] + try: + txt = conf.cmd_and_log(args) + except Errors.WafError as e: + Logs.debug('msvc: vswhere.exe failed %s', e) + return + + if sys.version_info[0] < 3: + txt = txt.decode(Utils.console_encoding()) + + arr = json.loads(txt) + arr.sort(key=lambda x: x['installationVersion']) + for entry in arr: + ver = entry['installationVersion'] + ver = str('.'.join(ver.split('.')[:2])) + path = str(os.path.abspath(entry['installationPath'])) + if os.path.exists(path) and ('msvc %s' % ver) not in versions: + conf.gather_msvc_targets(versions, ver, path) + +@conf +def gather_msvc_versions(conf, versions): + vc_paths = [] + for (v,version,reg) in gather_msvc_detected_versions(): + try: + try: + msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC") + except OSError: + msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++") + path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir') + except OSError: + try: + msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7") + path,type = Utils.winreg.QueryValueEx(msvc_version, version) + except OSError: + continue + else: + vc_paths.append((version, os.path.abspath(str(path)))) + continue + else: + vc_paths.append((version, os.path.abspath(str(path)))) + + wince_supported_platforms = gather_wince_supported_platforms() + + for version,vc_path in vc_paths: + vs_path = os.path.dirname(vc_path) + vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat') + if wince_supported_platforms and os.path.isfile(vsvars): + conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms) + + # WP80 works with 11.0Exp and 11.0, both of which resolve to the same vc_path. + # Stop after one is found. + for version,vc_path in vc_paths: + vs_path = os.path.dirname(vc_path) + vsvars = os.path.join(vs_path, 'VC', 'WPSDK', 'WP80', 'vcvarsphoneall.bat') + if os.path.isfile(vsvars): + conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars) + break + + for version,vc_path in vc_paths: + vs_path = os.path.dirname(vc_path) + conf.gather_msvc_targets(versions, version, vc_path) + +@conf +def gather_icl_versions(conf, versions): + """ + Checks ICL compilers + + :param versions: list to modify + :type versions: list + """ + version_pattern = re.compile(r'^...?.?\....?.?') + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') + except OSError: + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') + except OSError: + return + index = 0 + while 1: + try: + version = Utils.winreg.EnumKey(all_versions, index) + except OSError: + break + index += 1 + if not version_pattern.match(version): + continue + targets = {} + for target,arch in all_icl_platforms: + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target + try: + Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) + icl_version=Utils.winreg.OpenKey(all_versions,version) + path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') + except OSError: + pass + else: + batch_file=os.path.join(path,'bin','iclvars.bat') + if os.path.isfile(batch_file): + targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) + for target,arch in all_icl_platforms: + try: + icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) + path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') + except OSError: + continue + else: + batch_file=os.path.join(path,'bin','iclvars.bat') + if os.path.isfile(batch_file): + targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) + major = version[0:2] + versions['intel ' + major] = targets + +@conf +def gather_intel_composer_versions(conf, versions): + """ + Checks ICL compilers that are part of Intel Composer Suites + + :param versions: list to modify + :type versions: list + """ + version_pattern = re.compile(r'^...?.?\...?.?.?') + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites') + except OSError: + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites') + except OSError: + return + index = 0 + while 1: + try: + version = Utils.winreg.EnumKey(all_versions, index) + except OSError: + break + index += 1 + if not version_pattern.match(version): + continue + targets = {} + for target,arch in all_icl_platforms: + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target + try: + try: + defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir) + except OSError: + if targetDir == 'EM64T_NATIVE': + defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T') + else: + raise + uid,type = Utils.winreg.QueryValueEx(defaults, 'SubKey') + Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir) + icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++') + path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') + except OSError: + pass + else: + batch_file=os.path.join(path,'bin','iclvars.bat') + if os.path.isfile(batch_file): + targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) + # The intel compilervar_arch.bat is broken when used with Visual Studio Express 2012 + # http://software.intel.com/en-us/forums/topic/328487 + compilervars_warning_attr = '_compilervars_warning_key' + if version[0:2] == '13' and getattr(conf, compilervars_warning_attr, True): + setattr(conf, compilervars_warning_attr, False) + patch_url = 'http://software.intel.com/en-us/forums/topic/328487' + compilervars_arch = os.path.join(path, 'bin', 'compilervars_arch.bat') + for vscomntool in ('VS110COMNTOOLS', 'VS100COMNTOOLS'): + if vscomntool in os.environ: + vs_express_path = os.environ[vscomntool] + r'..\IDE\VSWinExpress.exe' + dev_env_path = os.environ[vscomntool] + r'..\IDE\devenv.exe' + if (r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"' in Utils.readf(compilervars_arch) and + not os.path.exists(vs_express_path) and not os.path.exists(dev_env_path)): + Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU ' + '(VSWinExpress.exe) but it does not seem to be installed at %r. ' + 'The intel command line set up will fail to configure unless the file %r' + 'is patched. See: %s') % (vs_express_path, compilervars_arch, patch_url)) + major = version[0:2] + versions['intel ' + major] = targets + +@conf +def detect_msvc(self): + return self.setup_msvc(self.get_msvc_versions()) + +@conf +def get_msvc_versions(self): + """ + :return: platform to compiler configurations + :rtype: dict + """ + dct = Utils.ordered_iter_dict() + self.gather_icl_versions(dct) + self.gather_intel_composer_versions(dct) + self.gather_wsdk_versions(dct) + self.gather_msvc_versions(dct) + self.gather_vswhere_versions(dct) + Logs.debug('msvc: detected versions %r', list(dct.keys())) + return dct + +@conf +def find_lt_names_msvc(self, libname, is_static=False): + """ + Win32/MSVC specific code to glean out information from libtool la files. + this function is not attached to the task_gen class. Returns a triplet: + (library absolute path, library name without extension, whether the library is static) + """ + lt_names=[ + 'lib%s.la' % libname, + '%s.la' % libname, + ] + + for path in self.env.LIBPATH: + for la in lt_names: + laf=os.path.join(path,la) + dll=None + if os.path.exists(laf): + ltdict = Utils.read_la_file(laf) + lt_libdir=None + if ltdict.get('libdir', ''): + lt_libdir = ltdict['libdir'] + if not is_static and ltdict.get('library_names', ''): + dllnames=ltdict['library_names'].split() + dll=dllnames[0].lower() + dll=re.sub(r'\.dll$', '', dll) + return (lt_libdir, dll, False) + elif ltdict.get('old_library', ''): + olib=ltdict['old_library'] + if os.path.exists(os.path.join(path,olib)): + return (path, olib, True) + elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)): + return (lt_libdir, olib, True) + else: + return (None, olib, True) + else: + raise self.errors.WafError('invalid libtool object file: %s' % laf) + return (None, None, None) + +@conf +def libname_msvc(self, libname, is_static=False): + lib = libname.lower() + lib = re.sub(r'\.lib$','',lib) + + if lib in g_msvc_systemlibs: + return lib + + lib=re.sub('^lib','',lib) + + if lib == 'm': + return None + + (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static) + + if lt_path != None and lt_libname != None: + if lt_static: + # file existence check has been made by find_lt_names + return os.path.join(lt_path,lt_libname) + + if lt_path != None: + _libpaths = [lt_path] + self.env.LIBPATH + else: + _libpaths = self.env.LIBPATH + + static_libs=[ + 'lib%ss.lib' % lib, + 'lib%s.lib' % lib, + '%ss.lib' % lib, + '%s.lib' %lib, + ] + + dynamic_libs=[ + 'lib%s.dll.lib' % lib, + 'lib%s.dll.a' % lib, + '%s.dll.lib' % lib, + '%s.dll.a' % lib, + 'lib%s_d.lib' % lib, + '%s_d.lib' % lib, + '%s.lib' %lib, + ] + + libnames=static_libs + if not is_static: + libnames=dynamic_libs + static_libs + + for path in _libpaths: + for libn in libnames: + if os.path.exists(os.path.join(path, libn)): + Logs.debug('msvc: lib found: %s', os.path.join(path,libn)) + return re.sub(r'\.lib$', '',libn) + + #if no lib can be found, just return the libname as msvc expects it + self.fatal('The library %r could not be found' % libname) + return re.sub(r'\.lib$', '', libname) + +@conf +def check_lib_msvc(self, libname, is_static=False, uselib_store=None): + """ + Ideally we should be able to place the lib in the right env var, either STLIB or LIB, + but we don't distinguish static libs from shared libs. + This is ok since msvc doesn't have any special linker flag to select static libs (no env.STLIB_MARKER) + """ + libn = self.libname_msvc(libname, is_static) + + if not uselib_store: + uselib_store = libname.upper() + + if False and is_static: # disabled + self.env['STLIB_' + uselib_store] = [libn] + else: + self.env['LIB_' + uselib_store] = [libn] + +@conf +def check_libs_msvc(self, libnames, is_static=False): + for libname in Utils.to_list(libnames): + self.check_lib_msvc(libname, is_static) + +def configure(conf): + """ + Configuration methods to call for detecting msvc + """ + conf.autodetect(True) + conf.find_msvc() + conf.msvc_common_flags() + conf.cc_load_tools() + conf.cxx_load_tools() + conf.cc_add_flags() + conf.cxx_add_flags() + conf.link_add_flags() + conf.visual_studio_add_flags() + +@conf +def no_autodetect(conf): + conf.env.NO_MSVC_DETECT = 1 + configure(conf) + +@conf +def autodetect(conf, arch=False): + v = conf.env + if v.NO_MSVC_DETECT: + return + + compiler, version, path, includes, libdirs, cpu = conf.detect_msvc() + if arch: + v.DEST_CPU = cpu + + v.PATH = path + v.INCLUDES = includes + v.LIBPATH = libdirs + v.MSVC_COMPILER = compiler + try: + v.MSVC_VERSION = float(version) + except ValueError: + v.MSVC_VERSION = float(version[:-3]) + +def _get_prog_names(conf, compiler): + if compiler == 'intel': + compiler_name = 'ICL' + linker_name = 'XILINK' + lib_name = 'XILIB' + else: + # assumes CL.exe + compiler_name = 'CL' + linker_name = 'LINK' + lib_name = 'LIB' + return compiler_name, linker_name, lib_name + +@conf +def find_msvc(conf): + """Due to path format limitations, limit operation only to native Win32. Yeah it sucks.""" + if sys.platform == 'cygwin': + conf.fatal('MSVC module does not work under cygwin Python!') + + # the autodetection is supposed to be performed before entering in this method + v = conf.env + path = v.PATH + compiler = v.MSVC_COMPILER + version = v.MSVC_VERSION + + compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) + v.MSVC_MANIFEST = (compiler == 'msvc' and version >= 8) or (compiler == 'wsdk' and version >= 6) or (compiler == 'intel' and version >= 11) + + # compiler + cxx = conf.find_program(compiler_name, var='CXX', path_list=path) + + # before setting anything, check if the compiler is really msvc + env = dict(conf.environ) + if path: + env.update(PATH = ';'.join(path)) + if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env): + conf.fatal('the msvc compiler could not be identified') + + # c/c++ compiler + v.CC = v.CXX = cxx + v.CC_NAME = v.CXX_NAME = 'msvc' + + # linker + if not v.LINK_CXX: + conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name, var='LINK_CXX') + + if not v.LINK_CC: + v.LINK_CC = v.LINK_CXX + + # staticlib linker + if not v.AR: + stliblink = conf.find_program(lib_name, path_list=path, var='AR') + if not stliblink: + return + v.ARFLAGS = ['/nologo'] + + # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later + if v.MSVC_MANIFEST: + conf.find_program('MT', path_list=path, var='MT') + v.MTFLAGS = ['/nologo'] + + try: + conf.load('winres') + except Errors.ConfigurationError: + Logs.warn('Resource compiler not found. Compiling resource file is disabled') + +@conf +def visual_studio_add_flags(self): + """visual studio flags found in the system environment""" + v = self.env + if self.environ.get('INCLUDE'): + v.prepend_value('INCLUDES', [x for x in self.environ['INCLUDE'].split(';') if x]) # notice the 'S' + if self.environ.get('LIB'): + v.prepend_value('LIBPATH', [x for x in self.environ['LIB'].split(';') if x]) + +@conf +def msvc_common_flags(conf): + """ + Setup the flags required for executing the msvc compiler + """ + v = conf.env + + v.DEST_BINFMT = 'pe' + v.append_value('CFLAGS', ['/nologo']) + v.append_value('CXXFLAGS', ['/nologo']) + v.append_value('LINKFLAGS', ['/nologo']) + v.DEFINES_ST = '/D%s' + + v.CC_SRC_F = '' + v.CC_TGT_F = ['/c', '/Fo'] + v.CXX_SRC_F = '' + v.CXX_TGT_F = ['/c', '/Fo'] + + if (v.MSVC_COMPILER == 'msvc' and v.MSVC_VERSION >= 8) or (v.MSVC_COMPILER == 'wsdk' and v.MSVC_VERSION >= 6): + v.CC_TGT_F = ['/FC'] + v.CC_TGT_F + v.CXX_TGT_F = ['/FC'] + v.CXX_TGT_F + + v.CPPPATH_ST = '/I%s' # template for adding include paths + + v.AR_TGT_F = v.CCLNK_TGT_F = v.CXXLNK_TGT_F = '/OUT:' + + # CRT specific flags + v.CFLAGS_CRT_MULTITHREADED = v.CXXFLAGS_CRT_MULTITHREADED = ['/MT'] + v.CFLAGS_CRT_MULTITHREADED_DLL = v.CXXFLAGS_CRT_MULTITHREADED_DLL = ['/MD'] + + v.CFLAGS_CRT_MULTITHREADED_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DBG = ['/MTd'] + v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = ['/MDd'] + + v.LIB_ST = '%s.lib' + v.LIBPATH_ST = '/LIBPATH:%s' + v.STLIB_ST = '%s.lib' + v.STLIBPATH_ST = '/LIBPATH:%s' + + if v.MSVC_MANIFEST: + v.append_value('LINKFLAGS', ['/MANIFEST']) + + v.CFLAGS_cshlib = [] + v.CXXFLAGS_cxxshlib = [] + v.LINKFLAGS_cshlib = v.LINKFLAGS_cxxshlib = ['/DLL'] + v.cshlib_PATTERN = v.cxxshlib_PATTERN = '%s.dll' + v.implib_PATTERN = '%s.lib' + v.IMPLIB_ST = '/IMPLIB:%s' + + v.LINKFLAGS_cstlib = [] + v.cstlib_PATTERN = v.cxxstlib_PATTERN = '%s.lib' + + v.cprogram_PATTERN = v.cxxprogram_PATTERN = '%s.exe' + + v.def_PATTERN = '/def:%s' + + +####################################################################################################### +##### conf above, build below + +@after_method('apply_link') +@feature('c', 'cxx') +def apply_flags_msvc(self): + """ + Add additional flags implied by msvc, such as subsystems and pdb files:: + + def build(bld): + bld.stlib(source='main.c', target='bar', subsystem='gruik') + """ + if self.env.CC_NAME != 'msvc' or not getattr(self, 'link_task', None): + return + + is_static = isinstance(self.link_task, ccroot.stlink_task) + + subsystem = getattr(self, 'subsystem', '') + if subsystem: + subsystem = '/subsystem:%s' % subsystem + flags = is_static and 'ARFLAGS' or 'LINKFLAGS' + self.env.append_value(flags, subsystem) + + if not is_static: + for f in self.env.LINKFLAGS: + d = f.lower() + if d[1:] in ('debug', 'debug:full', 'debug:fastlink'): + pdbnode = self.link_task.outputs[0].change_ext('.pdb') + self.link_task.outputs.append(pdbnode) + + if getattr(self, 'install_task', None): + self.pdb_install_task = self.add_install_files( + install_to=self.install_task.install_to, install_from=pdbnode) + break + +@feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib') +@after_method('apply_link') +def apply_manifest(self): + """ + Special linker for MSVC with support for embedding manifests into DLL's + and executables compiled by Visual Studio 2005 or probably later. Without + the manifest file, the binaries are unusable. + See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx + """ + if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None): + out_node = self.link_task.outputs[0] + man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') + self.link_task.outputs.append(man_node) + self.env.DO_MANIFEST = True + +def make_winapp(self, family): + append = self.env.append_unique + append('DEFINES', 'WINAPI_FAMILY=%s' % family) + append('CXXFLAGS', ['/ZW', '/TP']) + for lib_path in self.env.LIBPATH: + append('CXXFLAGS','/AI%s'%lib_path) + +@feature('winphoneapp') +@after_method('process_use') +@after_method('propagate_uselib_vars') +def make_winphone_app(self): + """ + Insert configuration flags for windows phone applications (adds /ZW, /TP...) + """ + make_winapp(self, 'WINAPI_FAMILY_PHONE_APP') + self.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib']) + +@feature('winapp') +@after_method('process_use') +@after_method('propagate_uselib_vars') +def make_windows_app(self): + """ + Insert configuration flags for windows applications (adds /ZW, /TP...) + """ + make_winapp(self, 'WINAPI_FAMILY_DESKTOP_APP') diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/nasm.py b/ldb-2.0.8/third_party/waf/waflib/Tools/nasm.py new file mode 100644 index 0000000..9c51c18 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/nasm.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2008-2018 (ita) + +""" +Nasm tool (asm processing) +""" + +import os +import waflib.Tools.asm # leave this +from waflib.TaskGen import feature + +@feature('asm') +def apply_nasm_vars(self): + """provided for compatibility""" + self.env.append_value('ASFLAGS', self.to_list(getattr(self, 'nasm_flags', []))) + +def configure(conf): + """ + Detect nasm/yasm and set the variable *AS* + """ + conf.find_program(['nasm', 'yasm'], var='AS') + conf.env.AS_TGT_F = ['-o'] + conf.env.ASLNK_TGT_F = ['-o'] + conf.load('asm') + conf.env.ASMPATH_ST = '-I%s' + os.sep + txt = conf.cmd_and_log(conf.env.AS + ['--version']) + if 'yasm' in txt.lower(): + conf.env.ASM_NAME = 'yasm' + else: + conf.env.ASM_NAME = 'nasm' diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/nobuild.py b/ldb-2.0.8/third_party/waf/waflib/Tools/nobuild.py new file mode 100644 index 0000000..2e4b055 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/nobuild.py @@ -0,0 +1,24 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2015 (ita) + +""" +Override the build commands to write empty files. +This is useful for profiling and evaluating the Python overhead. + +To use:: + + def build(bld): + ... + bld.load('nobuild') + +""" + +from waflib import Task +def build(bld): + def run(self): + for x in self.outputs: + x.write('') + for (name, cls) in Task.classes.items(): + cls.run = run + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/perl.py b/ldb-2.0.8/third_party/waf/waflib/Tools/perl.py new file mode 100644 index 0000000..32b03fb --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/perl.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# encoding: utf-8 +# andersg at 0x63.nu 2007 +# Thomas Nagy 2016-2018 (ita) + +""" +Support for Perl extensions. A C/C++ compiler is required:: + + def options(opt): + opt.load('compiler_c perl') + def configure(conf): + conf.load('compiler_c perl') + conf.check_perl_version((5,6,0)) + conf.check_perl_ext_devel() + conf.check_perl_module('Cairo') + conf.check_perl_module('Devel::PPPort 4.89') + def build(bld): + bld( + features = 'c cshlib perlext', + source = 'Mytest.xs', + target = 'Mytest', + install_path = '${ARCHDIR_PERL}/auto') + bld.install_files('${ARCHDIR_PERL}', 'Mytest.pm') +""" + +import os +from waflib import Task, Options, Utils, Errors +from waflib.Configure import conf +from waflib.TaskGen import extension, feature, before_method + +@before_method('apply_incpaths', 'apply_link', 'propagate_uselib_vars') +@feature('perlext') +def init_perlext(self): + """ + Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the + *lib* prefix from library names. + """ + self.uselib = self.to_list(getattr(self, 'uselib', [])) + if not 'PERLEXT' in self.uselib: + self.uselib.append('PERLEXT') + self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.perlext_PATTERN + +@extension('.xs') +def xsubpp_file(self, node): + """ + Create :py:class:`waflib.Tools.perl.xsubpp` tasks to process *.xs* files + """ + outnode = node.change_ext('.c') + self.create_task('xsubpp', node, outnode) + self.source.append(outnode) + +class xsubpp(Task.Task): + """ + Process *.xs* files + """ + run_str = '${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' + color = 'BLUE' + ext_out = ['.h'] + +@conf +def check_perl_version(self, minver=None): + """ + Check if Perl is installed, and set the variable PERL. + minver is supposed to be a tuple + """ + res = True + if minver: + cver = '.'.join(map(str,minver)) + else: + cver = '' + + self.start_msg('Checking for minimum perl version %s' % cver) + + perl = self.find_program('perl', var='PERL', value=getattr(Options.options, 'perlbinary', None)) + version = self.cmd_and_log(perl + ["-e", 'printf \"%vd\", $^V']) + if not version: + res = False + version = "Unknown" + elif not minver is None: + ver = tuple(map(int, version.split("."))) + if ver < minver: + res = False + + self.end_msg(version, color=res and 'GREEN' or 'YELLOW') + return res + +@conf +def check_perl_module(self, module): + """ + Check if specified perlmodule is installed. + + The minimum version can be specified by specifying it after modulename + like this:: + + def configure(conf): + conf.check_perl_module("Some::Module 2.92") + """ + cmd = self.env.PERL + ['-e', 'use %s' % module] + self.start_msg('perl module %s' % module) + try: + r = self.cmd_and_log(cmd) + except Errors.WafError: + self.end_msg(False) + return None + self.end_msg(r or True) + return r + +@conf +def check_perl_ext_devel(self): + """ + Check for configuration needed to build perl extensions. + + Sets different xxx_PERLEXT variables in the environment. + + Also sets the ARCHDIR_PERL variable useful as installation path, + which can be overridden by ``--with-perl-archdir`` option. + """ + + env = self.env + perl = env.PERL + if not perl: + self.fatal('find perl first') + + def cmd_perl_config(s): + return perl + ['-MConfig', '-e', 'print \"%s\"' % s] + def cfg_str(cfg): + return self.cmd_and_log(cmd_perl_config(cfg)) + def cfg_lst(cfg): + return Utils.to_list(cfg_str(cfg)) + def find_xsubpp(): + for var in ('privlib', 'vendorlib'): + xsubpp = cfg_lst('$Config{%s}/ExtUtils/xsubpp$Config{exe_ext}' % var) + if xsubpp and os.path.isfile(xsubpp[0]): + return xsubpp + return self.find_program('xsubpp') + + env.LINKFLAGS_PERLEXT = cfg_lst('$Config{lddlflags}') + env.INCLUDES_PERLEXT = cfg_lst('$Config{archlib}/CORE') + env.CFLAGS_PERLEXT = cfg_lst('$Config{ccflags} $Config{cccdlflags}') + env.EXTUTILS_TYPEMAP = cfg_lst('$Config{privlib}/ExtUtils/typemap') + env.XSUBPP = find_xsubpp() + + if not getattr(Options.options, 'perlarchdir', None): + env.ARCHDIR_PERL = cfg_str('$Config{sitearch}') + else: + env.ARCHDIR_PERL = getattr(Options.options, 'perlarchdir') + + env.perlext_PATTERN = '%s.' + cfg_str('$Config{dlext}') + +def options(opt): + """ + Add the ``--with-perl-archdir`` and ``--with-perl-binary`` command-line options. + """ + opt.add_option('--with-perl-binary', type='string', dest='perlbinary', help = 'Specify alternate perl binary', default=None) + opt.add_option('--with-perl-archdir', type='string', dest='perlarchdir', help = 'Specify directory where to install arch specific files', default=None) + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/python.py b/ldb-2.0.8/third_party/waf/waflib/Tools/python.py new file mode 100644 index 0000000..7c45a76 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/python.py @@ -0,0 +1,644 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2007-2015 (ita) +# Gustavo Carneiro (gjc), 2007 + +""" +Support for Python, detect the headers and libraries and provide +*use* variables to link C/C++ programs against them:: + + def options(opt): + opt.load('compiler_c python') + def configure(conf): + conf.load('compiler_c python') + conf.check_python_version((2,4,2)) + conf.check_python_headers() + def build(bld): + bld.program(features='pyembed', source='a.c', target='myprog') + bld.shlib(features='pyext', source='b.c', target='mylib') +""" + +import os, sys +from waflib import Errors, Logs, Node, Options, Task, Utils +from waflib.TaskGen import extension, before_method, after_method, feature +from waflib.Configure import conf + +FRAG = ''' +#include +#ifdef __cplusplus +extern "C" { +#endif + void Py_Initialize(void); + void Py_Finalize(void); +#ifdef __cplusplus +} +#endif +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + Py_Initialize(); + Py_Finalize(); + return 0; +} +''' +""" +Piece of C/C++ code used in :py:func:`waflib.Tools.python.check_python_headers` +""" + +INST = ''' +import sys, py_compile +py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3], True) +''' +""" +Piece of Python code used in :py:class:`waflib.Tools.python.pyo` and :py:class:`waflib.Tools.python.pyc` for byte-compiling python files +""" + +DISTUTILS_IMP = ['from distutils.sysconfig import get_config_var, get_python_lib'] + +@before_method('process_source') +@feature('py') +def feature_py(self): + """ + Create tasks to byte-compile .py files and install them, if requested + """ + self.install_path = getattr(self, 'install_path', '${PYTHONDIR}') + install_from = getattr(self, 'install_from', None) + if install_from and not isinstance(install_from, Node.Node): + install_from = self.path.find_dir(install_from) + self.install_from = install_from + + ver = self.env.PYTHON_VERSION + if not ver: + self.bld.fatal('Installing python files requires PYTHON_VERSION, try conf.check_python_version') + + if int(ver.replace('.', '')) > 31: + self.install_32 = True + +@extension('.py') +def process_py(self, node): + """ + Add signature of .py file, so it will be byte-compiled when necessary + """ + assert(hasattr(self, 'install_path')), 'add features="py" for target "%s" in "%s/wscript".' % (self.target, self.path.nice_path()) + self.install_from = getattr(self, 'install_from', None) + relative_trick = getattr(self, 'relative_trick', True) + if self.install_from: + assert isinstance(self.install_from, Node.Node), \ + 'add features="py" for target "%s" in "%s/wscript" (%s).' % (self.target, self.path.nice_path(), type(self.install_from)) + + # where to install the python file + if self.install_path: + if self.install_from: + self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=relative_trick) + else: + self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=relative_trick) + + lst = [] + if self.env.PYC: + lst.append('pyc') + if self.env.PYO: + lst.append('pyo') + + if self.install_path: + if self.install_from: + target_dir = node.path_from(self.install_from) if relative_trick else node.name + pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) + else: + target_dir = node.path_from(self.path) if relative_trick else node.name + pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) + else: + pyd = node.abspath() + + for ext in lst: + if self.env.PYTAG and not self.env.NOPYCACHE: + # __pycache__ installation for python 3.2 - PEP 3147 + name = node.name[:-3] + pyobj = node.parent.get_bld().make_node('__pycache__').make_node("%s.%s.%s" % (name, self.env.PYTAG, ext)) + pyobj.parent.mkdir() + else: + pyobj = node.change_ext(".%s" % ext) + + tsk = self.create_task(ext, node, pyobj) + tsk.pyd = pyd + + if self.install_path: + self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=relative_trick) + +class pyc(Task.Task): + """ + Byte-compiling python files + """ + color = 'PINK' + def __str__(self): + node = self.outputs[0] + return node.path_from(node.ctx.launch_node()) + def run(self): + cmd = [Utils.subst_vars('${PYTHON}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd] + ret = self.generator.bld.exec_command(cmd) + return ret + +class pyo(Task.Task): + """ + Byte-compiling python files + """ + color = 'PINK' + def __str__(self): + node = self.outputs[0] + return node.path_from(node.ctx.launch_node()) + def run(self): + cmd = [Utils.subst_vars('${PYTHON}', self.env), Utils.subst_vars('${PYFLAGS_OPT}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd] + ret = self.generator.bld.exec_command(cmd) + return ret + +@feature('pyext') +@before_method('propagate_uselib_vars', 'apply_link') +@after_method('apply_bundle') +def init_pyext(self): + """ + Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the + *lib* prefix from library names. + """ + self.uselib = self.to_list(getattr(self, 'uselib', [])) + if not 'PYEXT' in self.uselib: + self.uselib.append('PYEXT') + # override shlib_PATTERN set by the osx module + self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN = self.env.pyext_PATTERN + self.env.fcshlib_PATTERN = self.env.dshlib_PATTERN = self.env.pyext_PATTERN + + try: + if not self.install_path: + return + except AttributeError: + self.install_path = '${PYTHONARCHDIR}' + +@feature('pyext') +@before_method('apply_link', 'apply_bundle') +def set_bundle(self): + """Mac-specific pyext extension that enables bundles from c_osx.py""" + if Utils.unversioned_sys_platform() == 'darwin': + self.mac_bundle = True + +@before_method('propagate_uselib_vars') +@feature('pyembed') +def init_pyembed(self): + """ + Add the PYEMBED variable. + """ + self.uselib = self.to_list(getattr(self, 'uselib', [])) + if not 'PYEMBED' in self.uselib: + self.uselib.append('PYEMBED') + +@conf +def get_python_variables(self, variables, imports=None): + """ + Spawn a new python process to dump configuration variables + + :param variables: variables to print + :type variables: list of string + :param imports: one import by element + :type imports: list of string + :return: the variable values + :rtype: list of string + """ + if not imports: + try: + imports = self.python_imports + except AttributeError: + imports = DISTUTILS_IMP + + program = list(imports) # copy + program.append('') + for v in variables: + program.append("print(repr(%s))" % v) + os_env = dict(os.environ) + try: + del os_env['MACOSX_DEPLOYMENT_TARGET'] # see comments in the OSX tool + except KeyError: + pass + + try: + out = self.cmd_and_log(self.env.PYTHON + ['-c', '\n'.join(program)], env=os_env) + except Errors.WafError: + self.fatal('The distutils module is unusable: install "python-devel"?') + self.to_log(out) + return_values = [] + for s in out.splitlines(): + s = s.strip() + if not s: + continue + if s == 'None': + return_values.append(None) + elif (s[0] == "'" and s[-1] == "'") or (s[0] == '"' and s[-1] == '"'): + return_values.append(eval(s)) + elif s[0].isdigit(): + return_values.append(int(s)) + else: break + return return_values + +@conf +def test_pyembed(self, mode, msg='Testing pyembed configuration'): + self.check(header_name='Python.h', define_name='HAVE_PYEMBED', msg=msg, + fragment=FRAG, errmsg='Could not build a python embedded interpreter', + features='%s %sprogram pyembed' % (mode, mode)) + +@conf +def test_pyext(self, mode, msg='Testing pyext configuration'): + self.check(header_name='Python.h', define_name='HAVE_PYEXT', msg=msg, + fragment=FRAG, errmsg='Could not build python extensions', + features='%s %sshlib pyext' % (mode, mode)) + +@conf +def python_cross_compile(self, features='pyembed pyext'): + """ + For cross-compilation purposes, it is possible to bypass the normal detection and set the flags that you want: + PYTHON_VERSION='3.4' PYTAG='cpython34' pyext_PATTERN="%s.so" PYTHON_LDFLAGS='-lpthread -ldl' waf configure + + The following variables are used: + PYTHON_VERSION required + PYTAG required + PYTHON_LDFLAGS required + pyext_PATTERN required + PYTHON_PYEXT_LDFLAGS + PYTHON_PYEMBED_LDFLAGS + """ + features = Utils.to_list(features) + if not ('PYTHON_LDFLAGS' in self.environ or 'PYTHON_PYEXT_LDFLAGS' in self.environ or 'PYTHON_PYEMBED_LDFLAGS' in self.environ): + return False + + for x in 'PYTHON_VERSION PYTAG pyext_PATTERN'.split(): + if not x in self.environ: + self.fatal('Please set %s in the os environment' % x) + else: + self.env[x] = self.environ[x] + + xx = self.env.CXX_NAME and 'cxx' or 'c' + if 'pyext' in features: + flags = self.environ.get('PYTHON_PYEXT_LDFLAGS', self.environ.get('PYTHON_LDFLAGS')) + if flags is None: + self.fatal('No flags provided through PYTHON_PYEXT_LDFLAGS as required') + else: + self.parse_flags(flags, 'PYEXT') + self.test_pyext(xx) + if 'pyembed' in features: + flags = self.environ.get('PYTHON_PYEMBED_LDFLAGS', self.environ.get('PYTHON_LDFLAGS')) + if flags is None: + self.fatal('No flags provided through PYTHON_PYEMBED_LDFLAGS as required') + else: + self.parse_flags(flags, 'PYEMBED') + self.test_pyembed(xx) + return True + +@conf +def check_python_headers(conf, features='pyembed pyext'): + """ + Check for headers and libraries necessary to extend or embed python by using the module *distutils*. + On success the environment variables xxx_PYEXT and xxx_PYEMBED are added: + + * PYEXT: for compiling python extensions + * PYEMBED: for embedding a python interpreter + """ + features = Utils.to_list(features) + assert ('pyembed' in features) or ('pyext' in features), "check_python_headers features must include 'pyembed' and/or 'pyext'" + env = conf.env + if not env.CC_NAME and not env.CXX_NAME: + conf.fatal('load a compiler first (gcc, g++, ..)') + + # bypass all the code below for cross-compilation + if conf.python_cross_compile(features): + return + + if not env.PYTHON_VERSION: + conf.check_python_version() + + pybin = env.PYTHON + if not pybin: + conf.fatal('Could not find the python executable') + + # so we actually do all this for compatibility reasons and for obtaining pyext_PATTERN below + v = 'prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split() + try: + lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v]) + except RuntimeError: + conf.fatal("Python development headers not found (-v for details).") + + vals = ['%s = %r' % (x, y) for (x, y) in zip(v, lst)] + conf.to_log("Configuration returned from %r:\n%s\n" % (pybin, '\n'.join(vals))) + + dct = dict(zip(v, lst)) + x = 'MACOSX_DEPLOYMENT_TARGET' + if dct[x]: + env[x] = conf.environ[x] = dct[x] + env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake + + + # Try to get pythonX.Y-config + num = '.'.join(env.PYTHON_VERSION.split('.')[:2]) + conf.find_program([''.join(pybin) + '-config', 'python%s-config' % num, 'python-config-%s' % num, 'python%sm-config' % num], var='PYTHON_CONFIG', msg="python-config", mandatory=False) + + if env.PYTHON_CONFIG: + # check python-config output only once + if conf.env.HAVE_PYTHON_H: + return + + # python2.6-config requires 3 runs + all_flags = [['--cflags', '--libs', '--ldflags']] + if sys.hexversion < 0x2070000: + all_flags = [[k] for k in all_flags[0]] + + xx = env.CXX_NAME and 'cxx' or 'c' + + if 'pyembed' in features: + for flags in all_flags: + # Python 3.8 has different flags for pyembed, needs --embed + embedflags = flags + ['--embed'] + try: + conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(embedflags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=embedflags) + except conf.errors.ConfigurationError: + # However Python < 3.8 doesn't accept --embed, so we need a fallback + conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=flags) + + try: + conf.test_pyembed(xx) + except conf.errors.ConfigurationError: + # python bug 7352 + if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']: + env.append_unique('LIBPATH_PYEMBED', [dct['LIBDIR']]) + conf.test_pyembed(xx) + else: + raise + + if 'pyext' in features: + for flags in all_flags: + conf.check_cfg(msg='Asking python-config for pyext %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEXT', args=flags) + + try: + conf.test_pyext(xx) + except conf.errors.ConfigurationError: + # python bug 7352 + if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']: + env.append_unique('LIBPATH_PYEXT', [dct['LIBDIR']]) + conf.test_pyext(xx) + else: + raise + + conf.define('HAVE_PYTHON_H', 1) + return + + # No python-config, do something else on windows systems + all_flags = dct['LDFLAGS'] + ' ' + dct['CFLAGS'] + conf.parse_flags(all_flags, 'PYEMBED') + + all_flags = dct['LDFLAGS'] + ' ' + dct['LDSHARED'] + ' ' + dct['CFLAGS'] + conf.parse_flags(all_flags, 'PYEXT') + + result = None + if not dct["LDVERSION"]: + dct["LDVERSION"] = env.PYTHON_VERSION + + # further simplification will be complicated + for name in ('python' + dct['LDVERSION'], 'python' + env.PYTHON_VERSION + 'm', 'python' + env.PYTHON_VERSION.replace('.', '')): + + # LIBPATH_PYEMBED is already set; see if it works. + if not result and env.LIBPATH_PYEMBED: + path = env.LIBPATH_PYEMBED + conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n" % path) + result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBPATH_PYEMBED' % name) + + if not result and dct['LIBDIR']: + path = [dct['LIBDIR']] + conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n" % path) + result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBDIR' % name) + + if not result and dct['LIBPL']: + path = [dct['LIBPL']] + conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") + result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in python_LIBPL' % name) + + if not result: + path = [os.path.join(dct['prefix'], "libs")] + conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") + result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) + + if result: + break # do not forget to set LIBPATH_PYEMBED + + if result: + env.LIBPATH_PYEMBED = path + env.append_value('LIB_PYEMBED', [name]) + else: + conf.to_log("\n\n### LIB NOT FOUND\n") + + # under certain conditions, python extensions must link to + # python libraries, not just python embedding programs. + if Utils.is_win32 or dct['Py_ENABLE_SHARED']: + env.LIBPATH_PYEXT = env.LIBPATH_PYEMBED + env.LIB_PYEXT = env.LIB_PYEMBED + + conf.to_log("Include path for Python extensions (found via distutils module): %r\n" % (dct['INCLUDEPY'],)) + env.INCLUDES_PYEXT = [dct['INCLUDEPY']] + env.INCLUDES_PYEMBED = [dct['INCLUDEPY']] + + # Code using the Python API needs to be compiled with -fno-strict-aliasing + if env.CC_NAME == 'gcc': + env.append_unique('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) + env.append_unique('CFLAGS_PYEXT', ['-fno-strict-aliasing']) + if env.CXX_NAME == 'gcc': + env.append_unique('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) + env.append_unique('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) + + if env.CC_NAME == "msvc": + from distutils.msvccompiler import MSVCCompiler + dist_compiler = MSVCCompiler() + dist_compiler.initialize() + env.append_value('CFLAGS_PYEXT', dist_compiler.compile_options) + env.append_value('CXXFLAGS_PYEXT', dist_compiler.compile_options) + env.append_value('LINKFLAGS_PYEXT', dist_compiler.ldflags_shared) + + # See if it compiles + conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', uselib='PYEMBED', fragment=FRAG, errmsg='Distutils not installed? Broken python installation? Get python-config now!') + +@conf +def check_python_version(conf, minver=None): + """ + Check if the python interpreter is found matching a given minimum version. + minver should be a tuple, eg. to check for python >= 2.4.2 pass (2,4,2) as minver. + + If successful, PYTHON_VERSION is defined as 'MAJOR.MINOR' (eg. '2.4') + of the actual python version found, and PYTHONDIR and PYTHONARCHDIR + are defined, pointing to the site-packages directories appropriate for + this python version, where modules/packages/extensions should be + installed. + + :param minver: minimum version + :type minver: tuple of int + """ + assert minver is None or isinstance(minver, tuple) + pybin = conf.env.PYTHON + if not pybin: + conf.fatal('could not find the python executable') + + # Get python version string + cmd = pybin + ['-c', 'import sys\nfor x in sys.version_info: print(str(x))'] + Logs.debug('python: Running python command %r', cmd) + lines = conf.cmd_and_log(cmd).split() + assert len(lines) == 5, "found %r lines, expected 5: %r" % (len(lines), lines) + pyver_tuple = (int(lines[0]), int(lines[1]), int(lines[2]), lines[3], int(lines[4])) + + # Compare python version with the minimum required + result = (minver is None) or (pyver_tuple >= minver) + + if result: + # define useful environment variables + pyver = '.'.join([str(x) for x in pyver_tuple[:2]]) + conf.env.PYTHON_VERSION = pyver + + if 'PYTHONDIR' in conf.env: + # Check if --pythondir was specified + pydir = conf.env.PYTHONDIR + elif 'PYTHONDIR' in conf.environ: + # Check environment for PYTHONDIR + pydir = conf.environ['PYTHONDIR'] + else: + # Finally, try to guess + if Utils.is_win32: + (python_LIBDEST, pydir) = conf.get_python_variables( + ["get_config_var('LIBDEST') or ''", + "get_python_lib(standard_lib=0) or ''"]) + else: + python_LIBDEST = None + (pydir,) = conf.get_python_variables( ["get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX]) + if python_LIBDEST is None: + if conf.env.LIBDIR: + python_LIBDEST = os.path.join(conf.env.LIBDIR, 'python' + pyver) + else: + python_LIBDEST = os.path.join(conf.env.PREFIX, 'lib', 'python' + pyver) + + if 'PYTHONARCHDIR' in conf.env: + # Check if --pythonarchdir was specified + pyarchdir = conf.env.PYTHONARCHDIR + elif 'PYTHONARCHDIR' in conf.environ: + # Check environment for PYTHONDIR + pyarchdir = conf.environ['PYTHONARCHDIR'] + else: + # Finally, try to guess + (pyarchdir, ) = conf.get_python_variables( ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX]) + if not pyarchdir: + pyarchdir = pydir + + if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist + conf.define('PYTHONDIR', pydir) + conf.define('PYTHONARCHDIR', pyarchdir) + + conf.env.PYTHONDIR = pydir + conf.env.PYTHONARCHDIR = pyarchdir + + # Feedback + pyver_full = '.'.join(map(str, pyver_tuple[:3])) + if minver is None: + conf.msg('Checking for python version', pyver_full) + else: + minver_str = '.'.join(map(str, minver)) + conf.msg('Checking for python version >= %s' % (minver_str,), pyver_full, color=result and 'GREEN' or 'YELLOW') + + if not result: + conf.fatal('The python version is too old, expecting %r' % (minver,)) + +PYTHON_MODULE_TEMPLATE = ''' +import %s as current_module +version = getattr(current_module, '__version__', None) +if version is not None: + print(str(version)) +else: + print('unknown version') +''' + +@conf +def check_python_module(conf, module_name, condition=''): + """ + Check if the selected python interpreter can import the given python module:: + + def configure(conf): + conf.check_python_module('pygccxml') + conf.check_python_module('re', condition="ver > num(2, 0, 4) and ver <= num(3, 0, 0)") + + :param module_name: module + :type module_name: string + """ + msg = "Checking for python module %r" % module_name + if condition: + msg = '%s (%s)' % (msg, condition) + conf.start_msg(msg) + try: + ret = conf.cmd_and_log(conf.env.PYTHON + ['-c', PYTHON_MODULE_TEMPLATE % module_name]) + except Errors.WafError: + conf.end_msg(False) + conf.fatal('Could not find the python module %r' % module_name) + + ret = ret.strip() + if condition: + conf.end_msg(ret) + if ret == 'unknown version': + conf.fatal('Could not check the %s version' % module_name) + + from distutils.version import LooseVersion + def num(*k): + if isinstance(k[0], int): + return LooseVersion('.'.join([str(x) for x in k])) + else: + return LooseVersion(k[0]) + d = {'num': num, 'ver': LooseVersion(ret)} + ev = eval(condition, {}, d) + if not ev: + conf.fatal('The %s version does not satisfy the requirements' % module_name) + else: + if ret == 'unknown version': + conf.end_msg(True) + else: + conf.end_msg(ret) + +def configure(conf): + """ + Detect the python interpreter + """ + v = conf.env + if getattr(Options.options, 'pythondir', None): + v.PYTHONDIR = Options.options.pythondir + if getattr(Options.options, 'pythonarchdir', None): + v.PYTHONARCHDIR = Options.options.pythonarchdir + if getattr(Options.options, 'nopycache', None): + v.NOPYCACHE=Options.options.nopycache + + if not v.PYTHON: + v.PYTHON = [getattr(Options.options, 'python', None) or sys.executable] + v.PYTHON = Utils.to_list(v.PYTHON) + conf.find_program('python', var='PYTHON') + + v.PYFLAGS = '' + v.PYFLAGS_OPT = '-O' + + v.PYC = getattr(Options.options, 'pyc', 1) + v.PYO = getattr(Options.options, 'pyo', 1) + + try: + v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import imp;print(imp.get_tag())"]).strip() + except Errors.WafError: + pass + +def options(opt): + """ + Add python-specific options + """ + pyopt=opt.add_option_group("Python Options") + pyopt.add_option('--nopyc', dest = 'pyc', action='store_false', default=1, + help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]') + pyopt.add_option('--nopyo', dest='pyo', action='store_false', default=1, + help='Do not install optimised compiled .pyo files (configuration) [Default:install]') + pyopt.add_option('--nopycache',dest='nopycache', action='store_true', + help='Do not use __pycache__ directory to install objects [Default:auto]') + pyopt.add_option('--python', dest="python", + help='python binary to be used [Default: %s]' % sys.executable) + pyopt.add_option('--pythondir', dest='pythondir', + help='Installation path for python modules (py, platform-independent .py and .pyc files)') + pyopt.add_option('--pythonarchdir', dest='pythonarchdir', + help='Installation path for python extension (pyext, platform-dependent .so or .dylib files)') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/qt5.py b/ldb-2.0.8/third_party/waf/waflib/Tools/qt5.py new file mode 100644 index 0000000..287c253 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/qt5.py @@ -0,0 +1,800 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +""" +This tool helps with finding Qt5 tools and libraries, +and also provides syntactic sugar for using Qt5 tools. + +The following snippet illustrates the tool usage:: + + def options(opt): + opt.load('compiler_cxx qt5') + + def configure(conf): + conf.load('compiler_cxx qt5') + + def build(bld): + bld( + features = 'qt5 cxx cxxprogram', + uselib = 'QT5CORE QT5GUI QT5OPENGL QT5SVG', + source = 'main.cpp textures.qrc aboutDialog.ui', + target = 'window', + ) + +Here, the UI description and resource files will be processed +to generate code. + +Usage +===== + +Load the "qt5" tool. + +You also need to edit your sources accordingly: + +- the normal way of doing things is to have your C++ files + include the .moc file. + This is regarded as the best practice (and provides much faster + compilations). + It also implies that the include paths have beenset properly. + +- to have the include paths added automatically, use the following:: + + from waflib.TaskGen import feature, before_method, after_method + @feature('cxx') + @after_method('process_source') + @before_method('apply_incpaths') + def add_includes_paths(self): + incs = set(self.to_list(getattr(self, 'includes', ''))) + for x in self.compiled_tasks: + incs.add(x.inputs[0].parent.path_from(self.path)) + self.includes = sorted(incs) + +Note: another tool provides Qt processing that does not require +.moc includes, see 'playground/slow_qt/'. + +A few options (--qt{dir,bin,...}) and environment variables +(QT5_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool, +tool path selection, etc; please read the source for more info. + +The detection uses pkg-config on Linux by default. To force static library detection use: +QT5_XCOMPILE=1 QT5_FORCE_STATIC=1 waf configure +""" + +from __future__ import with_statement + +try: + from xml.sax import make_parser + from xml.sax.handler import ContentHandler +except ImportError: + has_xml = False + ContentHandler = object +else: + has_xml = True + +import os, sys, re +from waflib.Tools import cxx +from waflib import Build, Task, Utils, Options, Errors, Context +from waflib.TaskGen import feature, after_method, extension, before_method +from waflib.Configure import conf +from waflib import Logs + +MOC_H = ['.h', '.hpp', '.hxx', '.hh'] +""" +File extensions associated to .moc files +""" + +EXT_RCC = ['.qrc'] +""" +File extension for the resource (.qrc) files +""" + +EXT_UI = ['.ui'] +""" +File extension for the user interface (.ui) files +""" + +EXT_QT5 = ['.cpp', '.cc', '.cxx', '.C'] +""" +File extensions of C++ files that may require a .moc processing +""" + +class qxx(Task.classes['cxx']): + """ + Each C++ file can have zero or several .moc files to create. + They are known only when the files are scanned (preprocessor) + To avoid scanning the c++ files each time (parsing C/C++), the results + are retrieved from the task cache (bld.node_deps/bld.raw_deps). + The moc tasks are also created *dynamically* during the build. + """ + + def __init__(self, *k, **kw): + Task.Task.__init__(self, *k, **kw) + self.moc_done = 0 + + def runnable_status(self): + """ + Compute the task signature to make sure the scanner was executed. Create the + moc tasks by using :py:meth:`waflib.Tools.qt5.qxx.add_moc_tasks` (if necessary), + then postpone the task execution (there is no need to recompute the task signature). + """ + if self.moc_done: + return Task.Task.runnable_status(self) + else: + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + self.add_moc_tasks() + return Task.Task.runnable_status(self) + + def create_moc_task(self, h_node, m_node): + """ + If several libraries use the same classes, it is possible that moc will run several times (Issue 1318) + It is not possible to change the file names, but we can assume that the moc transformation will be identical, + and the moc tasks can be shared in a global cache. + """ + try: + moc_cache = self.generator.bld.moc_cache + except AttributeError: + moc_cache = self.generator.bld.moc_cache = {} + + try: + return moc_cache[h_node] + except KeyError: + tsk = moc_cache[h_node] = Task.classes['moc'](env=self.env, generator=self.generator) + tsk.set_inputs(h_node) + tsk.set_outputs(m_node) + tsk.env.append_unique('MOC_FLAGS', '-i') + + if self.generator: + self.generator.tasks.append(tsk) + + # direct injection in the build phase (safe because called from the main thread) + gen = self.generator.bld.producer + gen.outstanding.append(tsk) + gen.total += 1 + + return tsk + + else: + # remove the signature, it must be recomputed with the moc task + delattr(self, 'cache_sig') + + def add_moc_tasks(self): + """ + Creates moc tasks by looking in the list of file dependencies ``bld.raw_deps[self.uid()]`` + """ + node = self.inputs[0] + bld = self.generator.bld + + # skip on uninstall due to generated files + if bld.is_install == Build.UNINSTALL: + return + + try: + # compute the signature once to know if there is a moc file to create + self.signature() + except KeyError: + # the moc file may be referenced somewhere else + pass + else: + # remove the signature, it must be recomputed with the moc task + delattr(self, 'cache_sig') + + include_nodes = [node.parent] + self.generator.includes_nodes + + moctasks = [] + mocfiles = set() + for d in bld.raw_deps.get(self.uid(), []): + if not d.endswith('.moc'): + continue + + # process that base.moc only once + if d in mocfiles: + continue + mocfiles.add(d) + + # find the source associated with the moc file + h_node = None + base2 = d[:-4] + + # foo.moc from foo.cpp + prefix = node.name[:node.name.rfind('.')] + if base2 == prefix: + h_node = node + else: + # this deviates from the standard + # if bar.cpp includes foo.moc, then assume it is from foo.h + for x in include_nodes: + for e in MOC_H: + h_node = x.find_node(base2 + e) + if h_node: + break + else: + continue + break + if h_node: + m_node = h_node.change_ext('.moc') + else: + raise Errors.WafError('No source found for %r which is a moc file' % d) + + # create the moc task + task = self.create_moc_task(h_node, m_node) + moctasks.append(task) + + # simple scheduler dependency: run the moc task before others + self.run_after.update(set(moctasks)) + self.moc_done = 1 + +class trans_update(Task.Task): + """Updates a .ts files from a list of C++ files""" + run_str = '${QT_LUPDATE} ${SRC} -ts ${TGT}' + color = 'BLUE' + +class XMLHandler(ContentHandler): + """ + Parses ``.qrc`` files + """ + def __init__(self): + ContentHandler.__init__(self) + self.buf = [] + self.files = [] + def startElement(self, name, attrs): + if name == 'file': + self.buf = [] + def endElement(self, name): + if name == 'file': + self.files.append(str(''.join(self.buf))) + def characters(self, cars): + self.buf.append(cars) + +@extension(*EXT_RCC) +def create_rcc_task(self, node): + "Creates rcc and cxx tasks for ``.qrc`` files" + rcnode = node.change_ext('_rc.%d.cpp' % self.idx) + self.create_task('rcc', node, rcnode) + cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) + try: + self.compiled_tasks.append(cpptask) + except AttributeError: + self.compiled_tasks = [cpptask] + return cpptask + +@extension(*EXT_UI) +def create_uic_task(self, node): + "Create uic tasks for user interface ``.ui`` definition files" + + """ + If UIC file is used in more than one bld, we would have a conflict in parallel execution + It is not possible to change the file names (like .self.idx. as for objects) as they have + to be referenced by the source file, but we can assume that the transformation will be identical + and the tasks can be shared in a global cache. + """ + try: + uic_cache = self.bld.uic_cache + except AttributeError: + uic_cache = self.bld.uic_cache = {} + + if node not in uic_cache: + uictask = uic_cache[node] = self.create_task('ui5', node) + uictask.outputs = [node.parent.find_or_declare(self.env.ui_PATTERN % node.name[:-3])] + +@extension('.ts') +def add_lang(self, node): + """Adds all the .ts file into ``self.lang``""" + self.lang = self.to_list(getattr(self, 'lang', [])) + [node] + +@feature('qt5') +@before_method('process_source') +def process_mocs(self): + """ + Processes MOC files included in headers:: + + def build(bld): + bld.program(features='qt5', source='main.cpp', target='app', use='QT5CORE', moc='foo.h') + + The build will run moc on foo.h to create moc_foo.n.cpp. The number in the file name + is provided to avoid name clashes when the same headers are used by several targets. + """ + lst = self.to_nodes(getattr(self, 'moc', [])) + self.source = self.to_list(getattr(self, 'source', [])) + for x in lst: + prefix = x.name[:x.name.rfind('.')] # foo.h -> foo + moc_target = 'moc_%s.%d.cpp' % (prefix, self.idx) + moc_node = x.parent.find_or_declare(moc_target) + self.source.append(moc_node) + + self.create_task('moc', x, moc_node) + +@feature('qt5') +@after_method('apply_link') +def apply_qt5(self): + """ + Adds MOC_FLAGS which may be necessary for moc:: + + def build(bld): + bld.program(features='qt5', source='main.cpp', target='app', use='QT5CORE') + + The additional parameters are: + + :param lang: list of translation files (\\*.ts) to process + :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension + :param update: whether to process the C++ files to update the \\*.ts files (use **waf --translate**) + :type update: bool + :param langname: if given, transform the \\*.ts files into a .qrc files to include in the binary file + :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension + """ + if getattr(self, 'lang', None): + qmtasks = [] + for x in self.to_list(self.lang): + if isinstance(x, str): + x = self.path.find_resource(x + '.ts') + qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.%d.qm' % self.idx))) + + if getattr(self, 'update', None) and Options.options.trans_qt5: + cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [ + a.inputs[0] for a in self.tasks if a.inputs and a.inputs[0].name.endswith('.ui')] + for x in qmtasks: + self.create_task('trans_update', cxxnodes, x.inputs) + + if getattr(self, 'langname', None): + qmnodes = [x.outputs[0] for x in qmtasks] + rcnode = self.langname + if isinstance(rcnode, str): + rcnode = self.path.find_or_declare(rcnode + ('.%d.qrc' % self.idx)) + t = self.create_task('qm2rcc', qmnodes, rcnode) + k = create_rcc_task(self, t.outputs[0]) + self.link_task.inputs.append(k.outputs[0]) + + lst = [] + for flag in self.to_list(self.env.CXXFLAGS): + if len(flag) < 2: + continue + f = flag[0:2] + if f in ('-D', '-I', '/D', '/I'): + if (f[0] == '/'): + lst.append('-' + flag[1:]) + else: + lst.append(flag) + self.env.append_value('MOC_FLAGS', lst) + +@extension(*EXT_QT5) +def cxx_hook(self, node): + """ + Re-maps C++ file extensions to the :py:class:`waflib.Tools.qt5.qxx` task. + """ + return self.create_compiled_task('qxx', node) + +class rcc(Task.Task): + """ + Processes ``.qrc`` files + """ + color = 'BLUE' + run_str = '${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' + ext_out = ['.h'] + + def rcname(self): + return os.path.splitext(self.inputs[0].name)[0] + + def scan(self): + """Parse the *.qrc* files""" + if not has_xml: + Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') + return ([], []) + + parser = make_parser() + curHandler = XMLHandler() + parser.setContentHandler(curHandler) + with open(self.inputs[0].abspath(), 'r') as f: + parser.parse(f) + + nodes = [] + names = [] + root = self.inputs[0].parent + for x in curHandler.files: + nd = root.find_resource(x) + if nd: + nodes.append(nd) + else: + names.append(x) + return (nodes, names) + + def quote_flag(self, x): + """ + Override Task.quote_flag. QT parses the argument files + differently than cl.exe and link.exe + + :param x: flag + :type x: string + :return: quoted flag + :rtype: string + """ + return x + + +class moc(Task.Task): + """ + Creates ``.moc`` files + """ + color = 'BLUE' + run_str = '${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' + + def quote_flag(self, x): + """ + Override Task.quote_flag. QT parses the argument files + differently than cl.exe and link.exe + + :param x: flag + :type x: string + :return: quoted flag + :rtype: string + """ + return x + + +class ui5(Task.Task): + """ + Processes ``.ui`` files + """ + color = 'BLUE' + run_str = '${QT_UIC} ${SRC} -o ${TGT}' + ext_out = ['.h'] + +class ts2qm(Task.Task): + """ + Generates ``.qm`` files from ``.ts`` files + """ + color = 'BLUE' + run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' + +class qm2rcc(Task.Task): + """ + Generates ``.qrc`` files from ``.qm`` files + """ + color = 'BLUE' + after = 'ts2qm' + def run(self): + """Create a qrc file including the inputs""" + txt = '\n'.join(['%s' % k.path_from(self.outputs[0].parent) for k in self.inputs]) + code = '\n\n%s\n\n' % txt + self.outputs[0].write(code) + +def configure(self): + """ + Besides the configuration options, the environment variable QT5_ROOT may be used + to give the location of the qt5 libraries (absolute path). + + The detection uses the program ``pkg-config`` through :py:func:`waflib.Tools.config_c.check_cfg` + """ + self.find_qt5_binaries() + self.set_qt5_libs_dir() + self.set_qt5_libs_to_check() + self.set_qt5_defines() + self.find_qt5_libraries() + self.add_qt5_rpath() + self.simplify_qt5_libs() + + # warn about this during the configuration too + if not has_xml: + Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') + + if 'COMPILER_CXX' not in self.env: + self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') + + # Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC? + frag = '#include \nint main(int argc, char **argv) {return 0;}\n' + uses = 'QT5CORE QT5WIDGETS QT5GUI' + for flag in [[], '-fPIE', '-fPIC', '-std=c++11' , ['-std=c++11', '-fPIE'], ['-std=c++11', '-fPIC']]: + msg = 'See if Qt files compile ' + if flag: + msg += 'with %s' % flag + try: + self.check(features='qt5 cxx', use=uses, uselib_store='qt5', cxxflags=flag, fragment=frag, msg=msg) + except self.errors.ConfigurationError: + pass + else: + break + else: + self.fatal('Could not build a simple Qt application') + + # FreeBSD does not add /usr/local/lib and the pkg-config files do not provide it either :-/ + if Utils.unversioned_sys_platform() == 'freebsd': + frag = '#include \nint main(int argc, char **argv) { QApplication app(argc, argv); return NULL != (void*) (&app);}\n' + try: + self.check(features='qt5 cxx cxxprogram', use=uses, fragment=frag, msg='Can we link Qt programs on FreeBSD directly?') + except self.errors.ConfigurationError: + self.check(features='qt5 cxx cxxprogram', use=uses, uselib_store='qt5', libpath='/usr/local/lib', fragment=frag, msg='Is /usr/local/lib required?') + +@conf +def find_qt5_binaries(self): + """ + Detects Qt programs such as qmake, moc, uic, lrelease + """ + env = self.env + opt = Options.options + + qtdir = getattr(opt, 'qtdir', '') + qtbin = getattr(opt, 'qtbin', '') + + paths = [] + + if qtdir: + qtbin = os.path.join(qtdir, 'bin') + + # the qt directory has been given from QT5_ROOT - deduce the qt binary path + if not qtdir: + qtdir = self.environ.get('QT5_ROOT', '') + qtbin = self.environ.get('QT5_BIN') or os.path.join(qtdir, 'bin') + + if qtbin: + paths = [qtbin] + + # no qtdir, look in the path and in /usr/local/Trolltech + if not qtdir: + paths = self.environ.get('PATH', '').split(os.pathsep) + paths.extend(['/usr/share/qt5/bin', '/usr/local/lib/qt5/bin']) + try: + lst = Utils.listdir('/usr/local/Trolltech/') + except OSError: + pass + else: + if lst: + lst.sort() + lst.reverse() + + # keep the highest version + qtdir = '/usr/local/Trolltech/%s/' % lst[0] + qtbin = os.path.join(qtdir, 'bin') + paths.append(qtbin) + + # at the end, try to find qmake in the paths given + # keep the one with the highest version + cand = None + prev_ver = ['5', '0', '0'] + for qmk in ('qmake-qt5', 'qmake5', 'qmake'): + try: + qmake = self.find_program(qmk, path_list=paths) + except self.errors.ConfigurationError: + pass + else: + try: + version = self.cmd_and_log(qmake + ['-query', 'QT_VERSION']).strip() + except self.errors.WafError: + pass + else: + if version: + new_ver = version.split('.') + if new_ver > prev_ver: + cand = qmake + prev_ver = new_ver + + # qmake could not be found easily, rely on qtchooser + if not cand: + try: + self.find_program('qtchooser') + except self.errors.ConfigurationError: + pass + else: + cmd = self.env.QTCHOOSER + ['-qt=5', '-run-tool=qmake'] + try: + version = self.cmd_and_log(cmd + ['-query', 'QT_VERSION']) + except self.errors.WafError: + pass + else: + cand = cmd + + if cand: + self.env.QMAKE = cand + else: + self.fatal('Could not find qmake for qt5') + + self.env.QT_HOST_BINS = qtbin = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_HOST_BINS']).strip() + paths.insert(0, qtbin) + + def find_bin(lst, var): + if var in env: + return + for f in lst: + try: + ret = self.find_program(f, path_list=paths) + except self.errors.ConfigurationError: + pass + else: + env[var]=ret + break + + find_bin(['uic-qt5', 'uic'], 'QT_UIC') + if not env.QT_UIC: + self.fatal('cannot find the uic compiler for qt5') + + self.start_msg('Checking for uic version') + uicver = self.cmd_and_log(env.QT_UIC + ['-version'], output=Context.BOTH) + uicver = ''.join(uicver).strip() + uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '') + self.end_msg(uicver) + if uicver.find(' 3.') != -1 or uicver.find(' 4.') != -1: + self.fatal('this uic compiler is for qt3 or qt4, add uic for qt5 to your path') + + find_bin(['moc-qt5', 'moc'], 'QT_MOC') + find_bin(['rcc-qt5', 'rcc'], 'QT_RCC') + find_bin(['lrelease-qt5', 'lrelease'], 'QT_LRELEASE') + find_bin(['lupdate-qt5', 'lupdate'], 'QT_LUPDATE') + + env.UIC_ST = '%s -o %s' + env.MOC_ST = '-o' + env.ui_PATTERN = 'ui_%s.h' + env.QT_LRELEASE_FLAGS = ['-silent'] + env.MOCCPPPATH_ST = '-I%s' + env.MOCDEFINES_ST = '-D%s' + +@conf +def set_qt5_libs_dir(self): + env = self.env + qtlibs = getattr(Options.options, 'qtlibs', None) or self.environ.get('QT5_LIBDIR') + if not qtlibs: + try: + qtlibs = self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_LIBS']).strip() + except Errors.WafError: + qtdir = self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip() + qtlibs = os.path.join(qtdir, 'lib') + self.msg('Found the Qt5 libraries in', qtlibs) + env.QTLIBS = qtlibs + +@conf +def find_single_qt5_lib(self, name, uselib, qtlibs, qtincludes, force_static): + env = self.env + if force_static: + exts = ('.a', '.lib') + prefix = 'STLIB' + else: + exts = ('.so', '.lib') + prefix = 'LIB' + + def lib_names(): + for x in exts: + for k in ('', '5') if Utils.is_win32 else ['']: + for p in ('lib', ''): + yield (p, name, k, x) + + for tup in lib_names(): + k = ''.join(tup) + path = os.path.join(qtlibs, k) + if os.path.exists(path): + if env.DEST_OS == 'win32': + libval = ''.join(tup[:-1]) + else: + libval = name + env.append_unique(prefix + '_' + uselib, libval) + env.append_unique('%sPATH_%s' % (prefix, uselib), qtlibs) + env.append_unique('INCLUDES_' + uselib, qtincludes) + env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, name.replace('Qt5', 'Qt'))) + return k + return False + +@conf +def find_qt5_libraries(self): + env = self.env + + qtincludes = self.environ.get('QT5_INCLUDES') or self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_HEADERS']).strip() + force_static = self.environ.get('QT5_FORCE_STATIC') + try: + if self.environ.get('QT5_XCOMPILE'): + self.fatal('QT5_XCOMPILE Disables pkg-config detection') + self.check_cfg(atleast_pkgconfig_version='0.1') + except self.errors.ConfigurationError: + for i in self.qt5_vars: + uselib = i.upper() + if Utils.unversioned_sys_platform() == 'darwin': + # Since at least qt 4.7.3 each library locates in separate directory + fwk = i.replace('Qt5', 'Qt') + frameworkName = fwk + '.framework' + + qtDynamicLib = os.path.join(env.QTLIBS, frameworkName, fwk) + if os.path.exists(qtDynamicLib): + env.append_unique('FRAMEWORK_' + uselib, fwk) + env.append_unique('FRAMEWORKPATH_' + uselib, env.QTLIBS) + self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') + else: + self.msg('Checking for %s' % i, False, 'YELLOW') + env.append_unique('INCLUDES_' + uselib, os.path.join(env.QTLIBS, frameworkName, 'Headers')) + else: + ret = self.find_single_qt5_lib(i, uselib, env.QTLIBS, qtincludes, force_static) + if not force_static and not ret: + ret = self.find_single_qt5_lib(i, uselib, env.QTLIBS, qtincludes, True) + self.msg('Checking for %s' % i, ret, 'GREEN' if ret else 'YELLOW') + else: + path = '%s:%s:%s/pkgconfig:/usr/lib/qt5/lib/pkgconfig:/opt/qt5/lib/pkgconfig:/usr/lib/qt5/lib:/opt/qt5/lib' % ( + self.environ.get('PKG_CONFIG_PATH', ''), env.QTLIBS, env.QTLIBS) + for i in self.qt5_vars: + self.check_cfg(package=i, args='--cflags --libs', mandatory=False, force_static=force_static, pkg_config_path=path) + +@conf +def simplify_qt5_libs(self): + """ + Since library paths make really long command-lines, + and since everything depends on qtcore, remove the qtcore ones from qtgui, etc + """ + env = self.env + def process_lib(vars_, coreval): + for d in vars_: + var = d.upper() + if var == 'QTCORE': + continue + + value = env['LIBPATH_'+var] + if value: + core = env[coreval] + accu = [] + for lib in value: + if lib in core: + continue + accu.append(lib) + env['LIBPATH_'+var] = accu + process_lib(self.qt5_vars, 'LIBPATH_QTCORE') + +@conf +def add_qt5_rpath(self): + """ + Defines rpath entries for Qt libraries + """ + env = self.env + if getattr(Options.options, 'want_rpath', False): + def process_rpath(vars_, coreval): + for d in vars_: + var = d.upper() + value = env['LIBPATH_' + var] + if value: + core = env[coreval] + accu = [] + for lib in value: + if var != 'QTCORE': + if lib in core: + continue + accu.append('-Wl,--rpath='+lib) + env['RPATH_' + var] = accu + process_rpath(self.qt5_vars, 'LIBPATH_QTCORE') + +@conf +def set_qt5_libs_to_check(self): + self.qt5_vars = Utils.to_list(getattr(self, 'qt5_vars', [])) + if not self.qt5_vars: + dirlst = Utils.listdir(self.env.QTLIBS) + + pat = self.env.cxxshlib_PATTERN + if Utils.is_win32: + pat = pat.replace('.dll', '.lib') + if self.environ.get('QT5_FORCE_STATIC'): + pat = self.env.cxxstlib_PATTERN + if Utils.unversioned_sys_platform() == 'darwin': + pat = r"%s\.framework" + re_qt = re.compile(pat%'Qt5?(?P.*)'+'$') + for x in dirlst: + m = re_qt.match(x) + if m: + self.qt5_vars.append("Qt5%s" % m.group('name')) + if not self.qt5_vars: + self.fatal('cannot find any Qt5 library (%r)' % self.env.QTLIBS) + + qtextralibs = getattr(Options.options, 'qtextralibs', None) + if qtextralibs: + self.qt5_vars.extend(qtextralibs.split(',')) + +@conf +def set_qt5_defines(self): + if sys.platform != 'win32': + return + for x in self.qt5_vars: + y=x.replace('Qt5', 'Qt')[2:].upper() + self.env.append_unique('DEFINES_%s' % x.upper(), 'QT_%s_LIB' % y) + +def options(opt): + """ + Command-line options + """ + opt.add_option('--want-rpath', action='store_true', default=False, dest='want_rpath', help='enable the rpath for qt libraries') + for i in 'qtdir qtbin qtlibs'.split(): + opt.add_option('--'+i, type='string', default='', dest=i) + + opt.add_option('--translate', action='store_true', help='collect translation strings', dest='trans_qt5', default=False) + opt.add_option('--qtextralibs', type='string', default='', dest='qtextralibs', help='additional qt libraries on the system to add to default ones, comma separated') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/ruby.py b/ldb-2.0.8/third_party/waf/waflib/Tools/ruby.py new file mode 100644 index 0000000..8d92a79 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/ruby.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# encoding: utf-8 +# daniel.svensson at purplescout.se 2008 +# Thomas Nagy 2016-2018 (ita) + +""" +Support for Ruby extensions. A C/C++ compiler is required:: + + def options(opt): + opt.load('compiler_c ruby') + def configure(conf): + conf.load('compiler_c ruby') + conf.check_ruby_version((1,8,0)) + conf.check_ruby_ext_devel() + conf.check_ruby_module('libxml') + def build(bld): + bld( + features = 'c cshlib rubyext', + source = 'rb_mytest.c', + target = 'mytest_ext', + install_path = '${ARCHDIR_RUBY}') + bld.install_files('${LIBDIR_RUBY}', 'Mytest.rb') +""" + +import os +from waflib import Errors, Options, Task, Utils +from waflib.TaskGen import before_method, feature, extension +from waflib.Configure import conf + +@feature('rubyext') +@before_method('apply_incpaths', 'process_source', 'apply_bundle', 'apply_link') +def init_rubyext(self): + """ + Add required variables for ruby extensions + """ + self.install_path = '${ARCHDIR_RUBY}' + self.uselib = self.to_list(getattr(self, 'uselib', '')) + if not 'RUBY' in self.uselib: + self.uselib.append('RUBY') + if not 'RUBYEXT' in self.uselib: + self.uselib.append('RUBYEXT') + +@feature('rubyext') +@before_method('apply_link', 'propagate_uselib_vars') +def apply_ruby_so_name(self): + """ + Strip the *lib* prefix from ruby extensions + """ + self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.rubyext_PATTERN + +@conf +def check_ruby_version(self, minver=()): + """ + Checks if ruby is installed. + If installed the variable RUBY will be set in environment. + The ruby binary can be overridden by ``--with-ruby-binary`` command-line option. + """ + + ruby = self.find_program('ruby', var='RUBY', value=Options.options.rubybinary) + + try: + version = self.cmd_and_log(ruby + ['-e', 'puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() + except Errors.WafError: + self.fatal('could not determine ruby version') + self.env.RUBY_VERSION = version + + try: + ver = tuple(map(int, version.split('.'))) + except Errors.WafError: + self.fatal('unsupported ruby version %r' % version) + + cver = '' + if minver: + cver = '> ' + '.'.join(str(x) for x in minver) + if ver < minver: + self.fatal('ruby is too old %r' % ver) + + self.msg('Checking for ruby version %s' % cver, version) + +@conf +def check_ruby_ext_devel(self): + """ + Check if a ruby extension can be created + """ + if not self.env.RUBY: + self.fatal('ruby detection is required first') + + if not self.env.CC_NAME and not self.env.CXX_NAME: + self.fatal('load a c/c++ compiler first') + + version = tuple(map(int, self.env.RUBY_VERSION.split("."))) + + def read_out(cmd): + return Utils.to_list(self.cmd_and_log(self.env.RUBY + ['-rrbconfig', '-e', cmd])) + + def read_config(key): + return read_out('puts RbConfig::CONFIG[%r]' % key) + + cpppath = archdir = read_config('archdir') + + if version >= (1, 9, 0): + ruby_hdrdir = read_config('rubyhdrdir') + cpppath += ruby_hdrdir + if version >= (2, 0, 0): + cpppath += read_config('rubyarchhdrdir') + cpppath += [os.path.join(ruby_hdrdir[0], read_config('arch')[0])] + + self.check(header_name='ruby.h', includes=cpppath, errmsg='could not find ruby header file', link_header_test=False) + + self.env.LIBPATH_RUBYEXT = read_config('libdir') + self.env.LIBPATH_RUBYEXT += archdir + self.env.INCLUDES_RUBYEXT = cpppath + self.env.CFLAGS_RUBYEXT = read_config('CCDLFLAGS') + self.env.rubyext_PATTERN = '%s.' + read_config('DLEXT')[0] + + # ok this is really stupid, but the command and flags are combined. + # so we try to find the first argument... + flags = read_config('LDSHARED') + while flags and flags[0][0] != '-': + flags = flags[1:] + + # we also want to strip out the deprecated ppc flags + if len(flags) > 1 and flags[1] == "ppc": + flags = flags[2:] + + self.env.LINKFLAGS_RUBYEXT = flags + self.env.LINKFLAGS_RUBYEXT += read_config('LIBS') + self.env.LINKFLAGS_RUBYEXT += read_config('LIBRUBYARG_SHARED') + + if Options.options.rubyarchdir: + self.env.ARCHDIR_RUBY = Options.options.rubyarchdir + else: + self.env.ARCHDIR_RUBY = read_config('sitearchdir')[0] + + if Options.options.rubylibdir: + self.env.LIBDIR_RUBY = Options.options.rubylibdir + else: + self.env.LIBDIR_RUBY = read_config('sitelibdir')[0] + +@conf +def check_ruby_module(self, module_name): + """ + Check if the selected ruby interpreter can require the given ruby module:: + + def configure(conf): + conf.check_ruby_module('libxml') + + :param module_name: module + :type module_name: string + """ + self.start_msg('Ruby module %s' % module_name) + try: + self.cmd_and_log(self.env.RUBY + ['-e', 'require \'%s\';puts 1' % module_name]) + except Errors.WafError: + self.end_msg(False) + self.fatal('Could not find the ruby module %r' % module_name) + self.end_msg(True) + +@extension('.rb') +def process(self, node): + return self.create_task('run_ruby', node) + +class run_ruby(Task.Task): + """ + Task to run ruby files detected by file extension .rb:: + + def options(opt): + opt.load('ruby') + + def configure(ctx): + ctx.check_ruby_version() + + def build(bld): + bld.env.RBFLAGS = '-e puts "hello world"' + bld(source='a_ruby_file.rb') + """ + run_str = '${RUBY} ${RBFLAGS} -I ${SRC[0].parent.abspath()} ${SRC}' + +def options(opt): + """ + Add the ``--with-ruby-archdir``, ``--with-ruby-libdir`` and ``--with-ruby-binary`` options + """ + opt.add_option('--with-ruby-archdir', type='string', dest='rubyarchdir', help='Specify directory where to install arch specific files') + opt.add_option('--with-ruby-libdir', type='string', dest='rubylibdir', help='Specify alternate ruby library path') + opt.add_option('--with-ruby-binary', type='string', dest='rubybinary', help='Specify alternate ruby binary') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/suncc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/suncc.py new file mode 100644 index 0000000..33d34fc --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/suncc.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) +# Ralf Habacker, 2006 (rh) + +from waflib import Errors +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +@conf +def find_scc(conf): + """ + Detects the Sun C compiler + """ + v = conf.env + cc = conf.find_program('cc', var='CC') + try: + conf.cmd_and_log(cc + ['-flags']) + except Errors.WafError: + conf.fatal('%r is not a Sun compiler' % cc) + v.CC_NAME = 'sun' + conf.get_suncc_version(cc) + +@conf +def scc_common_flags(conf): + """ + Flags required for executing the sun C compiler + """ + v = conf.env + + v.CC_SRC_F = [] + v.CC_TGT_F = ['-c', '-o', ''] + + if not v.LINK_CC: + v.LINK_CC = v.CC + + v.CCLNK_SRC_F = '' + v.CCLNK_TGT_F = ['-o', ''] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + + v.SONAME_ST = '-Wl,-h,%s' + v.SHLIB_MARKER = '-Bdynamic' + v.STLIB_MARKER = '-Bstatic' + + v.cprogram_PATTERN = '%s' + + v.CFLAGS_cshlib = ['-xcode=pic32', '-DPIC'] + v.LINKFLAGS_cshlib = ['-G'] + v.cshlib_PATTERN = 'lib%s.so' + + v.LINKFLAGS_cstlib = ['-Bstatic'] + v.cstlib_PATTERN = 'lib%s.a' + +def configure(conf): + conf.find_scc() + conf.find_ar() + conf.scc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/suncxx.py b/ldb-2.0.8/third_party/waf/waflib/Tools/suncxx.py new file mode 100644 index 0000000..3b384f6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/suncxx.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) +# Ralf Habacker, 2006 (rh) + +from waflib import Errors +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +@conf +def find_sxx(conf): + """ + Detects the sun C++ compiler + """ + v = conf.env + cc = conf.find_program(['CC', 'c++'], var='CXX') + try: + conf.cmd_and_log(cc + ['-flags']) + except Errors.WafError: + conf.fatal('%r is not a Sun compiler' % cc) + v.CXX_NAME = 'sun' + conf.get_suncc_version(cc) + +@conf +def sxx_common_flags(conf): + """ + Flags required for executing the sun C++ compiler + """ + v = conf.env + + v.CXX_SRC_F = [] + v.CXX_TGT_F = ['-c', '-o', ''] + + if not v.LINK_CXX: + v.LINK_CXX = v.CXX + + v.CXXLNK_SRC_F = [] + v.CXXLNK_TGT_F = ['-o', ''] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + + v.SONAME_ST = '-Wl,-h,%s' + v.SHLIB_MARKER = '-Bdynamic' + v.STLIB_MARKER = '-Bstatic' + + v.cxxprogram_PATTERN = '%s' + + v.CXXFLAGS_cxxshlib = ['-xcode=pic32', '-DPIC'] + v.LINKFLAGS_cxxshlib = ['-G'] + v.cxxshlib_PATTERN = 'lib%s.so' + + v.LINKFLAGS_cxxstlib = ['-Bstatic'] + v.cxxstlib_PATTERN = 'lib%s.a' + +def configure(conf): + conf.find_sxx() + conf.find_ar() + conf.sxx_common_flags() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/tex.py b/ldb-2.0.8/third_party/waf/waflib/Tools/tex.py new file mode 100644 index 0000000..eaf9fdb --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/tex.py @@ -0,0 +1,543 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) + +""" +TeX/LaTeX/PDFLaTeX/XeLaTeX support + +Example:: + + def configure(conf): + conf.load('tex') + if not conf.env.LATEX: + conf.fatal('The program LaTex is required') + + def build(bld): + bld( + features = 'tex', + type = 'latex', # pdflatex or xelatex + source = 'document.ltx', # mandatory, the source + outs = 'ps', # 'pdf' or 'ps pdf' + deps = 'crossreferencing.lst', # to give dependencies directly + prompt = 1, # 0 for the batch mode + ) + +Notes: + +- To configure with a special program, use:: + + $ PDFLATEX=luatex waf configure + +- This tool does not use the target attribute of the task generator + (``bld(target=...)``); the target file name is built from the source + base name and the output type(s) +""" + +import os, re +from waflib import Utils, Task, Errors, Logs, Node +from waflib.TaskGen import feature, before_method + +re_bibunit = re.compile(r'\\(?Pputbib)\[(?P[^\[\]]*)\]',re.M) +def bibunitscan(self): + """ + Parses TeX inputs and try to find the *bibunit* file dependencies + + :return: list of bibunit files + :rtype: list of :py:class:`waflib.Node.Node` + """ + node = self.inputs[0] + + nodes = [] + if not node: + return nodes + + code = node.read() + for match in re_bibunit.finditer(code): + path = match.group('file') + if path: + found = None + for k in ('', '.bib'): + # add another loop for the tex include paths? + Logs.debug('tex: trying %s%s', path, k) + fi = node.parent.find_resource(path + k) + if fi: + found = True + nodes.append(fi) + # no break + if not found: + Logs.debug('tex: could not find %s', path) + + Logs.debug('tex: found the following bibunit files: %s', nodes) + return nodes + +exts_deps_tex = ['', '.ltx', '.tex', '.bib', '.pdf', '.png', '.eps', '.ps', '.sty'] +"""List of typical file extensions included in latex files""" + +exts_tex = ['.ltx', '.tex'] +"""List of typical file extensions that contain latex""" + +re_tex = re.compile(r'\\(?Pusepackage|RequirePackage|include|bibliography([^\[\]{}]*)|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P[^{}]*)}',re.M) +"""Regexp for expressions that may include latex files""" + +g_bibtex_re = re.compile('bibdata', re.M) +"""Regexp for bibtex files""" + +g_glossaries_re = re.compile('\\@newglossary', re.M) +"""Regexp for expressions that create glossaries""" + +class tex(Task.Task): + """ + Compiles a tex/latex file. + + .. inheritance-diagram:: waflib.Tools.tex.latex waflib.Tools.tex.xelatex waflib.Tools.tex.pdflatex + """ + + bibtex_fun, _ = Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False) + bibtex_fun.__doc__ = """ + Execute the program **bibtex** + """ + + makeindex_fun, _ = Task.compile_fun('${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}', shell=False) + makeindex_fun.__doc__ = """ + Execute the program **makeindex** + """ + + makeglossaries_fun, _ = Task.compile_fun('${MAKEGLOSSARIES} ${SRCFILE}', shell=False) + makeglossaries_fun.__doc__ = """ + Execute the program **makeglossaries** + """ + + def exec_command(self, cmd, **kw): + """ + Executes TeX commands without buffering (latex may prompt for inputs) + + :return: the return code + :rtype: int + """ + if self.env.PROMPT_LATEX: + # capture the outputs in configuration tests + kw['stdout'] = kw['stderr'] = None + return super(tex, self).exec_command(cmd, **kw) + + def scan_aux(self, node): + """ + Recursive regex-based scanner that finds included auxiliary files. + """ + nodes = [node] + re_aux = re.compile(r'\\@input{(?P[^{}]*)}', re.M) + + def parse_node(node): + code = node.read() + for match in re_aux.finditer(code): + path = match.group('file') + found = node.parent.find_or_declare(path) + if found and found not in nodes: + Logs.debug('tex: found aux node %r', found) + nodes.append(found) + parse_node(found) + parse_node(node) + return nodes + + def scan(self): + """ + Recursive regex-based scanner that finds latex dependencies. It uses :py:attr:`waflib.Tools.tex.re_tex` + + Depending on your needs you might want: + + * to change re_tex:: + + from waflib.Tools import tex + tex.re_tex = myregex + + * or to change the method scan from the latex tasks:: + + from waflib.Task import classes + classes['latex'].scan = myscanfunction + """ + node = self.inputs[0] + + nodes = [] + names = [] + seen = [] + if not node: + return (nodes, names) + + def parse_node(node): + if node in seen: + return + seen.append(node) + code = node.read() + for match in re_tex.finditer(code): + + multibib = match.group('type') + if multibib and multibib.startswith('bibliography'): + multibib = multibib[len('bibliography'):] + if multibib.startswith('style'): + continue + else: + multibib = None + + for path in match.group('file').split(','): + if path: + add_name = True + found = None + for k in exts_deps_tex: + + # issue 1067, scan in all texinputs folders + for up in self.texinputs_nodes: + Logs.debug('tex: trying %s%s', path, k) + found = up.find_resource(path + k) + if found: + break + + + for tsk in self.generator.tasks: + if not found or found in tsk.outputs: + break + else: + nodes.append(found) + add_name = False + for ext in exts_tex: + if found.name.endswith(ext): + parse_node(found) + break + + # multibib stuff + if found and multibib and found.name.endswith('.bib'): + try: + self.multibibs.append(found) + except AttributeError: + self.multibibs = [found] + + # no break, people are crazy + if add_name: + names.append(path) + parse_node(node) + + for x in nodes: + x.parent.get_bld().mkdir() + + Logs.debug("tex: found the following : %s and names %s", nodes, names) + return (nodes, names) + + def check_status(self, msg, retcode): + """ + Checks an exit status and raise an error with a particular message + + :param msg: message to display if the code is non-zero + :type msg: string + :param retcode: condition + :type retcode: boolean + """ + if retcode != 0: + raise Errors.WafError('%r command exit status %r' % (msg, retcode)) + + def info(self, *k, **kw): + try: + info = self.generator.bld.conf.logger.info + except AttributeError: + info = Logs.info + info(*k, **kw) + + def bibfile(self): + """ + Parses *.aux* files to find bibfiles to process. + If present, execute :py:meth:`waflib.Tools.tex.tex.bibtex_fun` + """ + for aux_node in self.aux_nodes: + try: + ct = aux_node.read() + except EnvironmentError: + Logs.error('Error reading %s: %r', aux_node.abspath()) + continue + + if g_bibtex_re.findall(ct): + self.info('calling bibtex') + + self.env.env = {} + self.env.env.update(os.environ) + self.env.env.update({'BIBINPUTS': self.texinputs(), 'BSTINPUTS': self.texinputs()}) + self.env.SRCFILE = aux_node.name[:-4] + self.check_status('error when calling bibtex', self.bibtex_fun()) + + for node in getattr(self, 'multibibs', []): + self.env.env = {} + self.env.env.update(os.environ) + self.env.env.update({'BIBINPUTS': self.texinputs(), 'BSTINPUTS': self.texinputs()}) + self.env.SRCFILE = node.name[:-4] + self.check_status('error when calling bibtex', self.bibtex_fun()) + + def bibunits(self): + """ + Parses *.aux* file to find bibunit files. If there are bibunit files, + runs :py:meth:`waflib.Tools.tex.tex.bibtex_fun`. + """ + try: + bibunits = bibunitscan(self) + except OSError: + Logs.error('error bibunitscan') + else: + if bibunits: + fn = ['bu' + str(i) for i in range(1, len(bibunits) + 1)] + if fn: + self.info('calling bibtex on bibunits') + + for f in fn: + self.env.env = {'BIBINPUTS': self.texinputs(), 'BSTINPUTS': self.texinputs()} + self.env.SRCFILE = f + self.check_status('error when calling bibtex', self.bibtex_fun()) + + def makeindex(self): + """ + Searches the filesystem for *.idx* files to process. If present, + runs :py:meth:`waflib.Tools.tex.tex.makeindex_fun` + """ + self.idx_node = self.inputs[0].change_ext('.idx') + try: + idx_path = self.idx_node.abspath() + os.stat(idx_path) + except OSError: + self.info('index file %s absent, not calling makeindex', idx_path) + else: + self.info('calling makeindex') + + self.env.SRCFILE = self.idx_node.name + self.env.env = {} + self.check_status('error when calling makeindex %s' % idx_path, self.makeindex_fun()) + + def bibtopic(self): + """ + Lists additional .aux files from the bibtopic package + """ + p = self.inputs[0].parent.get_bld() + if os.path.exists(os.path.join(p.abspath(), 'btaux.aux')): + self.aux_nodes += p.ant_glob('*[0-9].aux') + + def makeglossaries(self): + """ + Lists additional glossaries from .aux files. If present, runs the makeglossaries program. + """ + src_file = self.inputs[0].abspath() + base_file = os.path.basename(src_file) + base, _ = os.path.splitext(base_file) + for aux_node in self.aux_nodes: + try: + ct = aux_node.read() + except EnvironmentError: + Logs.error('Error reading %s: %r', aux_node.abspath()) + continue + + if g_glossaries_re.findall(ct): + if not self.env.MAKEGLOSSARIES: + raise Errors.WafError("The program 'makeglossaries' is missing!") + Logs.warn('calling makeglossaries') + self.env.SRCFILE = base + self.check_status('error when calling makeglossaries %s' % base, self.makeglossaries_fun()) + return + + def texinputs(self): + """ + Returns the list of texinput nodes as a string suitable for the TEXINPUTS environment variables + + :rtype: string + """ + return os.pathsep.join([k.abspath() for k in self.texinputs_nodes]) + os.pathsep + + def run(self): + """ + Runs the whole TeX build process + + Multiple passes are required depending on the usage of cross-references, + bibliographies, glossaries, indexes and additional contents + The appropriate TeX compiler is called until the *.aux* files stop changing. + """ + env = self.env + + if not env.PROMPT_LATEX: + env.append_value('LATEXFLAGS', '-interaction=batchmode') + env.append_value('PDFLATEXFLAGS', '-interaction=batchmode') + env.append_value('XELATEXFLAGS', '-interaction=batchmode') + + # important, set the cwd for everybody + self.cwd = self.inputs[0].parent.get_bld() + + self.info('first pass on %s', self.__class__.__name__) + + # Hash .aux files before even calling the LaTeX compiler + cur_hash = self.hash_aux_nodes() + + self.call_latex() + + # Find the .aux files again since bibtex processing can require it + self.hash_aux_nodes() + + self.bibtopic() + self.bibfile() + self.bibunits() + self.makeindex() + self.makeglossaries() + + for i in range(10): + # There is no need to call latex again if the .aux hash value has not changed + prev_hash = cur_hash + cur_hash = self.hash_aux_nodes() + if not cur_hash: + Logs.error('No aux.h to process') + if cur_hash and cur_hash == prev_hash: + break + + # run the command + self.info('calling %s', self.__class__.__name__) + self.call_latex() + + def hash_aux_nodes(self): + """ + Returns a hash of the .aux file contents + + :rtype: string or bytes + """ + try: + self.aux_nodes + except AttributeError: + try: + self.aux_nodes = self.scan_aux(self.inputs[0].change_ext('.aux')) + except IOError: + return None + return Utils.h_list([Utils.h_file(x.abspath()) for x in self.aux_nodes]) + + def call_latex(self): + """ + Runs the TeX compiler once + """ + self.env.env = {} + self.env.env.update(os.environ) + self.env.env.update({'TEXINPUTS': self.texinputs()}) + self.env.SRCFILE = self.inputs[0].abspath() + self.check_status('error when calling latex', self.texfun()) + +class latex(tex): + "Compiles LaTeX files" + texfun, vars = Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) + +class pdflatex(tex): + "Compiles PdfLaTeX files" + texfun, vars = Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) + +class xelatex(tex): + "XeLaTeX files" + texfun, vars = Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}', shell=False) + +class dvips(Task.Task): + "Converts dvi files to postscript" + run_str = '${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}' + color = 'BLUE' + after = ['latex', 'pdflatex', 'xelatex'] + +class dvipdf(Task.Task): + "Converts dvi files to pdf" + run_str = '${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}' + color = 'BLUE' + after = ['latex', 'pdflatex', 'xelatex'] + +class pdf2ps(Task.Task): + "Converts pdf files to postscript" + run_str = '${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}' + color = 'BLUE' + after = ['latex', 'pdflatex', 'xelatex'] + +@feature('tex') +@before_method('process_source') +def apply_tex(self): + """ + Creates :py:class:`waflib.Tools.tex.tex` objects, and + dvips/dvipdf/pdf2ps tasks if necessary (outs='ps', etc). + """ + if not getattr(self, 'type', None) in ('latex', 'pdflatex', 'xelatex'): + self.type = 'pdflatex' + + outs = Utils.to_list(getattr(self, 'outs', [])) + + # prompt for incomplete files (else the batchmode is used) + try: + self.generator.bld.conf + except AttributeError: + default_prompt = False + else: + default_prompt = True + self.env.PROMPT_LATEX = getattr(self, 'prompt', default_prompt) + + deps_lst = [] + + if getattr(self, 'deps', None): + deps = self.to_list(self.deps) + for dep in deps: + if isinstance(dep, str): + n = self.path.find_resource(dep) + if not n: + self.bld.fatal('Could not find %r for %r' % (dep, self)) + if not n in deps_lst: + deps_lst.append(n) + elif isinstance(dep, Node.Node): + deps_lst.append(dep) + + for node in self.to_nodes(self.source): + if self.type == 'latex': + task = self.create_task('latex', node, node.change_ext('.dvi')) + elif self.type == 'pdflatex': + task = self.create_task('pdflatex', node, node.change_ext('.pdf')) + elif self.type == 'xelatex': + task = self.create_task('xelatex', node, node.change_ext('.pdf')) + + task.env = self.env + + # add the manual dependencies + if deps_lst: + for n in deps_lst: + if not n in task.dep_nodes: + task.dep_nodes.append(n) + + # texinputs is a nasty beast + if hasattr(self, 'texinputs_nodes'): + task.texinputs_nodes = self.texinputs_nodes + else: + task.texinputs_nodes = [node.parent, node.parent.get_bld(), self.path, self.path.get_bld()] + lst = os.environ.get('TEXINPUTS', '') + if self.env.TEXINPUTS: + lst += os.pathsep + self.env.TEXINPUTS + if lst: + lst = lst.split(os.pathsep) + for x in lst: + if x: + if os.path.isabs(x): + p = self.bld.root.find_node(x) + if p: + task.texinputs_nodes.append(p) + else: + Logs.error('Invalid TEXINPUTS folder %s', x) + else: + Logs.error('Cannot resolve relative paths in TEXINPUTS %s', x) + + if self.type == 'latex': + if 'ps' in outs: + tsk = self.create_task('dvips', task.outputs, node.change_ext('.ps')) + tsk.env.env = dict(os.environ) + if 'pdf' in outs: + tsk = self.create_task('dvipdf', task.outputs, node.change_ext('.pdf')) + tsk.env.env = dict(os.environ) + elif self.type == 'pdflatex': + if 'ps' in outs: + self.create_task('pdf2ps', task.outputs, node.change_ext('.ps')) + self.source = [] + +def configure(self): + """ + Find the programs tex, latex and others without raising errors. + """ + v = self.env + for p in 'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps makeglossaries'.split(): + try: + self.find_program(p, var=p.upper()) + except self.errors.ConfigurationError: + pass + v.DVIPSFLAGS = '-Ppdf' + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/vala.py b/ldb-2.0.8/third_party/waf/waflib/Tools/vala.py new file mode 100644 index 0000000..822ec50 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/vala.py @@ -0,0 +1,355 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Ali Sabil, 2007 +# Radosław Szkodziński, 2010 + +""" +At this point, vala is still unstable, so do not expect +this tool to be too stable either (apis, etc) +""" + +import re +from waflib import Build, Context, Errors, Logs, Node, Options, Task, Utils +from waflib.TaskGen import extension, taskgen_method +from waflib.Configure import conf + +class valac(Task.Task): + """ + Compiles vala files + """ + #run_str = "${VALAC} ${VALAFLAGS}" # ideally + #vars = ['VALAC_VERSION'] + vars = ["VALAC", "VALAC_VERSION", "VALAFLAGS"] + ext_out = ['.h'] + + def run(self): + cmd = self.env.VALAC + self.env.VALAFLAGS + resources = getattr(self, 'vala_exclude', []) + cmd.extend([a.abspath() for a in self.inputs if a not in resources]) + ret = self.exec_command(cmd, cwd=self.vala_dir_node.abspath()) + + if ret: + return ret + + if self.generator.dump_deps_node: + self.generator.dump_deps_node.write('\n'.join(self.generator.packages)) + + return ret + +@taskgen_method +def init_vala_task(self): + """ + Initializes the vala task with the relevant data (acts as a constructor) + """ + self.profile = getattr(self, 'profile', 'gobject') + + self.packages = packages = Utils.to_list(getattr(self, 'packages', [])) + self.use = Utils.to_list(getattr(self, 'use', [])) + if packages and not self.use: + self.use = packages[:] # copy + + if self.profile == 'gobject': + if not 'GOBJECT' in self.use: + self.use.append('GOBJECT') + + def addflags(flags): + self.env.append_value('VALAFLAGS', flags) + + if self.profile: + addflags('--profile=%s' % self.profile) + + valatask = self.valatask + + # output directory + if hasattr(self, 'vala_dir'): + if isinstance(self.vala_dir, str): + valatask.vala_dir_node = self.path.get_bld().make_node(self.vala_dir) + try: + valatask.vala_dir_node.mkdir() + except OSError: + raise self.bld.fatal('Cannot create the vala dir %r' % valatask.vala_dir_node) + else: + valatask.vala_dir_node = self.vala_dir + else: + valatask.vala_dir_node = self.path.get_bld() + addflags('--directory=%s' % valatask.vala_dir_node.abspath()) + + if hasattr(self, 'thread'): + if self.profile == 'gobject': + if not 'GTHREAD' in self.use: + self.use.append('GTHREAD') + else: + #Vala doesn't have threading support for dova nor posix + Logs.warn('Profile %s means no threading support', self.profile) + self.thread = False + + if self.thread: + addflags('--thread') + + self.is_lib = 'cprogram' not in self.features + if self.is_lib: + addflags('--library=%s' % self.target) + + h_node = valatask.vala_dir_node.find_or_declare('%s.h' % self.target) + valatask.outputs.append(h_node) + addflags('--header=%s' % h_node.name) + + valatask.outputs.append(valatask.vala_dir_node.find_or_declare('%s.vapi' % self.target)) + + if getattr(self, 'gir', None): + gir_node = valatask.vala_dir_node.find_or_declare('%s.gir' % self.gir) + addflags('--gir=%s' % gir_node.name) + valatask.outputs.append(gir_node) + + self.vala_target_glib = getattr(self, 'vala_target_glib', getattr(Options.options, 'vala_target_glib', None)) + if self.vala_target_glib: + addflags('--target-glib=%s' % self.vala_target_glib) + + addflags(['--define=%s' % x for x in Utils.to_list(getattr(self, 'vala_defines', []))]) + + packages_private = Utils.to_list(getattr(self, 'packages_private', [])) + addflags(['--pkg=%s' % x for x in packages_private]) + + def _get_api_version(): + api_version = '1.0' + if hasattr(Context.g_module, 'API_VERSION'): + version = Context.g_module.API_VERSION.split(".") + if version[0] == "0": + api_version = "0." + version[1] + else: + api_version = version[0] + ".0" + return api_version + + self.includes = Utils.to_list(getattr(self, 'includes', [])) + valatask.install_path = getattr(self, 'install_path', '') + + valatask.vapi_path = getattr(self, 'vapi_path', '${DATAROOTDIR}/vala/vapi') + valatask.pkg_name = getattr(self, 'pkg_name', self.env.PACKAGE) + valatask.header_path = getattr(self, 'header_path', '${INCLUDEDIR}/%s-%s' % (valatask.pkg_name, _get_api_version())) + valatask.install_binding = getattr(self, 'install_binding', True) + + self.vapi_dirs = vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', [])) + #includes = [] + + if hasattr(self, 'use'): + local_packages = Utils.to_list(self.use)[:] # make sure to have a copy + seen = [] + while len(local_packages) > 0: + package = local_packages.pop() + if package in seen: + continue + seen.append(package) + + # check if the package exists + try: + package_obj = self.bld.get_tgen_by_name(package) + except Errors.WafError: + continue + + # in practice the other task is already processed + # but this makes it explicit + package_obj.post() + package_name = package_obj.target + task = getattr(package_obj, 'valatask', None) + if task: + for output in task.outputs: + if output.name == package_name + ".vapi": + valatask.set_run_after(task) + if package_name not in packages: + packages.append(package_name) + if output.parent not in vapi_dirs: + vapi_dirs.append(output.parent) + if output.parent not in self.includes: + self.includes.append(output.parent) + + if hasattr(package_obj, 'use'): + lst = self.to_list(package_obj.use) + lst.reverse() + local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages + + addflags(['--pkg=%s' % p for p in packages]) + + for vapi_dir in vapi_dirs: + if isinstance(vapi_dir, Node.Node): + v_node = vapi_dir + else: + v_node = self.path.find_dir(vapi_dir) + if not v_node: + Logs.warn('Unable to locate Vala API directory: %r', vapi_dir) + else: + addflags('--vapidir=%s' % v_node.abspath()) + + self.dump_deps_node = None + if self.is_lib and self.packages: + self.dump_deps_node = valatask.vala_dir_node.find_or_declare('%s.deps' % self.target) + valatask.outputs.append(self.dump_deps_node) + + if self.is_lib and valatask.install_binding: + headers_list = [o for o in valatask.outputs if o.suffix() == ".h"] + if headers_list: + self.install_vheader = self.add_install_files(install_to=valatask.header_path, install_from=headers_list) + + vapi_list = [o for o in valatask.outputs if (o.suffix() in (".vapi", ".deps"))] + if vapi_list: + self.install_vapi = self.add_install_files(install_to=valatask.vapi_path, install_from=vapi_list) + + gir_list = [o for o in valatask.outputs if o.suffix() == '.gir'] + if gir_list: + self.install_gir = self.add_install_files( + install_to=getattr(self, 'gir_path', '${DATAROOTDIR}/gir-1.0'), install_from=gir_list) + + if hasattr(self, 'vala_resources'): + nodes = self.to_nodes(self.vala_resources) + valatask.vala_exclude = getattr(valatask, 'vala_exclude', []) + nodes + valatask.inputs.extend(nodes) + for x in nodes: + addflags(['--gresources', x.abspath()]) + +@extension('.vala', '.gs') +def vala_file(self, node): + """ + Compile a vala file and bind the task to *self.valatask*. If an existing vala task is already set, add the node + to its inputs. The typical example is:: + + def build(bld): + bld.program( + packages = 'gtk+-2.0', + target = 'vala-gtk-example', + use = 'GTK GLIB', + source = 'vala-gtk-example.vala foo.vala', + vala_defines = ['DEBUG'] # adds --define= values to the command-line + + # the following arguments are for libraries + #gir = 'hello-1.0', + #gir_path = '/tmp', + #vapi_path = '/tmp', + #pkg_name = 'hello' + # disable installing of gir, vapi and header + #install_binding = False + + # profile = 'xyz' # adds --profile= to enable profiling + # thread = True, # adds --thread, except if profile is on or not on 'gobject' + # vala_target_glib = 'xyz' # adds --target-glib=, can be given through the command-line option --vala-target-glib= + ) + + + :param node: vala file + :type node: :py:class:`waflib.Node.Node` + """ + + try: + valatask = self.valatask + except AttributeError: + valatask = self.valatask = self.create_task('valac') + self.init_vala_task() + + valatask.inputs.append(node) + name = node.name[:node.name.rfind('.')] + '.c' + c_node = valatask.vala_dir_node.find_or_declare(name) + valatask.outputs.append(c_node) + self.source.append(c_node) + +@extension('.vapi') +def vapi_file(self, node): + try: + valatask = self.valatask + except AttributeError: + valatask = self.valatask = self.create_task('valac') + self.init_vala_task() + valatask.inputs.append(node) + +@conf +def find_valac(self, valac_name, min_version): + """ + Find the valac program, and execute it to store the version + number in *conf.env.VALAC_VERSION* + + :param valac_name: program name + :type valac_name: string or list of string + :param min_version: minimum version acceptable + :type min_version: tuple of int + """ + valac = self.find_program(valac_name, var='VALAC') + try: + output = self.cmd_and_log(valac + ['--version']) + except Errors.WafError: + valac_version = None + else: + ver = re.search(r'\d+.\d+.\d+', output).group().split('.') + valac_version = tuple([int(x) for x in ver]) + + self.msg('Checking for %s version >= %r' % (valac_name, min_version), + valac_version, valac_version and valac_version >= min_version) + if valac and valac_version < min_version: + self.fatal("%s version %r is too old, need >= %r" % (valac_name, valac_version, min_version)) + + self.env.VALAC_VERSION = valac_version + return valac + +@conf +def check_vala(self, min_version=(0,8,0), branch=None): + """ + Check if vala compiler from a given branch exists of at least a given + version. + + :param min_version: minimum version acceptable (0.8.0) + :type min_version: tuple + :param branch: first part of the version number, in case a snapshot is used (0, 8) + :type branch: tuple of int + """ + if self.env.VALA_MINVER: + min_version = self.env.VALA_MINVER + if self.env.VALA_MINVER_BRANCH: + branch = self.env.VALA_MINVER_BRANCH + if not branch: + branch = min_version[:2] + try: + find_valac(self, 'valac-%d.%d' % (branch[0], branch[1]), min_version) + except self.errors.ConfigurationError: + find_valac(self, 'valac', min_version) + +@conf +def check_vala_deps(self): + """ + Load the gobject and gthread packages if they are missing. + """ + if not self.env.HAVE_GOBJECT: + pkg_args = {'package': 'gobject-2.0', + 'uselib_store': 'GOBJECT', + 'args': '--cflags --libs'} + if getattr(Options.options, 'vala_target_glib', None): + pkg_args['atleast_version'] = Options.options.vala_target_glib + self.check_cfg(**pkg_args) + + if not self.env.HAVE_GTHREAD: + pkg_args = {'package': 'gthread-2.0', + 'uselib_store': 'GTHREAD', + 'args': '--cflags --libs'} + if getattr(Options.options, 'vala_target_glib', None): + pkg_args['atleast_version'] = Options.options.vala_target_glib + self.check_cfg(**pkg_args) + +def configure(self): + """ + Use the following to enforce minimum vala version:: + + def configure(conf): + conf.env.VALA_MINVER = (0, 10, 0) + conf.load('vala') + """ + self.load('gnu_dirs') + self.check_vala_deps() + self.check_vala() + self.add_os_flags('VALAFLAGS') + self.env.append_unique('VALAFLAGS', ['-C']) + +def options(opt): + """ + Load the :py:mod:`waflib.Tools.gnu_dirs` tool and add the ``--vala-target-glib`` command-line option + """ + opt.load('gnu_dirs') + valaopts = opt.add_option_group('Vala Compiler Options') + valaopts.add_option('--vala-target-glib', default=None, + dest='vala_target_glib', metavar='MAJOR.MINOR', + help='Target version of glib for Vala GObject code generation') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/waf_unit_test.py b/ldb-2.0.8/third_party/waf/waflib/Tools/waf_unit_test.py new file mode 100644 index 0000000..6ff6f72 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/waf_unit_test.py @@ -0,0 +1,296 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Carlos Rafael Giani, 2006 +# Thomas Nagy, 2010-2018 (ita) + +""" +Unit testing system for C/C++/D and interpreted languages providing test execution: + +* in parallel, by using ``waf -j`` +* partial (only the tests that have changed) or full (by using ``waf --alltests``) + +The tests are declared by adding the **test** feature to programs:: + + def options(opt): + opt.load('compiler_cxx waf_unit_test') + def configure(conf): + conf.load('compiler_cxx waf_unit_test') + def build(bld): + bld(features='cxx cxxprogram test', source='main.cpp', target='app') + # or + bld.program(features='test', source='main2.cpp', target='app2') + +When the build is executed, the program 'test' will be built and executed without arguments. +The success/failure is detected by looking at the return code. The status and the standard output/error +are stored on the build context. + +The results can be displayed by registering a callback function. Here is how to call +the predefined callback:: + + def build(bld): + bld(features='cxx cxxprogram test', source='main.c', target='app') + from waflib.Tools import waf_unit_test + bld.add_post_fun(waf_unit_test.summary) + +By passing --dump-test-scripts the build outputs corresponding python files +(with extension _run.py) that are useful for debugging purposes. +""" + +import os, shlex, sys +from waflib.TaskGen import feature, after_method, taskgen_method +from waflib import Utils, Task, Logs, Options +from waflib.Tools import ccroot +testlock = Utils.threading.Lock() + +SCRIPT_TEMPLATE = """#! %(python)s +import subprocess, sys +cmd = %(cmd)r +# if you want to debug with gdb: +#cmd = ['gdb', '-args'] + cmd +env = %(env)r +status = subprocess.call(cmd, env=env, cwd=%(cwd)r, shell=isinstance(cmd, str)) +sys.exit(status) +""" + +@taskgen_method +def handle_ut_cwd(self, key): + """ + Task generator method, used internally to limit code duplication. + This method may disappear anytime. + """ + cwd = getattr(self, key, None) + if cwd: + if isinstance(cwd, str): + # we want a Node instance + if os.path.isabs(cwd): + self.ut_cwd = self.bld.root.make_node(cwd) + else: + self.ut_cwd = self.path.make_node(cwd) + +@feature('test_scripts') +def make_interpreted_test(self): + """Create interpreted unit tests.""" + for x in ['test_scripts_source', 'test_scripts_template']: + if not hasattr(self, x): + Logs.warn('a test_scripts taskgen i missing %s' % x) + return + + self.ut_run, lst = Task.compile_fun(self.test_scripts_template, shell=getattr(self, 'test_scripts_shell', False)) + + script_nodes = self.to_nodes(self.test_scripts_source) + for script_node in script_nodes: + tsk = self.create_task('utest', [script_node]) + tsk.vars = lst + tsk.vars + tsk.env['SCRIPT'] = script_node.path_from(tsk.get_cwd()) + + self.handle_ut_cwd('test_scripts_cwd') + + env = getattr(self, 'test_scripts_env', None) + if env: + self.ut_env = env + else: + self.ut_env = dict(os.environ) + + paths = getattr(self, 'test_scripts_paths', {}) + for (k,v) in paths.items(): + p = self.ut_env.get(k, '').split(os.pathsep) + if isinstance(v, str): + v = v.split(os.pathsep) + self.ut_env[k] = os.pathsep.join(p + v) + +@feature('test') +@after_method('apply_link', 'process_use') +def make_test(self): + """Create the unit test task. There can be only one unit test task by task generator.""" + if not getattr(self, 'link_task', None): + return + + tsk = self.create_task('utest', self.link_task.outputs) + if getattr(self, 'ut_str', None): + self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) + tsk.vars = lst + tsk.vars + + self.handle_ut_cwd('ut_cwd') + + if not hasattr(self, 'ut_paths'): + paths = [] + for x in self.tmp_use_sorted: + try: + y = self.bld.get_tgen_by_name(x).link_task + except AttributeError: + pass + else: + if not isinstance(y, ccroot.stlink_task): + paths.append(y.outputs[0].parent.abspath()) + self.ut_paths = os.pathsep.join(paths) + os.pathsep + + if not hasattr(self, 'ut_env'): + self.ut_env = dct = dict(os.environ) + def add_path(var): + dct[var] = self.ut_paths + dct.get(var,'') + if Utils.is_win32: + add_path('PATH') + elif Utils.unversioned_sys_platform() == 'darwin': + add_path('DYLD_LIBRARY_PATH') + add_path('LD_LIBRARY_PATH') + else: + add_path('LD_LIBRARY_PATH') + + if not hasattr(self, 'ut_cmd'): + self.ut_cmd = getattr(Options.options, 'testcmd', False) + +@taskgen_method +def add_test_results(self, tup): + """Override and return tup[1] to interrupt the build immediately if a test does not run""" + Logs.debug("ut: %r", tup) + try: + self.utest_results.append(tup) + except AttributeError: + self.utest_results = [tup] + try: + self.bld.utest_results.append(tup) + except AttributeError: + self.bld.utest_results = [tup] + +@Task.deep_inputs +class utest(Task.Task): + """ + Execute a unit test + """ + color = 'PINK' + after = ['vnum', 'inst'] + vars = [] + + def runnable_status(self): + """ + Always execute the task if `waf --alltests` was used or no + tests if ``waf --notests`` was used + """ + if getattr(Options.options, 'no_tests', False): + return Task.SKIP_ME + + ret = super(utest, self).runnable_status() + if ret == Task.SKIP_ME: + if getattr(Options.options, 'all_tests', False): + return Task.RUN_ME + return ret + + def get_test_env(self): + """ + In general, tests may require any library built anywhere in the project. + Override this method if fewer paths are needed + """ + return self.generator.ut_env + + def post_run(self): + super(utest, self).post_run() + if getattr(Options.options, 'clear_failed_tests', False) and self.waf_unit_test_results[1]: + self.generator.bld.task_sigs[self.uid()] = None + + def run(self): + """ + Execute the test. The execution is always successful, and the results + are stored on ``self.generator.bld.utest_results`` for postprocessing. + + Override ``add_test_results`` to interrupt the build + """ + if hasattr(self.generator, 'ut_run'): + return self.generator.ut_run(self) + + self.ut_exec = getattr(self.generator, 'ut_exec', [self.inputs[0].abspath()]) + ut_cmd = getattr(self.generator, 'ut_cmd', False) + if ut_cmd: + self.ut_exec = shlex.split(ut_cmd % ' '.join(self.ut_exec)) + + return self.exec_command(self.ut_exec) + + def exec_command(self, cmd, **kw): + self.generator.bld.log_command(cmd, kw) + if getattr(Options.options, 'dump_test_scripts', False): + script_code = SCRIPT_TEMPLATE % { + 'python': sys.executable, + 'env': self.get_test_env(), + 'cwd': self.get_cwd().abspath(), + 'cmd': cmd + } + script_file = self.inputs[0].abspath() + '_run.py' + Utils.writef(script_file, script_code, encoding='utf-8') + os.chmod(script_file, Utils.O755) + if Logs.verbose > 1: + Logs.info('Test debug file written as %r' % script_file) + + proc = Utils.subprocess.Popen(cmd, cwd=self.get_cwd().abspath(), env=self.get_test_env(), + stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE, shell=isinstance(cmd,str)) + (stdout, stderr) = proc.communicate() + self.waf_unit_test_results = tup = (self.inputs[0].abspath(), proc.returncode, stdout, stderr) + testlock.acquire() + try: + return self.generator.add_test_results(tup) + finally: + testlock.release() + + def get_cwd(self): + return getattr(self.generator, 'ut_cwd', self.inputs[0].parent) + +def summary(bld): + """ + Display an execution summary:: + + def build(bld): + bld(features='cxx cxxprogram test', source='main.c', target='app') + from waflib.Tools import waf_unit_test + bld.add_post_fun(waf_unit_test.summary) + """ + lst = getattr(bld, 'utest_results', []) + if lst: + Logs.pprint('CYAN', 'execution summary') + + total = len(lst) + tfail = len([x for x in lst if x[1]]) + + Logs.pprint('GREEN', ' tests that pass %d/%d' % (total-tfail, total)) + for (f, code, out, err) in lst: + if not code: + Logs.pprint('GREEN', ' %s' % f) + + Logs.pprint('GREEN' if tfail == 0 else 'RED', ' tests that fail %d/%d' % (tfail, total)) + for (f, code, out, err) in lst: + if code: + Logs.pprint('RED', ' %s' % f) + +def set_exit_code(bld): + """ + If any of the tests fail waf will exit with that exit code. + This is useful if you have an automated build system which need + to report on errors from the tests. + You may use it like this: + + def build(bld): + bld(features='cxx cxxprogram test', source='main.c', target='app') + from waflib.Tools import waf_unit_test + bld.add_post_fun(waf_unit_test.set_exit_code) + """ + lst = getattr(bld, 'utest_results', []) + for (f, code, out, err) in lst: + if code: + msg = [] + if out: + msg.append('stdout:%s%s' % (os.linesep, out.decode('utf-8'))) + if err: + msg.append('stderr:%s%s' % (os.linesep, err.decode('utf-8'))) + bld.fatal(os.linesep.join(msg)) + + +def options(opt): + """ + Provide the ``--alltests``, ``--notests`` and ``--testcmd`` command-line options. + """ + opt.add_option('--notests', action='store_true', default=False, help='Exec no unit tests', dest='no_tests') + opt.add_option('--alltests', action='store_true', default=False, help='Exec all unit tests', dest='all_tests') + opt.add_option('--clear-failed', action='store_true', default=False, + help='Force failed unit tests to run again next time', dest='clear_failed_tests') + opt.add_option('--testcmd', action='store', default=False, dest='testcmd', + help='Run the unit tests using the test-cmd string example "--testcmd="valgrind --error-exitcode=1 %s" to run under valgrind') + opt.add_option('--dump-test-scripts', action='store_true', default=False, + help='Create python scripts to help debug tests', dest='dump_test_scripts') + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/winres.py b/ldb-2.0.8/third_party/waf/waflib/Tools/winres.py new file mode 100644 index 0000000..9be1ed6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/winres.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Brant Young, 2007 + +"Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}" + +import re +from waflib import Task +from waflib.TaskGen import extension +from waflib.Tools import c_preproc + +@extension('.rc') +def rc_file(self, node): + """ + Binds the .rc extension to a winrc task + """ + obj_ext = '.rc.o' + if self.env.WINRC_TGT_F == '/fo': + obj_ext = '.res' + rctask = self.create_task('winrc', node, node.change_ext(obj_ext)) + try: + self.compiled_tasks.append(rctask) + except AttributeError: + self.compiled_tasks = [rctask] + +re_lines = re.compile( + r'(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|'\ + r'(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)', + re.IGNORECASE | re.MULTILINE) + +class rc_parser(c_preproc.c_parser): + """ + Calculates dependencies in .rc files + """ + def filter_comments(self, node): + """ + Overrides :py:meth:`waflib.Tools.c_preproc.c_parser.filter_comments` + """ + code = node.read() + if c_preproc.use_trigraphs: + for (a, b) in c_preproc.trig_def: + code = code.split(a).join(b) + code = c_preproc.re_nl.sub('', code) + code = c_preproc.re_cpp.sub(c_preproc.repl, code) + ret = [] + for m in re.finditer(re_lines, code): + if m.group(2): + ret.append((m.group(2), m.group(3))) + else: + ret.append(('include', m.group(5))) + return ret + +class winrc(Task.Task): + """ + Compiles resource files + """ + run_str = '${WINRC} ${WINRCFLAGS} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' + color = 'BLUE' + def scan(self): + tmp = rc_parser(self.generator.includes_nodes) + tmp.start(self.inputs[0], self.env) + return (tmp.nodes, tmp.names) + +def configure(conf): + """ + Detects the programs RC or windres, depending on the C/C++ compiler in use + """ + v = conf.env + if not v.WINRC: + if v.CC_NAME == 'msvc': + conf.find_program('RC', var='WINRC', path_list=v.PATH) + v.WINRC_TGT_F = '/fo' + v.WINRC_SRC_F = '' + else: + conf.find_program('windres', var='WINRC', path_list=v.PATH) + v.WINRC_TGT_F = '-o' + v.WINRC_SRC_F = '-i' + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/xlc.py b/ldb-2.0.8/third_party/waf/waflib/Tools/xlc.py new file mode 100644 index 0000000..134dd41 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/xlc.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) +# Ralf Habacker, 2006 (rh) +# Yinon Ehrlich, 2009 +# Michael Kuhn, 2009 + +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +@conf +def find_xlc(conf): + """ + Detects the Aix C compiler + """ + cc = conf.find_program(['xlc_r', 'xlc'], var='CC') + conf.get_xlc_version(cc) + conf.env.CC_NAME = 'xlc' + +@conf +def xlc_common_flags(conf): + """ + Flags required for executing the Aix C compiler + """ + v = conf.env + + v.CC_SRC_F = [] + v.CC_TGT_F = ['-c', '-o'] + + if not v.LINK_CC: + v.LINK_CC = v.CC + + v.CCLNK_SRC_F = [] + v.CCLNK_TGT_F = ['-o'] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + v.RPATH_ST = '-Wl,-rpath,%s' + + v.SONAME_ST = [] + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + + v.LINKFLAGS_cprogram = ['-Wl,-brtl'] + v.cprogram_PATTERN = '%s' + + v.CFLAGS_cshlib = ['-fPIC'] + v.LINKFLAGS_cshlib = ['-G', '-Wl,-brtl,-bexpfull'] + v.cshlib_PATTERN = 'lib%s.so' + + v.LINKFLAGS_cstlib = [] + v.cstlib_PATTERN = 'lib%s.a' + +def configure(conf): + conf.find_xlc() + conf.find_ar() + conf.xlc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Tools/xlcxx.py b/ldb-2.0.8/third_party/waf/waflib/Tools/xlcxx.py new file mode 100644 index 0000000..76aa59b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Tools/xlcxx.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2018 (ita) +# Ralf Habacker, 2006 (rh) +# Yinon Ehrlich, 2009 +# Michael Kuhn, 2009 + +from waflib.Tools import ccroot, ar +from waflib.Configure import conf + +@conf +def find_xlcxx(conf): + """ + Detects the Aix C++ compiler + """ + cxx = conf.find_program(['xlc++_r', 'xlc++'], var='CXX') + conf.get_xlc_version(cxx) + conf.env.CXX_NAME = 'xlc++' + +@conf +def xlcxx_common_flags(conf): + """ + Flags required for executing the Aix C++ compiler + """ + v = conf.env + + v.CXX_SRC_F = [] + v.CXX_TGT_F = ['-c', '-o'] + + if not v.LINK_CXX: + v.LINK_CXX = v.CXX + + v.CXXLNK_SRC_F = [] + v.CXXLNK_TGT_F = ['-o'] + v.CPPPATH_ST = '-I%s' + v.DEFINES_ST = '-D%s' + + v.LIB_ST = '-l%s' # template for adding libs + v.LIBPATH_ST = '-L%s' # template for adding libpaths + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-L%s' + v.RPATH_ST = '-Wl,-rpath,%s' + + v.SONAME_ST = [] + v.SHLIB_MARKER = [] + v.STLIB_MARKER = [] + + v.LINKFLAGS_cxxprogram= ['-Wl,-brtl'] + v.cxxprogram_PATTERN = '%s' + + v.CXXFLAGS_cxxshlib = ['-fPIC'] + v.LINKFLAGS_cxxshlib = ['-G', '-Wl,-brtl,-bexpfull'] + v.cxxshlib_PATTERN = 'lib%s.so' + + v.LINKFLAGS_cxxstlib = [] + v.cxxstlib_PATTERN = 'lib%s.a' + +def configure(conf): + conf.find_xlcxx() + conf.find_ar() + conf.xlcxx_common_flags() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/Utils.py b/ldb-2.0.8/third_party/waf/waflib/Utils.py new file mode 100644 index 0000000..7472226 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/Utils.py @@ -0,0 +1,1035 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) + +""" +Utilities and platform-specific fixes + +The portability fixes try to provide a consistent behavior of the Waf API +through Python versions 2.5 to 3.X and across different platforms (win32, linux, etc) +""" + +from __future__ import with_statement + +import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time + +try: + import cPickle +except ImportError: + import pickle as cPickle + +# leave this +if os.name == 'posix' and sys.version_info[0] < 3: + try: + import subprocess32 as subprocess + except ImportError: + import subprocess +else: + import subprocess + +try: + TimeoutExpired = subprocess.TimeoutExpired +except AttributeError: + class TimeoutExpired(Exception): + pass + +from collections import deque, defaultdict + +try: + import _winreg as winreg +except ImportError: + try: + import winreg + except ImportError: + winreg = None + +from waflib import Errors + +try: + from hashlib import md5 +except ImportError: + try: + from hashlib import sha1 as md5 + except ImportError: + # never fail to enable potential fixes from another module + pass +else: + try: + md5().digest() + except ValueError: + # Fips? #2213 + from hashlib import sha1 as md5 + +try: + import threading +except ImportError: + if not 'JOBS' in os.environ: + # no threading :-( + os.environ['JOBS'] = '1' + + class threading(object): + """ + A fake threading class for platforms lacking the threading module. + Use ``waf -j1`` on those platforms + """ + pass + class Lock(object): + """Fake Lock class""" + def acquire(self): + pass + def release(self): + pass + threading.Lock = threading.Thread = Lock + +SIG_NIL = 'SIG_NIL_SIG_NIL_'.encode() +"""Arbitrary null value for hashes. Modify this value according to the hash function in use""" + +O644 = 420 +"""Constant representing the permissions for regular files (0644 raises a syntax error on python 3)""" + +O755 = 493 +"""Constant representing the permissions for executable files (0755 raises a syntax error on python 3)""" + +rot_chr = ['\\', '|', '/', '-'] +"List of characters to use when displaying the throbber (progress bar)" + +rot_idx = 0 +"Index of the current throbber character (progress bar)" + +class ordered_iter_dict(dict): + """Ordered dictionary that provides iteration from the most recently inserted keys first""" + def __init__(self, *k, **kw): + self.lst = deque() + dict.__init__(self, *k, **kw) + def clear(self): + dict.clear(self) + self.lst = deque() + def __setitem__(self, key, value): + if key in dict.keys(self): + self.lst.remove(key) + dict.__setitem__(self, key, value) + self.lst.append(key) + def __delitem__(self, key): + dict.__delitem__(self, key) + try: + self.lst.remove(key) + except ValueError: + pass + def __iter__(self): + return reversed(self.lst) + def keys(self): + return reversed(self.lst) + +class lru_node(object): + """ + Used by :py:class:`waflib.Utils.lru_cache` + """ + __slots__ = ('next', 'prev', 'key', 'val') + def __init__(self): + self.next = self + self.prev = self + self.key = None + self.val = None + +class lru_cache(object): + """ + A simple least-recently used cache with lazy allocation + """ + __slots__ = ('maxlen', 'table', 'head') + def __init__(self, maxlen=100): + self.maxlen = maxlen + """ + Maximum amount of elements in the cache + """ + self.table = {} + """ + Mapping key-value + """ + self.head = lru_node() + self.head.next = self.head + self.head.prev = self.head + + def __getitem__(self, key): + node = self.table[key] + # assert(key==node.key) + if node is self.head: + return node.val + + # detach the node found + node.prev.next = node.next + node.next.prev = node.prev + + # replace the head + node.next = self.head.next + node.prev = self.head + self.head = node.next.prev = node.prev.next = node + + return node.val + + def __setitem__(self, key, val): + if key in self.table: + # update the value for an existing key + node = self.table[key] + node.val = val + self.__getitem__(key) + else: + if len(self.table) < self.maxlen: + # the very first item is unused until the maximum is reached + node = lru_node() + node.prev = self.head + node.next = self.head.next + node.prev.next = node.next.prev = node + else: + node = self.head = self.head.next + try: + # that's another key + del self.table[node.key] + except KeyError: + pass + + node.key = key + node.val = val + self.table[key] = node + +class lazy_generator(object): + def __init__(self, fun, params): + self.fun = fun + self.params = params + + def __iter__(self): + return self + + def __next__(self): + try: + it = self.it + except AttributeError: + it = self.it = self.fun(*self.params) + return next(it) + + next = __next__ + +is_win32 = os.sep == '\\' or sys.platform == 'win32' or os.name == 'nt' # msys2 +""" +Whether this system is a Windows series +""" + +def readf(fname, m='r', encoding='latin-1'): + """ + Reads an entire file into a string. See also :py:meth:`waflib.Node.Node.readf`:: + + def build(ctx): + from waflib import Utils + txt = Utils.readf(self.path.find_node('wscript').abspath()) + txt = ctx.path.find_node('wscript').read() + + :type fname: string + :param fname: Path to file + :type m: string + :param m: Open mode + :type encoding: string + :param encoding: encoding value, only used for python 3 + :rtype: string + :return: Content of the file + """ + + if sys.hexversion > 0x3000000 and not 'b' in m: + m += 'b' + with open(fname, m) as f: + txt = f.read() + if encoding: + txt = txt.decode(encoding) + else: + txt = txt.decode() + else: + with open(fname, m) as f: + txt = f.read() + return txt + +def writef(fname, data, m='w', encoding='latin-1'): + """ + Writes an entire file from a string. + See also :py:meth:`waflib.Node.Node.writef`:: + + def build(ctx): + from waflib import Utils + txt = Utils.writef(self.path.make_node('i_like_kittens').abspath(), 'some data') + self.path.make_node('i_like_kittens').write('some data') + + :type fname: string + :param fname: Path to file + :type data: string + :param data: The contents to write to the file + :type m: string + :param m: Open mode + :type encoding: string + :param encoding: encoding value, only used for python 3 + """ + if sys.hexversion > 0x3000000 and not 'b' in m: + data = data.encode(encoding) + m += 'b' + with open(fname, m) as f: + f.write(data) + +def h_file(fname): + """ + Computes a hash value for a file by using md5. Use the md5_tstamp + extension to get faster build hashes if necessary. + + :type fname: string + :param fname: path to the file to hash + :return: hash of the file contents + :rtype: string or bytes + """ + m = md5() + with open(fname, 'rb') as f: + while fname: + fname = f.read(200000) + m.update(fname) + return m.digest() + +def readf_win32(f, m='r', encoding='latin-1'): + flags = os.O_NOINHERIT | os.O_RDONLY + if 'b' in m: + flags |= os.O_BINARY + if '+' in m: + flags |= os.O_RDWR + try: + fd = os.open(f, flags) + except OSError: + raise IOError('Cannot read from %r' % f) + + if sys.hexversion > 0x3000000 and not 'b' in m: + m += 'b' + with os.fdopen(fd, m) as f: + txt = f.read() + if encoding: + txt = txt.decode(encoding) + else: + txt = txt.decode() + else: + with os.fdopen(fd, m) as f: + txt = f.read() + return txt + +def writef_win32(f, data, m='w', encoding='latin-1'): + if sys.hexversion > 0x3000000 and not 'b' in m: + data = data.encode(encoding) + m += 'b' + flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | os.O_NOINHERIT + if 'b' in m: + flags |= os.O_BINARY + if '+' in m: + flags |= os.O_RDWR + try: + fd = os.open(f, flags) + except OSError: + raise OSError('Cannot write to %r' % f) + with os.fdopen(fd, m) as f: + f.write(data) + +def h_file_win32(fname): + try: + fd = os.open(fname, os.O_BINARY | os.O_RDONLY | os.O_NOINHERIT) + except OSError: + raise OSError('Cannot read from %r' % fname) + m = md5() + with os.fdopen(fd, 'rb') as f: + while fname: + fname = f.read(200000) + m.update(fname) + return m.digest() + +# always save these +readf_unix = readf +writef_unix = writef +h_file_unix = h_file +if hasattr(os, 'O_NOINHERIT') and sys.hexversion < 0x3040000: + # replace the default functions + readf = readf_win32 + writef = writef_win32 + h_file = h_file_win32 + +try: + x = ''.encode('hex') +except LookupError: + import binascii + def to_hex(s): + ret = binascii.hexlify(s) + if not isinstance(ret, str): + ret = ret.decode('utf-8') + return ret +else: + def to_hex(s): + return s.encode('hex') + +to_hex.__doc__ = """ +Return the hexadecimal representation of a string + +:param s: string to convert +:type s: string +""" + +def listdir_win32(s): + """ + Lists the contents of a folder in a portable manner. + On Win32, returns the list of drive letters: ['C:', 'X:', 'Z:'] when an empty string is given. + + :type s: string + :param s: a string, which can be empty on Windows + """ + if not s: + try: + import ctypes + except ImportError: + # there is nothing much we can do + return [x + ':\\' for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] + else: + dlen = 4 # length of "?:\\x00" + maxdrives = 26 + buf = ctypes.create_string_buffer(maxdrives * dlen) + ndrives = ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen, ctypes.byref(buf)) + return [ str(buf.raw[4*i:4*i+2].decode('ascii')) for i in range(int(ndrives/dlen)) ] + + if len(s) == 2 and s[1] == ":": + s += os.sep + + if not os.path.isdir(s): + e = OSError('%s is not a directory' % s) + e.errno = errno.ENOENT + raise e + return os.listdir(s) + +listdir = os.listdir +if is_win32: + listdir = listdir_win32 + +def num2ver(ver): + """ + Converts a string, tuple or version number into an integer. The number is supposed to have at most 4 digits:: + + from waflib.Utils import num2ver + num2ver('1.3.2') == num2ver((1,3,2)) == num2ver((1,3,2,0)) + + :type ver: string or tuple of numbers + :param ver: a version number + """ + if isinstance(ver, str): + ver = tuple(ver.split('.')) + if isinstance(ver, tuple): + ret = 0 + for i in range(4): + if i < len(ver): + ret += 256**(3 - i) * int(ver[i]) + return ret + return ver + +def to_list(val): + """ + Converts a string argument to a list by splitting it by spaces. + Returns the object if not a string:: + + from waflib.Utils import to_list + lst = to_list('a b c d') + + :param val: list of string or space-separated string + :rtype: list + :return: Argument converted to list + """ + if isinstance(val, str): + return val.split() + else: + return val + +def console_encoding(): + try: + import ctypes + except ImportError: + pass + else: + try: + codepage = ctypes.windll.kernel32.GetConsoleCP() + except AttributeError: + pass + else: + if codepage: + return 'cp%d' % codepage + return sys.stdout.encoding or ('cp1252' if is_win32 else 'latin-1') + +def split_path_unix(path): + return path.split('/') + +def split_path_cygwin(path): + if path.startswith('//'): + ret = path.split('/')[2:] + ret[0] = '/' + ret[0] + return ret + return path.split('/') + +re_sp = re.compile('[/\\\\]+') +def split_path_win32(path): + if path.startswith('\\\\'): + ret = re_sp.split(path)[1:] + ret[0] = '\\\\' + ret[0] + if ret[0] == '\\\\?': + return ret[1:] + return ret + return re_sp.split(path) + +msysroot = None +def split_path_msys(path): + if path.startswith(('/', '\\')) and not path.startswith(('//', '\\\\')): + # msys paths can be in the form /usr/bin + global msysroot + if not msysroot: + # msys has python 2.7 or 3, so we can use this + msysroot = subprocess.check_output(['cygpath', '-w', '/']).decode(sys.stdout.encoding or 'latin-1') + msysroot = msysroot.strip() + path = os.path.normpath(msysroot + os.sep + path) + return split_path_win32(path) + +if sys.platform == 'cygwin': + split_path = split_path_cygwin +elif is_win32: + # Consider this an MSYSTEM environment if $MSYSTEM is set and python + # reports is executable from a unix like path on a windows host. + if os.environ.get('MSYSTEM') and sys.executable.startswith('/'): + split_path = split_path_msys + else: + split_path = split_path_win32 +else: + split_path = split_path_unix + +split_path.__doc__ = """ +Splits a path by / or \\; do not confuse this function with with ``os.path.split`` + +:type path: string +:param path: path to split +:return: list of string +""" + +def check_dir(path): + """ + Ensures that a directory exists (similar to ``mkdir -p``). + + :type path: string + :param path: Path to directory + :raises: :py:class:`waflib.Errors.WafError` if the folder cannot be added. + """ + if not os.path.isdir(path): + try: + os.makedirs(path) + except OSError as e: + if not os.path.isdir(path): + raise Errors.WafError('Cannot create the folder %r' % path, ex=e) + +def check_exe(name, env=None): + """ + Ensures that a program exists + + :type name: string + :param name: path to the program + :param env: configuration object + :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :return: path of the program or None + :raises: :py:class:`waflib.Errors.WafError` if the folder cannot be added. + """ + if not name: + raise ValueError('Cannot execute an empty string!') + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + fpath, fname = os.path.split(name) + if fpath and is_exe(name): + return os.path.abspath(name) + else: + env = env or os.environ + for path in env['PATH'].split(os.pathsep): + path = path.strip('"') + exe_file = os.path.join(path, name) + if is_exe(exe_file): + return os.path.abspath(exe_file) + return None + +def def_attrs(cls, **kw): + """ + Sets default attributes on a class instance + + :type cls: class + :param cls: the class to update the given attributes in. + :type kw: dict + :param kw: dictionary of attributes names and values. + """ + for k, v in kw.items(): + if not hasattr(cls, k): + setattr(cls, k, v) + +def quote_define_name(s): + """ + Converts a string into an identifier suitable for C defines. + + :type s: string + :param s: String to convert + :rtype: string + :return: Identifier suitable for C defines + """ + fu = re.sub('[^a-zA-Z0-9]', '_', s) + fu = re.sub('_+', '_', fu) + fu = fu.upper() + return fu + +re_sh = re.compile('\\s|\'|"') +""" +Regexp used for shell_escape below +""" + +def shell_escape(cmd): + """ + Escapes a command: + ['ls', '-l', 'arg space'] -> ls -l 'arg space' + """ + if isinstance(cmd, str): + return cmd + return ' '.join(repr(x) if re_sh.search(x) else x for x in cmd) + +def h_list(lst): + """ + Hashes lists of ordered data. + + Using hash(tup) for tuples would be much more efficient, + but Python now enforces hash randomization + + :param lst: list to hash + :type lst: list of strings + :return: hash of the list + """ + return md5(repr(lst).encode()).digest() + +if sys.hexversion < 0x3000000: + def h_list_python2(lst): + return md5(repr(lst)).digest() + h_list_python2.__doc__ = h_list.__doc__ + h_list = h_list_python2 + +def h_fun(fun): + """ + Hash functions + + :param fun: function to hash + :type fun: function + :return: hash of the function + :rtype: string or bytes + """ + try: + return fun.code + except AttributeError: + if isinstance(fun, functools.partial): + code = list(fun.args) + # The method items() provides a sequence of tuples where the first element + # represents an optional argument of the partial function application + # + # The sorting result outcome will be consistent because: + # 1. tuples are compared in order of their elements + # 2. optional argument namess are unique + code.extend(sorted(fun.keywords.items())) + code.append(h_fun(fun.func)) + fun.code = h_list(code) + return fun.code + try: + h = inspect.getsource(fun) + except EnvironmentError: + h = 'nocode' + try: + fun.code = h + except AttributeError: + pass + return h + +def h_cmd(ins): + """ + Hashes objects recursively + + :param ins: input object + :type ins: string or list or tuple or function + :rtype: string or bytes + """ + # this function is not meant to be particularly fast + if isinstance(ins, str): + # a command is either a string + ret = ins + elif isinstance(ins, list) or isinstance(ins, tuple): + # or a list of functions/strings + ret = str([h_cmd(x) for x in ins]) + else: + # or just a python function + ret = str(h_fun(ins)) + if sys.hexversion > 0x3000000: + ret = ret.encode('latin-1', 'xmlcharrefreplace') + return ret + +reg_subst = re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") +def subst_vars(expr, params): + """ + Replaces ${VAR} with the value of VAR taken from a dict or a config set:: + + from waflib import Utils + s = Utils.subst_vars('${PREFIX}/bin', env) + + :type expr: string + :param expr: String to perform substitution on + :param params: Dictionary or config set to look up variable values. + """ + def repl_var(m): + if m.group(1): + return '\\' + if m.group(2): + return '$' + try: + # ConfigSet instances may contain lists + return params.get_flat(m.group(3)) + except AttributeError: + return params[m.group(3)] + # if you get a TypeError, it means that 'expr' is not a string... + # Utils.subst_vars(None, env) will not work + return reg_subst.sub(repl_var, expr) + +def destos_to_binfmt(key): + """ + Returns the binary format based on the unversioned platform name, + and defaults to ``elf`` if nothing is found. + + :param key: platform name + :type key: string + :return: string representing the binary format + """ + if key == 'darwin': + return 'mac-o' + elif key in ('win32', 'cygwin', 'uwin', 'msys'): + return 'pe' + return 'elf' + +def unversioned_sys_platform(): + """ + Returns the unversioned platform name. + Some Python platform names contain versions, that depend on + the build environment, e.g. linux2, freebsd6, etc. + This returns the name without the version number. Exceptions are + os2 and win32, which are returned verbatim. + + :rtype: string + :return: Unversioned platform name + """ + s = sys.platform + if s.startswith('java'): + # The real OS is hidden under the JVM. + from java.lang import System + s = System.getProperty('os.name') + # see http://lopica.sourceforge.net/os.html for a list of possible values + if s == 'Mac OS X': + return 'darwin' + elif s.startswith('Windows '): + return 'win32' + elif s == 'OS/2': + return 'os2' + elif s == 'HP-UX': + return 'hp-ux' + elif s in ('SunOS', 'Solaris'): + return 'sunos' + else: s = s.lower() + + # powerpc == darwin for our purposes + if s == 'powerpc': + return 'darwin' + if s == 'win32' or s == 'os2': + return s + if s == 'cli' and os.name == 'nt': + # ironpython is only on windows as far as we know + return 'win32' + return re.split(r'\d+$', s)[0] + +def nada(*k, **kw): + """ + Does nothing + + :return: None + """ + pass + +class Timer(object): + """ + Simple object for timing the execution of commands. + Its string representation is the duration:: + + from waflib.Utils import Timer + timer = Timer() + a_few_operations() + s = str(timer) + """ + def __init__(self): + self.start_time = self.now() + + def __str__(self): + delta = self.now() - self.start_time + if not isinstance(delta, datetime.timedelta): + delta = datetime.timedelta(seconds=delta) + days = delta.days + hours, rem = divmod(delta.seconds, 3600) + minutes, seconds = divmod(rem, 60) + seconds += delta.microseconds * 1e-6 + result = '' + if days: + result += '%dd' % days + if days or hours: + result += '%dh' % hours + if days or hours or minutes: + result += '%dm' % minutes + return '%s%.3fs' % (result, seconds) + + def now(self): + return datetime.datetime.utcnow() + + if hasattr(time, 'perf_counter'): + def now(self): + return time.perf_counter() + +def read_la_file(path): + """ + Reads property files, used by msvc.py + + :param path: file to read + :type path: string + """ + sp = re.compile(r'^([^=]+)=\'(.*)\'$') + dc = {} + for line in readf(path).splitlines(): + try: + _, left, right, _ = sp.split(line.strip()) + dc[left] = right + except ValueError: + pass + return dc + +def run_once(fun): + """ + Decorator: let a function cache its results, use like this:: + + @run_once + def foo(k): + return 345*2343 + + .. note:: in practice this can cause memory leaks, prefer a :py:class:`waflib.Utils.lru_cache` + + :param fun: function to execute + :type fun: function + :return: the return value of the function executed + """ + cache = {} + def wrap(*k): + try: + return cache[k] + except KeyError: + ret = fun(*k) + cache[k] = ret + return ret + wrap.__cache__ = cache + wrap.__name__ = fun.__name__ + return wrap + +def get_registry_app_path(key, filename): + """ + Returns the value of a registry key for an executable + + :type key: string + :type filename: list of string + """ + if not winreg: + return None + try: + result = winreg.QueryValue(key, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe" % filename[0]) + except OSError: + pass + else: + if os.path.isfile(result): + return result + +def lib64(): + """ + Guess the default ``/usr/lib`` extension for 64-bit applications + + :return: '64' or '' + :rtype: string + """ + # default settings for /usr/lib + if os.sep == '/': + if platform.architecture()[0] == '64bit': + if os.path.exists('/usr/lib64') and not os.path.exists('/usr/lib32'): + return '64' + return '' + +def sane_path(p): + # private function for the time being! + return os.path.abspath(os.path.expanduser(p)) + +process_pool = [] +""" +List of processes started to execute sub-process commands +""" + +def get_process(): + """ + Returns a process object that can execute commands as sub-processes + + :rtype: subprocess.Popen + """ + try: + return process_pool.pop() + except IndexError: + filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'processor.py' + cmd = [sys.executable, '-c', readf(filepath)] + return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0, close_fds=not is_win32) + +def run_prefork_process(cmd, kwargs, cargs): + """ + Delegates process execution to a pre-forked process instance. + """ + if not 'env' in kwargs: + kwargs['env'] = dict(os.environ) + try: + obj = base64.b64encode(cPickle.dumps([cmd, kwargs, cargs])) + except (TypeError, AttributeError): + return run_regular_process(cmd, kwargs, cargs) + + proc = get_process() + if not proc: + return run_regular_process(cmd, kwargs, cargs) + + proc.stdin.write(obj) + proc.stdin.write('\n'.encode()) + proc.stdin.flush() + obj = proc.stdout.readline() + if not obj: + raise OSError('Preforked sub-process %r died' % proc.pid) + + process_pool.append(proc) + lst = cPickle.loads(base64.b64decode(obj)) + # Jython wrapper failures (bash/execvp) + assert len(lst) == 5 + ret, out, err, ex, trace = lst + if ex: + if ex == 'OSError': + raise OSError(trace) + elif ex == 'ValueError': + raise ValueError(trace) + elif ex == 'TimeoutExpired': + exc = TimeoutExpired(cmd, timeout=cargs['timeout'], output=out) + exc.stderr = err + raise exc + else: + raise Exception(trace) + return ret, out, err + +def lchown(path, user=-1, group=-1): + """ + Change the owner/group of a path, raises an OSError if the + ownership change fails. + + :param user: user to change + :type user: int or str + :param group: group to change + :type group: int or str + """ + if isinstance(user, str): + import pwd + entry = pwd.getpwnam(user) + if not entry: + raise OSError('Unknown user %r' % user) + user = entry[2] + if isinstance(group, str): + import grp + entry = grp.getgrnam(group) + if not entry: + raise OSError('Unknown group %r' % group) + group = entry[2] + return os.lchown(path, user, group) + +def run_regular_process(cmd, kwargs, cargs={}): + """ + Executes a subprocess command by using subprocess.Popen + """ + proc = subprocess.Popen(cmd, **kwargs) + if kwargs.get('stdout') or kwargs.get('stderr'): + try: + out, err = proc.communicate(**cargs) + except TimeoutExpired: + if kwargs.get('start_new_session') and hasattr(os, 'killpg'): + os.killpg(proc.pid, signal.SIGKILL) + else: + proc.kill() + out, err = proc.communicate() + exc = TimeoutExpired(proc.args, timeout=cargs['timeout'], output=out) + exc.stderr = err + raise exc + status = proc.returncode + else: + out, err = (None, None) + try: + status = proc.wait(**cargs) + except TimeoutExpired as e: + if kwargs.get('start_new_session') and hasattr(os, 'killpg'): + os.killpg(proc.pid, signal.SIGKILL) + else: + proc.kill() + proc.wait() + raise e + return status, out, err + +def run_process(cmd, kwargs, cargs={}): + """ + Executes a subprocess by using a pre-forked process when possible + or falling back to subprocess.Popen. See :py:func:`waflib.Utils.run_prefork_process` + and :py:func:`waflib.Utils.run_regular_process` + """ + if kwargs.get('stdout') and kwargs.get('stderr'): + return run_prefork_process(cmd, kwargs, cargs) + else: + return run_regular_process(cmd, kwargs, cargs) + +def alloc_process_pool(n, force=False): + """ + Allocates an amount of processes to the default pool so its size is at least *n*. + It is useful to call this function early so that the pre-forked + processes use as little memory as possible. + + :param n: pool size + :type n: integer + :param force: if True then *n* more processes are added to the existing pool + :type force: bool + """ + # mandatory on python2, unnecessary on python >= 3.2 + global run_process, get_process, alloc_process_pool + if not force: + n = max(n - len(process_pool), 0) + try: + lst = [get_process() for x in range(n)] + except OSError: + run_process = run_regular_process + get_process = alloc_process_pool = nada + else: + for x in lst: + process_pool.append(x) + +def atexit_pool(): + for k in process_pool: + try: + os.kill(k.pid, 9) + except OSError: + pass + else: + k.wait() +# see #1889 +if (sys.hexversion<0x207000f and not is_win32) or sys.hexversion>=0x306000f: + atexit.register(atexit_pool) + +if os.environ.get('WAF_NO_PREFORK') or sys.platform == 'cli' or not sys.executable: + run_process = run_regular_process + get_process = alloc_process_pool = nada + diff --git a/ldb-2.0.8/third_party/waf/waflib/__init__.py b/ldb-2.0.8/third_party/waf/waflib/__init__.py new file mode 100644 index 0000000..079df35 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2018 (ita) diff --git a/ldb-2.0.8/third_party/waf/waflib/ansiterm.py b/ldb-2.0.8/third_party/waf/waflib/ansiterm.py new file mode 100644 index 0000000..027f0ad --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/ansiterm.py @@ -0,0 +1,342 @@ +#!/usr/bin/env python +# encoding: utf-8 + +""" +Emulate a vt100 terminal in cmd.exe + +By wrapping sys.stdout / sys.stderr with Ansiterm, +the vt100 escape characters will be interpreted and +the equivalent actions will be performed with Win32 +console commands. + +""" + +import os, re, sys +from waflib import Utils + +wlock = Utils.threading.Lock() + +try: + from ctypes import Structure, windll, c_short, c_ushort, c_ulong, c_int, byref, c_wchar, POINTER, c_long +except ImportError: + + class AnsiTerm(object): + def __init__(self, stream): + self.stream = stream + try: + self.errors = self.stream.errors + except AttributeError: + pass # python 2.5 + self.encoding = self.stream.encoding + + def write(self, txt): + try: + wlock.acquire() + self.stream.write(txt) + self.stream.flush() + finally: + wlock.release() + + def fileno(self): + return self.stream.fileno() + + def flush(self): + self.stream.flush() + + def isatty(self): + return self.stream.isatty() +else: + + class COORD(Structure): + _fields_ = [("X", c_short), ("Y", c_short)] + + class SMALL_RECT(Structure): + _fields_ = [("Left", c_short), ("Top", c_short), ("Right", c_short), ("Bottom", c_short)] + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + _fields_ = [("Size", COORD), ("CursorPosition", COORD), ("Attributes", c_ushort), ("Window", SMALL_RECT), ("MaximumWindowSize", COORD)] + + class CONSOLE_CURSOR_INFO(Structure): + _fields_ = [('dwSize', c_ulong), ('bVisible', c_int)] + + try: + _type = unicode + except NameError: + _type = str + + to_int = lambda number, default: number and int(number) or default + + STD_OUTPUT_HANDLE = -11 + STD_ERROR_HANDLE = -12 + + windll.kernel32.GetStdHandle.argtypes = [c_ulong] + windll.kernel32.GetStdHandle.restype = c_ulong + windll.kernel32.GetConsoleScreenBufferInfo.argtypes = [c_ulong, POINTER(CONSOLE_SCREEN_BUFFER_INFO)] + windll.kernel32.GetConsoleScreenBufferInfo.restype = c_long + windll.kernel32.SetConsoleTextAttribute.argtypes = [c_ulong, c_ushort] + windll.kernel32.SetConsoleTextAttribute.restype = c_long + windll.kernel32.FillConsoleOutputCharacterW.argtypes = [c_ulong, c_wchar, c_ulong, POINTER(COORD), POINTER(c_ulong)] + windll.kernel32.FillConsoleOutputCharacterW.restype = c_long + windll.kernel32.FillConsoleOutputAttribute.argtypes = [c_ulong, c_ushort, c_ulong, POINTER(COORD), POINTER(c_ulong) ] + windll.kernel32.FillConsoleOutputAttribute.restype = c_long + windll.kernel32.SetConsoleCursorPosition.argtypes = [c_ulong, POINTER(COORD) ] + windll.kernel32.SetConsoleCursorPosition.restype = c_long + windll.kernel32.SetConsoleCursorInfo.argtypes = [c_ulong, POINTER(CONSOLE_CURSOR_INFO)] + windll.kernel32.SetConsoleCursorInfo.restype = c_long + + class AnsiTerm(object): + """ + emulate a vt100 terminal in cmd.exe + """ + def __init__(self, s): + self.stream = s + try: + self.errors = s.errors + except AttributeError: + pass # python2.5 + self.encoding = s.encoding + self.cursor_history = [] + + handle = (s.fileno() == 2) and STD_ERROR_HANDLE or STD_OUTPUT_HANDLE + self.hconsole = windll.kernel32.GetStdHandle(handle) + + self._sbinfo = CONSOLE_SCREEN_BUFFER_INFO() + + self._csinfo = CONSOLE_CURSOR_INFO() + windll.kernel32.GetConsoleCursorInfo(self.hconsole, byref(self._csinfo)) + + # just to double check that the console is usable + self._orig_sbinfo = CONSOLE_SCREEN_BUFFER_INFO() + r = windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self._orig_sbinfo)) + self._isatty = r == 1 + + def screen_buffer_info(self): + """ + Updates self._sbinfo and returns it + """ + windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self._sbinfo)) + return self._sbinfo + + def clear_line(self, param): + mode = param and int(param) or 0 + sbinfo = self.screen_buffer_info() + if mode == 1: # Clear from beginning of line to cursor position + line_start = COORD(0, sbinfo.CursorPosition.Y) + line_length = sbinfo.Size.X + elif mode == 2: # Clear entire line + line_start = COORD(sbinfo.CursorPosition.X, sbinfo.CursorPosition.Y) + line_length = sbinfo.Size.X - sbinfo.CursorPosition.X + else: # Clear from cursor position to end of line + line_start = sbinfo.CursorPosition + line_length = sbinfo.Size.X - sbinfo.CursorPosition.X + chars_written = c_ulong() + windll.kernel32.FillConsoleOutputCharacterW(self.hconsole, c_wchar(' '), line_length, line_start, byref(chars_written)) + windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, line_length, line_start, byref(chars_written)) + + def clear_screen(self, param): + mode = to_int(param, 0) + sbinfo = self.screen_buffer_info() + if mode == 1: # Clear from beginning of screen to cursor position + clear_start = COORD(0, 0) + clear_length = sbinfo.CursorPosition.X * sbinfo.CursorPosition.Y + elif mode == 2: # Clear entire screen and return cursor to home + clear_start = COORD(0, 0) + clear_length = sbinfo.Size.X * sbinfo.Size.Y + windll.kernel32.SetConsoleCursorPosition(self.hconsole, clear_start) + else: # Clear from cursor position to end of screen + clear_start = sbinfo.CursorPosition + clear_length = ((sbinfo.Size.X - sbinfo.CursorPosition.X) + sbinfo.Size.X * (sbinfo.Size.Y - sbinfo.CursorPosition.Y)) + chars_written = c_ulong() + windll.kernel32.FillConsoleOutputCharacterW(self.hconsole, c_wchar(' '), clear_length, clear_start, byref(chars_written)) + windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, clear_length, clear_start, byref(chars_written)) + + def push_cursor(self, param): + sbinfo = self.screen_buffer_info() + self.cursor_history.append(sbinfo.CursorPosition) + + def pop_cursor(self, param): + if self.cursor_history: + old_pos = self.cursor_history.pop() + windll.kernel32.SetConsoleCursorPosition(self.hconsole, old_pos) + + def set_cursor(self, param): + y, sep, x = param.partition(';') + x = to_int(x, 1) - 1 + y = to_int(y, 1) - 1 + sbinfo = self.screen_buffer_info() + new_pos = COORD( + min(max(0, x), sbinfo.Size.X), + min(max(0, y), sbinfo.Size.Y) + ) + windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) + + def set_column(self, param): + x = to_int(param, 1) - 1 + sbinfo = self.screen_buffer_info() + new_pos = COORD( + min(max(0, x), sbinfo.Size.X), + sbinfo.CursorPosition.Y + ) + windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) + + def move_cursor(self, x_offset=0, y_offset=0): + sbinfo = self.screen_buffer_info() + new_pos = COORD( + min(max(0, sbinfo.CursorPosition.X + x_offset), sbinfo.Size.X), + min(max(0, sbinfo.CursorPosition.Y + y_offset), sbinfo.Size.Y) + ) + windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) + + def move_up(self, param): + self.move_cursor(y_offset = -to_int(param, 1)) + + def move_down(self, param): + self.move_cursor(y_offset = to_int(param, 1)) + + def move_left(self, param): + self.move_cursor(x_offset = -to_int(param, 1)) + + def move_right(self, param): + self.move_cursor(x_offset = to_int(param, 1)) + + def next_line(self, param): + sbinfo = self.screen_buffer_info() + self.move_cursor( + x_offset = -sbinfo.CursorPosition.X, + y_offset = to_int(param, 1) + ) + + def prev_line(self, param): + sbinfo = self.screen_buffer_info() + self.move_cursor( + x_offset = -sbinfo.CursorPosition.X, + y_offset = -to_int(param, 1) + ) + + def rgb2bgr(self, c): + return ((c&1) << 2) | (c&2) | ((c&4)>>2) + + def set_color(self, param): + cols = param.split(';') + sbinfo = self.screen_buffer_info() + attr = sbinfo.Attributes + for c in cols: + c = to_int(c, 0) + if 29 < c < 38: # fgcolor + attr = (attr & 0xfff0) | self.rgb2bgr(c - 30) + elif 39 < c < 48: # bgcolor + attr = (attr & 0xff0f) | (self.rgb2bgr(c - 40) << 4) + elif c == 0: # reset + attr = self._orig_sbinfo.Attributes + elif c == 1: # strong + attr |= 0x08 + elif c == 4: # blink not available -> bg intensity + attr |= 0x80 + elif c == 7: # negative + attr = (attr & 0xff88) | ((attr & 0x70) >> 4) | ((attr & 0x07) << 4) + + windll.kernel32.SetConsoleTextAttribute(self.hconsole, attr) + + def show_cursor(self,param): + self._csinfo.bVisible = 1 + windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(self._csinfo)) + + def hide_cursor(self,param): + self._csinfo.bVisible = 0 + windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(self._csinfo)) + + ansi_command_table = { + 'A': move_up, + 'B': move_down, + 'C': move_right, + 'D': move_left, + 'E': next_line, + 'F': prev_line, + 'G': set_column, + 'H': set_cursor, + 'f': set_cursor, + 'J': clear_screen, + 'K': clear_line, + 'h': show_cursor, + 'l': hide_cursor, + 'm': set_color, + 's': push_cursor, + 'u': pop_cursor, + } + # Match either the escape sequence or text not containing escape sequence + ansi_tokens = re.compile(r'(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') + def write(self, text): + try: + wlock.acquire() + if self._isatty: + for param, cmd, txt in self.ansi_tokens.findall(text): + if cmd: + cmd_func = self.ansi_command_table.get(cmd) + if cmd_func: + cmd_func(self, param) + else: + self.writeconsole(txt) + else: + # no support for colors in the console, just output the text: + # eclipse or msys may be able to interpret the escape sequences + self.stream.write(text) + finally: + wlock.release() + + def writeconsole(self, txt): + chars_written = c_ulong() + writeconsole = windll.kernel32.WriteConsoleA + if isinstance(txt, _type): + writeconsole = windll.kernel32.WriteConsoleW + + # MSDN says that there is a shared buffer of 64 KB for the console + # writes. Attempt to not get ERROR_NOT_ENOUGH_MEMORY, see waf issue #746 + done = 0 + todo = len(txt) + chunk = 32<<10 + while todo != 0: + doing = min(chunk, todo) + buf = txt[done:done+doing] + r = writeconsole(self.hconsole, buf, doing, byref(chars_written), None) + if r == 0: + chunk >>= 1 + continue + done += doing + todo -= doing + + + def fileno(self): + return self.stream.fileno() + + def flush(self): + pass + + def isatty(self): + return self._isatty + + if sys.stdout.isatty() or sys.stderr.isatty(): + handle = sys.stdout.isatty() and STD_OUTPUT_HANDLE or STD_ERROR_HANDLE + console = windll.kernel32.GetStdHandle(handle) + sbinfo = CONSOLE_SCREEN_BUFFER_INFO() + def get_term_cols(): + windll.kernel32.GetConsoleScreenBufferInfo(console, byref(sbinfo)) + # Issue 1401 - the progress bar cannot reach the last character + return sbinfo.Size.X - 1 + +# just try and see +try: + import struct, fcntl, termios +except ImportError: + pass +else: + if (sys.stdout.isatty() or sys.stderr.isatty()) and os.environ.get('TERM', '') not in ('dumb', 'emacs'): + FD = sys.stdout.isatty() and sys.stdout.fileno() or sys.stderr.fileno() + def fun(): + return struct.unpack("HHHH", fcntl.ioctl(FD, termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0)))[1] + try: + fun() + except Exception as e: + pass + else: + get_term_cols = fun + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/__init__.py b/ldb-2.0.8/third_party/waf/waflib/extras/__init__.py new file mode 100644 index 0000000..c8a3c34 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2010 (ita) diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/batched_cc.py b/ldb-2.0.8/third_party/waf/waflib/extras/batched_cc.py new file mode 100644 index 0000000..aad2872 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/batched_cc.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2015 (ita) + +""" +Instead of compiling object files one by one, c/c++ compilers are often able to compile at once: +cc -c ../file1.c ../file2.c ../file3.c + +Files are output on the directory where the compiler is called, and dependencies are more difficult +to track (do not run the command on all source files if only one file changes) +As such, we do as if the files were compiled one by one, but no command is actually run: +replace each cc/cpp Task by a TaskSlave. A new task called TaskMaster collects the +signatures from each slave and finds out the command-line to run. + +Just import this module to start using it: +def build(bld): + bld.load('batched_cc') + +Note that this is provided as an example, unity builds are recommended +for best performance results (fewer tasks and fewer jobs to execute). +See waflib/extras/unity.py. +""" + +from waflib import Task, Utils +from waflib.TaskGen import extension, feature, after_method +from waflib.Tools import c, cxx + +MAX_BATCH = 50 + +c_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${tsk.batch_incpaths()} ${DEFINES_ST:DEFINES} -c ${SRCLST} ${CXX_TGT_F_BATCHED} ${CPPFLAGS}' +c_fun, _ = Task.compile_fun_noshell(c_str) + +cxx_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${tsk.batch_incpaths()} ${DEFINES_ST:DEFINES} -c ${SRCLST} ${CXX_TGT_F_BATCHED} ${CPPFLAGS}' +cxx_fun, _ = Task.compile_fun_noshell(cxx_str) + +count = 70000 +class batch(Task.Task): + color = 'PINK' + + after = ['c', 'cxx'] + before = ['cprogram', 'cshlib', 'cstlib', 'cxxprogram', 'cxxshlib', 'cxxstlib'] + + def uid(self): + return Utils.h_list([Task.Task.uid(self), self.generator.idx, self.generator.path.abspath(), self.generator.target]) + + def __str__(self): + return 'Batch compilation for %d slaves' % len(self.slaves) + + def __init__(self, *k, **kw): + Task.Task.__init__(self, *k, **kw) + self.slaves = [] + self.inputs = [] + self.hasrun = 0 + + global count + count += 1 + self.idx = count + + def add_slave(self, slave): + self.slaves.append(slave) + self.set_run_after(slave) + + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + + for t in self.slaves: + #if t.executed: + if t.hasrun != Task.SKIPPED: + return Task.RUN_ME + + return Task.SKIP_ME + + def get_cwd(self): + return self.slaves[0].outputs[0].parent + + def batch_incpaths(self): + st = self.env.CPPPATH_ST + return [st % node.abspath() for node in self.generator.includes_nodes] + + def run(self): + self.outputs = [] + + srclst = [] + slaves = [] + for t in self.slaves: + if t.hasrun != Task.SKIPPED: + slaves.append(t) + srclst.append(t.inputs[0].abspath()) + + self.env.SRCLST = srclst + + if self.slaves[0].__class__.__name__ == 'c': + ret = c_fun(self) + else: + ret = cxx_fun(self) + + if ret: + return ret + + for t in slaves: + t.old_post_run() + +def hook(cls_type): + def n_hook(self, node): + + ext = '.obj' if self.env.CC_NAME == 'msvc' else '.o' + name = node.name + k = name.rfind('.') + if k >= 0: + basename = name[:k] + ext + else: + basename = name + ext + + outdir = node.parent.get_bld().make_node('%d' % self.idx) + outdir.mkdir() + out = outdir.find_or_declare(basename) + + task = self.create_task(cls_type, node, out) + + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks = [task] + + if not getattr(self, 'masters', None): + self.masters = {} + self.allmasters = [] + + def fix_path(tsk): + if self.env.CC_NAME == 'msvc': + tsk.env.append_unique('CXX_TGT_F_BATCHED', '/Fo%s\\' % outdir.abspath()) + + if not node.parent in self.masters: + m = self.masters[node.parent] = self.master = self.create_task('batch') + fix_path(m) + self.allmasters.append(m) + else: + m = self.masters[node.parent] + if len(m.slaves) > MAX_BATCH: + m = self.masters[node.parent] = self.master = self.create_task('batch') + fix_path(m) + self.allmasters.append(m) + m.add_slave(task) + return task + return n_hook + +extension('.c')(hook('c')) +extension('.cpp','.cc','.cxx','.C','.c++')(hook('cxx')) + +@feature('cprogram', 'cshlib', 'cstaticlib', 'cxxprogram', 'cxxshlib', 'cxxstlib') +@after_method('apply_link') +def link_after_masters(self): + if getattr(self, 'allmasters', None): + for m in self.allmasters: + self.link_task.set_run_after(m) + +# Modify the c and cxx task classes - in theory it would be best to +# create subclasses and to re-map the c/c++ extensions +for x in ('c', 'cxx'): + t = Task.classes[x] + def run(self): + pass + + def post_run(self): + pass + + setattr(t, 'oldrun', getattr(t, 'run', None)) + setattr(t, 'run', run) + setattr(t, 'old_post_run', t.post_run) + setattr(t, 'post_run', post_run) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/biber.py b/ldb-2.0.8/third_party/waf/waflib/extras/biber.py new file mode 100644 index 0000000..fd9db4e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/biber.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011 (ita) + +""" +Latex processing using "biber" +""" + +import os +from waflib import Task, Logs + +from waflib.Tools import tex as texmodule + +class tex(texmodule.tex): + biber_fun, _ = Task.compile_fun('${BIBER} ${BIBERFLAGS} ${SRCFILE}',shell=False) + biber_fun.__doc__ = """ + Execute the program **biber** + """ + + def bibfile(self): + return None + + def bibunits(self): + self.env.env = {} + self.env.env.update(os.environ) + self.env.env.update({'BIBINPUTS': self.texinputs(), 'BSTINPUTS': self.texinputs()}) + self.env.SRCFILE = self.aux_nodes[0].name[:-4] + + if not self.env['PROMPT_LATEX']: + self.env.append_unique('BIBERFLAGS', '--quiet') + + path = self.aux_nodes[0].abspath()[:-4] + '.bcf' + if os.path.isfile(path): + Logs.warn('calling biber') + self.check_status('error when calling biber, check %s.blg for errors' % (self.env.SRCFILE), self.biber_fun()) + else: + super(tex, self).bibfile() + super(tex, self).bibunits() + +class latex(tex): + texfun, vars = Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) +class pdflatex(tex): + texfun, vars = Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) +class xelatex(tex): + texfun, vars = Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}', shell=False) + +def configure(self): + """ + Almost the same as in tex.py, but try to detect 'biber' + """ + v = self.env + for p in ' biber tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): + try: + self.find_program(p, var=p.upper()) + except self.errors.ConfigurationError: + pass + v['DVIPSFLAGS'] = '-Ppdf' + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/bjam.py b/ldb-2.0.8/third_party/waf/waflib/extras/bjam.py new file mode 100644 index 0000000..8e04d3a --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/bjam.py @@ -0,0 +1,128 @@ +#! /usr/bin/env python +# per rosengren 2011 + +from os import sep, readlink +from waflib import Logs +from waflib.TaskGen import feature, after_method +from waflib.Task import Task, always_run + +def options(opt): + grp = opt.add_option_group('Bjam Options') + grp.add_option('--bjam_src', default=None, help='You can find it in /tools/jam/src') + grp.add_option('--bjam_uname', default='linuxx86_64', help='bjam is built in /bin./bjam') + grp.add_option('--bjam_config', default=None) + grp.add_option('--bjam_toolset', default=None) + +def configure(cnf): + if not cnf.env.BJAM_SRC: + cnf.env.BJAM_SRC = cnf.options.bjam_src + if not cnf.env.BJAM_UNAME: + cnf.env.BJAM_UNAME = cnf.options.bjam_uname + try: + cnf.find_program('bjam', path_list=[ + cnf.env.BJAM_SRC + sep + 'bin.' + cnf.env.BJAM_UNAME + ]) + except Exception: + cnf.env.BJAM = None + if not cnf.env.BJAM_CONFIG: + cnf.env.BJAM_CONFIG = cnf.options.bjam_config + if not cnf.env.BJAM_TOOLSET: + cnf.env.BJAM_TOOLSET = cnf.options.bjam_toolset + +@feature('bjam') +@after_method('process_rule') +def process_bjam(self): + if not self.bld.env.BJAM: + self.create_task('bjam_creator') + self.create_task('bjam_build') + self.create_task('bjam_installer') + if getattr(self, 'always', False): + always_run(bjam_creator) + always_run(bjam_build) + always_run(bjam_installer) + +class bjam_creator(Task): + ext_out = 'bjam_exe' + vars=['BJAM_SRC', 'BJAM_UNAME'] + def run(self): + env = self.env + gen = self.generator + bjam = gen.bld.root.find_dir(env.BJAM_SRC) + if not bjam: + Logs.error('Can not find bjam source') + return -1 + bjam_exe_relpath = 'bin.' + env.BJAM_UNAME + '/bjam' + bjam_exe = bjam.find_resource(bjam_exe_relpath) + if bjam_exe: + env.BJAM = bjam_exe.srcpath() + return 0 + bjam_cmd = ['./build.sh'] + Logs.debug('runner: ' + bjam.srcpath() + '> ' + str(bjam_cmd)) + result = self.exec_command(bjam_cmd, cwd=bjam.srcpath()) + if not result == 0: + Logs.error('bjam failed') + return -1 + bjam_exe = bjam.find_resource(bjam_exe_relpath) + if bjam_exe: + env.BJAM = bjam_exe.srcpath() + return 0 + Logs.error('bjam failed') + return -1 + +class bjam_build(Task): + ext_in = 'bjam_exe' + ext_out = 'install' + vars = ['BJAM_TOOLSET'] + def run(self): + env = self.env + gen = self.generator + path = gen.path + bld = gen.bld + if hasattr(gen, 'root'): + build_root = path.find_node(gen.root) + else: + build_root = path + jam = bld.srcnode.find_resource(env.BJAM_CONFIG) + if jam: + Logs.debug('bjam: Using jam configuration from ' + jam.srcpath()) + jam_rel = jam.relpath_gen(build_root) + else: + Logs.warn('No build configuration in build_config/user-config.jam. Using default') + jam_rel = None + bjam_exe = bld.srcnode.find_node(env.BJAM) + if not bjam_exe: + Logs.error('env.BJAM is not set') + return -1 + bjam_exe_rel = bjam_exe.relpath_gen(build_root) + cmd = ([bjam_exe_rel] + + (['--user-config=' + jam_rel] if jam_rel else []) + + ['--stagedir=' + path.get_bld().path_from(build_root)] + + ['--debug-configuration'] + + ['--with-' + lib for lib in self.generator.target] + + (['toolset=' + env.BJAM_TOOLSET] if env.BJAM_TOOLSET else []) + + ['link=' + 'shared'] + + ['variant=' + 'release'] + ) + Logs.debug('runner: ' + build_root.srcpath() + '> ' + str(cmd)) + ret = self.exec_command(cmd, cwd=build_root.srcpath()) + if ret != 0: + return ret + self.set_outputs(path.get_bld().ant_glob('lib/*') + path.get_bld().ant_glob('bin/*')) + return 0 + +class bjam_installer(Task): + ext_in = 'install' + def run(self): + gen = self.generator + path = gen.path + for idir, pat in (('${LIBDIR}', 'lib/*'), ('${BINDIR}', 'bin/*')): + files = [] + for n in path.get_bld().ant_glob(pat): + try: + t = readlink(n.srcpath()) + gen.bld.symlink_as(sep.join([idir, n.name]), t, postpone=False) + except OSError: + files.append(n) + gen.bld.install_files(idir, files, postpone=False) + return 0 + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/blender.py b/ldb-2.0.8/third_party/waf/waflib/extras/blender.py new file mode 100644 index 0000000..e5efc28 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/blender.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Michal Proszek, 2014 (poxip) + +""" +Detect the version of Blender, path +and install the extension: + + def options(opt): + opt.load('blender') + def configure(cnf): + cnf.load('blender') + def build(bld): + bld(name='io_mesh_raw', + feature='blender', + files=['file1.py', 'file2.py'] + ) +If name variable is empty, files are installed in scripts/addons, otherwise scripts/addons/name +Use ./waf configure --system to set the installation directory to system path +""" +import os +import re +from getpass import getuser + +from waflib import Utils +from waflib.TaskGen import feature +from waflib.Configure import conf + +def options(opt): + opt.add_option( + '-s', '--system', + dest='directory_system', + default=False, + action='store_true', + help='determines installation directory (default: user)' + ) + +@conf +def find_blender(ctx): + '''Return version number of blender, if not exist return None''' + blender = ctx.find_program('blender') + output = ctx.cmd_and_log(blender + ['--version']) + m = re.search(r'Blender\s*((\d+(\.|))*)', output) + if not m: + ctx.fatal('Could not retrieve blender version') + + try: + blender_version = m.group(1) + except IndexError: + ctx.fatal('Could not retrieve blender version') + + ctx.env['BLENDER_VERSION'] = blender_version + return blender + +@conf +def configure_paths(ctx): + """Setup blender paths""" + # Get the username + user = getuser() + _platform = Utils.unversioned_sys_platform() + config_path = {'user': '', 'system': ''} + if _platform.startswith('linux'): + config_path['user'] = '/home/%s/.config/blender/' % user + config_path['system'] = '/usr/share/blender/' + elif _platform == 'darwin': + # MAC OS X + config_path['user'] = \ + '/Users/%s/Library/Application Support/Blender/' % user + config_path['system'] = '/Library/Application Support/Blender/' + elif Utils.is_win32: + # Windows + appdata_path = ctx.getenv('APPDATA').replace('\\', '/') + homedrive = ctx.getenv('HOMEDRIVE').replace('\\', '/') + + config_path['user'] = '%s/Blender Foundation/Blender/' % appdata_path + config_path['system'] = \ + '%sAll Users/AppData/Roaming/Blender Foundation/Blender/' % homedrive + else: + ctx.fatal( + 'Unsupported platform. ' + 'Available platforms: Linux, OSX, MS-Windows.' + ) + + blender_version = ctx.env['BLENDER_VERSION'] + + config_path['user'] += blender_version + '/' + config_path['system'] += blender_version + '/' + + ctx.env['BLENDER_CONFIG_DIR'] = os.path.abspath(config_path['user']) + if ctx.options.directory_system: + ctx.env['BLENDER_CONFIG_DIR'] = config_path['system'] + + ctx.env['BLENDER_ADDONS_DIR'] = os.path.join( + ctx.env['BLENDER_CONFIG_DIR'], 'scripts/addons' + ) + Utils.check_dir(ctx.env['BLENDER_ADDONS_DIR']) + +def configure(ctx): + ctx.find_blender() + ctx.configure_paths() + +@feature('blender_list') +def blender(self): + # Two ways to install a blender extension: as a module or just .py files + dest_dir = os.path.join(self.env.BLENDER_ADDONS_DIR, self.get_name()) + Utils.check_dir(dest_dir) + self.add_install_files(install_to=dest_dir, install_from=getattr(self, 'files', '.')) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/boo.py b/ldb-2.0.8/third_party/waf/waflib/extras/boo.py new file mode 100644 index 0000000..06623d4 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/boo.py @@ -0,0 +1,81 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Yannick LM 2011 + +""" +Support for the boo programming language, for example:: + + bld(features = "boo", # necessary feature + source = "src.boo", # list of boo files + gen = "world.dll", # target + type = "library", # library/exe ("-target:xyz" flag) + name = "world" # necessary if the target is referenced by 'use' + ) +""" + +from waflib import Task +from waflib.Configure import conf +from waflib.TaskGen import feature, after_method, before_method, extension + +@extension('.boo') +def boo_hook(self, node): + # Nothing here yet ... + # TODO filter the non-boo source files in 'apply_booc' and remove this method + pass + +@feature('boo') +@before_method('process_source') +def apply_booc(self): + """Create a booc task """ + src_nodes = self.to_nodes(self.source) + out_node = self.path.find_or_declare(self.gen) + + self.boo_task = self.create_task('booc', src_nodes, [out_node]) + + # Set variables used by the 'booc' task + self.boo_task.env.OUT = '-o:%s' % out_node.abspath() + + # type is "exe" by default + type = getattr(self, "type", "exe") + self.boo_task.env.BOO_TARGET_TYPE = "-target:%s" % type + +@feature('boo') +@after_method('apply_boo') +def use_boo(self): + """" + boo applications honor the **use** keyword:: + """ + dep_names = self.to_list(getattr(self, 'use', [])) + for dep_name in dep_names: + dep_task_gen = self.bld.get_tgen_by_name(dep_name) + if not dep_task_gen: + continue + dep_task_gen.post() + dep_task = getattr(dep_task_gen, 'boo_task', None) + if not dep_task: + # Try a cs task: + dep_task = getattr(dep_task_gen, 'cs_task', None) + if not dep_task: + # Try a link task: + dep_task = getattr(dep_task, 'link_task', None) + if not dep_task: + # Abort ... + continue + self.boo_task.set_run_after(dep_task) # order + self.boo_task.dep_nodes.extend(dep_task.outputs) # dependency + self.boo_task.env.append_value('BOO_FLAGS', '-reference:%s' % dep_task.outputs[0].abspath()) + +class booc(Task.Task): + """Compiles .boo files """ + color = 'YELLOW' + run_str = '${BOOC} ${BOO_FLAGS} ${BOO_TARGET_TYPE} ${OUT} ${SRC}' + +@conf +def check_booc(self): + self.find_program('booc', 'BOOC') + self.env.BOO_FLAGS = ['-nologo'] + +def configure(self): + """Check that booc is available """ + self.check_booc() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/boost.py b/ldb-2.0.8/third_party/waf/waflib/extras/boost.py new file mode 100644 index 0000000..c2aaaa9 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/boost.py @@ -0,0 +1,525 @@ +#!/usr/bin/env python +# encoding: utf-8 +# +# partially based on boost.py written by Gernot Vormayr +# written by Ruediger Sonderfeld , 2008 +# modified by Bjoern Michaelsen, 2008 +# modified by Luca Fossati, 2008 +# rewritten for waf 1.5.1, Thomas Nagy, 2008 +# rewritten for waf 1.6.2, Sylvain Rouquette, 2011 + +''' + +This is an extra tool, not bundled with the default waf binary. +To add the boost tool to the waf file: +$ ./waf-light --tools=compat15,boost + or, if you have waf >= 1.6.2 +$ ./waf update --files=boost + +When using this tool, the wscript will look like: + + def options(opt): + opt.load('compiler_cxx boost') + + def configure(conf): + conf.load('compiler_cxx boost') + conf.check_boost(lib='system filesystem') + + def build(bld): + bld(source='main.cpp', target='app', use='BOOST') + +Options are generated, in order to specify the location of boost includes/libraries. +The `check_boost` configuration function allows to specify the used boost libraries. +It can also provide default arguments to the --boost-mt command-line arguments. +Everything will be packaged together in a BOOST component that you can use. + +When using MSVC, a lot of compilation flags need to match your BOOST build configuration: + - you may have to add /EHsc to your CXXFLAGS or define boost::throw_exception if BOOST_NO_EXCEPTIONS is defined. + Errors: C4530 + - boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC + So before calling `conf.check_boost` you might want to disabling by adding + conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB'] + Errors: + - boost might also be compiled with /MT, which links the runtime statically. + If you have problems with redefined symbols, + self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] + self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc'] +Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases. + +''' + +import sys +import re +from waflib import Utils, Logs, Errors +from waflib.Configure import conf +from waflib.TaskGen import feature, after_method + +BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] +BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include'] +BOOST_VERSION_FILE = 'boost/version.hpp' +BOOST_VERSION_CODE = ''' +#include +#include +int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; } +''' + +BOOST_ERROR_CODE = ''' +#include +int main() { boost::system::error_code c; } +''' + +PTHREAD_CODE = ''' +#include +static void* f(void*) { return 0; } +int main() { + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_create(&th, &attr, &f, 0); + pthread_join(th, 0); + pthread_cleanup_push(0, 0); + pthread_cleanup_pop(0); + pthread_attr_destroy(&attr); +} +''' + +BOOST_THREAD_CODE = ''' +#include +int main() { boost::thread t; } +''' + +BOOST_LOG_CODE = ''' +#include +#include +#include +int main() { + using namespace boost::log; + add_common_attributes(); + add_console_log(std::clog, keywords::format = "%Message%"); + BOOST_LOG_TRIVIAL(debug) << "log is working" << std::endl; +} +''' + +# toolsets from {boost_dir}/tools/build/v2/tools/common.jam +PLATFORM = Utils.unversioned_sys_platform() +detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il' +detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang' +detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc' +BOOST_TOOLSETS = { + 'borland': 'bcb', + 'clang': detect_clang, + 'como': 'como', + 'cw': 'cw', + 'darwin': 'xgcc', + 'edg': 'edg', + 'g++': detect_mingw, + 'gcc': detect_mingw, + 'icpc': detect_intel, + 'intel': detect_intel, + 'kcc': 'kcc', + 'kylix': 'bck', + 'mipspro': 'mp', + 'mingw': 'mgw', + 'msvc': 'vc', + 'qcc': 'qcc', + 'sun': 'sw', + 'sunc++': 'sw', + 'tru64cxx': 'tru', + 'vacpp': 'xlc' +} + + +def options(opt): + opt = opt.add_option_group('Boost Options') + opt.add_option('--boost-includes', type='string', + default='', dest='boost_includes', + help='''path to the directory where the boost includes are, + e.g., /path/to/boost_1_55_0/stage/include''') + opt.add_option('--boost-libs', type='string', + default='', dest='boost_libs', + help='''path to the directory where the boost libs are, + e.g., path/to/boost_1_55_0/stage/lib''') + opt.add_option('--boost-mt', action='store_true', + default=False, dest='boost_mt', + help='select multi-threaded libraries') + opt.add_option('--boost-abi', type='string', default='', dest='boost_abi', + help='''select libraries with tags (gd for debug, static is automatically added), + see doc Boost, Getting Started, chapter 6.1''') + opt.add_option('--boost-linkage_autodetect', action="store_true", dest='boost_linkage_autodetect', + help="auto-detect boost linkage options (don't get used to it / might break other stuff)") + opt.add_option('--boost-toolset', type='string', + default='', dest='boost_toolset', + help='force a toolset e.g. msvc, vc90, \ + gcc, mingw, mgw45 (default: auto)') + py_version = '%d%d' % (sys.version_info[0], sys.version_info[1]) + opt.add_option('--boost-python', type='string', + default=py_version, dest='boost_python', + help='select the lib python with this version \ + (default: %s)' % py_version) + + +@conf +def __boost_get_version_file(self, d): + if not d: + return None + dnode = self.root.find_dir(d) + if dnode: + return dnode.find_node(BOOST_VERSION_FILE) + return None + +@conf +def boost_get_version(self, d): + """silently retrieve the boost version number""" + node = self.__boost_get_version_file(d) + if node: + try: + txt = node.read() + except EnvironmentError: + Logs.error("Could not read the file %r", node.abspath()) + else: + re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M) + m1 = re_but1.search(txt) + re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M) + m2 = re_but2.search(txt) + if m1 and m2: + return (m1.group(1), m2.group(1)) + return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(":") + +@conf +def boost_get_includes(self, *k, **kw): + includes = k and k[0] or kw.get('includes') + if includes and self.__boost_get_version_file(includes): + return includes + for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES: + if self.__boost_get_version_file(d): + return d + if includes: + self.end_msg('headers not found in %s' % includes) + self.fatal('The configuration failed') + else: + self.end_msg('headers not found, please provide a --boost-includes argument (see help)') + self.fatal('The configuration failed') + + +@conf +def boost_get_toolset(self, cc): + toolset = cc + if not cc: + build_platform = Utils.unversioned_sys_platform() + if build_platform in BOOST_TOOLSETS: + cc = build_platform + else: + cc = self.env.CXX_NAME + if cc in BOOST_TOOLSETS: + toolset = BOOST_TOOLSETS[cc] + return isinstance(toolset, str) and toolset or toolset(self.env) + + +@conf +def __boost_get_libs_path(self, *k, **kw): + ''' return the lib path and all the files in it ''' + if 'files' in kw: + return self.root.find_dir('.'), Utils.to_list(kw['files']) + libs = k and k[0] or kw.get('libs') + if libs: + path = self.root.find_dir(libs) + files = path.ant_glob('*boost_*') + if not libs or not files: + for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS: + if not d: + continue + path = self.root.find_dir(d) + if path: + files = path.ant_glob('*boost_*') + if files: + break + path = self.root.find_dir(d + '64') + if path: + files = path.ant_glob('*boost_*') + if files: + break + if not path: + if libs: + self.end_msg('libs not found in %s' % libs) + self.fatal('The configuration failed') + else: + self.end_msg('libs not found, please provide a --boost-libs argument (see help)') + self.fatal('The configuration failed') + + self.to_log('Found the boost path in %r with the libraries:' % path) + for x in files: + self.to_log(' %r' % x) + return path, files + +@conf +def boost_get_libs(self, *k, **kw): + ''' + return the lib path and the required libs + according to the parameters + ''' + path, files = self.__boost_get_libs_path(**kw) + files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True) + toolset = self.boost_get_toolset(kw.get('toolset', '')) + toolset_pat = '(-%s[0-9]{0,3})' % toolset + version = '-%s' % self.env.BOOST_VERSION + + def find_lib(re_lib, files): + for file in files: + if re_lib.search(file.name): + self.to_log('Found boost lib %s' % file) + return file + return None + + def format_lib_name(name): + if name.startswith('lib') and self.env.CC_NAME != 'msvc': + name = name[3:] + return name[:name.rfind('.')] + + def match_libs(lib_names, is_static): + libs = [] + lib_names = Utils.to_list(lib_names) + if not lib_names: + return libs + t = [] + if kw.get('mt', False): + t.append('-mt') + if kw.get('abi'): + t.append('%s%s' % (is_static and '-s' or '-', kw['abi'])) + elif is_static: + t.append('-s') + tags_pat = t and ''.join(t) or '' + ext = is_static and self.env.cxxstlib_PATTERN or self.env.cxxshlib_PATTERN + ext = ext.partition('%s')[2] # remove '%s' or 'lib%s' from PATTERN + + for lib in lib_names: + if lib == 'python': + # for instance, with python='27', + # accepts '-py27', '-py2', '27', '-2.7' and '2' + # but will reject '-py3', '-py26', '26' and '3' + tags = '({0})?((-py{2})|(-py{1}(?=[^0-9]))|({2})|(-{1}.{3})|({1}(?=[^0-9]))|(?=[^0-9])(?!-py))'.format(tags_pat, kw['python'][0], kw['python'], kw['python'][1]) + else: + tags = tags_pat + # Trying libraries, from most strict match to least one + for pattern in ['boost_%s%s%s%s%s$' % (lib, toolset_pat, tags, version, ext), + 'boost_%s%s%s%s$' % (lib, tags, version, ext), + # Give up trying to find the right version + 'boost_%s%s%s%s$' % (lib, toolset_pat, tags, ext), + 'boost_%s%s%s$' % (lib, tags, ext), + 'boost_%s%s$' % (lib, ext), + 'boost_%s' % lib]: + self.to_log('Trying pattern %s' % pattern) + file = find_lib(re.compile(pattern), files) + if file: + libs.append(format_lib_name(file.name)) + break + else: + self.end_msg('lib %s not found in %s' % (lib, path.abspath())) + self.fatal('The configuration failed') + return libs + + return path.abspath(), match_libs(kw.get('lib'), False), match_libs(kw.get('stlib'), True) + +@conf +def _check_pthread_flag(self, *k, **kw): + ''' + Computes which flags should be added to CXXFLAGS and LINKFLAGS to compile in multi-threading mode + + Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, + boost/thread.hpp will trigger a #error if -pthread isn't used: + boost/config/requires_threads.hpp:47:5: #error "Compiler threading support + is not turned on. Please set the correct command line options for + threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" + + Based on _BOOST_PTHREAD_FLAG(): https://github.com/tsuna/boost.m4/blob/master/build-aux/boost.m4 + ''' + + var = kw.get('uselib_store', 'BOOST') + + self.start_msg('Checking the flags needed to use pthreads') + + # The ordering *is* (sometimes) important. Some notes on the + # individual items follow: + # (none): in case threads are in libc; should be tried before -Kthread and + # other compiler flags to prevent continual compiler warnings + # -lpthreads: AIX (must check this before -lpthread) + # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) + # -pthreads: Solaris/GCC + # -mthreads: MinGW32/GCC, Lynx/GCC + # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it + # doesn't hurt to check since this sometimes defines pthreads too; + # also defines -D_REENTRANT) + # ... -mt is also the pthreads flag for HP/aCC + # -lpthread: GNU Linux, etc. + # --thread-safe: KAI C++ + if Utils.unversioned_sys_platform() == "sunos": + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + boost_pthread_flags = ["-pthreads", "-lpthread", "-mt", "-pthread"] + else: + boost_pthread_flags = ["", "-lpthreads", "-Kthread", "-kthread", "-llthread", "-pthread", + "-pthreads", "-mthreads", "-lpthread", "--thread-safe", "-mt"] + + for boost_pthread_flag in boost_pthread_flags: + try: + self.env.stash() + self.env.append_value('CXXFLAGS_%s' % var, boost_pthread_flag) + self.env.append_value('LINKFLAGS_%s' % var, boost_pthread_flag) + self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False) + + self.end_msg(boost_pthread_flag) + return + except self.errors.ConfigurationError: + self.env.revert() + self.end_msg('None') + +@conf +def check_boost(self, *k, **kw): + """ + Initialize boost libraries to be used. + + Keywords: you can pass the same parameters as with the command line (without "--boost-"). + Note that the command line has the priority, and should preferably be used. + """ + if not self.env['CXX']: + self.fatal('load a c++ compiler first, conf.load("compiler_cxx")') + + params = { + 'lib': k and k[0] or kw.get('lib'), + 'stlib': kw.get('stlib') + } + for key, value in self.options.__dict__.items(): + if not key.startswith('boost_'): + continue + key = key[len('boost_'):] + params[key] = value and value or kw.get(key, '') + + var = kw.get('uselib_store', 'BOOST') + + self.find_program('dpkg-architecture', var='DPKG_ARCHITECTURE', mandatory=False) + if self.env.DPKG_ARCHITECTURE: + deb_host_multiarch = self.cmd_and_log([self.env.DPKG_ARCHITECTURE[0], '-qDEB_HOST_MULTIARCH']) + BOOST_LIBS.insert(0, '/usr/lib/%s' % deb_host_multiarch.strip()) + + self.start_msg('Checking boost includes') + self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params) + versions = self.boost_get_version(inc) + self.env.BOOST_VERSION = versions[0] + self.env.BOOST_VERSION_NUMBER = int(versions[1]) + self.end_msg("%d.%d.%d" % (int(versions[1]) / 100000, + int(versions[1]) / 100 % 1000, + int(versions[1]) % 100)) + if Logs.verbose: + Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var]) + + if not params['lib'] and not params['stlib']: + return + if 'static' in kw or 'static' in params: + Logs.warn('boost: static parameter is deprecated, use stlib instead.') + self.start_msg('Checking boost libs') + path, libs, stlibs = self.boost_get_libs(**params) + self.env['LIBPATH_%s' % var] = [path] + self.env['STLIBPATH_%s' % var] = [path] + self.env['LIB_%s' % var] = libs + self.env['STLIB_%s' % var] = stlibs + self.end_msg('ok') + if Logs.verbose: + Logs.pprint('CYAN', ' path : %s' % path) + Logs.pprint('CYAN', ' shared libs : %s' % libs) + Logs.pprint('CYAN', ' static libs : %s' % stlibs) + + def has_shlib(lib): + return params['lib'] and lib in params['lib'] + def has_stlib(lib): + return params['stlib'] and lib in params['stlib'] + def has_lib(lib): + return has_shlib(lib) or has_stlib(lib) + if has_lib('thread'): + # not inside try_link to make check visible in the output + self._check_pthread_flag(k, kw) + + def try_link(): + if has_lib('system'): + self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False) + if has_lib('thread'): + self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False) + if has_lib('log'): + if not has_lib('thread'): + self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS'] + if has_shlib('log'): + self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK'] + self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False) + + if params.get('linkage_autodetect', False): + self.start_msg("Attempting to detect boost linkage flags") + toolset = self.boost_get_toolset(kw.get('toolset', '')) + if toolset in ('vc',): + # disable auto-linking feature, causing error LNK1181 + # because the code wants to be linked against + self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] + + # if no dlls are present, we guess the .lib files are not stubs + has_dlls = False + for x in Utils.listdir(path): + if x.endswith(self.env.cxxshlib_PATTERN % ''): + has_dlls = True + break + if not has_dlls: + self.env['STLIBPATH_%s' % var] = [path] + self.env['STLIB_%s' % var] = libs + del self.env['LIB_%s' % var] + del self.env['LIBPATH_%s' % var] + + # we attempt to play with some known-to-work CXXFLAGS combinations + for cxxflags in (['/MD', '/EHsc'], []): + self.env.stash() + self.env["CXXFLAGS_%s" % var] += cxxflags + try: + try_link() + except Errors.ConfigurationError as e: + self.env.revert() + exc = e + else: + self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var])) + exc = None + self.env.commit() + break + + if exc is not None: + self.end_msg("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=exc) + self.fatal('The configuration failed') + else: + self.end_msg("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain") + self.fatal('The configuration failed') + else: + self.start_msg('Checking for boost linkage') + try: + try_link() + except Errors.ConfigurationError as e: + self.end_msg("Could not link against boost libraries using supplied options") + self.fatal('The configuration failed') + self.end_msg('ok') + + +@feature('cxx') +@after_method('apply_link') +def install_boost(self): + if install_boost.done or not Utils.is_win32 or not self.bld.cmd.startswith('install'): + return + install_boost.done = True + inst_to = getattr(self, 'install_path', '${BINDIR}') + for lib in self.env.LIB_BOOST: + try: + file = self.bld.find_file(self.env.cxxshlib_PATTERN % lib, self.env.LIBPATH_BOOST) + self.add_install_files(install_to=inst_to, install_from=self.bld.root.find_node(file)) + except: + continue +install_boost.done = False + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/build_file_tracker.py b/ldb-2.0.8/third_party/waf/waflib/extras/build_file_tracker.py new file mode 100644 index 0000000..c4f26fd --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/build_file_tracker.py @@ -0,0 +1,28 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2015 + +""" +Force files to depend on the timestamps of those located in the build directory. You may +want to use this to force partial rebuilds, see playground/track_output_files/ for a working example. + +Note that there is a variety of ways to implement this, one may want use timestamps on source files too for example, +or one may want to hash the files in the source directory only under certain conditions (md5_tstamp tool) +or to hash the file in the build directory with its timestamp +""" + +import os +from waflib import Node, Utils + +def get_bld_sig(self): + if not self.is_bld() or self.ctx.bldnode is self.ctx.srcnode: + return Utils.h_file(self.abspath()) + + try: + # add the creation time to the signature + return self.sig + str(os.stat(self.abspath()).st_mtime) + except AttributeError: + return None + +Node.Node.get_bld_sig = get_bld_sig + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/build_logs.py b/ldb-2.0.8/third_party/waf/waflib/extras/build_logs.py new file mode 100644 index 0000000..cdf8ed0 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/build_logs.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2013 (ita) + +""" +A system for recording all outputs to a log file. Just add the following to your wscript file:: + + def init(ctx): + ctx.load('build_logs') +""" + +import atexit, sys, time, os, shutil, threading +from waflib import ansiterm, Logs, Context + +# adding the logs under the build/ directory will clash with the clean/ command +try: + up = os.path.dirname(Context.g_module.__file__) +except AttributeError: + up = '.' +LOGFILE = os.path.join(up, 'logs', time.strftime('%Y_%m_%d_%H_%M.log')) + +wlock = threading.Lock() +class log_to_file(object): + def __init__(self, stream, fileobj, filename): + self.stream = stream + self.encoding = self.stream.encoding + self.fileobj = fileobj + self.filename = filename + self.is_valid = True + def replace_colors(self, data): + for x in Logs.colors_lst.values(): + if isinstance(x, str): + data = data.replace(x, '') + return data + def write(self, data): + try: + wlock.acquire() + self.stream.write(data) + self.stream.flush() + if self.is_valid: + self.fileobj.write(self.replace_colors(data)) + finally: + wlock.release() + def fileno(self): + return self.stream.fileno() + def flush(self): + self.stream.flush() + if self.is_valid: + self.fileobj.flush() + def isatty(self): + return self.stream.isatty() + +def init(ctx): + global LOGFILE + filename = os.path.abspath(LOGFILE) + try: + os.makedirs(os.path.dirname(os.path.abspath(filename))) + except OSError: + pass + + if hasattr(os, 'O_NOINHERIT'): + fd = os.open(LOGFILE, os.O_CREAT | os.O_TRUNC | os.O_WRONLY | os.O_NOINHERIT) + fileobj = os.fdopen(fd, 'w') + else: + fileobj = open(LOGFILE, 'w') + old_stderr = sys.stderr + + # sys.stdout has already been replaced, so __stdout__ will be faster + #sys.stdout = log_to_file(sys.stdout, fileobj, filename) + #sys.stderr = log_to_file(sys.stderr, fileobj, filename) + def wrap(stream): + if stream.isatty(): + return ansiterm.AnsiTerm(stream) + return stream + sys.stdout = log_to_file(wrap(sys.__stdout__), fileobj, filename) + sys.stderr = log_to_file(wrap(sys.__stderr__), fileobj, filename) + + # now mess with the logging module... + for x in Logs.log.handlers: + try: + stream = x.stream + except AttributeError: + pass + else: + if id(stream) == id(old_stderr): + x.stream = sys.stderr + +def exit_cleanup(): + try: + fileobj = sys.stdout.fileobj + except AttributeError: + pass + else: + sys.stdout.is_valid = False + sys.stderr.is_valid = False + fileobj.close() + filename = sys.stdout.filename + + Logs.info('Output logged to %r', filename) + + # then copy the log file to "latest.log" if possible + up = os.path.dirname(os.path.abspath(filename)) + try: + shutil.copy(filename, os.path.join(up, 'latest.log')) + except OSError: + # this may fail on windows due to processes spawned + pass + +atexit.register(exit_cleanup) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/buildcopy.py b/ldb-2.0.8/third_party/waf/waflib/extras/buildcopy.py new file mode 100644 index 0000000..eaff7e6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/buildcopy.py @@ -0,0 +1,85 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Calle Rosenquist, 2017 (xbreak) +""" +Create task that copies source files to the associated build node. +This is useful to e.g. construct a complete Python package so it can be unit tested +without installation. + +Source files to be copied can be specified either in `buildcopy_source` attribute, or +`source` attribute. If both are specified `buildcopy_source` has priority. + +Examples:: + + def build(bld): + bld(name = 'bar', + features = 'py buildcopy', + source = bld.path.ant_glob('src/bar/*.py')) + + bld(name = 'py baz', + features = 'buildcopy', + buildcopy_source = bld.path.ant_glob('src/bar/*.py') + ['src/bar/resource.txt']) + +""" +import os, shutil +from waflib import Errors, Task, TaskGen, Utils, Node, Logs + +@TaskGen.before_method('process_source') +@TaskGen.feature('buildcopy') +def make_buildcopy(self): + """ + Creates the buildcopy task. + """ + def to_src_nodes(lst): + """Find file nodes only in src, TaskGen.to_nodes will not work for this since it gives + preference to nodes in build. + """ + if isinstance(lst, Node.Node): + if not lst.is_src(): + raise Errors.WafError('buildcopy: node %s is not in src'%lst) + if not os.path.isfile(lst.abspath()): + raise Errors.WafError('buildcopy: Cannot copy directory %s (unsupported action)'%lst) + return lst + + if isinstance(lst, str): + lst = [x for x in Utils.split_path(lst) if x and x != '.'] + + node = self.bld.path.get_src().search_node(lst) + if node: + if not os.path.isfile(node.abspath()): + raise Errors.WafError('buildcopy: Cannot copy directory %s (unsupported action)'%node) + return node + + node = self.bld.path.get_src().find_node(lst) + if node: + if not os.path.isfile(node.abspath()): + raise Errors.WafError('buildcopy: Cannot copy directory %s (unsupported action)'%node) + return node + raise Errors.WafError('buildcopy: File not found in src: %s'%os.path.join(*lst)) + + nodes = [ to_src_nodes(n) for n in getattr(self, 'buildcopy_source', getattr(self, 'source', [])) ] + if not nodes: + Logs.warn('buildcopy: No source files provided to buildcopy in %s (set `buildcopy_source` or `source`)', + self) + return + node_pairs = [(n, n.get_bld()) for n in nodes] + self.create_task('buildcopy', [n[0] for n in node_pairs], [n[1] for n in node_pairs], node_pairs=node_pairs) + +class buildcopy(Task.Task): + """ + Copy for each pair `n` in `node_pairs`: n[0] -> n[1]. + + Attribute `node_pairs` should contain a list of tuples describing source and target: + + node_pairs = [(in, out), ...] + + """ + color = 'PINK' + + def keyword(self): + return 'Copying' + + def run(self): + for f,t in self.node_pairs: + t.parent.mkdir() + shutil.copy2(f.abspath(), t.abspath()) diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/c_bgxlc.py b/ldb-2.0.8/third_party/waf/waflib/extras/c_bgxlc.py new file mode 100644 index 0000000..6e3eaf7 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/c_bgxlc.py @@ -0,0 +1,32 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +""" +IBM XL Compiler for Blue Gene +""" + +from waflib.Tools import ccroot,ar +from waflib.Configure import conf + +from waflib.Tools import xlc # method xlc_common_flags +from waflib.Tools.compiler_c import c_compiler +c_compiler['linux'].append('c_bgxlc') + +@conf +def find_bgxlc(conf): + cc = conf.find_program(['bgxlc_r','bgxlc'], var='CC') + conf.get_xlc_version(cc) + conf.env.CC = cc + conf.env.CC_NAME = 'bgxlc' + +def configure(conf): + conf.find_bgxlc() + conf.find_ar() + conf.xlc_common_flags() + conf.env.LINKFLAGS_cshlib = ['-G','-Wl,-bexpfull'] + conf.env.LINKFLAGS_cprogram = [] + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/c_dumbpreproc.py b/ldb-2.0.8/third_party/waf/waflib/extras/c_dumbpreproc.py new file mode 100644 index 0000000..ce9e1a4 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/c_dumbpreproc.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2010 (ita) + +""" +Dumb C/C++ preprocessor for finding dependencies + +It will look at all include files it can find after removing the comments, so the following +will always add the dependency on both "a.h" and "b.h":: + + #include "a.h" + #ifdef B + #include "b.h" + #endif + int main() { + return 0; + } + +To use:: + + def configure(conf): + conf.load('compiler_c') + conf.load('c_dumbpreproc') +""" + +import re +from waflib.Tools import c_preproc + +re_inc = re.compile( + '^[ \t]*(#|%:)[ \t]*(include)[ \t]*[<"](.*)[>"]\r*$', + re.IGNORECASE | re.MULTILINE) + +def lines_includes(node): + code = node.read() + if c_preproc.use_trigraphs: + for (a, b) in c_preproc.trig_def: + code = code.split(a).join(b) + code = c_preproc.re_nl.sub('', code) + code = c_preproc.re_cpp.sub(c_preproc.repl, code) + return [(m.group(2), m.group(3)) for m in re.finditer(re_inc, code)] + +parser = c_preproc.c_parser +class dumb_parser(parser): + def addlines(self, node): + if node in self.nodes[:-1]: + return + self.currentnode_stack.append(node.parent) + + # Avoid reading the same files again + try: + lines = self.parse_cache[node] + except KeyError: + lines = self.parse_cache[node] = lines_includes(node) + + self.lines = lines + [(c_preproc.POPFILE, '')] + self.lines + + def start(self, node, env): + try: + self.parse_cache = node.ctx.parse_cache + except AttributeError: + self.parse_cache = node.ctx.parse_cache = {} + + self.addlines(node) + while self.lines: + (x, y) = self.lines.pop(0) + if x == c_preproc.POPFILE: + self.currentnode_stack.pop() + continue + self.tryfind(y) + +c_preproc.c_parser = dumb_parser + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/c_emscripten.py b/ldb-2.0.8/third_party/waf/waflib/extras/c_emscripten.py new file mode 100644 index 0000000..e1ac494 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/c_emscripten.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 vi:ts=4:noexpandtab + +import subprocess, shlex, sys + +from waflib.Tools import ccroot, gcc, gxx +from waflib.Configure import conf +from waflib.TaskGen import after_method, feature + +from waflib.Tools.compiler_c import c_compiler +from waflib.Tools.compiler_cxx import cxx_compiler + +for supported_os in ('linux', 'darwin', 'gnu', 'aix'): + c_compiler[supported_os].append('c_emscripten') + cxx_compiler[supported_os].append('c_emscripten') + + +@conf +def get_emscripten_version(conf, cc): + """ + Emscripten doesn't support processing '-' like clang/gcc + """ + + dummy = conf.cachedir.parent.make_node("waf-emscripten.c") + dummy.write("") + cmd = cc + ['-dM', '-E', '-x', 'c', dummy.abspath()] + env = conf.env.env or None + try: + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) + out = p.communicate()[0] + except Exception as e: + conf.fatal('Could not determine emscripten version %r: %s' % (cmd, e)) + + if not isinstance(out, str): + out = out.decode(sys.stdout.encoding or 'latin-1') + + k = {} + out = out.splitlines() + for line in out: + lst = shlex.split(line) + if len(lst)>2: + key = lst[1] + val = lst[2] + k[key] = val + + if not ('__clang__' in k and 'EMSCRIPTEN' in k): + conf.fatal('Could not determine the emscripten compiler version.') + + conf.env.DEST_OS = 'generic' + conf.env.DEST_BINFMT = 'elf' + conf.env.DEST_CPU = 'asm-js' + conf.env.CC_VERSION = (k['__clang_major__'], k['__clang_minor__'], k['__clang_patchlevel__']) + return k + +@conf +def find_emscripten(conf): + cc = conf.find_program(['emcc'], var='CC') + conf.get_emscripten_version(cc) + conf.env.CC = cc + conf.env.CC_NAME = 'emscripten' + cxx = conf.find_program(['em++'], var='CXX') + conf.env.CXX = cxx + conf.env.CXX_NAME = 'emscripten' + conf.find_program(['emar'], var='AR') + +def configure(conf): + conf.find_emscripten() + conf.find_ar() + conf.gcc_common_flags() + conf.gxx_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() + conf.env.ARFLAGS = ['rcs'] + conf.env.cshlib_PATTERN = '%s.js' + conf.env.cxxshlib_PATTERN = '%s.js' + conf.env.cstlib_PATTERN = '%s.a' + conf.env.cxxstlib_PATTERN = '%s.a' + conf.env.cprogram_PATTERN = '%s.html' + conf.env.cxxprogram_PATTERN = '%s.html' + conf.env.CXX_TGT_F = ['-c', '-o', ''] + conf.env.CC_TGT_F = ['-c', '-o', ''] + conf.env.CXXLNK_TGT_F = ['-o', ''] + conf.env.CCLNK_TGT_F = ['-o', ''] + conf.env.append_value('LINKFLAGS',['-Wl,--enable-auto-import']) diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/c_nec.py b/ldb-2.0.8/third_party/waf/waflib/extras/c_nec.py new file mode 100644 index 0000000..96bfae4 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/c_nec.py @@ -0,0 +1,74 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +""" +NEC SX Compiler for SX vector systems +""" + +import re +from waflib import Utils +from waflib.Tools import ccroot,ar +from waflib.Configure import conf + +from waflib.Tools import xlc # method xlc_common_flags +from waflib.Tools.compiler_c import c_compiler +c_compiler['linux'].append('c_nec') + +@conf +def find_sxc(conf): + cc = conf.find_program(['sxcc'], var='CC') + conf.get_sxc_version(cc) + conf.env.CC = cc + conf.env.CC_NAME = 'sxcc' + +@conf +def get_sxc_version(conf, fc): + version_re = re.compile(r"C\+\+/SX\s*Version\s*(?P\d*)\.(?P\d*)", re.I).search + cmd = fc + ['-V'] + p = Utils.subprocess.Popen(cmd, stdin=False, stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE, env=None) + out, err = p.communicate() + + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('Could not determine the NEC C compiler version.') + k = match.groupdict() + conf.env['C_VERSION'] = (k['major'], k['minor']) + +@conf +def sxc_common_flags(conf): + v=conf.env + v['CC_SRC_F']=[] + v['CC_TGT_F']=['-c','-o'] + if not v['LINK_CC']: + v['LINK_CC']=v['CC'] + v['CCLNK_SRC_F']=[] + v['CCLNK_TGT_F']=['-o'] + v['CPPPATH_ST']='-I%s' + v['DEFINES_ST']='-D%s' + v['LIB_ST']='-l%s' + v['LIBPATH_ST']='-L%s' + v['STLIB_ST']='-l%s' + v['STLIBPATH_ST']='-L%s' + v['RPATH_ST']='' + v['SONAME_ST']=[] + v['SHLIB_MARKER']=[] + v['STLIB_MARKER']=[] + v['LINKFLAGS_cprogram']=[''] + v['cprogram_PATTERN']='%s' + v['CFLAGS_cshlib']=['-fPIC'] + v['LINKFLAGS_cshlib']=[''] + v['cshlib_PATTERN']='lib%s.so' + v['LINKFLAGS_cstlib']=[] + v['cstlib_PATTERN']='lib%s.a' + +def configure(conf): + conf.find_sxc() + conf.find_program('sxar',VAR='AR') + conf.sxc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/cabal.py b/ldb-2.0.8/third_party/waf/waflib/extras/cabal.py new file mode 100644 index 0000000..e10a0d1 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/cabal.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Anton Feldmann, 2012 +# "Base for cabal" + +from waflib import Task, Utils +from waflib.TaskGen import extension +from waflib.Utils import threading +from shutil import rmtree + +lock = threading.Lock() +registering = False + +def configure(self): + self.find_program('cabal', var='CABAL') + self.find_program('ghc-pkg', var='GHCPKG') + pkgconfd = self.bldnode.abspath() + '/package.conf.d' + self.env.PREFIX = self.bldnode.abspath() + '/dist' + self.env.PKGCONFD = pkgconfd + if self.root.find_node(pkgconfd + '/package.cache'): + self.msg('Using existing package database', pkgconfd, color='CYAN') + else: + pkgdir = self.root.find_dir(pkgconfd) + if pkgdir: + self.msg('Deleting corrupt package database', pkgdir.abspath(), color ='RED') + rmtree(pkgdir.abspath()) + pkgdir = None + + self.cmd_and_log(self.env.GHCPKG + ['init', pkgconfd]) + self.msg('Created package database', pkgconfd, color = 'YELLOW' if pkgdir else 'GREEN') + +@extension('.cabal') +def process_cabal(self, node): + out_dir_node = self.bld.root.find_dir(self.bld.out_dir) + package_node = node.change_ext('.package') + package_node = out_dir_node.find_or_declare(package_node.name) + build_node = node.parent.get_bld() + build_path = build_node.abspath() + config_node = build_node.find_or_declare('setup-config') + inplace_node = build_node.find_or_declare('package.conf.inplace') + + config_task = self.create_task('cabal_configure', node) + config_task.cwd = node.parent.abspath() + config_task.depends_on = getattr(self, 'depends_on', '') + config_task.build_path = build_path + config_task.set_outputs(config_node) + + build_task = self.create_task('cabal_build', config_node) + build_task.cwd = node.parent.abspath() + build_task.build_path = build_path + build_task.set_outputs(inplace_node) + + copy_task = self.create_task('cabal_copy', inplace_node) + copy_task.cwd = node.parent.abspath() + copy_task.depends_on = getattr(self, 'depends_on', '') + copy_task.build_path = build_path + + last_task = copy_task + task_list = [config_task, build_task, copy_task] + + if (getattr(self, 'register', False)): + register_task = self.create_task('cabal_register', inplace_node) + register_task.cwd = node.parent.abspath() + register_task.set_run_after(copy_task) + register_task.build_path = build_path + + pkgreg_task = self.create_task('ghcpkg_register', inplace_node) + pkgreg_task.cwd = node.parent.abspath() + pkgreg_task.set_run_after(register_task) + pkgreg_task.build_path = build_path + + last_task = pkgreg_task + task_list += [register_task, pkgreg_task] + + touch_task = self.create_task('cabal_touch', inplace_node) + touch_task.set_run_after(last_task) + touch_task.set_outputs(package_node) + touch_task.build_path = build_path + + task_list += [touch_task] + + return task_list + +def get_all_src_deps(node): + hs_deps = node.ant_glob('**/*.hs') + hsc_deps = node.ant_glob('**/*.hsc') + lhs_deps = node.ant_glob('**/*.lhs') + c_deps = node.ant_glob('**/*.c') + cpp_deps = node.ant_glob('**/*.cpp') + proto_deps = node.ant_glob('**/*.proto') + return sum([hs_deps, hsc_deps, lhs_deps, c_deps, cpp_deps, proto_deps], []) + +class Cabal(Task.Task): + def scan(self): + return (get_all_src_deps(self.generator.path), ()) + +class cabal_configure(Cabal): + run_str = '${CABAL} configure -v0 --prefix=${PREFIX} --global --user --package-db=${PKGCONFD} --builddir=${tsk.build_path}' + shell = True + + def scan(self): + out_node = self.generator.bld.root.find_dir(self.generator.bld.out_dir) + deps = [out_node.find_or_declare(dep).change_ext('.package') for dep in Utils.to_list(self.depends_on)] + return (deps, ()) + +class cabal_build(Cabal): + run_str = '${CABAL} build -v1 --builddir=${tsk.build_path}/' + shell = True + +class cabal_copy(Cabal): + run_str = '${CABAL} copy -v0 --builddir=${tsk.build_path}' + shell = True + +class cabal_register(Cabal): + run_str = '${CABAL} register -v0 --gen-pkg-config=${tsk.build_path}/pkg.config --builddir=${tsk.build_path}' + shell = True + +class ghcpkg_register(Cabal): + run_str = '${GHCPKG} update -v0 --global --user --package-conf=${PKGCONFD} ${tsk.build_path}/pkg.config' + shell = True + + def runnable_status(self): + global lock, registering + + val = False + lock.acquire() + val = registering + lock.release() + + if val: + return Task.ASK_LATER + + ret = Task.Task.runnable_status(self) + if ret == Task.RUN_ME: + lock.acquire() + registering = True + lock.release() + + return ret + + def post_run(self): + global lock, registering + + lock.acquire() + registering = False + lock.release() + + return Task.Task.post_run(self) + +class cabal_touch(Cabal): + run_str = 'touch ${TGT}' + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/cfg_altoptions.py b/ldb-2.0.8/third_party/waf/waflib/extras/cfg_altoptions.py new file mode 100644 index 0000000..47b1189 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/cfg_altoptions.py @@ -0,0 +1,110 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Tool to extend c_config.check_cfg() + +__author__ = __maintainer__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2014" + +""" + +This tool allows to work around the absence of ``*-config`` programs +on systems, by keeping the same clean configuration syntax but inferring +values or permitting their modification via the options interface. + +Note that pkg-config can also support setting ``PKG_CONFIG_PATH``, +so you can put custom files in a folder containing new .pc files. +This tool could also be implemented by taking advantage of this fact. + +Usage:: + + def options(opt): + opt.load('c_config_alt') + opt.add_package_option('package') + + def configure(cfg): + conf.load('c_config_alt') + conf.check_cfg(...) + +Known issues: + +- Behavior with different build contexts... + +""" + +import os +import functools +from waflib import Configure, Options, Errors + +def name_to_dest(x): + return x.lower().replace('-', '_') + + +def options(opt): + def x(opt, param): + dest = name_to_dest(param) + gr = opt.get_option_group("configure options") + gr.add_option('--%s-root' % dest, + help="path containing include and lib subfolders for %s" \ + % param, + ) + + opt.add_package_option = functools.partial(x, opt) + + +check_cfg_old = getattr(Configure.ConfigurationContext, 'check_cfg') + +@Configure.conf +def check_cfg(conf, *k, **kw): + if k: + lst = k[0].split() + kw['package'] = lst[0] + kw['args'] = ' '.join(lst[1:]) + + if not 'package' in kw: + return check_cfg_old(conf, **kw) + + package = kw['package'] + + package_lo = name_to_dest(package) + package_hi = package.upper().replace('-', '_') # TODO FIXME + package_hi = kw.get('uselib_store', package_hi) + + def check_folder(path, name): + try: + assert os.path.isdir(path) + except AssertionError: + raise Errors.ConfigurationError( + "%s_%s (%s) is not a folder!" \ + % (package_lo, name, path)) + return path + + root = getattr(Options.options, '%s_root' % package_lo, None) + + if root is None: + return check_cfg_old(conf, **kw) + else: + def add_manual_var(k, v): + conf.start_msg('Adding for %s a manual var' % (package)) + conf.env["%s_%s" % (k, package_hi)] = v + conf.end_msg("%s = %s" % (k, v)) + + + check_folder(root, 'root') + + pkg_inc = check_folder(os.path.join(root, "include"), 'inc') + add_manual_var('INCLUDES', [pkg_inc]) + pkg_lib = check_folder(os.path.join(root, "lib"), 'libpath') + add_manual_var('LIBPATH', [pkg_lib]) + add_manual_var('LIB', [package]) + + for x in kw.get('manual_deps', []): + for k, v in sorted(conf.env.get_merged_dict().items()): + if k.endswith('_%s' % x): + k = k.replace('_%s' % x, '') + conf.start_msg('Adding for %s a manual dep' \ + %(package)) + conf.env["%s_%s" % (k, package_hi)] += v + conf.end_msg('%s += %s' % (k, v)) + + return True + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/clang_compilation_database.py b/ldb-2.0.8/third_party/waf/waflib/extras/clang_compilation_database.py new file mode 100644 index 0000000..4d9b5e2 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/clang_compilation_database.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Christoph Koke, 2013 + +""" +Writes the c and cpp compile commands into build/compile_commands.json +see http://clang.llvm.org/docs/JSONCompilationDatabase.html + +Usage: + + def configure(conf): + conf.load('compiler_cxx') + ... + conf.load('clang_compilation_database') +""" + +import sys, os, json, shlex, pipes +from waflib import Logs, TaskGen, Task + +Task.Task.keep_last_cmd = True + +@TaskGen.feature('c', 'cxx') +@TaskGen.after_method('process_use') +def collect_compilation_db_tasks(self): + "Add a compilation database entry for compiled tasks" + try: + clang_db = self.bld.clang_compilation_database_tasks + except AttributeError: + clang_db = self.bld.clang_compilation_database_tasks = [] + self.bld.add_post_fun(write_compilation_database) + + tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) + for task in getattr(self, 'compiled_tasks', []): + if isinstance(task, tup): + clang_db.append(task) + +def write_compilation_database(ctx): + "Write the clang compilation database as JSON" + database_file = ctx.bldnode.make_node('compile_commands.json') + Logs.info('Build commands will be stored in %s', database_file.path_from(ctx.path)) + try: + root = json.load(database_file) + except IOError: + root = [] + clang_db = dict((x['file'], x) for x in root) + for task in getattr(ctx, 'clang_compilation_database_tasks', []): + try: + cmd = task.last_cmd + except AttributeError: + continue + directory = getattr(task, 'cwd', ctx.variant_dir) + f_node = task.inputs[0] + filename = os.path.relpath(f_node.abspath(), directory) + entry = { + "directory": directory, + "arguments": cmd, + "file": filename, + } + clang_db[filename] = entry + root = list(clang_db.values()) + database_file.write(json.dumps(root, indent=2)) + +# Override the runnable_status function to do a dummy/dry run when the file doesn't need to be compiled. +# This will make sure compile_commands.json is always fully up to date. +# Previously you could end up with a partial compile_commands.json if the build failed. +for x in ('c', 'cxx'): + if x not in Task.classes: + continue + + t = Task.classes[x] + + def runnable_status(self): + def exec_command(cmd, **kw): + pass + + run_status = self.old_runnable_status() + if run_status == Task.SKIP_ME: + setattr(self, 'old_exec_command', getattr(self, 'exec_command', None)) + setattr(self, 'exec_command', exec_command) + self.run() + setattr(self, 'exec_command', getattr(self, 'old_exec_command', None)) + return run_status + + setattr(t, 'old_runnable_status', getattr(t, 'runnable_status', None)) + setattr(t, 'runnable_status', runnable_status) diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/clang_cross.py b/ldb-2.0.8/third_party/waf/waflib/extras/clang_cross.py new file mode 100644 index 0000000..1b51e28 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/clang_cross.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Krzysztof Kosiński 2014 +# DragoonX6 2018 + +""" +Detect the Clang C compiler +This version is an attempt at supporting the -target and -sysroot flag of Clang. +""" + +from waflib.Tools import ccroot, ar, gcc +from waflib.Configure import conf +import waflib.Context +import waflib.extras.clang_cross_common + +def options(opt): + """ + Target triplet for clang:: + $ waf configure --clang-target-triple=x86_64-pc-linux-gnu + """ + cc_compiler_opts = opt.add_option_group('Configuration options') + cc_compiler_opts.add_option('--clang-target-triple', default=None, + help='Target triple for clang', + dest='clang_target_triple') + cc_compiler_opts.add_option('--clang-sysroot', default=None, + help='Sysroot for clang', + dest='clang_sysroot') + +@conf +def find_clang(conf): + """ + Finds the program clang and executes it to ensure it really is clang + """ + + import os + + cc = conf.find_program('clang', var='CC') + + if conf.options.clang_target_triple != None: + conf.env.append_value('CC', ['-target', conf.options.clang_target_triple]) + + if conf.options.clang_sysroot != None: + sysroot = str() + + if os.path.isabs(conf.options.clang_sysroot): + sysroot = conf.options.clang_sysroot + else: + sysroot = os.path.normpath(os.path.join(os.getcwd(), conf.options.clang_sysroot)) + + conf.env.append_value('CC', ['--sysroot', sysroot]) + + conf.get_cc_version(cc, clang=True) + conf.env.CC_NAME = 'clang' + +@conf +def clang_modifier_x86_64_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clang_modifier_i386_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clang_modifier_x86_64_windows_msvc(conf): + conf.clang_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clang_modifier_x86_64_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +@conf +def clang_modifier_i386_windows_msvc(conf): + conf.clang_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clang_modifier_i386_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +def configure(conf): + conf.find_clang() + conf.find_program(['llvm-ar', 'ar'], var='AR') + conf.find_ar() + conf.gcc_common_flags() + # Allow the user to provide flags for the target platform. + conf.gcc_modifier_platform() + # And allow more fine grained control based on the compiler's triplet. + conf.clang_modifier_target_triple() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/clang_cross_common.py b/ldb-2.0.8/third_party/waf/waflib/extras/clang_cross_common.py new file mode 100644 index 0000000..b76a070 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/clang_cross_common.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# encoding: utf-8 +# DragoonX6 2018 + +""" +Common routines for cross_clang.py and cross_clangxx.py +""" + +from waflib.Configure import conf +import waflib.Context + +def normalize_target_triple(target_triple): + target_triple = target_triple[:-1] + normalized_triple = target_triple.replace('--', '-unknown-') + + if normalized_triple.startswith('-'): + normalized_triple = 'unknown' + normalized_triple + + if normalized_triple.endswith('-'): + normalized_triple += 'unknown' + + # Normalize MinGW builds to *arch*-w64-mingw32 + if normalized_triple.endswith('windows-gnu'): + normalized_triple = normalized_triple[:normalized_triple.index('-')] + '-w64-mingw32' + + # Strip the vendor when doing msvc builds, since it's unused anyway. + if normalized_triple.endswith('windows-msvc'): + normalized_triple = normalized_triple[:normalized_triple.index('-')] + '-windows-msvc' + + return normalized_triple.replace('-', '_') + +@conf +def clang_modifier_msvc(conf): + import os + + """ + Really basic setup to use clang in msvc mode. + We actually don't really want to do a lot, even though clang is msvc compatible + in this mode, that doesn't mean we're actually using msvc. + It's probably the best to leave it to the user, we can assume msvc mode if the user + uses the clang-cl frontend, but this module only concerns itself with the gcc-like frontend. + """ + v = conf.env + v.cprogram_PATTERN = '%s.exe' + + v.cshlib_PATTERN = '%s.dll' + v.implib_PATTERN = '%s.lib' + v.IMPLIB_ST = '-Wl,-IMPLIB:%s' + v.SHLIB_MARKER = [] + + v.CFLAGS_cshlib = [] + v.LINKFLAGS_cshlib = ['-Wl,-DLL'] + v.cstlib_PATTERN = '%s.lib' + v.STLIB_MARKER = [] + + del(v.AR) + conf.find_program(['llvm-lib', 'lib'], var='AR') + v.ARFLAGS = ['-nologo'] + v.AR_TGT_F = ['-out:'] + + # Default to the linker supplied with llvm instead of link.exe or ld + v.LINK_CC = v.CC + ['-fuse-ld=lld', '-nostdlib'] + v.CCLNK_TGT_F = ['-o'] + v.def_PATTERN = '-Wl,-def:%s' + + v.LINKFLAGS = [] + + v.LIB_ST = '-l%s' + v.LIBPATH_ST = '-Wl,-LIBPATH:%s' + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-Wl,-LIBPATH:%s' + + CFLAGS_CRT_COMMON = [ + '-Xclang', '--dependent-lib=oldnames', + '-Xclang', '-fno-rtti-data', + '-D_MT' + ] + + v.CFLAGS_CRT_MULTITHREADED = CFLAGS_CRT_COMMON + [ + '-Xclang', '-flto-visibility-public-std', + '-Xclang', '--dependent-lib=libcmt', + ] + v.CXXFLAGS_CRT_MULTITHREADED = v.CFLAGS_CRT_MULTITHREADED + + v.CFLAGS_CRT_MULTITHREADED_DBG = CFLAGS_CRT_COMMON + [ + '-D_DEBUG', + '-Xclang', '-flto-visibility-public-std', + '-Xclang', '--dependent-lib=libcmtd', + ] + v.CXXFLAGS_CRT_MULTITHREADED_DBG = v.CFLAGS_CRT_MULTITHREADED_DBG + + v.CFLAGS_CRT_MULTITHREADED_DLL = CFLAGS_CRT_COMMON + [ + '-D_DLL', + '-Xclang', '--dependent-lib=msvcrt' + ] + v.CXXFLAGS_CRT_MULTITHREADED_DLL = v.CFLAGS_CRT_MULTITHREADED_DLL + + v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = CFLAGS_CRT_COMMON + [ + '-D_DLL', + '-D_DEBUG', + '-Xclang', '--dependent-lib=msvcrtd', + ] + v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CFLAGS_CRT_MULTITHREADED_DLL_DBG + +@conf +def clang_modifier_target_triple(conf, cpp=False): + compiler = conf.env.CXX if cpp else conf.env.CC + output = conf.cmd_and_log(compiler + ['-dumpmachine'], output=waflib.Context.STDOUT) + + modifier = ('clangxx' if cpp else 'clang') + '_modifier_' + clang_modifier_func = getattr(conf, modifier + normalize_target_triple(output), None) + if clang_modifier_func: + clang_modifier_func() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/clangxx_cross.py b/ldb-2.0.8/third_party/waf/waflib/extras/clangxx_cross.py new file mode 100644 index 0000000..0ad38ad --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/clangxx_cross.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy 2009-2018 (ita) +# DragoonX6 2018 + +""" +Detect the Clang++ C++ compiler +This version is an attempt at supporting the -target and -sysroot flag of Clang++. +""" + +from waflib.Tools import ccroot, ar, gxx +from waflib.Configure import conf +import waflib.extras.clang_cross_common + +def options(opt): + """ + Target triplet for clang++:: + $ waf configure --clangxx-target-triple=x86_64-pc-linux-gnu + """ + cxx_compiler_opts = opt.add_option_group('Configuration options') + cxx_compiler_opts.add_option('--clangxx-target-triple', default=None, + help='Target triple for clang++', + dest='clangxx_target_triple') + cxx_compiler_opts.add_option('--clangxx-sysroot', default=None, + help='Sysroot for clang++', + dest='clangxx_sysroot') + +@conf +def find_clangxx(conf): + """ + Finds the program clang++, and executes it to ensure it really is clang++ + """ + + import os + + cxx = conf.find_program('clang++', var='CXX') + + if conf.options.clangxx_target_triple != None: + conf.env.append_value('CXX', ['-target', conf.options.clangxx_target_triple]) + + if conf.options.clangxx_sysroot != None: + sysroot = str() + + if os.path.isabs(conf.options.clangxx_sysroot): + sysroot = conf.options.clangxx_sysroot + else: + sysroot = os.path.normpath(os.path.join(os.getcwd(), conf.options.clangxx_sysroot)) + + conf.env.append_value('CXX', ['--sysroot', sysroot]) + + conf.get_cc_version(cxx, clang=True) + conf.env.CXX_NAME = 'clang' + +@conf +def clangxx_modifier_x86_64_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clangxx_modifier_i386_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clangxx_modifier_msvc(conf): + v = conf.env + v.cxxprogram_PATTERN = v.cprogram_PATTERN + v.cxxshlib_PATTERN = v.cshlib_PATTERN + + v.CXXFLAGS_cxxshlib = [] + v.LINKFLAGS_cxxshlib = v.LINKFLAGS_cshlib + v.cxxstlib_PATTERN = v.cstlib_PATTERN + + v.LINK_CXX = v.CXX + ['-fuse-ld=lld', '-nostdlib'] + v.CXXLNK_TGT_F = v.CCLNK_TGT_F + +@conf +def clangxx_modifier_x86_64_windows_msvc(conf): + conf.clang_modifier_msvc() + conf.clangxx_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clangxx_modifier_x86_64_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +@conf +def clangxx_modifier_i386_windows_msvc(conf): + conf.clang_modifier_msvc() + conf.clangxx_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clangxx_modifier_i386_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +def configure(conf): + conf.find_clangxx() + conf.find_program(['llvm-ar', 'ar'], var='AR') + conf.find_ar() + conf.gxx_common_flags() + # Allow the user to provide flags for the target platform. + conf.gxx_modifier_platform() + # And allow more fine grained control based on the compiler's triplet. + conf.clang_modifier_target_triple(cpp=True) + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/codelite.py b/ldb-2.0.8/third_party/waf/waflib/extras/codelite.py new file mode 100644 index 0000000..523302c --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/codelite.py @@ -0,0 +1,875 @@ +#! /usr/bin/env python +# encoding: utf-8 +# CodeLite Project +# Christian Klein (chrikle@berlios.de) +# Created: Jan 2012 +# As templete for this file I used the msvs.py +# I hope this template will work proper + +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +""" + + +To add this tool to your project: +def options(conf): + opt.load('codelite') + +It can be a good idea to add the sync_exec tool too. + +To generate solution files: +$ waf configure codelite + +To customize the outputs, provide subclasses in your wscript files: + +from waflib.extras import codelite +class vsnode_target(codelite.vsnode_target): + def get_build_command(self, props): + # likely to be required + return "waf.bat build" + def collect_source(self): + # likely to be required + ... +class codelite_bar(codelite.codelite_generator): + def init(self): + codelite.codelite_generator.init(self) + self.vsnode_target = vsnode_target + +The codelite class re-uses the same build() function for reading the targets (task generators), +you may therefore specify codelite settings on the context object: + +def build(bld): + bld.codelite_solution_name = 'foo.workspace' + bld.waf_command = 'waf.bat' + bld.projects_dir = bld.srcnode.make_node('') + bld.projects_dir.mkdir() + + +ASSUMPTIONS: +* a project can be either a directory or a target, project files are written only for targets that have source files +* each project is a vcxproj file, therefore the project uuid needs only to be a hash of the absolute path +""" + +import os, re, sys +import uuid # requires python 2.5 +from waflib.Build import BuildContext +from waflib import Utils, TaskGen, Logs, Task, Context, Node, Options + +HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' + +PROJECT_TEMPLATE = r''' + + + + + + + + + + ${for x in project.source} + ${if (project.get_key(x)=="sourcefile")} + + ${endif} + ${endfor} + + + ${for x in project.source} + ${if (project.get_key(x)=="headerfile")} + + ${endif} + ${endfor} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $b = project.build_properties[0]} + ${xml:project.get_rebuild_command(project.build_properties[0])} + ${xml:project.get_clean_command(project.build_properties[0])} + ${xml:project.get_build_command(project.build_properties[0])} + ${xml:project.get_install_command(project.build_properties[0])} + ${xml:project.get_build_and_install_command(project.build_properties[0])} + ${xml:project.get_build_all_command(project.build_properties[0])} + ${xml:project.get_rebuild_all_command(project.build_properties[0])} + ${xml:project.get_clean_all_command(project.build_properties[0])} + ${xml:project.get_build_and_install_all_command(project.build_properties[0])} + + + + None + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +''' + + + + +SOLUTION_TEMPLATE = ''' + +${for p in project.all_projects} + +${endfor} + + +${for p in project.all_projects} + +${endfor} + + +''' + + + +COMPILE_TEMPLATE = '''def f(project): + lst = [] + def xml_escape(value): + return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") + + %s + + #f = open('cmd.txt', 'w') + #f.write(str(lst)) + #f.close() + return ''.join(lst) +''' +reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P[^}]*?)\})", re.M) +def compile_template(line): + """ + Compile a template expression into a python function (like jsps, but way shorter) + """ + extr = [] + def repl(match): + g = match.group + if g('dollar'): + return "$" + elif g('backslash'): + return "\\" + elif g('subst'): + extr.append(g('code')) + return "<<|@|>>" + return None + + line2 = reg_act.sub(repl, line) + params = line2.split('<<|@|>>') + assert(extr) + + + indent = 0 + buf = [] + app = buf.append + + def app(txt): + buf.append(indent * '\t' + txt) + + for x in range(len(extr)): + if params[x]: + app("lst.append(%r)" % params[x]) + + f = extr[x] + if f.startswith(('if', 'for')): + app(f + ':') + indent += 1 + elif f.startswith('py:'): + app(f[3:]) + elif f.startswith(('endif', 'endfor')): + indent -= 1 + elif f.startswith(('else', 'elif')): + indent -= 1 + app(f + ':') + indent += 1 + elif f.startswith('xml:'): + app('lst.append(xml_escape(%s))' % f[4:]) + else: + #app('lst.append((%s) or "cannot find %s")' % (f, f)) + app('lst.append(%s)' % f) + + if extr: + if params[-1]: + app("lst.append(%r)" % params[-1]) + + fun = COMPILE_TEMPLATE % "\n\t".join(buf) + #print(fun) + return Task.funex(fun) + + +re_blank = re.compile('(\n|\r|\\s)*\n', re.M) +def rm_blank_lines(txt): + txt = re_blank.sub('\r\n', txt) + return txt + +BOM = '\xef\xbb\xbf' +try: + BOM = bytes(BOM, 'latin-1') # python 3 +except (TypeError, NameError): + pass + +def stealth_write(self, data, flags='wb'): + try: + unicode + except NameError: + data = data.encode('utf-8') # python 3 + else: + data = data.decode(sys.getfilesystemencoding(), 'replace') + data = data.encode('utf-8') + + if self.name.endswith('.project'): + data = BOM + data + + try: + txt = self.read(flags='rb') + if txt != data: + raise ValueError('must write') + except (IOError, ValueError): + self.write(data, flags=flags) + else: + Logs.debug('codelite: skipping %r', self) +Node.Node.stealth_write = stealth_write + +re_quote = re.compile("[^a-zA-Z0-9-]") +def quote(s): + return re_quote.sub("_", s) + +def xml_escape(value): + return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") + +def make_uuid(v, prefix = None): + """ + simple utility function + """ + if isinstance(v, dict): + keys = list(v.keys()) + keys.sort() + tmp = str([(k, v[k]) for k in keys]) + else: + tmp = str(v) + d = Utils.md5(tmp.encode()).hexdigest().upper() + if prefix: + d = '%s%s' % (prefix, d[8:]) + gid = uuid.UUID(d, version = 4) + return str(gid).upper() + +def diff(node, fromnode): + # difference between two nodes, but with "(..)" instead of ".." + c1 = node + c2 = fromnode + + c1h = c1.height() + c2h = c2.height() + + lst = [] + up = 0 + + while c1h > c2h: + lst.append(c1.name) + c1 = c1.parent + c1h -= 1 + + while c2h > c1h: + up += 1 + c2 = c2.parent + c2h -= 1 + + while id(c1) != id(c2): + lst.append(c1.name) + up += 1 + + c1 = c1.parent + c2 = c2.parent + + for i in range(up): + lst.append('(..)') + lst.reverse() + return tuple(lst) + +class build_property(object): + pass + +class vsnode(object): + """ + Abstract class representing visual studio elements + We assume that all visual studio nodes have a uuid and a parent + """ + def __init__(self, ctx): + self.ctx = ctx # codelite context + self.name = '' # string, mandatory + self.vspath = '' # path in visual studio (name for dirs, absolute path for projects) + self.uuid = '' # string, mandatory + self.parent = None # parent node for visual studio nesting + + def get_waf(self): + """ + Override in subclasses... + """ + return '%s/%s' % (self.ctx.srcnode.abspath(), getattr(self.ctx, 'waf_command', 'waf')) + + def ptype(self): + """ + Return a special uuid for projects written in the solution file + """ + pass + + def write(self): + """ + Write the project file, by default, do nothing + """ + pass + + def make_uuid(self, val): + """ + Alias for creating uuid values easily (the templates cannot access global variables) + """ + return make_uuid(val) + +class vsnode_vsdir(vsnode): + """ + Nodes representing visual studio folders (which do not match the filesystem tree!) + """ + VS_GUID_SOLUTIONFOLDER = "2150E333-8FDC-42A3-9474-1A3956D46DE8" + def __init__(self, ctx, uuid, name, vspath=''): + vsnode.__init__(self, ctx) + self.title = self.name = name + self.uuid = uuid + self.vspath = vspath or name + + def ptype(self): + return self.VS_GUID_SOLUTIONFOLDER + +class vsnode_project(vsnode): + """ + Abstract class representing visual studio project elements + A project is assumed to be writable, and has a node representing the file to write to + """ + VS_GUID_VCPROJ = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" + def ptype(self): + return self.VS_GUID_VCPROJ + + def __init__(self, ctx, node): + vsnode.__init__(self, ctx) + self.path = node + self.uuid = make_uuid(node.abspath()) + self.name = node.name + self.title = self.path.abspath() + self.source = [] # list of node objects + self.build_properties = [] # list of properties (nmake commands, output dir, etc) + + def dirs(self): + """ + Get the list of parent folders of the source files (header files included) + for writing the filters + """ + lst = [] + def add(x): + if x.height() > self.tg.path.height() and x not in lst: + lst.append(x) + add(x.parent) + for x in self.source: + add(x.parent) + return lst + + def write(self): + Logs.debug('codelite: creating %r', self.path) + #print "self.name:",self.name + + # first write the project file + template1 = compile_template(PROJECT_TEMPLATE) + proj_str = template1(self) + proj_str = rm_blank_lines(proj_str) + self.path.stealth_write(proj_str) + + # then write the filter + #template2 = compile_template(FILTER_TEMPLATE) + #filter_str = template2(self) + #filter_str = rm_blank_lines(filter_str) + #tmp = self.path.parent.make_node(self.path.name + '.filters') + #tmp.stealth_write(filter_str) + + def get_key(self, node): + """ + required for writing the source files + """ + name = node.name + if name.endswith(('.cpp', '.c')): + return 'sourcefile' + return 'headerfile' + + def collect_properties(self): + """ + Returns a list of triplet (configuration, platform, output_directory) + """ + ret = [] + for c in self.ctx.configurations: + for p in self.ctx.platforms: + x = build_property() + x.outdir = '' + + x.configuration = c + x.platform = p + + x.preprocessor_definitions = '' + x.includes_search_path = '' + + # can specify "deploy_dir" too + ret.append(x) + self.build_properties = ret + + def get_build_params(self, props): + opt = '' + return (self.get_waf(), opt) + + def get_build_command(self, props): + return "%s build %s" % self.get_build_params(props) + + def get_clean_command(self, props): + return "%s clean %s" % self.get_build_params(props) + + def get_rebuild_command(self, props): + return "%s clean build %s" % self.get_build_params(props) + + def get_install_command(self, props): + return "%s install %s" % self.get_build_params(props) + def get_build_and_install_command(self, props): + return "%s build install %s" % self.get_build_params(props) + + def get_build_and_install_all_command(self, props): + return "%s build install" % self.get_build_params(props)[0] + + def get_clean_all_command(self, props): + return "%s clean" % self.get_build_params(props)[0] + + def get_build_all_command(self, props): + return "%s build" % self.get_build_params(props)[0] + + def get_rebuild_all_command(self, props): + return "%s clean build" % self.get_build_params(props)[0] + + def get_filter_name(self, node): + lst = diff(node, self.tg.path) + return '\\'.join(lst) or '.' + +class vsnode_alias(vsnode_project): + def __init__(self, ctx, node, name): + vsnode_project.__init__(self, ctx, node) + self.name = name + self.output_file = '' + +class vsnode_build_all(vsnode_alias): + """ + Fake target used to emulate the behaviour of "make all" (starting one process by target is slow) + This is the only alias enabled by default + """ + def __init__(self, ctx, node, name='build_all_projects'): + vsnode_alias.__init__(self, ctx, node, name) + self.is_active = True + +class vsnode_install_all(vsnode_alias): + """ + Fake target used to emulate the behaviour of "make install" + """ + def __init__(self, ctx, node, name='install_all_projects'): + vsnode_alias.__init__(self, ctx, node, name) + + def get_build_command(self, props): + return "%s build install %s" % self.get_build_params(props) + + def get_clean_command(self, props): + return "%s clean %s" % self.get_build_params(props) + + def get_rebuild_command(self, props): + return "%s clean build install %s" % self.get_build_params(props) + +class vsnode_project_view(vsnode_alias): + """ + Fake target used to emulate a file system view + """ + def __init__(self, ctx, node, name='project_view'): + vsnode_alias.__init__(self, ctx, node, name) + self.tg = self.ctx() # fake one, cannot remove + self.exclude_files = Node.exclude_regs + ''' +waf-2* +waf3-2*/** +.waf-2* +.waf3-2*/** +**/*.sdf +**/*.suo +**/*.ncb +**/%s + ''' % Options.lockfile + + def collect_source(self): + # this is likely to be slow + self.source = self.ctx.srcnode.ant_glob('**', excl=self.exclude_files) + + def get_build_command(self, props): + params = self.get_build_params(props) + (self.ctx.cmd,) + return "%s %s %s" % params + + def get_clean_command(self, props): + return "" + + def get_rebuild_command(self, props): + return self.get_build_command(props) + +class vsnode_target(vsnode_project): + """ + CodeLite project representing a targets (programs, libraries, etc) and bound + to a task generator + """ + def __init__(self, ctx, tg): + """ + A project is more or less equivalent to a file/folder + """ + base = getattr(ctx, 'projects_dir', None) or tg.path + node = base.make_node(quote(tg.name) + ctx.project_extension) # the project file as a Node + vsnode_project.__init__(self, ctx, node) + self.name = quote(tg.name) + self.tg = tg # task generator + + def get_build_params(self, props): + """ + Override the default to add the target name + """ + opt = '' + if getattr(self, 'tg', None): + opt += " --targets=%s" % self.tg.name + return (self.get_waf(), opt) + + def collect_source(self): + tg = self.tg + source_files = tg.to_nodes(getattr(tg, 'source', [])) + include_dirs = Utils.to_list(getattr(tg, 'codelite_includes', [])) + include_files = [] + for x in include_dirs: + if isinstance(x, str): + x = tg.path.find_node(x) + if x: + lst = [y for y in x.ant_glob(HEADERS_GLOB, flat=False)] + include_files.extend(lst) + + # remove duplicates + self.source.extend(list(set(source_files + include_files))) + self.source.sort(key=lambda x: x.abspath()) + + def collect_properties(self): + """ + CodeLite projects are associated with platforms and configurations (for building especially) + """ + super(vsnode_target, self).collect_properties() + for x in self.build_properties: + x.outdir = self.path.parent.abspath() + x.preprocessor_definitions = '' + x.includes_search_path = '' + + try: + tsk = self.tg.link_task + except AttributeError: + pass + else: + x.output_file = tsk.outputs[0].abspath() + x.preprocessor_definitions = ';'.join(tsk.env.DEFINES) + x.includes_search_path = ';'.join(self.tg.env.INCPATHS) + +class codelite_generator(BuildContext): + '''generates a CodeLite workspace''' + cmd = 'codelite' + fun = 'build' + + def init(self): + """ + Some data that needs to be present + """ + if not getattr(self, 'configurations', None): + self.configurations = ['Release'] # LocalRelease, RemoteDebug, etc + if not getattr(self, 'platforms', None): + self.platforms = ['Win32'] + if not getattr(self, 'all_projects', None): + self.all_projects = [] + if not getattr(self, 'project_extension', None): + self.project_extension = '.project' + if not getattr(self, 'projects_dir', None): + self.projects_dir = self.srcnode.make_node('') + self.projects_dir.mkdir() + + # bind the classes to the object, so that subclass can provide custom generators + if not getattr(self, 'vsnode_vsdir', None): + self.vsnode_vsdir = vsnode_vsdir + if not getattr(self, 'vsnode_target', None): + self.vsnode_target = vsnode_target + if not getattr(self, 'vsnode_build_all', None): + self.vsnode_build_all = vsnode_build_all + if not getattr(self, 'vsnode_install_all', None): + self.vsnode_install_all = vsnode_install_all + if not getattr(self, 'vsnode_project_view', None): + self.vsnode_project_view = vsnode_project_view + + self.numver = '11.00' + self.vsver = '2010' + + def execute(self): + """ + Entry point + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + + # user initialization + self.init() + + # two phases for creating the solution + self.collect_projects() # add project objects into "self.all_projects" + self.write_files() # write the corresponding project and solution files + + def collect_projects(self): + """ + Fill the list self.all_projects with project objects + Fill the list of build targets + """ + self.collect_targets() + #self.add_aliases() + #self.collect_dirs() + default_project = getattr(self, 'default_project', None) + def sortfun(x): + if x.name == default_project: + return '' + return getattr(x, 'path', None) and x.path.abspath() or x.name + self.all_projects.sort(key=sortfun) + + def write_files(self): + """ + Write the project and solution files from the data collected + so far. It is unlikely that you will want to change this + """ + for p in self.all_projects: + p.write() + + # and finally write the solution file + node = self.get_solution_node() + node.parent.mkdir() + Logs.warn('Creating %r', node) + #a = dir(self.root) + #for b in a: + # print b + #print self.group_names + #print "Hallo2: ",self.root.listdir() + #print getattr(self, 'codelite_solution_name', None) + template1 = compile_template(SOLUTION_TEMPLATE) + sln_str = template1(self) + sln_str = rm_blank_lines(sln_str) + node.stealth_write(sln_str) + + def get_solution_node(self): + """ + The solution filename is required when writing the .vcproj files + return self.solution_node and if it does not exist, make one + """ + try: + return self.solution_node + except: + pass + + codelite_solution_name = getattr(self, 'codelite_solution_name', None) + if not codelite_solution_name: + codelite_solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '.workspace' + setattr(self, 'codelite_solution_name', codelite_solution_name) + if os.path.isabs(codelite_solution_name): + self.solution_node = self.root.make_node(codelite_solution_name) + else: + self.solution_node = self.srcnode.make_node(codelite_solution_name) + return self.solution_node + + def project_configurations(self): + """ + Helper that returns all the pairs (config,platform) + """ + ret = [] + for c in self.configurations: + for p in self.platforms: + ret.append((c, p)) + return ret + + def collect_targets(self): + """ + Process the list of task generators + """ + for g in self.groups: + for tg in g: + if not isinstance(tg, TaskGen.task_gen): + continue + + if not hasattr(tg, 'codelite_includes'): + tg.codelite_includes = tg.to_list(getattr(tg, 'includes', [])) + tg.to_list(getattr(tg, 'export_includes', [])) + tg.post() + if not getattr(tg, 'link_task', None): + continue + + p = self.vsnode_target(self, tg) + p.collect_source() # delegate this processing + p.collect_properties() + self.all_projects.append(p) + + def add_aliases(self): + """ + Add a specific target that emulates the "make all" necessary for Visual studio when pressing F7 + We also add an alias for "make install" (disabled by default) + """ + base = getattr(self, 'projects_dir', None) or self.tg.path + + node_project = base.make_node('build_all_projects' + self.project_extension) # Node + p_build = self.vsnode_build_all(self, node_project) + p_build.collect_properties() + self.all_projects.append(p_build) + + node_project = base.make_node('install_all_projects' + self.project_extension) # Node + p_install = self.vsnode_install_all(self, node_project) + p_install.collect_properties() + self.all_projects.append(p_install) + + node_project = base.make_node('project_view' + self.project_extension) # Node + p_view = self.vsnode_project_view(self, node_project) + p_view.collect_source() + p_view.collect_properties() + self.all_projects.append(p_view) + + n = self.vsnode_vsdir(self, make_uuid(self.srcnode.abspath() + 'build_aliases'), "build_aliases") + p_build.parent = p_install.parent = p_view.parent = n + self.all_projects.append(n) + + def collect_dirs(self): + """ + Create the folder structure in the CodeLite project view + """ + seen = {} + def make_parents(proj): + # look at a project, try to make a parent + if getattr(proj, 'parent', None): + # aliases already have parents + return + x = proj.iter_path + if x in seen: + proj.parent = seen[x] + return + + # There is not vsnode_vsdir for x. + # So create a project representing the folder "x" + n = proj.parent = seen[x] = self.vsnode_vsdir(self, make_uuid(x.abspath()), x.name) + n.iter_path = x.parent + self.all_projects.append(n) + + # recurse up to the project directory + if x.height() > self.srcnode.height() + 1: + make_parents(n) + + for p in self.all_projects[:]: # iterate over a copy of all projects + if not getattr(p, 'tg', None): + # but only projects that have a task generator + continue + + # make a folder for each task generator + p.iter_path = p.tg.path + make_parents(p) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/color_gcc.py b/ldb-2.0.8/third_party/waf/waflib/extras/color_gcc.py new file mode 100644 index 0000000..b68c5eb --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/color_gcc.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# encoding: utf-8 + +# Replaces the default formatter by one which understands GCC output and colorizes it. + +__author__ = __maintainer__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2012" + +import sys +from waflib import Logs + +class ColorGCCFormatter(Logs.formatter): + def __init__(self, colors): + self.colors = colors + Logs.formatter.__init__(self) + def format(self, rec): + frame = sys._getframe() + while frame: + func = frame.f_code.co_name + if func == 'exec_command': + cmd = frame.f_locals.get('cmd') + if isinstance(cmd, list) and ('gcc' in cmd[0] or 'g++' in cmd[0]): + lines = [] + for line in rec.msg.splitlines(): + if 'warning: ' in line: + lines.append(self.colors.YELLOW + line) + elif 'error: ' in line: + lines.append(self.colors.RED + line) + elif 'note: ' in line: + lines.append(self.colors.CYAN + line) + else: + lines.append(line) + rec.msg = "\n".join(lines) + frame = frame.f_back + return Logs.formatter.format(self, rec) + +def options(opt): + Logs.log.handlers[0].setFormatter(ColorGCCFormatter(Logs.colors)) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/color_msvc.py b/ldb-2.0.8/third_party/waf/waflib/extras/color_msvc.py new file mode 100644 index 0000000..60bacb7 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/color_msvc.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# encoding: utf-8 + +# Replaces the default formatter by one which understands MSVC output and colorizes it. +# Modified from color_gcc.py + +__author__ = __maintainer__ = "Alibek Omarov " +__copyright__ = "Alibek Omarov, 2019" + +import sys +from waflib import Logs + +class ColorMSVCFormatter(Logs.formatter): + def __init__(self, colors): + self.colors = colors + Logs.formatter.__init__(self) + + def parseMessage(self, line, color): + # Split messaage from 'disk:filepath: type: message' + arr = line.split(':', 3) + if len(arr) < 4: + return line + + colored = self.colors.BOLD + arr[0] + ':' + arr[1] + ':' + self.colors.NORMAL + colored += color + arr[2] + ':' + self.colors.NORMAL + colored += arr[3] + return colored + + def format(self, rec): + frame = sys._getframe() + while frame: + func = frame.f_code.co_name + if func == 'exec_command': + cmd = frame.f_locals.get('cmd') + if isinstance(cmd, list): + # Fix file case, it may be CL.EXE or cl.exe + argv0 = cmd[0].lower() + if 'cl.exe' in argv0: + lines = [] + # This will not work with "localized" versions + # of MSVC + for line in rec.msg.splitlines(): + if ': warning ' in line: + lines.append(self.parseMessage(line, self.colors.YELLOW)) + elif ': error ' in line: + lines.append(self.parseMessage(line, self.colors.RED)) + elif ': fatal error ' in line: + lines.append(self.parseMessage(line, self.colors.RED + self.colors.BOLD)) + elif ': note: ' in line: + lines.append(self.parseMessage(line, self.colors.CYAN)) + else: + lines.append(line) + rec.msg = "\n".join(lines) + frame = frame.f_back + return Logs.formatter.format(self, rec) + +def options(opt): + Logs.log.handlers[0].setFormatter(ColorMSVCFormatter(Logs.colors)) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/color_rvct.py b/ldb-2.0.8/third_party/waf/waflib/extras/color_rvct.py new file mode 100644 index 0000000..f89ccbd --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/color_rvct.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# encoding: utf-8 + +# Replaces the default formatter by one which understands RVCT output and colorizes it. + +__author__ = __maintainer__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2012" + +import sys +import atexit +from waflib import Logs + +errors = [] + +def show_errors(): + for i, e in enumerate(errors): + if i > 5: + break + print("Error: %s" % e) + +atexit.register(show_errors) + +class RcvtFormatter(Logs.formatter): + def __init__(self, colors): + Logs.formatter.__init__(self) + self.colors = colors + def format(self, rec): + frame = sys._getframe() + while frame: + func = frame.f_code.co_name + if func == 'exec_command': + cmd = frame.f_locals['cmd'] + if isinstance(cmd, list) and ('armcc' in cmd[0] or 'armld' in cmd[0]): + lines = [] + for line in rec.msg.splitlines(): + if 'Warning: ' in line: + lines.append(self.colors.YELLOW + line) + elif 'Error: ' in line: + lines.append(self.colors.RED + line) + errors.append(line) + elif 'note: ' in line: + lines.append(self.colors.CYAN + line) + else: + lines.append(line) + rec.msg = "\n".join(lines) + frame = frame.f_back + return Logs.formatter.format(self, rec) + +def options(opt): + Logs.log.handlers[0].setFormatter(RcvtFormatter(Logs.colors)) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/compat15.py b/ldb-2.0.8/third_party/waf/waflib/extras/compat15.py new file mode 100644 index 0000000..0e74df8 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/compat15.py @@ -0,0 +1,406 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010 (ita) + +""" +This file is provided to enable compatibility with waf 1.5 +It was enabled by default in waf 1.6, but it is not used in waf 1.7 +""" + +import sys +from waflib import ConfigSet, Logs, Options, Scripting, Task, Build, Configure, Node, Runner, TaskGen, Utils, Errors, Context + +# the following is to bring some compatibility with waf 1.5 "import waflib.Configure → import Configure" +sys.modules['Environment'] = ConfigSet +ConfigSet.Environment = ConfigSet.ConfigSet + +sys.modules['Logs'] = Logs +sys.modules['Options'] = Options +sys.modules['Scripting'] = Scripting +sys.modules['Task'] = Task +sys.modules['Build'] = Build +sys.modules['Configure'] = Configure +sys.modules['Node'] = Node +sys.modules['Runner'] = Runner +sys.modules['TaskGen'] = TaskGen +sys.modules['Utils'] = Utils +sys.modules['Constants'] = Context +Context.SRCDIR = '' +Context.BLDDIR = '' + +from waflib.Tools import c_preproc +sys.modules['preproc'] = c_preproc + +from waflib.Tools import c_config +sys.modules['config_c'] = c_config + +ConfigSet.ConfigSet.copy = ConfigSet.ConfigSet.derive +ConfigSet.ConfigSet.set_variant = Utils.nada + +Utils.pproc = Utils.subprocess + +Build.BuildContext.add_subdirs = Build.BuildContext.recurse +Build.BuildContext.new_task_gen = Build.BuildContext.__call__ +Build.BuildContext.is_install = 0 +Node.Node.relpath_gen = Node.Node.path_from + +Utils.pproc = Utils.subprocess +Utils.get_term_cols = Logs.get_term_cols + +def cmd_output(cmd, **kw): + + silent = False + if 'silent' in kw: + silent = kw['silent'] + del(kw['silent']) + + if 'e' in kw: + tmp = kw['e'] + del(kw['e']) + kw['env'] = tmp + + kw['shell'] = isinstance(cmd, str) + kw['stdout'] = Utils.subprocess.PIPE + if silent: + kw['stderr'] = Utils.subprocess.PIPE + + try: + p = Utils.subprocess.Popen(cmd, **kw) + output = p.communicate()[0] + except OSError as e: + raise ValueError(str(e)) + + if p.returncode: + if not silent: + msg = "command execution failed: %s -> %r" % (cmd, str(output)) + raise ValueError(msg) + output = '' + return output +Utils.cmd_output = cmd_output + +def name_to_obj(self, s, env=None): + if Logs.verbose: + Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"') + return self.get_tgen_by_name(s) +Build.BuildContext.name_to_obj = name_to_obj + +def env_of_name(self, name): + try: + return self.all_envs[name] + except KeyError: + Logs.error('no such environment: '+name) + return None +Build.BuildContext.env_of_name = env_of_name + + +def set_env_name(self, name, env): + self.all_envs[name] = env + return env +Configure.ConfigurationContext.set_env_name = set_env_name + +def retrieve(self, name, fromenv=None): + try: + env = self.all_envs[name] + except KeyError: + env = ConfigSet.ConfigSet() + self.prepare_env(env) + self.all_envs[name] = env + else: + if fromenv: + Logs.warn('The environment %s may have been configured already', name) + return env +Configure.ConfigurationContext.retrieve = retrieve + +Configure.ConfigurationContext.sub_config = Configure.ConfigurationContext.recurse +Configure.ConfigurationContext.check_tool = Configure.ConfigurationContext.load +Configure.conftest = Configure.conf +Configure.ConfigurationError = Errors.ConfigurationError +Utils.WafError = Errors.WafError + +Options.OptionsContext.sub_options = Options.OptionsContext.recurse +Options.OptionsContext.tool_options = Context.Context.load +Options.Handler = Options.OptionsContext + +Task.simple_task_type = Task.task_type_from_func = Task.task_factory +Task.Task.classes = Task.classes + +def setitem(self, key, value): + if key.startswith('CCFLAGS'): + key = key[1:] + self.table[key] = value +ConfigSet.ConfigSet.__setitem__ = setitem + +@TaskGen.feature('d') +@TaskGen.before('apply_incpaths') +def old_importpaths(self): + if getattr(self, 'importpaths', []): + self.includes = self.importpaths + +from waflib import Context +eld = Context.load_tool +def load_tool(*k, **kw): + ret = eld(*k, **kw) + if 'set_options' in ret.__dict__: + if Logs.verbose: + Logs.warn('compat: rename "set_options" to options') + ret.options = ret.set_options + if 'detect' in ret.__dict__: + if Logs.verbose: + Logs.warn('compat: rename "detect" to "configure"') + ret.configure = ret.detect + return ret +Context.load_tool = load_tool + +def get_curdir(self): + return self.path.abspath() +Context.Context.curdir = property(get_curdir, Utils.nada) + +def get_srcdir(self): + return self.srcnode.abspath() +Configure.ConfigurationContext.srcdir = property(get_srcdir, Utils.nada) + +def get_blddir(self): + return self.bldnode.abspath() +Configure.ConfigurationContext.blddir = property(get_blddir, Utils.nada) + +Configure.ConfigurationContext.check_message_1 = Configure.ConfigurationContext.start_msg +Configure.ConfigurationContext.check_message_2 = Configure.ConfigurationContext.end_msg + +rev = Context.load_module +def load_module(path, encoding=None): + ret = rev(path, encoding) + if 'set_options' in ret.__dict__: + if Logs.verbose: + Logs.warn('compat: rename "set_options" to "options" (%r)', path) + ret.options = ret.set_options + if 'srcdir' in ret.__dict__: + if Logs.verbose: + Logs.warn('compat: rename "srcdir" to "top" (%r)', path) + ret.top = ret.srcdir + if 'blddir' in ret.__dict__: + if Logs.verbose: + Logs.warn('compat: rename "blddir" to "out" (%r)', path) + ret.out = ret.blddir + Utils.g_module = Context.g_module + Options.launch_dir = Context.launch_dir + return ret +Context.load_module = load_module + +old_post = TaskGen.task_gen.post +def post(self): + self.features = self.to_list(self.features) + if 'cc' in self.features: + if Logs.verbose: + Logs.warn('compat: the feature cc does not exist anymore (use "c")') + self.features.remove('cc') + self.features.append('c') + if 'cstaticlib' in self.features: + if Logs.verbose: + Logs.warn('compat: the feature cstaticlib does not exist anymore (use "cstlib" or "cxxstlib")') + self.features.remove('cstaticlib') + self.features.append(('cxx' in self.features) and 'cxxstlib' or 'cstlib') + if getattr(self, 'ccflags', None): + if Logs.verbose: + Logs.warn('compat: "ccflags" was renamed to "cflags"') + self.cflags = self.ccflags + return old_post(self) +TaskGen.task_gen.post = post + +def waf_version(*k, **kw): + Logs.warn('wrong version (waf_version was removed in waf 1.6)') +Utils.waf_version = waf_version + + +import os +@TaskGen.feature('c', 'cxx', 'd') +@TaskGen.before('apply_incpaths', 'propagate_uselib_vars') +@TaskGen.after('apply_link', 'process_source') +def apply_uselib_local(self): + """ + process the uselib_local attribute + execute after apply_link because of the execution order set on 'link_task' + """ + env = self.env + from waflib.Tools.ccroot import stlink_task + + # 1. the case of the libs defined in the project (visit ancestors first) + # the ancestors external libraries (uselib) will be prepended + self.uselib = self.to_list(getattr(self, 'uselib', [])) + self.includes = self.to_list(getattr(self, 'includes', [])) + names = self.to_list(getattr(self, 'uselib_local', [])) + get = self.bld.get_tgen_by_name + seen = set() + seen_uselib = set() + tmp = Utils.deque(names) # consume a copy of the list of names + if tmp: + if Logs.verbose: + Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') + while tmp: + lib_name = tmp.popleft() + # visit dependencies only once + if lib_name in seen: + continue + + y = get(lib_name) + y.post() + seen.add(lib_name) + + # object has ancestors to process (shared libraries): add them to the end of the list + if getattr(y, 'uselib_local', None): + for x in self.to_list(getattr(y, 'uselib_local', [])): + obj = get(x) + obj.post() + if getattr(obj, 'link_task', None): + if not isinstance(obj.link_task, stlink_task): + tmp.append(x) + + # link task and flags + if getattr(y, 'link_task', None): + + link_name = y.target[y.target.rfind(os.sep) + 1:] + if isinstance(y.link_task, stlink_task): + env.append_value('STLIB', [link_name]) + else: + # some linkers can link against programs + env.append_value('LIB', [link_name]) + + # the order + self.link_task.set_run_after(y.link_task) + + # for the recompilation + self.link_task.dep_nodes += y.link_task.outputs + + # add the link path too + tmp_path = y.link_task.outputs[0].parent.bldpath() + if not tmp_path in env['LIBPATH']: + env.prepend_value('LIBPATH', [tmp_path]) + + # add ancestors uselib too - but only propagate those that have no staticlib defined + for v in self.to_list(getattr(y, 'uselib', [])): + if v not in seen_uselib: + seen_uselib.add(v) + if not env['STLIB_' + v]: + if not v in self.uselib: + self.uselib.insert(0, v) + + # if the library task generator provides 'export_includes', add to the include path + # the export_includes must be a list of paths relative to the other library + if getattr(y, 'export_includes', None): + self.includes.extend(y.to_incnodes(y.export_includes)) + +@TaskGen.feature('cprogram', 'cxxprogram', 'cstlib', 'cxxstlib', 'cshlib', 'cxxshlib', 'dprogram', 'dstlib', 'dshlib') +@TaskGen.after('apply_link') +def apply_objdeps(self): + "add the .o files produced by some other object files in the same manner as uselib_local" + names = getattr(self, 'add_objects', []) + if not names: + return + names = self.to_list(names) + + get = self.bld.get_tgen_by_name + seen = [] + while names: + x = names[0] + + # visit dependencies only once + if x in seen: + names = names[1:] + continue + + # object does not exist ? + y = get(x) + + # object has ancestors to process first ? update the list of names + if getattr(y, 'add_objects', None): + added = 0 + lst = y.to_list(y.add_objects) + lst.reverse() + for u in lst: + if u in seen: + continue + added = 1 + names = [u]+names + if added: + continue # list of names modified, loop + + # safe to process the current object + y.post() + seen.append(x) + + for t in getattr(y, 'compiled_tasks', []): + self.link_task.inputs.extend(t.outputs) + +@TaskGen.after('apply_link') +def process_obj_files(self): + if not hasattr(self, 'obj_files'): + return + for x in self.obj_files: + node = self.path.find_resource(x) + self.link_task.inputs.append(node) + +@TaskGen.taskgen_method +def add_obj_file(self, file): + """Small example on how to link object files as if they were source + obj = bld.create_obj('cc') + obj.add_obj_file('foo.o')""" + if not hasattr(self, 'obj_files'): + self.obj_files = [] + if not 'process_obj_files' in self.meths: + self.meths.append('process_obj_files') + self.obj_files.append(file) + + +old_define = Configure.ConfigurationContext.__dict__['define'] + +@Configure.conf +def define(self, key, val, quote=True, comment=''): + old_define(self, key, val, quote, comment) + if key.startswith('HAVE_'): + self.env[key] = 1 + +old_undefine = Configure.ConfigurationContext.__dict__['undefine'] + +@Configure.conf +def undefine(self, key, comment=''): + old_undefine(self, key, comment) + if key.startswith('HAVE_'): + self.env[key] = 0 + +# some people might want to use export_incdirs, but it was renamed +def set_incdirs(self, val): + Logs.warn('compat: change "export_incdirs" by "export_includes"') + self.export_includes = val +TaskGen.task_gen.export_incdirs = property(None, set_incdirs) + +def install_dir(self, path): + if not path: + return [] + + destpath = Utils.subst_vars(path, self.env) + + if self.is_install > 0: + Logs.info('* creating %s', destpath) + Utils.check_dir(destpath) + elif self.is_install < 0: + Logs.info('* removing %s', destpath) + try: + os.remove(destpath) + except OSError: + pass +Build.BuildContext.install_dir = install_dir + +# before/after names +repl = {'apply_core': 'process_source', + 'apply_lib_vars': 'process_source', + 'apply_obj_vars': 'propagate_uselib_vars', + 'exec_rule': 'process_rule' +} +def after(*k): + k = [repl.get(key, key) for key in k] + return TaskGen.after_method(*k) + +def before(*k): + k = [repl.get(key, key) for key in k] + return TaskGen.before_method(*k) +TaskGen.before = before + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/cppcheck.py b/ldb-2.0.8/third_party/waf/waflib/extras/cppcheck.py new file mode 100644 index 0000000..13ff424 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/cppcheck.py @@ -0,0 +1,591 @@ +#! /usr/bin/env python +# -*- encoding: utf-8 -*- +# Michel Mooij, michel.mooij7@gmail.com + +""" +Tool Description +================ +This module provides a waf wrapper (i.e. waftool) around the C/C++ source code +checking tool 'cppcheck'. + +See http://cppcheck.sourceforge.net/ for more information on the cppcheck tool +itself. +Note that many linux distributions already provide a ready to install version +of cppcheck. On fedora, for instance, it can be installed using yum: + + 'sudo yum install cppcheck' + + +Usage +===== +In order to use this waftool simply add it to the 'options' and 'configure' +functions of your main waf script as shown in the example below: + + def options(opt): + opt.load('cppcheck', tooldir='./waftools') + + def configure(conf): + conf.load('cppcheck') + +Note that example shown above assumes that the cppcheck waftool is located in +the sub directory named 'waftools'. + +When configured as shown in the example above, cppcheck will automatically +perform a source code analysis on all C/C++ build tasks that have been +defined in your waf build system. + +The example shown below for a C program will be used as input for cppcheck when +building the task. + + def build(bld): + bld.program(name='foo', src='foobar.c') + +The result of the source code analysis will be stored both as xml and html +files in the build location for the task. Should any error be detected by +cppcheck the build will be aborted and a link to the html report will be shown. +By default, one index.html file is created for each task generator. A global +index.html file can be obtained by setting the following variable +in the configuration section: + + conf.env.CPPCHECK_SINGLE_HTML = False + +When needed source code checking by cppcheck can be disabled per task, per +detected error or warning for a particular task. It can be also be disabled for +all tasks. + +In order to exclude a task from source code checking add the skip option to the +task as shown below: + + def build(bld): + bld.program( + name='foo', + src='foobar.c' + cppcheck_skip=True + ) + +When needed problems detected by cppcheck may be suppressed using a file +containing a list of suppression rules. The relative or absolute path to this +file can be added to the build task as shown in the example below: + + bld.program( + name='bar', + src='foobar.c', + cppcheck_suppress='bar.suppress' + ) + +A cppcheck suppress file should contain one suppress rule per line. Each of +these rules will be passed as an '--suppress=' argument to cppcheck. + +Dependencies +================ +This waftool depends on the python pygments module, it is used for source code +syntax highlighting when creating the html reports. see http://pygments.org/ for +more information on this package. + +Remarks +================ +The generation of the html report is originally based on the cppcheck-htmlreport.py +script that comes shipped with the cppcheck tool. +""" + +import sys +import xml.etree.ElementTree as ElementTree +from waflib import Task, TaskGen, Logs, Context, Options + +PYGMENTS_EXC_MSG= ''' +The required module 'pygments' could not be found. Please install it using your +platform package manager (e.g. apt-get or yum), using 'pip' or 'easy_install', +see 'http://pygments.org/download/' for installation instructions. +''' + +try: + import pygments + from pygments import formatters, lexers +except ImportError as e: + Logs.warn(PYGMENTS_EXC_MSG) + raise e + + +def options(opt): + opt.add_option('--cppcheck-skip', dest='cppcheck_skip', + default=False, action='store_true', + help='do not check C/C++ sources (default=False)') + + opt.add_option('--cppcheck-err-resume', dest='cppcheck_err_resume', + default=False, action='store_true', + help='continue in case of errors (default=False)') + + opt.add_option('--cppcheck-bin-enable', dest='cppcheck_bin_enable', + default='warning,performance,portability,style,unusedFunction', action='store', + help="cppcheck option '--enable=' for binaries (default=warning,performance,portability,style,unusedFunction)") + + opt.add_option('--cppcheck-lib-enable', dest='cppcheck_lib_enable', + default='warning,performance,portability,style', action='store', + help="cppcheck option '--enable=' for libraries (default=warning,performance,portability,style)") + + opt.add_option('--cppcheck-std-c', dest='cppcheck_std_c', + default='c99', action='store', + help='cppcheck standard to use when checking C (default=c99)') + + opt.add_option('--cppcheck-std-cxx', dest='cppcheck_std_cxx', + default='c++03', action='store', + help='cppcheck standard to use when checking C++ (default=c++03)') + + opt.add_option('--cppcheck-check-config', dest='cppcheck_check_config', + default=False, action='store_true', + help='forced check for missing buildin include files, e.g. stdio.h (default=False)') + + opt.add_option('--cppcheck-max-configs', dest='cppcheck_max_configs', + default='20', action='store', + help='maximum preprocessor (--max-configs) define iterations (default=20)') + + opt.add_option('--cppcheck-jobs', dest='cppcheck_jobs', + default='1', action='store', + help='number of jobs (-j) to do the checking work (default=1)') + +def configure(conf): + if conf.options.cppcheck_skip: + conf.env.CPPCHECK_SKIP = [True] + conf.env.CPPCHECK_STD_C = conf.options.cppcheck_std_c + conf.env.CPPCHECK_STD_CXX = conf.options.cppcheck_std_cxx + conf.env.CPPCHECK_MAX_CONFIGS = conf.options.cppcheck_max_configs + conf.env.CPPCHECK_BIN_ENABLE = conf.options.cppcheck_bin_enable + conf.env.CPPCHECK_LIB_ENABLE = conf.options.cppcheck_lib_enable + conf.env.CPPCHECK_JOBS = conf.options.cppcheck_jobs + if conf.options.cppcheck_jobs != '1' and ('unusedFunction' in conf.options.cppcheck_bin_enable or 'unusedFunction' in conf.options.cppcheck_lib_enable or 'all' in conf.options.cppcheck_bin_enable or 'all' in conf.options.cppcheck_lib_enable): + Logs.warn('cppcheck: unusedFunction cannot be used with multiple threads, cppcheck will disable it automatically') + conf.find_program('cppcheck', var='CPPCHECK') + + # set to True to get a single index.html file + conf.env.CPPCHECK_SINGLE_HTML = False + +@TaskGen.feature('c') +@TaskGen.feature('cxx') +def cppcheck_execute(self): + if hasattr(self.bld, 'conf'): + return + if len(self.env.CPPCHECK_SKIP) or Options.options.cppcheck_skip: + return + if getattr(self, 'cppcheck_skip', False): + return + task = self.create_task('cppcheck') + task.cmd = _tgen_create_cmd(self) + task.fatal = [] + if not Options.options.cppcheck_err_resume: + task.fatal.append('error') + + +def _tgen_create_cmd(self): + features = getattr(self, 'features', []) + std_c = self.env.CPPCHECK_STD_C + std_cxx = self.env.CPPCHECK_STD_CXX + max_configs = self.env.CPPCHECK_MAX_CONFIGS + bin_enable = self.env.CPPCHECK_BIN_ENABLE + lib_enable = self.env.CPPCHECK_LIB_ENABLE + jobs = self.env.CPPCHECK_JOBS + + cmd = self.env.CPPCHECK + args = ['--inconclusive','--report-progress','--verbose','--xml','--xml-version=2'] + args.append('--max-configs=%s' % max_configs) + args.append('-j %s' % jobs) + + if 'cxx' in features: + args.append('--language=c++') + args.append('--std=%s' % std_cxx) + else: + args.append('--language=c') + args.append('--std=%s' % std_c) + + if Options.options.cppcheck_check_config: + args.append('--check-config') + + if set(['cprogram','cxxprogram']) & set(features): + args.append('--enable=%s' % bin_enable) + else: + args.append('--enable=%s' % lib_enable) + + for src in self.to_list(getattr(self, 'source', [])): + if not isinstance(src, str): + src = repr(src) + args.append(src) + for inc in self.to_incnodes(self.to_list(getattr(self, 'includes', []))): + if not isinstance(inc, str): + inc = repr(inc) + args.append('-I%s' % inc) + for inc in self.to_incnodes(self.to_list(self.env.INCLUDES)): + if not isinstance(inc, str): + inc = repr(inc) + args.append('-I%s' % inc) + return cmd + args + + +class cppcheck(Task.Task): + quiet = True + + def run(self): + stderr = self.generator.bld.cmd_and_log(self.cmd, quiet=Context.STDERR, output=Context.STDERR) + self._save_xml_report(stderr) + defects = self._get_defects(stderr) + index = self._create_html_report(defects) + self._errors_evaluate(defects, index) + return 0 + + def _save_xml_report(self, s): + '''use cppcheck xml result string, add the command string used to invoke cppcheck + and save as xml file. + ''' + header = '%s\n' % s.splitlines()[0] + root = ElementTree.fromstring(s) + cmd = ElementTree.SubElement(root.find('cppcheck'), 'cmd') + cmd.text = str(self.cmd) + body = ElementTree.tostring(root).decode('us-ascii') + body_html_name = 'cppcheck-%s.xml' % self.generator.get_name() + if self.env.CPPCHECK_SINGLE_HTML: + body_html_name = 'cppcheck.xml' + node = self.generator.path.get_bld().find_or_declare(body_html_name) + node.write(header + body) + + def _get_defects(self, xml_string): + '''evaluate the xml string returned by cppcheck (on sdterr) and use it to create + a list of defects. + ''' + defects = [] + for error in ElementTree.fromstring(xml_string).iter('error'): + defect = {} + defect['id'] = error.get('id') + defect['severity'] = error.get('severity') + defect['msg'] = str(error.get('msg')).replace('<','<') + defect['verbose'] = error.get('verbose') + for location in error.findall('location'): + defect['file'] = location.get('file') + defect['line'] = str(int(location.get('line')) - 1) + defects.append(defect) + return defects + + def _create_html_report(self, defects): + files, css_style_defs = self._create_html_files(defects) + index = self._create_html_index(files) + self._create_css_file(css_style_defs) + return index + + def _create_html_files(self, defects): + sources = {} + defects = [defect for defect in defects if 'file' in defect] + for defect in defects: + name = defect['file'] + if not name in sources: + sources[name] = [defect] + else: + sources[name].append(defect) + + files = {} + css_style_defs = None + bpath = self.generator.path.get_bld().abspath() + names = list(sources.keys()) + for i in range(0,len(names)): + name = names[i] + if self.env.CPPCHECK_SINGLE_HTML: + htmlfile = 'cppcheck/%i.html' % (i) + else: + htmlfile = 'cppcheck/%s%i.html' % (self.generator.get_name(),i) + errors = sources[name] + files[name] = { 'htmlfile': '%s/%s' % (bpath, htmlfile), 'errors': errors } + css_style_defs = self._create_html_file(name, htmlfile, errors) + return files, css_style_defs + + def _create_html_file(self, sourcefile, htmlfile, errors): + name = self.generator.get_name() + root = ElementTree.fromstring(CPPCHECK_HTML_FILE) + title = root.find('head/title') + title.text = 'cppcheck - report - %s' % name + + body = root.find('body') + for div in body.findall('div'): + if div.get('id') == 'page': + page = div + break + for div in page.findall('div'): + if div.get('id') == 'header': + h1 = div.find('h1') + h1.text = 'cppcheck report - %s' % name + if div.get('id') == 'menu': + indexlink = div.find('a') + if self.env.CPPCHECK_SINGLE_HTML: + indexlink.attrib['href'] = 'index.html' + else: + indexlink.attrib['href'] = 'index-%s.html' % name + if div.get('id') == 'content': + content = div + srcnode = self.generator.bld.root.find_node(sourcefile) + hl_lines = [e['line'] for e in errors if 'line' in e] + formatter = CppcheckHtmlFormatter(linenos=True, style='colorful', hl_lines=hl_lines, lineanchors='line') + formatter.errors = [e for e in errors if 'line' in e] + css_style_defs = formatter.get_style_defs('.highlight') + lexer = pygments.lexers.guess_lexer_for_filename(sourcefile, "") + s = pygments.highlight(srcnode.read(), lexer, formatter) + table = ElementTree.fromstring(s) + content.append(table) + + s = ElementTree.tostring(root, method='html').decode('us-ascii') + s = CCPCHECK_HTML_TYPE + s + node = self.generator.path.get_bld().find_or_declare(htmlfile) + node.write(s) + return css_style_defs + + def _create_html_index(self, files): + name = self.generator.get_name() + root = ElementTree.fromstring(CPPCHECK_HTML_FILE) + title = root.find('head/title') + title.text = 'cppcheck - report - %s' % name + + body = root.find('body') + for div in body.findall('div'): + if div.get('id') == 'page': + page = div + break + for div in page.findall('div'): + if div.get('id') == 'header': + h1 = div.find('h1') + h1.text = 'cppcheck report - %s' % name + if div.get('id') == 'content': + content = div + self._create_html_table(content, files) + if div.get('id') == 'menu': + indexlink = div.find('a') + if self.env.CPPCHECK_SINGLE_HTML: + indexlink.attrib['href'] = 'index.html' + else: + indexlink.attrib['href'] = 'index-%s.html' % name + + s = ElementTree.tostring(root, method='html').decode('us-ascii') + s = CCPCHECK_HTML_TYPE + s + index_html_name = 'cppcheck/index-%s.html' % name + if self.env.CPPCHECK_SINGLE_HTML: + index_html_name = 'cppcheck/index.html' + node = self.generator.path.get_bld().find_or_declare(index_html_name) + node.write(s) + return node + + def _create_html_table(self, content, files): + table = ElementTree.fromstring(CPPCHECK_HTML_TABLE) + for name, val in files.items(): + f = val['htmlfile'] + s = '%s\n' % (f,name) + row = ElementTree.fromstring(s) + table.append(row) + + errors = sorted(val['errors'], key=lambda e: int(e['line']) if 'line' in e else sys.maxint) + for e in errors: + if not 'line' in e: + s = '%s%s%s\n' % (e['id'], e['severity'], e['msg']) + else: + attr = '' + if e['severity'] == 'error': + attr = 'class="error"' + s = '%s' % (f, e['line'], e['line']) + s+= '%s%s%s\n' % (e['id'], e['severity'], attr, e['msg']) + row = ElementTree.fromstring(s) + table.append(row) + content.append(table) + + def _create_css_file(self, css_style_defs): + css = str(CPPCHECK_CSS_FILE) + if css_style_defs: + css = "%s\n%s\n" % (css, css_style_defs) + node = self.generator.path.get_bld().find_or_declare('cppcheck/style.css') + node.write(css) + + def _errors_evaluate(self, errors, http_index): + name = self.generator.get_name() + fatal = self.fatal + severity = [err['severity'] for err in errors] + problems = [err for err in errors if err['severity'] != 'information'] + + if set(fatal) & set(severity): + exc = "\n" + exc += "\nccpcheck detected fatal error(s) in task '%s', see report for details:" % name + exc += "\n file://%r" % (http_index) + exc += "\n" + self.generator.bld.fatal(exc) + + elif len(problems): + msg = "\nccpcheck detected (possible) problem(s) in task '%s', see report for details:" % name + msg += "\n file://%r" % http_index + msg += "\n" + Logs.error(msg) + + +class CppcheckHtmlFormatter(pygments.formatters.HtmlFormatter): + errors = [] + + def wrap(self, source, outfile): + line_no = 1 + for i, t in super(CppcheckHtmlFormatter, self).wrap(source, outfile): + # If this is a source code line we want to add a span tag at the end. + if i == 1: + for error in self.errors: + if int(error['line']) == line_no: + t = t.replace('\n', CPPCHECK_HTML_ERROR % error['msg']) + line_no += 1 + yield i, t + + +CCPCHECK_HTML_TYPE = \ +'\n' + +CPPCHECK_HTML_FILE = """ +]> + + + cppcheck - report - XXX + + + + + +
+ + +
+
+ +   +
+ + + +""" + +CPPCHECK_HTML_TABLE = """ + + + + + + + +
LineIdSeverityMessage
+""" + +CPPCHECK_HTML_ERROR = \ +'<--- %s\n' + +CPPCHECK_CSS_FILE = """ +body.body { + font-family: Arial; + font-size: 13px; + background-color: black; + padding: 0px; + margin: 0px; +} + +.error { + font-family: Arial; + font-size: 13px; + background-color: #ffb7b7; + padding: 0px; + margin: 0px; +} + +th, td { + min-width: 100px; + text-align: left; +} + +#page-header { + clear: both; + width: 1200px; + margin: 20px auto 0px auto; + height: 10px; + border-bottom-width: 2px; + border-bottom-style: solid; + border-bottom-color: #aaaaaa; +} + +#page { + width: 1160px; + margin: auto; + border-left-width: 2px; + border-left-style: solid; + border-left-color: #aaaaaa; + border-right-width: 2px; + border-right-style: solid; + border-right-color: #aaaaaa; + background-color: White; + padding: 20px; +} + +#page-footer { + clear: both; + width: 1200px; + margin: auto; + height: 10px; + border-top-width: 2px; + border-top-style: solid; + border-top-color: #aaaaaa; +} + +#header { + width: 100%; + height: 70px; + background-image: url(logo.png); + background-repeat: no-repeat; + background-position: left top; + border-bottom-style: solid; + border-bottom-width: thin; + border-bottom-color: #aaaaaa; +} + +#menu { + margin-top: 5px; + text-align: left; + float: left; + width: 100px; + height: 300px; +} + +#menu > a { + margin-left: 10px; + display: block; +} + +#content { + float: left; + width: 1020px; + margin: 5px; + padding: 0px 10px 10px 10px; + border-left-style: solid; + border-left-width: thin; + border-left-color: #aaaaaa; +} + +#footer { + padding-bottom: 5px; + padding-top: 5px; + border-top-style: solid; + border-top-width: thin; + border-top-color: #aaaaaa; + clear: both; + font-size: 10px; +} + +#footer > div { + float: left; + width: 33%; +} + +""" + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/cpplint.py b/ldb-2.0.8/third_party/waf/waflib/extras/cpplint.py new file mode 100644 index 0000000..8cdd6dd --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/cpplint.py @@ -0,0 +1,209 @@ +#! /usr/bin/env python +# encoding: utf-8 +# +# written by Sylvain Rouquette, 2014 + +''' + +This is an extra tool, not bundled with the default waf binary. +To add the cpplint tool to the waf file: +$ ./waf-light --tools=compat15,cpplint + +this tool also requires cpplint for python. +If you have PIP, you can install it like this: pip install cpplint + +When using this tool, the wscript will look like: + + def options(opt): + opt.load('compiler_cxx cpplint') + + def configure(conf): + conf.load('compiler_cxx cpplint') + # optional, you can also specify them on the command line + conf.env.CPPLINT_FILTERS = ','.join(( + '-whitespace/newline', # c++11 lambda + '-readability/braces', # c++11 constructor + '-whitespace/braces', # c++11 constructor + '-build/storage_class', # c++11 for-range + '-whitespace/blank_line', # user pref + '-whitespace/labels' # user pref + )) + + def build(bld): + bld(features='cpplint', source='main.cpp', target='app') + # add include files, because they aren't usually built + bld(features='cpplint', source=bld.path.ant_glob('**/*.hpp')) +''' + +from __future__ import absolute_import +import sys, re +import logging +from waflib import Errors, Task, TaskGen, Logs, Options, Node, Utils + + +critical_errors = 0 +CPPLINT_FORMAT = '[CPPLINT] %(filename)s:\nline %(linenum)s, severity %(confidence)s, category: %(category)s\n%(message)s\n' +RE_EMACS = re.compile(r'(?P.*):(?P\d+): (?P.*) \[(?P.*)\] \[(?P\d+)\]') +CPPLINT_RE = { + 'waf': RE_EMACS, + 'emacs': RE_EMACS, + 'vs7': re.compile(r'(?P.*)\((?P\d+)\): (?P.*) \[(?P.*)\] \[(?P\d+)\]'), + 'eclipse': re.compile(r'(?P.*):(?P\d+): warning: (?P.*) \[(?P.*)\] \[(?P\d+)\]'), +} +CPPLINT_STR = ('${CPPLINT} ' + '--verbose=${CPPLINT_LEVEL} ' + '--output=${CPPLINT_OUTPUT} ' + '--filter=${CPPLINT_FILTERS} ' + '--root=${CPPLINT_ROOT} ' + '--linelength=${CPPLINT_LINE_LENGTH} ') + + +def options(opt): + opt.add_option('--cpplint-filters', type='string', + default='', dest='CPPLINT_FILTERS', + help='add filters to cpplint') + opt.add_option('--cpplint-length', type='int', + default=80, dest='CPPLINT_LINE_LENGTH', + help='specify the line length (default: 80)') + opt.add_option('--cpplint-level', default=1, type='int', dest='CPPLINT_LEVEL', + help='specify the log level (default: 1)') + opt.add_option('--cpplint-break', default=5, type='int', dest='CPPLINT_BREAK', + help='break the build if error >= level (default: 5)') + opt.add_option('--cpplint-root', type='string', + default='', dest='CPPLINT_ROOT', + help='root directory used to derive header guard') + opt.add_option('--cpplint-skip', action='store_true', + default=False, dest='CPPLINT_SKIP', + help='skip cpplint during build') + opt.add_option('--cpplint-output', type='string', + default='waf', dest='CPPLINT_OUTPUT', + help='select output format (waf, emacs, vs7, eclipse)') + + +def configure(conf): + try: + conf.find_program('cpplint', var='CPPLINT') + except Errors.ConfigurationError: + conf.env.CPPLINT_SKIP = True + + +class cpplint_formatter(Logs.formatter, object): + def __init__(self, fmt): + logging.Formatter.__init__(self, CPPLINT_FORMAT) + self.fmt = fmt + + def format(self, rec): + if self.fmt == 'waf': + result = CPPLINT_RE[self.fmt].match(rec.msg).groupdict() + rec.msg = CPPLINT_FORMAT % result + if rec.levelno <= logging.INFO: + rec.c1 = Logs.colors.CYAN + return super(cpplint_formatter, self).format(rec) + + +class cpplint_handler(Logs.log_handler, object): + def __init__(self, stream=sys.stderr, **kw): + super(cpplint_handler, self).__init__(stream, **kw) + self.stream = stream + + def emit(self, rec): + rec.stream = self.stream + self.emit_override(rec) + self.flush() + + +class cpplint_wrapper(object): + def __init__(self, logger, threshold, fmt): + self.logger = logger + self.threshold = threshold + self.fmt = fmt + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + if isinstance(exc_value, Utils.subprocess.CalledProcessError): + messages = [m for m in exc_value.output.splitlines() + if 'Done processing' not in m + and 'Total errors found' not in m] + for message in messages: + self.write(message) + return True + + def write(self, message): + global critical_errors + result = CPPLINT_RE[self.fmt].match(message) + if not result: + return + level = int(result.groupdict()['confidence']) + if level >= self.threshold: + critical_errors += 1 + if level <= 2: + self.logger.info(message) + elif level <= 4: + self.logger.warning(message) + else: + self.logger.error(message) + + +cpplint_logger = None +def get_cpplint_logger(fmt): + global cpplint_logger + if cpplint_logger: + return cpplint_logger + cpplint_logger = logging.getLogger('cpplint') + hdlr = cpplint_handler() + hdlr.setFormatter(cpplint_formatter(fmt)) + cpplint_logger.addHandler(hdlr) + cpplint_logger.setLevel(logging.DEBUG) + return cpplint_logger + + +class cpplint(Task.Task): + color = 'PINK' + + def __init__(self, *k, **kw): + super(cpplint, self).__init__(*k, **kw) + + def run(self): + global critical_errors + with cpplint_wrapper(get_cpplint_logger(self.env.CPPLINT_OUTPUT), self.env.CPPLINT_BREAK, self.env.CPPLINT_OUTPUT): + params = {key: str(self.env[key]) for key in self.env if 'CPPLINT_' in key} + if params['CPPLINT_OUTPUT'] is 'waf': + params['CPPLINT_OUTPUT'] = 'emacs' + params['CPPLINT'] = self.env.get_flat('CPPLINT') + cmd = Utils.subst_vars(CPPLINT_STR, params) + env = self.env.env or None + Utils.subprocess.check_output(cmd + self.inputs[0].abspath(), + stderr=Utils.subprocess.STDOUT, + env=env, shell=True) + return critical_errors + +@TaskGen.extension('.h', '.hh', '.hpp', '.hxx') +def cpplint_includes(self, node): + pass + +@TaskGen.feature('cpplint') +@TaskGen.before_method('process_source') +def post_cpplint(self): + if not self.env.CPPLINT_INITIALIZED: + for key, value in Options.options.__dict__.items(): + if not key.startswith('CPPLINT_') or self.env[key]: + continue + self.env[key] = value + self.env.CPPLINT_INITIALIZED = True + + if self.env.CPPLINT_SKIP: + return + + if not self.env.CPPLINT_OUTPUT in CPPLINT_RE: + return + + for src in self.to_list(getattr(self, 'source', [])): + if isinstance(src, Node.Node): + node = src + else: + node = self.path.find_or_declare(src) + if not node: + self.bld.fatal('Could not find %r' % src) + self.create_task('cpplint', node) diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/cross_gnu.py b/ldb-2.0.8/third_party/waf/waflib/extras/cross_gnu.py new file mode 100644 index 0000000..309f53b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/cross_gnu.py @@ -0,0 +1,227 @@ +#!/usr/bin/python +# -*- coding: utf-8 vi:ts=4:noexpandtab +# Tool to provide dedicated variables for cross-compilation + +__author__ = __maintainer__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2014" + +""" +This tool allows to use environment variables to define cross-compilation +variables intended for build variants. + +The variables are obtained from the environment in 3 ways: + +1. By defining CHOST, they can be derived as ${CHOST}-${TOOL} +2. By defining HOST_x +3. By defining ${CHOST//-/_}_x + +else one can set ``cfg.env.CHOST`` in ``wscript`` before loading ``cross_gnu``. + +Usage: + +- In your build script:: + + def configure(cfg): + ... + for variant in x_variants: + setenv(variant) + conf.load('cross_gnu') + conf.xcheck_host_var('POUET') + ... + + +- Then:: + + CHOST=arm-hardfloat-linux-gnueabi waf configure + env arm-hardfloat-linux-gnueabi-CC="clang -..." waf configure + CFLAGS=... CHOST=arm-hardfloat-linux-gnueabi HOST_CFLAGS=-g waf configure + HOST_CC="clang -..." waf configure + +This example ``wscript`` compiles to Microchip PIC (xc16-gcc-xyz must be in PATH): + +.. code:: python + + from waflib import Configure + + #from https://gist.github.com/rpuntaie/2bddfb5d7b77db26415ee14371289971 + import waf_variants + + variants='pc fw/variant1 fw/variant2'.split() + + top = "." + out = "../build" + + PIC = '33FJ128GP804' #dsPICxxx + + @Configure.conf + def gcc_modifier_xc16(cfg): + v = cfg.env + v.cprogram_PATTERN = '%s.elf' + v.LINKFLAGS_cprogram = ','.join(['-Wl','','','--defsym=__MPLAB_BUILD=0','','--script=p'+PIC+'.gld', + '--stack=16','--check-sections','--data-init','--pack-data','--handles','--isr','--no-gc-sections', + '--fill-upper=0','--stackguard=16','--no-force-link','--smart-io']) #,'--report-mem']) + v.CFLAGS_cprogram=['-mcpu='+PIC,'-omf=elf','-mlarge-code','-msmart-io=1', + '-msfr-warn=off','-mno-override-inline','-finline','-Winline'] + + def configure(cfg): + if 'fw' in cfg.variant: #firmware + cfg.env.DEST_OS = 'xc16' #cfg.env.CHOST = 'xc16' #works too + cfg.load('c cross_gnu') #cfg.env.CHOST becomes ['xc16'] + ... + else: #configure for pc SW + ... + + def build(bld): + if 'fw' in bld.variant: #firmware + bld.program(source='maintst.c', target='maintst'); + bld(source='maintst.elf', target='maintst.hex', rule="xc16-bin2hex ${SRC} -a -omf=elf") + else: #build for pc SW + ... + +""" + +import os +from waflib import Utils, Configure +from waflib.Tools import ccroot, gcc + +try: + from shlex import quote +except ImportError: + from pipes import quote + +def get_chost_stuff(conf): + """ + Get the CHOST environment variable contents + """ + chost = None + chost_envar = None + if conf.env.CHOST: + chost = conf.env.CHOST[0] + chost_envar = chost.replace('-', '_') + return chost, chost_envar + + +@Configure.conf +def xcheck_var(conf, name, wafname=None, cross=False): + wafname = wafname or name + + if wafname in conf.env: + value = conf.env[wafname] + if isinstance(value, str): + value = [value] + else: + envar = os.environ.get(name) + if not envar: + return + value = Utils.to_list(envar) if envar != '' else [envar] + + conf.env[wafname] = value + if cross: + pretty = 'cross-compilation %s' % wafname + else: + pretty = wafname + conf.msg('Will use %s' % pretty, " ".join(quote(x) for x in value)) + +@Configure.conf +def xcheck_host_prog(conf, name, tool, wafname=None): + wafname = wafname or name + + chost, chost_envar = get_chost_stuff(conf) + + specific = None + if chost: + specific = os.environ.get('%s_%s' % (chost_envar, name)) + + if specific: + value = Utils.to_list(specific) + conf.env[wafname] += value + conf.msg('Will use cross-compilation %s from %s_%s' % (name, chost_envar, name), + " ".join(quote(x) for x in value)) + return + else: + envar = os.environ.get('HOST_%s' % name) + if envar is not None: + value = Utils.to_list(envar) + conf.env[wafname] = value + conf.msg('Will use cross-compilation %s from HOST_%s' % (name, name), + " ".join(quote(x) for x in value)) + return + + if conf.env[wafname]: + return + + value = None + if chost: + value = '%s-%s' % (chost, tool) + + if value: + conf.env[wafname] = value + conf.msg('Will use cross-compilation %s from CHOST' % wafname, value) + +@Configure.conf +def xcheck_host_envar(conf, name, wafname=None): + wafname = wafname or name + + chost, chost_envar = get_chost_stuff(conf) + + specific = None + if chost: + specific = os.environ.get('%s_%s' % (chost_envar, name)) + + if specific: + value = Utils.to_list(specific) + conf.env[wafname] += value + conf.msg('Will use cross-compilation %s from %s_%s' \ + % (name, chost_envar, name), + " ".join(quote(x) for x in value)) + return + + + envar = os.environ.get('HOST_%s' % name) + if envar is None: + return + + value = Utils.to_list(envar) if envar != '' else [envar] + + conf.env[wafname] = value + conf.msg('Will use cross-compilation %s from HOST_%s' % (name, name), + " ".join(quote(x) for x in value)) + + +@Configure.conf +def xcheck_host(conf): + conf.xcheck_var('CHOST', cross=True) + conf.env.CHOST = conf.env.CHOST or [conf.env.DEST_OS] + conf.env.DEST_OS = conf.env.CHOST[0].replace('-','_') + conf.xcheck_host_prog('CC', 'gcc') + conf.xcheck_host_prog('CXX', 'g++') + conf.xcheck_host_prog('LINK_CC', 'gcc') + conf.xcheck_host_prog('LINK_CXX', 'g++') + conf.xcheck_host_prog('AR', 'ar') + conf.xcheck_host_prog('AS', 'as') + conf.xcheck_host_prog('LD', 'ld') + conf.xcheck_host_envar('CFLAGS') + conf.xcheck_host_envar('CXXFLAGS') + conf.xcheck_host_envar('LDFLAGS', 'LINKFLAGS') + conf.xcheck_host_envar('LIB') + conf.xcheck_host_envar('PKG_CONFIG_LIBDIR') + conf.xcheck_host_envar('PKG_CONFIG_PATH') + + if not conf.env.env: + conf.env.env = {} + conf.env.env.update(os.environ) + if conf.env.PKG_CONFIG_LIBDIR: + conf.env.env['PKG_CONFIG_LIBDIR'] = conf.env.PKG_CONFIG_LIBDIR[0] + if conf.env.PKG_CONFIG_PATH: + conf.env.env['PKG_CONFIG_PATH'] = conf.env.PKG_CONFIG_PATH[0] + +def configure(conf): + """ + Configuration example for gcc, it will not work for g++/clang/clang++ + """ + conf.xcheck_host() + conf.gcc_common_flags() + conf.gcc_modifier_platform() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/cython.py b/ldb-2.0.8/third_party/waf/waflib/extras/cython.py new file mode 100644 index 0000000..591c274 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/cython.py @@ -0,0 +1,147 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010-2015 + +import re +from waflib import Task, Logs +from waflib.TaskGen import extension + +cy_api_pat = re.compile(r'\s*?cdef\s*?(public|api)\w*') +re_cyt = re.compile(r""" + ^\s* # must begin with some whitespace characters + (?:from\s+(\w+)(?:\.\w+)*\s+)? # optionally match "from foo(.baz)" and capture foo + c?import\s(\w+|[*]) # require "import bar" and capture bar + """, re.M | re.VERBOSE) + +@extension('.pyx') +def add_cython_file(self, node): + """ + Process a *.pyx* file given in the list of source files. No additional + feature is required:: + + def build(bld): + bld(features='c cshlib pyext', source='main.c foo.pyx', target='app') + """ + ext = '.c' + if 'cxx' in self.features: + self.env.append_unique('CYTHONFLAGS', '--cplus') + ext = '.cc' + + for x in getattr(self, 'cython_includes', []): + # TODO re-use these nodes in "scan" below + d = self.path.find_dir(x) + if d: + self.env.append_unique('CYTHONFLAGS', '-I%s' % d.abspath()) + + tsk = self.create_task('cython', node, node.change_ext(ext)) + self.source += tsk.outputs + +class cython(Task.Task): + run_str = '${CYTHON} ${CYTHONFLAGS} -o ${TGT[0].abspath()} ${SRC}' + color = 'GREEN' + + vars = ['INCLUDES'] + """ + Rebuild whenever the INCLUDES change. The variables such as CYTHONFLAGS will be appended + by the metaclass. + """ + + ext_out = ['.h'] + """ + The creation of a .h file is known only after the build has begun, so it is not + possible to compute a build order just by looking at the task inputs/outputs. + """ + + def runnable_status(self): + """ + Perform a double-check to add the headers created by cython + to the output nodes. The scanner is executed only when the cython task + must be executed (optimization). + """ + ret = super(cython, self).runnable_status() + if ret == Task.ASK_LATER: + return ret + for x in self.generator.bld.raw_deps[self.uid()]: + if x.startswith('header:'): + self.outputs.append(self.inputs[0].parent.find_or_declare(x.replace('header:', ''))) + return super(cython, self).runnable_status() + + def post_run(self): + for x in self.outputs: + if x.name.endswith('.h'): + if not x.exists(): + if Logs.verbose: + Logs.warn('Expected %r', x.abspath()) + x.write('') + return Task.Task.post_run(self) + + def scan(self): + """ + Return the dependent files (.pxd) by looking in the include folders. + Put the headers to generate in the custom list "bld.raw_deps". + To inspect the scanne results use:: + + $ waf clean build --zones=deps + """ + node = self.inputs[0] + txt = node.read() + + mods = set() + for m in re_cyt.finditer(txt): + if m.group(1): # matches "from foo import bar" + mods.add(m.group(1)) + else: + mods.add(m.group(2)) + + Logs.debug('cython: mods %r', mods) + incs = getattr(self.generator, 'cython_includes', []) + incs = [self.generator.path.find_dir(x) for x in incs] + incs.append(node.parent) + + found = [] + missing = [] + for x in sorted(mods): + for y in incs: + k = y.find_resource(x + '.pxd') + if k: + found.append(k) + break + else: + missing.append(x) + + # the cython file implicitly depends on a pxd file that might be present + implicit = node.parent.find_resource(node.name[:-3] + 'pxd') + if implicit: + found.append(implicit) + + Logs.debug('cython: found %r', found) + + # Now the .h created - store them in bld.raw_deps for later use + has_api = False + has_public = False + for l in txt.splitlines(): + if cy_api_pat.match(l): + if ' api ' in l: + has_api = True + if ' public ' in l: + has_public = True + name = node.name.replace('.pyx', '') + if has_api: + missing.append('header:%s_api.h' % name) + if has_public: + missing.append('header:%s.h' % name) + + return (found, missing) + +def options(ctx): + ctx.add_option('--cython-flags', action='store', default='', help='space separated list of flags to pass to cython') + +def configure(ctx): + if not ctx.env.CC and not ctx.env.CXX: + ctx.fatal('Load a C/C++ compiler first') + if not ctx.env.PYTHON: + ctx.fatal('Load the python tool first!') + ctx.find_program('cython', var='CYTHON') + if hasattr(ctx.options, 'cython_flags'): + ctx.env.CYTHONFLAGS = ctx.options.cython_flags + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/dcc.py b/ldb-2.0.8/third_party/waf/waflib/extras/dcc.py new file mode 100644 index 0000000..c1a57c0 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/dcc.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Jérôme Carretero, 2011 (zougloub) + +from waflib import Options +from waflib.Tools import ccroot +from waflib.Configure import conf + +@conf +def find_dcc(conf): + conf.find_program(['dcc'], var='CC', path_list=getattr(Options.options, 'diabbindir', "")) + conf.env.CC_NAME = 'dcc' + +@conf +def find_dld(conf): + conf.find_program(['dld'], var='LINK_CC', path_list=getattr(Options.options, 'diabbindir', "")) + conf.env.LINK_CC_NAME = 'dld' + +@conf +def find_dar(conf): + conf.find_program(['dar'], var='AR', path_list=getattr(Options.options, 'diabbindir', "")) + conf.env.AR_NAME = 'dar' + conf.env.ARFLAGS = 'rcs' + +@conf +def find_ddump(conf): + conf.find_program(['ddump'], var='DDUMP', path_list=getattr(Options.options, 'diabbindir', "")) + +@conf +def dcc_common_flags(conf): + v = conf.env + v['CC_SRC_F'] = [] + v['CC_TGT_F'] = ['-c', '-o'] + + # linker + if not v['LINK_CC']: + v['LINK_CC'] = v['CC'] + v['CCLNK_SRC_F'] = [] + v['CCLNK_TGT_F'] = ['-o'] + v['CPPPATH_ST'] = '-I%s' + v['DEFINES_ST'] = '-D%s' + + v['LIB_ST'] = '-l:%s' # template for adding libs + v['LIBPATH_ST'] = '-L%s' # template for adding libpaths + v['STLIB_ST'] = '-l:%s' + v['STLIBPATH_ST'] = '-L%s' + v['RPATH_ST'] = '-Wl,-rpath,%s' + #v['STLIB_MARKER'] = '-Wl,-Bstatic' + + # program + v['cprogram_PATTERN'] = '%s.elf' + + # static lib + v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic'] + v['cstlib_PATTERN'] = 'lib%s.a' + +def configure(conf): + conf.find_dcc() + conf.find_dar() + conf.find_dld() + conf.find_ddump() + conf.dcc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + +def options(opt): + """ + Add the ``--with-diab-bindir`` command-line options. + """ + opt.add_option('--with-diab-bindir', type='string', dest='diabbindir', help = 'Specify alternate diab bin folder', default="") + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/distnet.py b/ldb-2.0.8/third_party/waf/waflib/extras/distnet.py new file mode 100644 index 0000000..ff3ed8e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/distnet.py @@ -0,0 +1,430 @@ +#! /usr/bin/env python +# encoding: utf-8 + +""" +waf-powered distributed network builds, with a network cache. + +Caching files from a server has advantages over a NFS/Samba shared folder: + +- builds are much faster because they use local files +- builds just continue to work in case of a network glitch +- permissions are much simpler to manage +""" + +import os, urllib, tarfile, re, shutil, tempfile, sys +from collections import OrderedDict +from waflib import Context, Utils, Logs + +try: + from urllib.parse import urlencode +except ImportError: + urlencode = urllib.urlencode + +def safe_urlencode(data): + x = urlencode(data) + try: + x = x.encode('utf-8') + except Exception: + pass + return x + +try: + from urllib.error import URLError +except ImportError: + from urllib2 import URLError + +try: + from urllib.request import Request, urlopen +except ImportError: + from urllib2 import Request, urlopen + +DISTNETCACHE = os.environ.get('DISTNETCACHE', '/tmp/distnetcache') +DISTNETSERVER = os.environ.get('DISTNETSERVER', 'http://localhost:8000/cgi-bin/') +TARFORMAT = 'w:bz2' +TIMEOUT = 60 +REQUIRES = 'requires.txt' + +re_com = re.compile(r'\s*#.*', re.M) + +def total_version_order(num): + lst = num.split('.') + template = '%10s' * len(lst) + ret = template % tuple(lst) + return ret + +def get_distnet_cache(): + return getattr(Context.g_module, 'DISTNETCACHE', DISTNETCACHE) + +def get_server_url(): + return getattr(Context.g_module, 'DISTNETSERVER', DISTNETSERVER) + +def get_download_url(): + return '%s/download.py' % get_server_url() + +def get_upload_url(): + return '%s/upload.py' % get_server_url() + +def get_resolve_url(): + return '%s/resolve.py' % get_server_url() + +def send_package_name(): + out = getattr(Context.g_module, 'out', 'build') + pkgfile = '%s/package_to_upload.tarfile' % out + return pkgfile + +class package(Context.Context): + fun = 'package' + cmd = 'package' + + def execute(self): + try: + files = self.files + except AttributeError: + files = self.files = [] + + Context.Context.execute(self) + pkgfile = send_package_name() + if not pkgfile in files: + if not REQUIRES in files: + files.append(REQUIRES) + self.make_tarfile(pkgfile, files, add_to_package=False) + + def make_tarfile(self, filename, files, **kw): + if kw.get('add_to_package', True): + self.files.append(filename) + + with tarfile.open(filename, TARFORMAT) as tar: + endname = os.path.split(filename)[-1] + endname = endname.split('.')[0] + '/' + for x in files: + tarinfo = tar.gettarinfo(x, x) + tarinfo.uid = tarinfo.gid = 0 + tarinfo.uname = tarinfo.gname = 'root' + tarinfo.size = os.stat(x).st_size + + # TODO - more archive creation options? + if kw.get('bare', True): + tarinfo.name = os.path.split(x)[1] + else: + tarinfo.name = endname + x # todo, if tuple, then.. + Logs.debug('distnet: adding %r to %s', tarinfo.name, filename) + with open(x, 'rb') as f: + tar.addfile(tarinfo, f) + Logs.info('Created %s', filename) + +class publish(Context.Context): + fun = 'publish' + cmd = 'publish' + def execute(self): + if hasattr(Context.g_module, 'publish'): + Context.Context.execute(self) + mod = Context.g_module + + rfile = getattr(self, 'rfile', send_package_name()) + if not os.path.isfile(rfile): + self.fatal('Create the release file with "waf release" first! %r' % rfile) + + fdata = Utils.readf(rfile, m='rb') + data = safe_urlencode([('pkgdata', fdata), ('pkgname', mod.APPNAME), ('pkgver', mod.VERSION)]) + + req = Request(get_upload_url(), data) + response = urlopen(req, timeout=TIMEOUT) + data = response.read().strip() + + if sys.hexversion>0x300000f: + data = data.decode('utf-8') + + if data != 'ok': + self.fatal('Could not publish the package %r' % data) + +class constraint(object): + def __init__(self, line=''): + self.required_line = line + self.info = [] + + line = line.strip() + if not line: + return + + lst = line.split(',') + if lst: + self.pkgname = lst[0] + self.required_version = lst[1] + for k in lst: + a, b, c = k.partition('=') + if a and c: + self.info.append((a, c)) + def __str__(self): + buf = [] + buf.append(self.pkgname) + buf.append(self.required_version) + for k in self.info: + buf.append('%s=%s' % k) + return ','.join(buf) + + def __repr__(self): + return "requires %s-%s" % (self.pkgname, self.required_version) + + def human_display(self, pkgname, pkgver): + return '%s-%s requires %s-%s' % (pkgname, pkgver, self.pkgname, self.required_version) + + def why(self): + ret = [] + for x in self.info: + if x[0] == 'reason': + ret.append(x[1]) + return ret + + def add_reason(self, reason): + self.info.append(('reason', reason)) + +def parse_constraints(text): + assert(text is not None) + constraints = [] + text = re.sub(re_com, '', text) + lines = text.splitlines() + for line in lines: + line = line.strip() + if not line: + continue + constraints.append(constraint(line)) + return constraints + +def list_package_versions(cachedir, pkgname): + pkgdir = os.path.join(cachedir, pkgname) + try: + versions = os.listdir(pkgdir) + except OSError: + return [] + versions.sort(key=total_version_order) + versions.reverse() + return versions + +class package_reader(Context.Context): + cmd = 'solver' + fun = 'solver' + + def __init__(self, **kw): + Context.Context.__init__(self, **kw) + + self.myproject = getattr(Context.g_module, 'APPNAME', 'project') + self.myversion = getattr(Context.g_module, 'VERSION', '1.0') + self.cache_constraints = {} + self.constraints = [] + + def compute_dependencies(self, filename=REQUIRES): + text = Utils.readf(filename) + data = safe_urlencode([('text', text)]) + + if '--offline' in sys.argv: + self.constraints = self.local_resolve(text) + else: + req = Request(get_resolve_url(), data) + try: + response = urlopen(req, timeout=TIMEOUT) + except URLError as e: + Logs.warn('The package server is down! %r', e) + self.constraints = self.local_resolve(text) + else: + ret = response.read() + try: + ret = ret.decode('utf-8') + except Exception: + pass + self.trace(ret) + self.constraints = parse_constraints(ret) + self.check_errors() + + def check_errors(self): + errors = False + for c in self.constraints: + if not c.required_version: + errors = True + + reasons = c.why() + if len(reasons) == 1: + Logs.error('%s but no matching package could be found in this repository', reasons[0]) + else: + Logs.error('Conflicts on package %r:', c.pkgname) + for r in reasons: + Logs.error(' %s', r) + if errors: + self.fatal('The package requirements cannot be satisfied!') + + def load_constraints(self, pkgname, pkgver, requires=REQUIRES): + try: + return self.cache_constraints[(pkgname, pkgver)] + except KeyError: + text = Utils.readf(os.path.join(get_distnet_cache(), pkgname, pkgver, requires)) + ret = parse_constraints(text) + self.cache_constraints[(pkgname, pkgver)] = ret + return ret + + def apply_constraint(self, domain, constraint): + vname = constraint.required_version.replace('*', '.*') + rev = re.compile(vname, re.M) + ret = [x for x in domain if rev.match(x)] + return ret + + def trace(self, *k): + if getattr(self, 'debug', None): + Logs.error(*k) + + def solve(self, packages_to_versions={}, packages_to_constraints={}, pkgname='', pkgver='', todo=[], done=[]): + # breadth first search + n_packages_to_versions = dict(packages_to_versions) + n_packages_to_constraints = dict(packages_to_constraints) + + self.trace("calling solve with %r %r %r" % (packages_to_versions, todo, done)) + done = done + [pkgname] + + constraints = self.load_constraints(pkgname, pkgver) + self.trace("constraints %r" % constraints) + + for k in constraints: + try: + domain = n_packages_to_versions[k.pkgname] + except KeyError: + domain = list_package_versions(get_distnet_cache(), k.pkgname) + + + self.trace("constraints?") + if not k.pkgname in done: + todo = todo + [k.pkgname] + + self.trace("domain before %s -> %s, %r" % (pkgname, k.pkgname, domain)) + + # apply the constraint + domain = self.apply_constraint(domain, k) + + self.trace("domain after %s -> %s, %r" % (pkgname, k.pkgname, domain)) + + n_packages_to_versions[k.pkgname] = domain + + # then store the constraint applied + constraints = list(packages_to_constraints.get(k.pkgname, [])) + constraints.append((pkgname, pkgver, k)) + n_packages_to_constraints[k.pkgname] = constraints + + if not domain: + self.trace("no domain while processing constraint %r from %r %r" % (domain, pkgname, pkgver)) + return (n_packages_to_versions, n_packages_to_constraints) + + # next package on the todo list + if not todo: + return (n_packages_to_versions, n_packages_to_constraints) + + n_pkgname = todo[0] + n_pkgver = n_packages_to_versions[n_pkgname][0] + tmp = dict(n_packages_to_versions) + tmp[n_pkgname] = [n_pkgver] + + self.trace("fixed point %s" % n_pkgname) + + return self.solve(tmp, n_packages_to_constraints, n_pkgname, n_pkgver, todo[1:], done) + + def get_results(self): + return '\n'.join([str(c) for c in self.constraints]) + + def solution_to_constraints(self, versions, constraints): + solution = [] + for p in versions: + c = constraint() + solution.append(c) + + c.pkgname = p + if versions[p]: + c.required_version = versions[p][0] + else: + c.required_version = '' + for (from_pkgname, from_pkgver, c2) in constraints.get(p, ''): + c.add_reason(c2.human_display(from_pkgname, from_pkgver)) + return solution + + def local_resolve(self, text): + self.cache_constraints[(self.myproject, self.myversion)] = parse_constraints(text) + p2v = OrderedDict({self.myproject: [self.myversion]}) + (versions, constraints) = self.solve(p2v, {}, self.myproject, self.myversion, []) + return self.solution_to_constraints(versions, constraints) + + def download_to_file(self, pkgname, pkgver, subdir, tmp): + data = safe_urlencode([('pkgname', pkgname), ('pkgver', pkgver), ('pkgfile', subdir)]) + req = urlopen(get_download_url(), data, timeout=TIMEOUT) + with open(tmp, 'wb') as f: + while True: + buf = req.read(8192) + if not buf: + break + f.write(buf) + + def extract_tar(self, subdir, pkgdir, tmpfile): + with tarfile.open(tmpfile) as f: + temp = tempfile.mkdtemp(dir=pkgdir) + try: + f.extractall(temp) + os.rename(temp, os.path.join(pkgdir, subdir)) + finally: + try: + shutil.rmtree(temp) + except Exception: + pass + + def get_pkg_dir(self, pkgname, pkgver, subdir): + pkgdir = os.path.join(get_distnet_cache(), pkgname, pkgver) + if not os.path.isdir(pkgdir): + os.makedirs(pkgdir) + + target = os.path.join(pkgdir, subdir) + + if os.path.exists(target): + return target + + (fd, tmp) = tempfile.mkstemp(dir=pkgdir) + try: + os.close(fd) + self.download_to_file(pkgname, pkgver, subdir, tmp) + if subdir == REQUIRES: + os.rename(tmp, target) + else: + self.extract_tar(subdir, pkgdir, tmp) + finally: + try: + os.remove(tmp) + except OSError: + pass + + return target + + def __iter__(self): + if not self.constraints: + self.compute_dependencies() + for x in self.constraints: + if x.pkgname == self.myproject: + continue + yield x + + def execute(self): + self.compute_dependencies() + +packages = package_reader() + +def load_tools(ctx, extra): + global packages + for c in packages: + packages.get_pkg_dir(c.pkgname, c.required_version, extra) + noarchdir = packages.get_pkg_dir(c.pkgname, c.required_version, 'noarch') + for x in os.listdir(noarchdir): + if x.startswith('waf_') and x.endswith('.py'): + ctx.load([x.rstrip('.py')], tooldir=[noarchdir]) + +def options(opt): + opt.add_option('--offline', action='store_true') + packages.execute() + load_tools(opt, REQUIRES) + +def configure(conf): + load_tools(conf, conf.variant) + +def build(bld): + load_tools(bld, bld.variant) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/doxygen.py b/ldb-2.0.8/third_party/waf/waflib/extras/doxygen.py new file mode 100644 index 0000000..20cd9e1 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/doxygen.py @@ -0,0 +1,235 @@ +#! /usr/bin/env python +# encoding: UTF-8 +# Thomas Nagy 2008-2010 (ita) + +""" + +Doxygen support + +Variables passed to bld(): +* doxyfile -- the Doxyfile to use +* doxy_tar -- destination archive for generated documentation (if desired) +* install_path -- where to install the documentation +* pars -- dictionary overriding doxygen configuration settings + +When using this tool, the wscript will look like: + + def options(opt): + opt.load('doxygen') + + def configure(conf): + conf.load('doxygen') + # check conf.env.DOXYGEN, if it is mandatory + + def build(bld): + if bld.env.DOXYGEN: + bld(features="doxygen", doxyfile='Doxyfile', ...) +""" + +import os, os.path, re +from collections import OrderedDict +from waflib import Task, Utils, Node +from waflib.TaskGen import feature + +DOXY_STR = '"${DOXYGEN}" - ' +DOXY_FMTS = 'html latex man rft xml'.split() +DOXY_FILE_PATTERNS = '*.' + ' *.'.join(''' +c cc cxx cpp c++ java ii ixx ipp i++ inl h hh hxx hpp h++ idl odl cs php php3 +inc m mm py f90c cc cxx cpp c++ java ii ixx ipp i++ inl h hh hxx +'''.split()) + +re_rl = re.compile('\\\\\r*\n', re.MULTILINE) +re_nl = re.compile('\r*\n', re.M) +def parse_doxy(txt): + ''' + Parses a doxygen file. + Returns an ordered dictionary. We cannot return a default dictionary, as the + order in which the entries are reported does matter, especially for the + '@INCLUDE' lines. + ''' + tbl = OrderedDict() + txt = re_rl.sub('', txt) + lines = re_nl.split(txt) + for x in lines: + x = x.strip() + if not x or x.startswith('#') or x.find('=') < 0: + continue + if x.find('+=') >= 0: + tmp = x.split('+=') + key = tmp[0].strip() + if key in tbl: + tbl[key] += ' ' + '+='.join(tmp[1:]).strip() + else: + tbl[key] = '+='.join(tmp[1:]).strip() + else: + tmp = x.split('=') + tbl[tmp[0].strip()] = '='.join(tmp[1:]).strip() + return tbl + +class doxygen(Task.Task): + vars = ['DOXYGEN', 'DOXYFLAGS'] + color = 'BLUE' + + def runnable_status(self): + ''' + self.pars are populated in runnable_status - because this function is being + run *before* both self.pars "consumers" - scan() and run() + + set output_dir (node) for the output + ''' + + for x in self.run_after: + if not x.hasrun: + return Task.ASK_LATER + + if not getattr(self, 'pars', None): + txt = self.inputs[0].read() + self.pars = parse_doxy(txt) + + # Override with any parameters passed to the task generator + if getattr(self.generator, 'pars', None): + for k, v in self.generator.pars.items(): + self.pars[k] = v + + if self.pars.get('OUTPUT_DIRECTORY'): + # Use the path parsed from the Doxyfile as an absolute path + output_node = self.inputs[0].parent.get_bld().make_node(self.pars['OUTPUT_DIRECTORY']) + else: + # If no OUTPUT_PATH was specified in the Doxyfile, build path from the Doxyfile name + '.doxy' + output_node = self.inputs[0].parent.get_bld().make_node(self.inputs[0].name + '.doxy') + output_node.mkdir() + self.pars['OUTPUT_DIRECTORY'] = output_node.abspath() + + self.doxy_inputs = getattr(self, 'doxy_inputs', []) + if not self.pars.get('INPUT'): + self.doxy_inputs.append(self.inputs[0].parent) + else: + for i in self.pars.get('INPUT').split(): + if os.path.isabs(i): + node = self.generator.bld.root.find_node(i) + else: + node = self.inputs[0].parent.find_node(i) + if not node: + self.generator.bld.fatal('Could not find the doxygen input %r' % i) + self.doxy_inputs.append(node) + + if not getattr(self, 'output_dir', None): + bld = self.generator.bld + # Output path is always an absolute path as it was transformed above. + self.output_dir = bld.root.find_dir(self.pars['OUTPUT_DIRECTORY']) + + self.signature() + ret = Task.Task.runnable_status(self) + if ret == Task.SKIP_ME: + # in case the files were removed + self.add_install() + return ret + + def scan(self): + exclude_patterns = self.pars.get('EXCLUDE_PATTERNS','').split() + exclude_patterns = [pattern.replace('*/', '**/') for pattern in exclude_patterns] + file_patterns = self.pars.get('FILE_PATTERNS','').split() + if not file_patterns: + file_patterns = DOXY_FILE_PATTERNS.split() + if self.pars.get('RECURSIVE') == 'YES': + file_patterns = ["**/%s" % pattern for pattern in file_patterns] + nodes = [] + names = [] + for node in self.doxy_inputs: + if os.path.isdir(node.abspath()): + for m in node.ant_glob(incl=file_patterns, excl=exclude_patterns): + nodes.append(m) + else: + nodes.append(node) + return (nodes, names) + + def run(self): + dct = self.pars.copy() + code = '\n'.join(['%s = %s' % (x, dct[x]) for x in self.pars]) + code = code.encode() # for python 3 + #fmt = DOXY_STR % (self.inputs[0].parent.abspath()) + cmd = Utils.subst_vars(DOXY_STR, self.env) + env = self.env.env or None + proc = Utils.subprocess.Popen(cmd, shell=True, stdin=Utils.subprocess.PIPE, env=env, cwd=self.inputs[0].parent.abspath()) + proc.communicate(code) + return proc.returncode + + def post_run(self): + nodes = self.output_dir.ant_glob('**/*', quiet=True) + for x in nodes: + self.generator.bld.node_sigs[x] = self.uid() + self.add_install() + return Task.Task.post_run(self) + + def add_install(self): + nodes = self.output_dir.ant_glob('**/*', quiet=True) + self.outputs += nodes + if getattr(self.generator, 'install_path', None): + if not getattr(self.generator, 'doxy_tar', None): + self.generator.add_install_files(install_to=self.generator.install_path, + install_from=self.outputs, + postpone=False, + cwd=self.output_dir, + relative_trick=True) + +class tar(Task.Task): + "quick tar creation" + run_str = '${TAR} ${TAROPTS} ${TGT} ${SRC}' + color = 'RED' + after = ['doxygen'] + def runnable_status(self): + for x in getattr(self, 'input_tasks', []): + if not x.hasrun: + return Task.ASK_LATER + + if not getattr(self, 'tar_done_adding', None): + # execute this only once + self.tar_done_adding = True + for x in getattr(self, 'input_tasks', []): + self.set_inputs(x.outputs) + if not self.inputs: + return Task.SKIP_ME + return Task.Task.runnable_status(self) + + def __str__(self): + tgt_str = ' '.join([a.path_from(a.ctx.launch_node()) for a in self.outputs]) + return '%s: %s\n' % (self.__class__.__name__, tgt_str) + +@feature('doxygen') +def process_doxy(self): + if not getattr(self, 'doxyfile', None): + self.bld.fatal('no doxyfile variable specified??') + + node = self.doxyfile + if not isinstance(node, Node.Node): + node = self.path.find_resource(node) + if not node: + self.bld.fatal('doxygen file %s not found' % self.doxyfile) + + # the task instance + dsk = self.create_task('doxygen', node) + + if getattr(self, 'doxy_tar', None): + tsk = self.create_task('tar') + tsk.input_tasks = [dsk] + tsk.set_outputs(self.path.find_or_declare(self.doxy_tar)) + if self.doxy_tar.endswith('bz2'): + tsk.env['TAROPTS'] = ['cjf'] + elif self.doxy_tar.endswith('gz'): + tsk.env['TAROPTS'] = ['czf'] + else: + tsk.env['TAROPTS'] = ['cf'] + if getattr(self, 'install_path', None): + self.add_install_files(install_to=self.install_path, install_from=tsk.outputs) + +def configure(conf): + ''' + Check if doxygen and tar commands are present in the system + + If the commands are present, then conf.env.DOXYGEN and conf.env.TAR + variables will be set. Detection can be controlled by setting DOXYGEN and + TAR environmental variables. + ''' + + conf.find_program('doxygen', var='DOXYGEN', mandatory=False) + conf.find_program('tar', var='TAR', mandatory=False) diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/dpapi.py b/ldb-2.0.8/third_party/waf/waflib/extras/dpapi.py new file mode 100644 index 0000000..b94d482 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/dpapi.py @@ -0,0 +1,87 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Matt Clarkson, 2012 + +''' +DPAPI access library (http://msdn.microsoft.com/en-us/library/ms995355.aspx) +This file uses code originally created by Crusher Joe: +http://article.gmane.org/gmane.comp.python.ctypes/420 +And modified by Wayne Koorts: +http://stackoverflow.com/questions/463832/using-dpapi-with-python +''' + +from ctypes import windll, byref, cdll, Structure, POINTER, c_char, c_buffer +from ctypes.wintypes import DWORD +from waflib.Configure import conf + +LocalFree = windll.kernel32.LocalFree +memcpy = cdll.msvcrt.memcpy +CryptProtectData = windll.crypt32.CryptProtectData +CryptUnprotectData = windll.crypt32.CryptUnprotectData +CRYPTPROTECT_UI_FORBIDDEN = 0x01 +try: + extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd'.encode('ascii') +except AttributeError: + extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd' + +class DATA_BLOB(Structure): + _fields_ = [ + ('cbData', DWORD), + ('pbData', POINTER(c_char)) + ] + +def get_data(blob_out): + cbData = int(blob_out.cbData) + pbData = blob_out.pbData + buffer = c_buffer(cbData) + memcpy(buffer, pbData, cbData) + LocalFree(pbData) + return buffer.raw + +@conf +def dpapi_encrypt_data(self, input_bytes, entropy = extra_entropy): + ''' + Encrypts data and returns byte string + + :param input_bytes: The data to be encrypted + :type input_bytes: String or Bytes + :param entropy: Extra entropy to add to the encryption process (optional) + :type entropy: String or Bytes + ''' + if not isinstance(input_bytes, bytes) or not isinstance(entropy, bytes): + self.fatal('The inputs to dpapi must be bytes') + buffer_in = c_buffer(input_bytes, len(input_bytes)) + buffer_entropy = c_buffer(entropy, len(entropy)) + blob_in = DATA_BLOB(len(input_bytes), buffer_in) + blob_entropy = DATA_BLOB(len(entropy), buffer_entropy) + blob_out = DATA_BLOB() + + if CryptProtectData(byref(blob_in), 'python_data', byref(blob_entropy), + None, None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)): + return get_data(blob_out) + else: + self.fatal('Failed to decrypt data') + +@conf +def dpapi_decrypt_data(self, encrypted_bytes, entropy = extra_entropy): + ''' + Decrypts data and returns byte string + + :param encrypted_bytes: The encrypted data + :type encrypted_bytes: Bytes + :param entropy: Extra entropy to add to the encryption process (optional) + :type entropy: String or Bytes + ''' + if not isinstance(encrypted_bytes, bytes) or not isinstance(entropy, bytes): + self.fatal('The inputs to dpapi must be bytes') + buffer_in = c_buffer(encrypted_bytes, len(encrypted_bytes)) + buffer_entropy = c_buffer(entropy, len(entropy)) + blob_in = DATA_BLOB(len(encrypted_bytes), buffer_in) + blob_entropy = DATA_BLOB(len(entropy), buffer_entropy) + blob_out = DATA_BLOB() + if CryptUnprotectData(byref(blob_in), None, byref(blob_entropy), None, + None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)): + return get_data(blob_out) + else: + self.fatal('Failed to decrypt data') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/eclipse.py b/ldb-2.0.8/third_party/waf/waflib/extras/eclipse.py new file mode 100644 index 0000000..bb78741 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/eclipse.py @@ -0,0 +1,431 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Eclipse CDT 5.0 generator for Waf +# Richard Quirk 2009-1011 (New BSD License) +# Thomas Nagy 2011 (ported to Waf 1.6) + +""" +Usage: + +def options(opt): + opt.load('eclipse') + +$ waf configure eclipse +""" + +import sys, os +from waflib import Utils, Logs, Context, Build, TaskGen, Scripting, Errors, Node +from xml.dom.minidom import Document + +STANDARD_INCLUDES = [ '/usr/local/include', '/usr/include' ] + +oe_cdt = 'org.eclipse.cdt' +cdt_mk = oe_cdt + '.make.core' +cdt_core = oe_cdt + '.core' +cdt_bld = oe_cdt + '.build.core' +extbuilder_dir = '.externalToolBuilders' +extbuilder_name = 'Waf_Builder.launch' + +class eclipse(Build.BuildContext): + cmd = 'eclipse' + fun = Scripting.default_cmd + + def execute(self): + """ + Entry point + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + + appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) + self.create_cproject(appname, pythonpath=self.env['ECLIPSE_PYTHON_PATH']) + + # Helper to dump the XML document content to XML with UTF-8 encoding + def write_conf_to_xml(self, filename, document): + self.srcnode.make_node(filename).write(document.toprettyxml(encoding='UTF-8'), flags='wb') + + def create_cproject(self, appname, workspace_includes=[], pythonpath=[]): + """ + Create the Eclipse CDT .project and .cproject files + @param appname The name that will appear in the Project Explorer + @param build The BuildContext object to extract includes from + @param workspace_includes Optional project includes to prevent + "Unresolved Inclusion" errors in the Eclipse editor + @param pythonpath Optional project specific python paths + """ + hasc = hasjava = haspython = False + source_dirs = [] + cpppath = self.env['CPPPATH'] + javasrcpath = [] + javalibpath = [] + includes = STANDARD_INCLUDES + if sys.platform != 'win32': + cc = self.env.CC or self.env.CXX + if cc: + cmd = cc + ['-xc++', '-E', '-Wp,-v', '-'] + try: + gccout = self.cmd_and_log(cmd, output=Context.STDERR, quiet=Context.BOTH, input='\n'.encode()).splitlines() + except Errors.WafError: + pass + else: + includes = [] + for ipath in gccout: + if ipath.startswith(' /'): + includes.append(ipath[1:]) + cpppath += includes + Logs.warn('Generating Eclipse CDT project files') + + for g in self.groups: + for tg in g: + if not isinstance(tg, TaskGen.task_gen): + continue + + tg.post() + + # Add local Python modules paths to configuration so object resolving will work in IDE + # This may also contain generated files (ie. pyqt5 or protoc) that get picked from build + if 'py' in tg.features: + pypath = tg.path.relpath() + py_installfrom = getattr(tg, 'install_from', None) + if isinstance(py_installfrom, Node.Node): + pypath = py_installfrom.path_from(self.root.make_node(self.top_dir)) + if pypath not in pythonpath: + pythonpath.append(pypath) + haspython = True + + # Add Java source directories so object resolving works in IDE + # This may also contain generated files (ie. protoc) that get picked from build + if 'javac' in tg.features: + java_src = tg.path.relpath() + java_srcdir = getattr(tg.javac_task, 'srcdir', None) + if java_srcdir: + if isinstance(java_srcdir, Node.Node): + java_srcdir = [java_srcdir] + for x in Utils.to_list(java_srcdir): + x = x.path_from(self.root.make_node(self.top_dir)) + if x not in javasrcpath: + javasrcpath.append(x) + else: + if java_src not in javasrcpath: + javasrcpath.append(java_src) + hasjava = True + + # Check if there are external dependencies and add them as external jar so they will be resolved by Eclipse + usedlibs=getattr(tg, 'use', []) + for x in Utils.to_list(usedlibs): + for cl in Utils.to_list(tg.env['CLASSPATH_'+x]): + if cl not in javalibpath: + javalibpath.append(cl) + + if not getattr(tg, 'link_task', None): + continue + + features = Utils.to_list(getattr(tg, 'features', '')) + + is_cc = 'c' in features or 'cxx' in features + + incnodes = tg.to_incnodes(tg.to_list(getattr(tg, 'includes', [])) + tg.env['INCLUDES']) + for p in incnodes: + path = p.path_from(self.srcnode) + + if (path.startswith("/")): + cpppath.append(path) + else: + workspace_includes.append(path) + + if is_cc and path not in source_dirs: + source_dirs.append(path) + + hasc = True + + waf_executable = os.path.abspath(sys.argv[0]) + project = self.impl_create_project(sys.executable, appname, hasc, hasjava, haspython, waf_executable) + self.write_conf_to_xml('.project', project) + + if hasc: + project = self.impl_create_cproject(sys.executable, waf_executable, appname, workspace_includes, cpppath, source_dirs) + self.write_conf_to_xml('.cproject', project) + + if haspython: + project = self.impl_create_pydevproject(sys.path, pythonpath) + self.write_conf_to_xml('.pydevproject', project) + + if hasjava: + project = self.impl_create_javaproject(javasrcpath, javalibpath) + self.write_conf_to_xml('.classpath', project) + + def impl_create_project(self, executable, appname, hasc, hasjava, haspython, waf_executable): + doc = Document() + projectDescription = doc.createElement('projectDescription') + self.add(doc, projectDescription, 'name', appname) + self.add(doc, projectDescription, 'comment') + self.add(doc, projectDescription, 'projects') + buildSpec = self.add(doc, projectDescription, 'buildSpec') + buildCommand = self.add(doc, buildSpec, 'buildCommand') + self.add(doc, buildCommand, 'triggers', 'clean,full,incremental,') + arguments = self.add(doc, buildCommand, 'arguments') + dictionaries = {} + + # If CDT is present, instruct this one to call waf as it is more flexible (separate build/clean ...) + if hasc: + self.add(doc, buildCommand, 'name', oe_cdt + '.managedbuilder.core.genmakebuilder') + # the default make-style targets are overwritten by the .cproject values + dictionaries = { + cdt_mk + '.contents': cdt_mk + '.activeConfigSettings', + cdt_mk + '.enableAutoBuild': 'false', + cdt_mk + '.enableCleanBuild': 'true', + cdt_mk + '.enableFullBuild': 'true', + } + else: + # Otherwise for Java/Python an external builder tool is created that will call waf build + self.add(doc, buildCommand, 'name', 'org.eclipse.ui.externaltools.ExternalToolBuilder') + dictionaries = { + 'LaunchConfigHandle': '/%s/%s'%(extbuilder_dir, extbuilder_name), + } + # The definition is in a separate directory XML file + try: + os.mkdir(extbuilder_dir) + except OSError: + pass # Ignore error if already exists + + # Populate here the external builder XML calling waf + builder = Document() + launchConfiguration = doc.createElement('launchConfiguration') + launchConfiguration.setAttribute('type', 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType') + self.add(doc, launchConfiguration, 'booleanAttribute', {'key': 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'false'}) + self.add(doc, launchConfiguration, 'booleanAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED', 'value': 'true'}) + self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': waf_executable}) + self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'full,incremental,'}) + self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': 'build'}) + self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': '${project_loc}'}) + builder.appendChild(launchConfiguration) + # And write the XML to the file references before + self.write_conf_to_xml('%s%s%s'%(extbuilder_dir, os.path.sep, extbuilder_name), builder) + + + for k, v in dictionaries.items(): + self.addDictionary(doc, arguments, k, v) + + natures = self.add(doc, projectDescription, 'natures') + + if hasc: + nature_list = """ + core.ccnature + managedbuilder.core.ScannerConfigNature + managedbuilder.core.managedBuildNature + core.cnature + """.split() + for n in nature_list: + self.add(doc, natures, 'nature', oe_cdt + '.' + n) + + if haspython: + self.add(doc, natures, 'nature', 'org.python.pydev.pythonNature') + if hasjava: + self.add(doc, natures, 'nature', 'org.eclipse.jdt.core.javanature') + + doc.appendChild(projectDescription) + return doc + + def impl_create_cproject(self, executable, waf_executable, appname, workspace_includes, cpppath, source_dirs=[]): + doc = Document() + doc.appendChild(doc.createProcessingInstruction('fileVersion', '4.0.0')) + cconf_id = cdt_core + '.default.config.1' + cproject = doc.createElement('cproject') + storageModule = self.add(doc, cproject, 'storageModule', + {'moduleId': cdt_core + '.settings'}) + cconf = self.add(doc, storageModule, 'cconfiguration', {'id':cconf_id}) + + storageModule = self.add(doc, cconf, 'storageModule', + {'buildSystemId': oe_cdt + '.managedbuilder.core.configurationDataProvider', + 'id': cconf_id, + 'moduleId': cdt_core + '.settings', + 'name': 'Default'}) + + self.add(doc, storageModule, 'externalSettings') + + extensions = self.add(doc, storageModule, 'extensions') + extension_list = """ + VCErrorParser + MakeErrorParser + GCCErrorParser + GASErrorParser + GLDErrorParser + """.split() + self.add(doc, extensions, 'extension', {'id': cdt_core + '.ELF', 'point':cdt_core + '.BinaryParser'}) + for e in extension_list: + self.add(doc, extensions, 'extension', {'id': cdt_core + '.' + e, 'point':cdt_core + '.ErrorParser'}) + + storageModule = self.add(doc, cconf, 'storageModule', + {'moduleId': 'cdtBuildSystem', 'version': '4.0.0'}) + config = self.add(doc, storageModule, 'configuration', + {'artifactName': appname, + 'id': cconf_id, + 'name': 'Default', + 'parent': cdt_bld + '.prefbase.cfg'}) + folderInfo = self.add(doc, config, 'folderInfo', + {'id': cconf_id+'.', 'name': '/', 'resourcePath': ''}) + + toolChain = self.add(doc, folderInfo, 'toolChain', + {'id': cdt_bld + '.prefbase.toolchain.1', + 'name': 'No ToolChain', + 'resourceTypeBasedDiscovery': 'false', + 'superClass': cdt_bld + '.prefbase.toolchain'}) + + self.add(doc, toolChain, 'targetPlatform', {'binaryParser': 'org.eclipse.cdt.core.ELF', 'id': cdt_bld + '.prefbase.toolchain.1', 'name': ''}) + + waf_build = '"%s" %s'%(waf_executable, eclipse.fun) + waf_clean = '"%s" clean'%(waf_executable) + self.add(doc, toolChain, 'builder', + {'autoBuildTarget': waf_build, + 'command': executable, + 'enableAutoBuild': 'false', + 'cleanBuildTarget': waf_clean, + 'enableIncrementalBuild': 'true', + 'id': cdt_bld + '.settings.default.builder.1', + 'incrementalBuildTarget': waf_build, + 'managedBuildOn': 'false', + 'name': 'Gnu Make Builder', + 'superClass': cdt_bld + '.settings.default.builder'}) + + tool_index = 1; + for tool_name in ("Assembly", "GNU C++", "GNU C"): + tool = self.add(doc, toolChain, 'tool', + {'id': cdt_bld + '.settings.holder.' + str(tool_index), + 'name': tool_name, + 'superClass': cdt_bld + '.settings.holder'}) + if cpppath or workspace_includes: + incpaths = cdt_bld + '.settings.holder.incpaths' + option = self.add(doc, tool, 'option', + {'id': incpaths + '.' + str(tool_index), + 'name': 'Include Paths', + 'superClass': incpaths, + 'valueType': 'includePath'}) + for i in workspace_includes: + self.add(doc, option, 'listOptionValue', + {'builtIn': 'false', + 'value': '"${workspace_loc:/%s/%s}"'%(appname, i)}) + for i in cpppath: + self.add(doc, option, 'listOptionValue', + {'builtIn': 'false', + 'value': '"%s"'%(i)}) + if tool_name == "GNU C++" or tool_name == "GNU C": + self.add(doc,tool,'inputType',{ 'id':'org.eclipse.cdt.build.core.settings.holder.inType.' + str(tool_index), \ + 'languageId':'org.eclipse.cdt.core.gcc' if tool_name == "GNU C" else 'org.eclipse.cdt.core.g++','languageName':tool_name, \ + 'sourceContentType':'org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader', \ + 'superClass':'org.eclipse.cdt.build.core.settings.holder.inType' }) + tool_index += 1 + + if source_dirs: + sourceEntries = self.add(doc, config, 'sourceEntries') + for i in source_dirs: + self.add(doc, sourceEntries, 'entry', + {'excluding': i, + 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', + 'kind': 'sourcePath', + 'name': ''}) + self.add(doc, sourceEntries, 'entry', + { + 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', + 'kind': 'sourcePath', + 'name': i}) + + storageModule = self.add(doc, cconf, 'storageModule', + {'moduleId': cdt_mk + '.buildtargets'}) + buildTargets = self.add(doc, storageModule, 'buildTargets') + def addTargetWrap(name, runAll): + return self.addTarget(doc, buildTargets, executable, name, + '"%s" %s'%(waf_executable, name), runAll) + addTargetWrap('configure', True) + addTargetWrap('dist', False) + addTargetWrap('install', False) + addTargetWrap('check', False) + + storageModule = self.add(doc, cproject, 'storageModule', + {'moduleId': 'cdtBuildSystem', + 'version': '4.0.0'}) + + self.add(doc, storageModule, 'project', {'id': '%s.null.1'%appname, 'name': appname}) + + doc.appendChild(cproject) + return doc + + def impl_create_pydevproject(self, system_path, user_path): + # create a pydevproject file + doc = Document() + doc.appendChild(doc.createProcessingInstruction('eclipse-pydev', 'version="1.0"')) + pydevproject = doc.createElement('pydev_project') + prop = self.add(doc, pydevproject, + 'pydev_property', + 'python %d.%d'%(sys.version_info[0], sys.version_info[1])) + prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_VERSION') + prop = self.add(doc, pydevproject, 'pydev_property', 'Default') + prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_INTERPRETER') + # add waf's paths + wafadmin = [p for p in system_path if p.find('wafadmin') != -1] + if wafadmin: + prop = self.add(doc, pydevproject, 'pydev_pathproperty', + {'name':'org.python.pydev.PROJECT_EXTERNAL_SOURCE_PATH'}) + for i in wafadmin: + self.add(doc, prop, 'path', i) + if user_path: + prop = self.add(doc, pydevproject, 'pydev_pathproperty', + {'name':'org.python.pydev.PROJECT_SOURCE_PATH'}) + for i in user_path: + self.add(doc, prop, 'path', '/${PROJECT_DIR_NAME}/'+i) + + doc.appendChild(pydevproject) + return doc + + def impl_create_javaproject(self, javasrcpath, javalibpath): + # create a .classpath file for java usage + doc = Document() + javaproject = doc.createElement('classpath') + if javasrcpath: + for i in javasrcpath: + self.add(doc, javaproject, 'classpathentry', + {'kind': 'src', 'path': i}) + + if javalibpath: + for i in javalibpath: + self.add(doc, javaproject, 'classpathentry', + {'kind': 'lib', 'path': i}) + + self.add(doc, javaproject, 'classpathentry', {'kind': 'con', 'path': 'org.eclipse.jdt.launching.JRE_CONTAINER'}) + self.add(doc, javaproject, 'classpathentry', {'kind': 'output', 'path': self.bldnode.name }) + doc.appendChild(javaproject) + return doc + + def addDictionary(self, doc, parent, k, v): + dictionary = self.add(doc, parent, 'dictionary') + self.add(doc, dictionary, 'key', k) + self.add(doc, dictionary, 'value', v) + return dictionary + + def addTarget(self, doc, buildTargets, executable, name, buildTarget, runAllBuilders=True): + target = self.add(doc, buildTargets, 'target', + {'name': name, + 'path': '', + 'targetID': oe_cdt + '.build.MakeTargetBuilder'}) + self.add(doc, target, 'buildCommand', executable) + self.add(doc, target, 'buildArguments', None) + self.add(doc, target, 'buildTarget', buildTarget) + self.add(doc, target, 'stopOnError', 'true') + self.add(doc, target, 'useDefaultCommand', 'false') + self.add(doc, target, 'runAllBuilders', str(runAllBuilders).lower()) + + def add(self, doc, parent, tag, value = None): + el = doc.createElement(tag) + if (value): + if type(value) == type(str()): + el.appendChild(doc.createTextNode(value)) + elif type(value) == type(dict()): + self.setAttributes(el, value) + parent.appendChild(el) + return el + + def setAttributes(self, node, attrs): + for k, v in attrs.items(): + node.setAttribute(k, v) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/erlang.py b/ldb-2.0.8/third_party/waf/waflib/extras/erlang.py new file mode 100644 index 0000000..0b93d9a --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/erlang.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010 (ita) +# Przemyslaw Rzepecki, 2016 + +""" +Erlang support +""" + +import re +from waflib import Task, TaskGen +from waflib.TaskGen import feature, after_method, before_method +# to load the method "to_incnodes" below +from waflib.Tools import ccroot + +# Those flags are required by the Erlang VM to execute/evaluate code in +# non-interactive mode. It is used in this tool to create Erlang modules +# documentation and run unit tests. The user can pass additional arguments to the +# 'erl' command with ERL_FLAGS environment variable. +EXEC_NON_INTERACTIVE = ['-noshell', '-noinput', '-eval'] + +def configure(conf): + conf.find_program('erlc', var='ERLC') + conf.find_program('erl', var='ERL') + conf.add_os_flags('ERLC_FLAGS') + conf.add_os_flags('ERL_FLAGS') + conf.env.ERLC_DEF_PATTERN = '-D%s' + conf.env.ERLC_INC_PATTERN = '-I%s' + +@TaskGen.extension('.erl') +def process_erl_node(self, node): + tsk = self.create_task('erl', node, node.change_ext('.beam')) + tsk.erlc_incnodes = [tsk.outputs[0].parent] + self.to_incnodes(self.includes) + tsk.env.append_value('ERLC_INCPATHS', [x.abspath() for x in tsk.erlc_incnodes]) + tsk.env.append_value('ERLC_DEFINES', self.to_list(getattr(self, 'defines', []))) + tsk.env.append_value('ERLC_FLAGS', self.to_list(getattr(self, 'flags', []))) + tsk.cwd = tsk.outputs[0].parent + +class erl(Task.Task): + color = 'GREEN' + run_str = '${ERLC} ${ERL_FLAGS} ${ERLC_INC_PATTERN:ERLC_INCPATHS} ${ERLC_DEF_PATTERN:ERLC_DEFINES} ${SRC}' + + def scan(task): + node = task.inputs[0] + + deps = [] + scanned = set([]) + nodes_to_scan = [node] + + for n in nodes_to_scan: + if n.abspath() in scanned: + continue + + for i in re.findall(r'-include\("(.*)"\)\.', n.read()): + for d in task.erlc_incnodes: + r = d.find_node(i) + if r: + deps.append(r) + nodes_to_scan.append(r) + break + scanned.add(n.abspath()) + + return (deps, []) + +@TaskGen.extension('.beam') +def process(self, node): + pass + + +class erl_test(Task.Task): + color = 'BLUE' + run_str = '${ERL} ${ERL_FLAGS} ${ERL_TEST_FLAGS}' + +@feature('eunit') +@after_method('process_source') +def add_erl_test_run(self): + test_modules = [t.outputs[0] for t in self.tasks] + test_task = self.create_task('erl_test') + test_task.set_inputs(self.source + test_modules) + test_task.cwd = test_modules[0].parent + + test_task.env.append_value('ERL_FLAGS', self.to_list(getattr(self, 'flags', []))) + + test_list = ", ".join([m.change_ext("").path_from(test_task.cwd)+":test()" for m in test_modules]) + test_flag = 'halt(case lists:all(fun(Elem) -> Elem == ok end, [%s]) of true -> 0; false -> 1 end).' % test_list + test_task.env.append_value('ERL_TEST_FLAGS', EXEC_NON_INTERACTIVE) + test_task.env.append_value('ERL_TEST_FLAGS', test_flag) + + +class edoc(Task.Task): + color = 'BLUE' + run_str = "${ERL} ${ERL_FLAGS} ${ERL_DOC_FLAGS}" + def keyword(self): + return 'Generating edoc' + +@feature('edoc') +@before_method('process_source') +def add_edoc_task(self): + # do not process source, it would create double erl->beam task + self.meths.remove('process_source') + e = self.path.find_resource(self.source) + t = e.change_ext('.html') + png = t.parent.make_node('erlang.png') + css = t.parent.make_node('stylesheet.css') + tsk = self.create_task('edoc', e, [t, png, css]) + tsk.cwd = tsk.outputs[0].parent + tsk.env.append_value('ERL_DOC_FLAGS', EXEC_NON_INTERACTIVE) + tsk.env.append_value('ERL_DOC_FLAGS', 'edoc:files(["%s"]), halt(0).' % tsk.inputs[0].abspath()) + # TODO the above can break if a file path contains '"' + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fast_partial.py b/ldb-2.0.8/third_party/waf/waflib/extras/fast_partial.py new file mode 100644 index 0000000..90a9472 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fast_partial.py @@ -0,0 +1,531 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2017-2018 (ita) + +""" +A system for fast partial rebuilds + +Creating a large amount of task objects up front can take some time. +By making a few assumptions, it is possible to avoid posting creating +task objects for targets that are already up-to-date. + +On a silly benchmark the gain observed for 1M tasks can be 5m->10s +for a single file change. + +Usage:: + + def options(opt): + opt.load('fast_partial') + +Assumptions: +* Start with a clean build (run "waf distclean" after enabling) +* Mostly for C/C++/Fortran targets with link tasks (object-only targets are not handled) + try it in the folder generated by utils/genbench.py +* For full project builds: no --targets and no pruning from subfolders +* The installation phase is ignored +* `use=` dependencies are specified up front even across build groups +* Task generator source files are not obtained from globs + +Implementation details: +* The first layer obtains file timestamps to recalculate file hashes only + when necessary (similar to md5_tstamp); the timestamps are then stored + in a dedicated pickle file +* A second layer associates each task generator to a file set to help + detecting changes. Task generators are to create their tasks only when + the related files have been modified. A specific db file is created + to store such data (5m -> 1m10) +* A third layer binds build context proxies onto task generators, replacing + the default context. While loading data for the full build uses more memory + (4GB -> 9GB), partial builds are then much faster (1m10 -> 13s) +* A fourth layer enables a 2-level cache on file signatures to + reduce the size of the main pickle file (13s -> 10s) +""" + +import os +from waflib import Build, Context, Errors, Logs, Task, TaskGen, Utils +from waflib.TaskGen import feature, after_method, taskgen_method +import waflib.Node + +DONE = 0 +DIRTY = 1 +NEEDED = 2 + +SKIPPABLE = ['cshlib', 'cxxshlib', 'cstlib', 'cxxstlib', 'cprogram', 'cxxprogram'] + +TSTAMP_DB = '.wafpickle_tstamp_db_file' + +SAVED_ATTRS = 'root node_sigs task_sigs imp_sigs raw_deps node_deps'.split() + +class bld_proxy(object): + def __init__(self, bld): + object.__setattr__(self, 'bld', bld) + + object.__setattr__(self, 'node_class', type('Nod3', (waflib.Node.Node,), {})) + self.node_class.__module__ = 'waflib.Node' + self.node_class.ctx = self + + object.__setattr__(self, 'root', self.node_class('', None)) + for x in SAVED_ATTRS: + if x != 'root': + object.__setattr__(self, x, {}) + + self.fix_nodes() + + def __setattr__(self, name, value): + bld = object.__getattribute__(self, 'bld') + setattr(bld, name, value) + + def __delattr__(self, name): + bld = object.__getattribute__(self, 'bld') + delattr(bld, name) + + def __getattribute__(self, name): + try: + return object.__getattribute__(self, name) + except AttributeError: + bld = object.__getattribute__(self, 'bld') + return getattr(bld, name) + + def __call__(self, *k, **kw): + return self.bld(*k, **kw) + + def fix_nodes(self): + for x in ('srcnode', 'path', 'bldnode'): + node = self.root.find_dir(getattr(self.bld, x).abspath()) + object.__setattr__(self, x, node) + + def set_key(self, store_key): + object.__setattr__(self, 'store_key', store_key) + + def fix_tg_path(self, *tgs): + # changing Node objects on task generators is possible + # yet, all Node objects must belong to the same parent + for tg in tgs: + tg.path = self.root.make_node(tg.path.abspath()) + + def restore(self): + dbfn = os.path.join(self.variant_dir, Context.DBFILE + self.store_key) + Logs.debug('rev_use: reading %s', dbfn) + try: + data = Utils.readf(dbfn, 'rb') + except (EnvironmentError, EOFError): + # handle missing file/empty file + Logs.debug('rev_use: Could not load the build cache %s (missing)', dbfn) + else: + try: + waflib.Node.pickle_lock.acquire() + waflib.Node.Nod3 = self.node_class + try: + data = Build.cPickle.loads(data) + except Exception as e: + Logs.debug('rev_use: Could not pickle the build cache %s: %r', dbfn, e) + else: + for x in SAVED_ATTRS: + object.__setattr__(self, x, data.get(x, {})) + finally: + waflib.Node.pickle_lock.release() + self.fix_nodes() + + def store(self): + data = {} + for x in Build.SAVED_ATTRS: + data[x] = getattr(self, x) + db = os.path.join(self.variant_dir, Context.DBFILE + self.store_key) + + with waflib.Node.pickle_lock: + waflib.Node.Nod3 = self.node_class + try: + x = Build.cPickle.dumps(data, Build.PROTOCOL) + except Build.cPickle.PicklingError: + root = data['root'] + for node_deps in data['node_deps'].values(): + for idx, node in enumerate(node_deps): + # there may be more cross-context Node objects to fix, + # but this should be the main source + node_deps[idx] = root.find_node(node.abspath()) + x = Build.cPickle.dumps(data, Build.PROTOCOL) + + Logs.debug('rev_use: storing %s', db) + Utils.writef(db + '.tmp', x, m='wb') + try: + st = os.stat(db) + os.remove(db) + if not Utils.is_win32: + os.chown(db + '.tmp', st.st_uid, st.st_gid) + except (AttributeError, OSError): + pass + os.rename(db + '.tmp', db) + +class bld(Build.BuildContext): + def __init__(self, **kw): + super(bld, self).__init__(**kw) + self.hashes_md5_tstamp = {} + + def __call__(self, *k, **kw): + # this is one way of doing it, one could use a task generator method too + bld = kw['bld'] = bld_proxy(self) + ret = TaskGen.task_gen(*k, **kw) + self.task_gen_cache_names = {} + self.add_to_group(ret, group=kw.get('group')) + ret.bld = bld + bld.set_key(ret.path.abspath().replace(os.sep, '') + str(ret.idx)) + return ret + + def is_dirty(self): + return True + + def store_tstamps(self): + # Called after a build is finished + # For each task generator, record all files involved in task objects + # optimization: done only if there was something built + do_store = False + try: + f_deps = self.f_deps + except AttributeError: + f_deps = self.f_deps = {} + self.f_tstamps = {} + + allfiles = set() + for g in self.groups: + for tg in g: + try: + staleness = tg.staleness + except AttributeError: + staleness = DIRTY + + if staleness != DIRTY: + # DONE case: there was nothing built + # NEEDED case: the tg was brought in because of 'use' propagation + # but nothing really changed for them, there may be incomplete + # tasks (object files) and in this case it is best to let the next build + # figure out if an input/output file changed + continue + + do_cache = False + for tsk in tg.tasks: + if tsk.hasrun == Task.SUCCESS: + do_cache = True + pass + elif tsk.hasrun == Task.SKIPPED: + pass + else: + # one failed task, clear the cache for this tg + try: + del f_deps[(tg.path.abspath(), tg.idx)] + except KeyError: + pass + else: + # just store the new state because there is a change + do_store = True + + # skip the rest because there is no valid cache possible + break + else: + if not do_cache: + # all skipped, but is there anything in cache? + try: + f_deps[(tg.path.abspath(), tg.idx)] + except KeyError: + # probably cleared because a wscript file changed + # store it + do_cache = True + + if do_cache: + + # there was a rebuild, store the data structure too + tg.bld.store() + + # all tasks skipped but no cache + # or a successful task build + do_store = True + st = set() + for tsk in tg.tasks: + st.update(tsk.inputs) + st.update(self.node_deps.get(tsk.uid(), [])) + + # TODO do last/when loading the tgs? + lst = [] + for k in ('wscript', 'wscript_build'): + n = tg.path.find_node(k) + if n: + n.get_bld_sig() + lst.append(n.abspath()) + + lst.extend(sorted(x.abspath() for x in st)) + allfiles.update(lst) + f_deps[(tg.path.abspath(), tg.idx)] = lst + + for x in allfiles: + # f_tstamps has everything, while md5_tstamp can be relatively empty on partial builds + self.f_tstamps[x] = self.hashes_md5_tstamp[x][0] + + if do_store: + dbfn = os.path.join(self.variant_dir, TSTAMP_DB) + Logs.debug('rev_use: storing %s', dbfn) + dbfn_tmp = dbfn + '.tmp' + x = Build.cPickle.dumps([self.f_tstamps, f_deps], Build.PROTOCOL) + Utils.writef(dbfn_tmp, x, m='wb') + os.rename(dbfn_tmp, dbfn) + Logs.debug('rev_use: stored %s', dbfn) + + def store(self): + self.store_tstamps() + if self.producer.dirty: + Build.BuildContext.store(self) + + def compute_needed_tgs(self): + # assume the 'use' keys are not modified during the build phase + + dbfn = os.path.join(self.variant_dir, TSTAMP_DB) + Logs.debug('rev_use: Loading %s', dbfn) + try: + data = Utils.readf(dbfn, 'rb') + except (EnvironmentError, EOFError): + Logs.debug('rev_use: Could not load the build cache %s (missing)', dbfn) + self.f_deps = {} + self.f_tstamps = {} + else: + try: + self.f_tstamps, self.f_deps = Build.cPickle.loads(data) + except Exception as e: + Logs.debug('rev_use: Could not pickle the build cache %s: %r', dbfn, e) + self.f_deps = {} + self.f_tstamps = {} + else: + Logs.debug('rev_use: Loaded %s', dbfn) + + + # 1. obtain task generators that contain rebuilds + # 2. obtain the 'use' graph and its dual + stales = set() + reverse_use_map = Utils.defaultdict(list) + use_map = Utils.defaultdict(list) + + for g in self.groups: + for tg in g: + if tg.is_stale(): + stales.add(tg) + + try: + lst = tg.use = Utils.to_list(tg.use) + except AttributeError: + pass + else: + for x in lst: + try: + xtg = self.get_tgen_by_name(x) + except Errors.WafError: + pass + else: + use_map[tg].append(xtg) + reverse_use_map[xtg].append(tg) + + Logs.debug('rev_use: found %r stale tgs', len(stales)) + + # 3. dfs to post downstream tg as stale + visited = set() + def mark_down(tg): + if tg in visited: + return + visited.add(tg) + Logs.debug('rev_use: marking down %r as stale', tg.name) + tg.staleness = DIRTY + for x in reverse_use_map[tg]: + mark_down(x) + for tg in stales: + mark_down(tg) + + # 4. dfs to find ancestors tg to mark as needed + self.needed_tgs = needed_tgs = set() + def mark_needed(tg): + if tg in needed_tgs: + return + needed_tgs.add(tg) + if tg.staleness == DONE: + Logs.debug('rev_use: marking up %r as needed', tg.name) + tg.staleness = NEEDED + for x in use_map[tg]: + mark_needed(x) + for xx in visited: + mark_needed(xx) + + # so we have the whole tg trees to post in the set "needed" + # load their build trees + for tg in needed_tgs: + tg.bld.restore() + tg.bld.fix_tg_path(tg) + + # the stale ones should be fully build, while the needed ones + # may skip a few tasks, see create_compiled_task and apply_link_after below + Logs.debug('rev_use: amount of needed task gens: %r', len(needed_tgs)) + + def post_group(self): + # assumption: we can ignore the folder/subfolders cuts + def tgpost(tg): + try: + f = tg.post + except AttributeError: + pass + else: + f() + + if not self.targets or self.targets == '*': + for tg in self.groups[self.current_group]: + # this can cut quite a lot of tg objects + if tg in self.needed_tgs: + tgpost(tg) + else: + # default implementation + return Build.BuildContext.post_group() + + def get_build_iterator(self): + if not self.targets or self.targets == '*': + self.compute_needed_tgs() + return Build.BuildContext.get_build_iterator(self) + +@taskgen_method +def is_stale(self): + # assume no globs + self.staleness = DIRTY + + # 1. the case of always stale targets + if getattr(self, 'always_stale', False): + return True + + # 2. check if the db file exists + db = os.path.join(self.bld.variant_dir, Context.DBFILE) + try: + dbstat = os.stat(db).st_mtime + except OSError: + Logs.debug('rev_use: must post %r because this is a clean build') + return True + + # 3.a check if the configuration exists + cache_node = self.bld.bldnode.find_node('c4che/build.config.py') + if not cache_node: + return True + + # 3.b check if the configuration changed + if os.stat(cache_node.abspath()).st_mtime > dbstat: + Logs.debug('rev_use: must post %r because the configuration has changed', self.name) + return True + + # 3.c any tstamp data? + try: + f_deps = self.bld.f_deps + except AttributeError: + Logs.debug('rev_use: must post %r because there is no f_deps', self.name) + return True + + # 4. check if this is the first build (no cache) + try: + lst = f_deps[(self.path.abspath(), self.idx)] + except KeyError: + Logs.debug('rev_use: must post %r because there it has no cached data', self.name) + return True + + try: + cache = self.bld.cache_tstamp_rev_use + except AttributeError: + cache = self.bld.cache_tstamp_rev_use = {} + + # 5. check the timestamp of each dependency files listed is unchanged + f_tstamps = self.bld.f_tstamps + for x in lst: + try: + old_ts = f_tstamps[x] + except KeyError: + Logs.debug('rev_use: must post %r because %r is not in cache', self.name, x) + return True + + try: + try: + ts = cache[x] + except KeyError: + ts = cache[x] = os.stat(x).st_mtime + except OSError: + del f_deps[(self.path.abspath(), self.idx)] + Logs.debug('rev_use: must post %r because %r does not exist anymore', self.name, x) + return True + else: + if ts != old_ts: + Logs.debug('rev_use: must post %r because the timestamp on %r changed %r %r', self.name, x, old_ts, ts) + return True + + self.staleness = DONE + return False + +@taskgen_method +def create_compiled_task(self, name, node): + # skip the creation of object files + # assumption: object-only targets are not skippable + if self.staleness == NEEDED: + # only libraries/programs can skip object files + for x in SKIPPABLE: + if x in self.features: + return None + + out = '%s.%d.o' % (node.name, self.idx) + task = self.create_task(name, node, node.parent.find_or_declare(out)) + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks = [task] + return task + +@feature(*SKIPPABLE) +@after_method('apply_link') +def apply_link_after(self): + # cprogram/cxxprogram might be unnecessary + if self.staleness != NEEDED: + return + for tsk in self.tasks: + tsk.hasrun = Task.SKIPPED + +def path_from(self, node): + # handle nodes of distinct types + if node.ctx is not self.ctx: + node = self.ctx.root.make_node(node.abspath()) + return self.default_path_from(node) +waflib.Node.Node.default_path_from = waflib.Node.Node.path_from +waflib.Node.Node.path_from = path_from + +def h_file(self): + # similar to md5_tstamp.py, but with 2-layer cache + # global_cache for the build context common for all task generators + # local_cache for the build context proxy (one by task generator) + # + # the global cache is not persistent + # the local cache is persistent and meant for partial builds + # + # assume all calls are made from a single thread + # + filename = self.abspath() + st = os.stat(filename) + + global_cache = self.ctx.bld.hashes_md5_tstamp + local_cache = self.ctx.hashes_md5_tstamp + + if filename in global_cache: + # value already calculated in this build + cval = global_cache[filename] + + # the value in global cache is assumed to be calculated once + # reverifying it could cause task generators + # to get distinct tstamp values, thus missing rebuilds + local_cache[filename] = cval + return cval[1] + + if filename in local_cache: + cval = local_cache[filename] + if cval[0] == st.st_mtime: + # correct value from a previous build + # put it in the global cache + global_cache[filename] = cval + return cval[1] + + ret = Utils.h_file(filename) + local_cache[filename] = global_cache[filename] = (st.st_mtime, ret) + return ret +waflib.Node.Node.h_file = h_file + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_bgxlf.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_bgxlf.py new file mode 100644 index 0000000..cca1810 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_bgxlf.py @@ -0,0 +1,32 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +from waflib.Tools import fc, fc_config, fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].insert(0, 'fc_bgxlf') + +@conf +def find_bgxlf(conf): + fc = conf.find_program(['bgxlf2003_r','bgxlf2003'], var='FC') + conf.get_xlf_version(fc) + conf.env.FC_NAME = 'BGXLF' + +@conf +def bg_flags(self): + self.env.SONAME_ST = '' + self.env.FCSHLIB_MARKER = '' + self.env.FCSTLIB_MARKER = '' + self.env.FCFLAGS_fcshlib = ['-fPIC'] + self.env.LINKFLAGS_fcshlib = ['-G', '-Wl,-bexpfull'] + +def configure(conf): + conf.find_bgxlf() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.xlf_flags() + conf.bg_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_cray.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_cray.py new file mode 100644 index 0000000..da733fa --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_cray.py @@ -0,0 +1,51 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +import re +from waflib.Tools import fc, fc_config, fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].append('fc_cray') + +@conf +def find_crayftn(conf): + """Find the Cray fortran compiler (will look in the environment variable 'FC')""" + fc = conf.find_program(['crayftn'], var='FC') + conf.get_crayftn_version(fc) + conf.env.FC_NAME = 'CRAY' + conf.env.FC_MOD_CAPITALIZATION = 'UPPER.mod' + +@conf +def crayftn_flags(conf): + v = conf.env + v['_FCMODOUTFLAGS'] = ['-em', '-J.'] # enable module files and put them in the current directory + v['FCFLAGS_DEBUG'] = ['-m1'] # more verbose compiler warnings + v['FCFLAGS_fcshlib'] = ['-h pic'] + v['LINKFLAGS_fcshlib'] = ['-h shared'] + + v['FCSTLIB_MARKER'] = '-h static' + v['FCSHLIB_MARKER'] = '-h dynamic' + +@conf +def get_crayftn_version(conf, fc): + version_re = re.compile(r"Cray Fortran\s*:\s*Version\s*(?P\d*)\.(?P\d*)", re.I).search + cmd = fc + ['-V'] + out,err = fc_config.getoutput(conf, cmd, stdin=False) + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('Could not determine the Cray Fortran compiler version.') + k = match.groupdict() + conf.env['FC_VERSION'] = (k['major'], k['minor']) + +def configure(conf): + conf.find_crayftn() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.crayftn_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_nag.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_nag.py new file mode 100644 index 0000000..edcb218 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_nag.py @@ -0,0 +1,61 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +import re +from waflib import Utils +from waflib.Tools import fc,fc_config,fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].insert(0, 'fc_nag') + +@conf +def find_nag(conf): + """Find the NAG Fortran Compiler (will look in the environment variable 'FC')""" + + fc = conf.find_program(['nagfor'], var='FC') + conf.get_nag_version(fc) + conf.env.FC_NAME = 'NAG' + conf.env.FC_MOD_CAPITALIZATION = 'lower' + +@conf +def nag_flags(conf): + v = conf.env + v.FCFLAGS_DEBUG = ['-C=all'] + v.FCLNK_TGT_F = ['-o', ''] + v.FC_TGT_F = ['-c', '-o', ''] + +@conf +def nag_modifier_platform(conf): + dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() + nag_modifier_func = getattr(conf, 'nag_modifier_' + dest_os, None) + if nag_modifier_func: + nag_modifier_func() + +@conf +def get_nag_version(conf, fc): + """Get the NAG compiler version""" + + version_re = re.compile(r"^NAG Fortran Compiler *Release *(?P\d*)\.(?P\d*)", re.M).search + cmd = fc + ['-V'] + + out, err = fc_config.getoutput(conf,cmd,stdin=False) + if out: + match = version_re(out) + if not match: + match = version_re(err) + else: match = version_re(err) + if not match: + conf.fatal('Could not determine the NAG version.') + k = match.groupdict() + conf.env['FC_VERSION'] = (k['major'], k['minor']) + +def configure(conf): + conf.find_nag() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.nag_flags() + conf.nag_modifier_platform() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_nec.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_nec.py new file mode 100644 index 0000000..67c8680 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_nec.py @@ -0,0 +1,60 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +import re +from waflib.Tools import fc, fc_config, fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].append('fc_nec') + +@conf +def find_sxfc(conf): + """Find the NEC fortran compiler (will look in the environment variable 'FC')""" + fc = conf.find_program(['sxf90','sxf03'], var='FC') + conf.get_sxfc_version(fc) + conf.env.FC_NAME = 'NEC' + conf.env.FC_MOD_CAPITALIZATION = 'lower' + +@conf +def sxfc_flags(conf): + v = conf.env + v['_FCMODOUTFLAGS'] = [] # enable module files and put them in the current directory + v['FCFLAGS_DEBUG'] = [] # more verbose compiler warnings + v['FCFLAGS_fcshlib'] = [] + v['LINKFLAGS_fcshlib'] = [] + + v['FCSTLIB_MARKER'] = '' + v['FCSHLIB_MARKER'] = '' + +@conf +def get_sxfc_version(conf, fc): + version_re = re.compile(r"FORTRAN90/SX\s*Version\s*(?P\d*)\.(?P\d*)", re.I).search + cmd = fc + ['-V'] + out,err = fc_config.getoutput(conf, cmd, stdin=False) + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + version_re=re.compile(r"NEC Fortran 2003 Compiler for\s*(?P\S*)\s*\(c\)\s*(?P\d*)",re.I).search + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('Could not determine the NEC Fortran compiler version.') + k = match.groupdict() + conf.env['FC_VERSION'] = (k['major'], k['minor']) + +def configure(conf): + conf.find_sxfc() + conf.find_program('sxar',var='AR') + conf.add_os_flags('ARFLAGS') + if not conf.env.ARFLAGS: + conf.env.ARFLAGS=['rcs'] + + conf.fc_flags() + conf.fc_add_flags() + conf.sxfc_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_nfort.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_nfort.py new file mode 100644 index 0000000..c25886b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_nfort.py @@ -0,0 +1,52 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Detection of the NEC Fortran compiler for Aurora Tsubasa + +import re +from waflib.Tools import fc,fc_config,fc_scan +from waflib.Configure import conf +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].append('fc_nfort') + +@conf +def find_nfort(conf): + fc=conf.find_program(['nfort'],var='FC') + conf.get_nfort_version(fc) + conf.env.FC_NAME='NFORT' + conf.env.FC_MOD_CAPITALIZATION='lower' + +@conf +def nfort_flags(conf): + v=conf.env + v['_FCMODOUTFLAGS']=[] + v['FCFLAGS_DEBUG']=[] + v['FCFLAGS_fcshlib']=[] + v['LINKFLAGS_fcshlib']=[] + v['FCSTLIB_MARKER']='' + v['FCSHLIB_MARKER']='' + +@conf +def get_nfort_version(conf,fc): + version_re=re.compile(r"nfort\s*\(NFORT\)\s*(?P\d+)\.(?P\d+)\.",re.I).search + cmd=fc+['--version'] + out,err=fc_config.getoutput(conf,cmd,stdin=False) + if out: + match=version_re(out) + else: + match=version_re(err) + if not match: + return(False) + conf.fatal('Could not determine the NEC NFORT Fortran compiler version.') + else: + k=match.groupdict() + conf.env['FC_VERSION']=(k['major'],k['minor']) + +def configure(conf): + conf.find_nfort() + conf.find_program('nar',var='AR') + conf.add_os_flags('ARFLAGS') + if not conf.env.ARFLAGS: + conf.env.ARFLAGS=['rcs'] + conf.fc_flags() + conf.fc_add_flags() + conf.nfort_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_open64.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_open64.py new file mode 100644 index 0000000..413719f --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_open64.py @@ -0,0 +1,58 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +import re +from waflib import Utils +from waflib.Tools import fc,fc_config,fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].insert(0, 'fc_open64') + +@conf +def find_openf95(conf): + """Find the Open64 Fortran Compiler (will look in the environment variable 'FC')""" + + fc = conf.find_program(['openf95', 'openf90'], var='FC') + conf.get_open64_version(fc) + conf.env.FC_NAME = 'OPEN64' + conf.env.FC_MOD_CAPITALIZATION = 'UPPER.mod' + +@conf +def openf95_flags(conf): + v = conf.env + v['FCFLAGS_DEBUG'] = ['-fullwarn'] + +@conf +def openf95_modifier_platform(conf): + dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() + openf95_modifier_func = getattr(conf, 'openf95_modifier_' + dest_os, None) + if openf95_modifier_func: + openf95_modifier_func() + +@conf +def get_open64_version(conf, fc): + """Get the Open64 compiler version""" + + version_re = re.compile(r"Open64 Compiler Suite: *Version *(?P\d*)\.(?P\d*)", re.I).search + cmd = fc + ['-version'] + + out, err = fc_config.getoutput(conf,cmd,stdin=False) + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('Could not determine the Open64 version.') + k = match.groupdict() + conf.env['FC_VERSION'] = (k['major'], k['minor']) + +def configure(conf): + conf.find_openf95() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.openf95_flags() + conf.openf95_modifier_platform() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_pgfortran.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_pgfortran.py new file mode 100644 index 0000000..afb2817 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_pgfortran.py @@ -0,0 +1,68 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +import re +from waflib.Tools import fc, fc_config, fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].append('fc_pgfortran') + +@conf +def find_pgfortran(conf): + """Find the PGI fortran compiler (will look in the environment variable 'FC')""" + fc = conf.find_program(['pgfortran', 'pgf95', 'pgf90'], var='FC') + conf.get_pgfortran_version(fc) + conf.env.FC_NAME = 'PGFC' + +@conf +def pgfortran_flags(conf): + v = conf.env + v['FCFLAGS_fcshlib'] = ['-shared'] + v['FCFLAGS_DEBUG'] = ['-Minform=inform', '-Mstandard'] # why not + v['FCSTLIB_MARKER'] = '-Bstatic' + v['FCSHLIB_MARKER'] = '-Bdynamic' + v['SONAME_ST'] = '-soname %s' + +@conf +def get_pgfortran_version(conf,fc): + version_re = re.compile(r"The Portland Group", re.I).search + cmd = fc + ['-V'] + out,err = fc_config.getoutput(conf, cmd, stdin=False) + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('Could not verify PGI signature') + cmd = fc + ['-help=variable'] + out,err = fc_config.getoutput(conf, cmd, stdin=False) + if out.find('COMPVER')<0: + conf.fatal('Could not determine the compiler type') + k = {} + prevk = '' + out = out.splitlines() + for line in out: + lst = line.partition('=') + if lst[1] == '=': + key = lst[0].rstrip() + if key == '': + key = prevk + val = lst[2].rstrip() + k[key] = val + else: + prevk = line.partition(' ')[0] + def isD(var): + return var in k + def isT(var): + return var in k and k[var]!='0' + conf.env['FC_VERSION'] = (k['COMPVER'].split('.')) + +def configure(conf): + conf.find_pgfortran() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.pgfortran_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_solstudio.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_solstudio.py new file mode 100644 index 0000000..53766df --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_solstudio.py @@ -0,0 +1,62 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +import re +from waflib import Utils +from waflib.Tools import fc,fc_config,fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].append('fc_solstudio') + +@conf +def find_solstudio(conf): + """Find the Solaris Studio compiler (will look in the environment variable 'FC')""" + + fc = conf.find_program(['sunf95', 'f95', 'sunf90', 'f90'], var='FC') + conf.get_solstudio_version(fc) + conf.env.FC_NAME = 'SOL' + +@conf +def solstudio_flags(conf): + v = conf.env + v['FCFLAGS_fcshlib'] = ['-Kpic'] + v['FCFLAGS_DEBUG'] = ['-w3'] + v['LINKFLAGS_fcshlib'] = ['-G'] + v['FCSTLIB_MARKER'] = '-Bstatic' + v['FCSHLIB_MARKER'] = '-Bdynamic' + v['SONAME_ST'] = '-h %s' + +@conf +def solstudio_modifier_platform(conf): + dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() + solstudio_modifier_func = getattr(conf, 'solstudio_modifier_' + dest_os, None) + if solstudio_modifier_func: + solstudio_modifier_func() + +@conf +def get_solstudio_version(conf, fc): + """Get the compiler version""" + + version_re = re.compile(r"Sun Fortran 95 *(?P\d*)\.(?P\d*)", re.I).search + cmd = fc + ['-V'] + + out, err = fc_config.getoutput(conf,cmd,stdin=False) + if out: + match = version_re(out) + else: + match = version_re(err) + if not match: + conf.fatal('Could not determine the Sun Studio Fortran version.') + k = match.groupdict() + conf.env['FC_VERSION'] = (k['major'], k['minor']) + +def configure(conf): + conf.find_solstudio() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.solstudio_flags() + conf.solstudio_modifier_platform() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fc_xlf.py b/ldb-2.0.8/third_party/waf/waflib/extras/fc_xlf.py new file mode 100644 index 0000000..5a3da03 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fc_xlf.py @@ -0,0 +1,63 @@ +#! /usr/bin/env python +# encoding: utf-8 +# harald at klimachs.de + +import re +from waflib import Utils,Errors +from waflib.Tools import fc,fc_config,fc_scan +from waflib.Configure import conf + +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['aix'].insert(0, 'fc_xlf') + +@conf +def find_xlf(conf): + """Find the xlf program (will look in the environment variable 'FC')""" + + fc = conf.find_program(['xlf2003_r', 'xlf2003', 'xlf95_r', 'xlf95', 'xlf90_r', 'xlf90', 'xlf_r', 'xlf'], var='FC') + conf.get_xlf_version(fc) + conf.env.FC_NAME='XLF' + +@conf +def xlf_flags(conf): + v = conf.env + v['FCDEFINES_ST'] = '-WF,-D%s' + v['FCFLAGS_fcshlib'] = ['-qpic=small'] + v['FCFLAGS_DEBUG'] = ['-qhalt=w'] + v['LINKFLAGS_fcshlib'] = ['-Wl,-shared'] + +@conf +def xlf_modifier_platform(conf): + dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() + xlf_modifier_func = getattr(conf, 'xlf_modifier_' + dest_os, None) + if xlf_modifier_func: + xlf_modifier_func() + +@conf +def get_xlf_version(conf, fc): + """Get the compiler version""" + + cmd = fc + ['-qversion'] + try: + out, err = conf.cmd_and_log(cmd, output=0) + except Errors.WafError: + conf.fatal('Could not find xlf %r' % cmd) + + for v in (r"IBM XL Fortran.* V(?P\d*)\.(?P\d*)",): + version_re = re.compile(v, re.I).search + match = version_re(out or err) + if match: + k = match.groupdict() + conf.env['FC_VERSION'] = (k['major'], k['minor']) + break + else: + conf.fatal('Could not determine the XLF version.') + +def configure(conf): + conf.find_xlf() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.xlf_flags() + conf.xlf_modifier_platform() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/file_to_object.py b/ldb-2.0.8/third_party/waf/waflib/extras/file_to_object.py new file mode 100644 index 0000000..1393b51 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/file_to_object.py @@ -0,0 +1,137 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Tool to embed file into objects + +__author__ = __maintainer__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2014" + +""" + +This tool allows to embed file contents in object files (.o). +It is not exactly portable, and the file contents are reachable +using various non-portable fashions. +The goal here is to provide a functional interface to the embedding +of file data in objects. +See the ``playground/embedded_resources`` example for an example. + +Usage:: + + bld( + name='pipeline', + # ^ Reference this in use="..." for things using the generated code + features='file_to_object', + source='some.file', + # ^ Name of the file to embed in binary section. + ) + +Known issues: + +- Destination is named like source, with extension renamed to .o + eg. some.file -> some.o + +""" + +import os +from waflib import Task, TaskGen, Errors + +def filename_c_escape(x): + return x.replace("\\", "\\\\") + +class file_to_object_s(Task.Task): + color = 'CYAN' + vars = ['DEST_CPU', 'DEST_BINFMT'] + + def run(self): + name = [] + for i, x in enumerate(self.inputs[0].name): + if x.isalnum(): + name.append(x) + else: + name.append('_') + file = self.inputs[0].abspath() + size = os.path.getsize(file) + if self.env.DEST_CPU in ('x86_64', 'ia', 'aarch64'): + unit = 'quad' + align = 8 + elif self.env.DEST_CPU in ('x86','arm', 'thumb', 'm68k'): + unit = 'long' + align = 4 + else: + raise Errors.WafError("Unsupported DEST_CPU, please report bug!") + + file = filename_c_escape(file) + name = "_binary_" + "".join(name) + rodata = ".section .rodata" + if self.env.DEST_BINFMT == "mac-o": + name = "_" + name + rodata = ".section __TEXT,__const" + + with open(self.outputs[0].abspath(), 'w') as f: + f.write(\ +""" + .global %(name)s_start + .global %(name)s_end + .global %(name)s_size + %(rodata)s +%(name)s_start: + .incbin "%(file)s" +%(name)s_end: + .align %(align)d +%(name)s_size: + .%(unit)s 0x%(size)x +""" % locals()) + +class file_to_object_c(Task.Task): + color = 'CYAN' + def run(self): + name = [] + for i, x in enumerate(self.inputs[0].name): + if x.isalnum(): + name.append(x) + else: + name.append('_') + file = self.inputs[0].abspath() + size = os.path.getsize(file) + + name = "_binary_" + "".join(name) + + data = self.inputs[0].read('rb') + lines, line = [], [] + for idx_byte, byte in enumerate(data): + line.append(byte) + if len(line) > 15 or idx_byte == size-1: + lines.append(", ".join(("0x%02x" % ord(x)) for x in line)) + line = [] + data = ",\n ".join(lines) + + self.outputs[0].write(\ +""" +unsigned long %(name)s_size = %(size)dL; +char const %(name)s_start[] = { + %(data)s +}; +char const %(name)s_end[] = {}; +""" % locals()) + +@TaskGen.feature('file_to_object') +@TaskGen.before_method('process_source') +def tg_file_to_object(self): + bld = self.bld + sources = self.to_nodes(self.source) + targets = [] + for src in sources: + if bld.env.F2O_METHOD == ["asm"]: + tgt = src.parent.find_or_declare(src.name + '.f2o.s') + tsk = self.create_task('file_to_object_s', src, tgt) + tsk.cwd = src.parent.abspath() # verify + else: + tgt = src.parent.find_or_declare(src.name + '.f2o.c') + tsk = self.create_task('file_to_object_c', src, tgt) + tsk.cwd = src.parent.abspath() # verify + targets.append(tgt) + self.source = targets + +def configure(conf): + conf.load('gas') + conf.env.F2O_METHOD = ["c"] + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fluid.py b/ldb-2.0.8/third_party/waf/waflib/extras/fluid.py new file mode 100644 index 0000000..4814a35 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fluid.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +# encoding: utf-8 +# Grygoriy Fuchedzhy 2009 + +""" +Compile fluid files (fltk graphic library). Use the 'fluid' feature in conjunction with the 'cxx' feature. +""" + +from waflib import Task +from waflib.TaskGen import extension + +class fluid(Task.Task): + color = 'BLUE' + ext_out = ['.h'] + run_str = '${FLUID} -c -o ${TGT[0].abspath()} -h ${TGT[1].abspath()} ${SRC}' + +@extension('.fl') +def process_fluid(self, node): + """add the .fl to the source list; the cxx file generated will be compiled when possible""" + cpp = node.change_ext('.cpp') + hpp = node.change_ext('.hpp') + self.create_task('fluid', node, [cpp, hpp]) + + if 'cxx' in self.features: + self.source.append(cpp) + +def configure(conf): + conf.find_program('fluid', var='FLUID') + conf.check_cfg(path='fltk-config', package='', args='--cxxflags --ldflags', uselib_store='FLTK', mandatory=True) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/freeimage.py b/ldb-2.0.8/third_party/waf/waflib/extras/freeimage.py new file mode 100644 index 0000000..f27e525 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/freeimage.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# encoding: utf-8 +# +# written by Sylvain Rouquette, 2011 + +''' +To add the freeimage tool to the waf file: +$ ./waf-light --tools=compat15,freeimage + or, if you have waf >= 1.6.2 +$ ./waf update --files=freeimage + +The wscript will look like: + +def options(opt): + opt.load('compiler_cxx freeimage') + +def configure(conf): + conf.load('compiler_cxx freeimage') + + # you can call check_freeimage with some parameters. + # It's optional on Linux, it's 'mandatory' on Windows if + # you didn't use --fi-path on the command-line + + # conf.check_freeimage(path='FreeImage/Dist', fip=True) + +def build(bld): + bld(source='main.cpp', target='app', use='FREEIMAGE') +''' + +from waflib import Utils +from waflib.Configure import conf + + +def options(opt): + opt.add_option('--fi-path', type='string', default='', dest='fi_path', + help='''path to the FreeImage directory \ + where the files are e.g. /FreeImage/Dist''') + opt.add_option('--fip', action='store_true', default=False, dest='fip', + help='link with FreeImagePlus') + opt.add_option('--fi-static', action='store_true', + default=False, dest='fi_static', + help="link as shared libraries") + + +@conf +def check_freeimage(self, path=None, fip=False): + self.start_msg('Checking FreeImage') + if not self.env['CXX']: + self.fatal('you must load compiler_cxx before loading freeimage') + prefix = self.options.fi_static and 'ST' or '' + platform = Utils.unversioned_sys_platform() + if platform == 'win32': + if not path: + self.fatal('you must specify the path to FreeImage. \ + use --fi-path=/FreeImage/Dist') + else: + self.env['INCLUDES_FREEIMAGE'] = path + self.env['%sLIBPATH_FREEIMAGE' % prefix] = path + libs = ['FreeImage'] + if self.options.fip: + libs.append('FreeImagePlus') + if platform == 'win32': + self.env['%sLIB_FREEIMAGE' % prefix] = libs + else: + self.env['%sLIB_FREEIMAGE' % prefix] = [i.lower() for i in libs] + self.end_msg('ok') + + +def configure(conf): + platform = Utils.unversioned_sys_platform() + if platform == 'win32' and not conf.options.fi_path: + return + conf.check_freeimage(conf.options.fi_path, conf.options.fip) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fsb.py b/ldb-2.0.8/third_party/waf/waflib/extras/fsb.py new file mode 100644 index 0000000..1b8f398 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fsb.py @@ -0,0 +1,31 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011 (ita) + +""" +Fully sequential builds + +The previous tasks from task generators are re-processed, and this may lead to speed issues +Yet, if you are using this, speed is probably a minor concern +""" + +from waflib import Build + +def options(opt): + pass + +def configure(conf): + pass + +class FSBContext(Build.BuildContext): + def __call__(self, *k, **kw): + ret = Build.BuildContext.__call__(self, *k, **kw) + + # evaluate the results immediately + Build.BuildContext.compile(self) + + return ret + + def compile(self): + pass + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/fsc.py b/ldb-2.0.8/third_party/waf/waflib/extras/fsc.py new file mode 100644 index 0000000..c67e70b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/fsc.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011 (ita) + +""" +Experimental F# stuff + +FSC="mono /path/to/fsc.exe" waf configure build +""" + +from waflib import Utils, Task +from waflib.TaskGen import before_method, after_method, feature +from waflib.Tools import ccroot, cs + +ccroot.USELIB_VARS['fsc'] = set(['CSFLAGS', 'ASSEMBLIES', 'RESOURCES']) + +@feature('fs') +@before_method('process_source') +def apply_fsc(self): + cs_nodes = [] + no_nodes = [] + for x in self.to_nodes(self.source): + if x.name.endswith('.fs'): + cs_nodes.append(x) + else: + no_nodes.append(x) + self.source = no_nodes + + bintype = getattr(self, 'type', self.gen.endswith('.dll') and 'library' or 'exe') + self.cs_task = tsk = self.create_task('fsc', cs_nodes, self.path.find_or_declare(self.gen)) + tsk.env.CSTYPE = '/target:%s' % bintype + tsk.env.OUT = '/out:%s' % tsk.outputs[0].abspath() + + inst_to = getattr(self, 'install_path', bintype=='exe' and '${BINDIR}' or '${LIBDIR}') + if inst_to: + # note: we are making a copy, so the files added to cs_task.outputs won't be installed automatically + mod = getattr(self, 'chmod', bintype=='exe' and Utils.O755 or Utils.O644) + self.install_task = self.add_install_files(install_to=inst_to, install_from=self.cs_task.outputs[:], chmod=mod) + +feature('fs')(cs.use_cs) +after_method('apply_fsc')(cs.use_cs) + +feature('fs')(cs.debug_cs) +after_method('apply_fsc', 'use_cs')(cs.debug_cs) + +class fsc(Task.Task): + """ + Compile F# files + """ + color = 'YELLOW' + run_str = '${FSC} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' + +def configure(conf): + """ + Find a F# compiler, set the variable FSC for the compiler and FS_NAME (mono or fsc) + """ + conf.find_program(['fsc.exe', 'fsharpc'], var='FSC') + conf.env.ASS_ST = '/r:%s' + conf.env.RES_ST = '/resource:%s' + + conf.env.FS_NAME = 'fsc' + if str(conf.env.FSC).lower().find('fsharpc') > -1: + conf.env.FS_NAME = 'mono' + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/gccdeps.py b/ldb-2.0.8/third_party/waf/waflib/extras/gccdeps.py new file mode 100644 index 0000000..bfabe72 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/gccdeps.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2008-2010 (ita) + +""" +Execute the tasks with gcc -MD, read the dependencies from the .d file +and prepare the dependency calculation for the next run. +This affects the cxx class, so make sure to load Qt5 after this tool. + +Usage:: + + def options(opt): + opt.load('compiler_cxx') + def configure(conf): + conf.load('compiler_cxx gccdeps') +""" + +import os, re, threading +from waflib import Task, Logs, Utils, Errors +from waflib.Tools import c_preproc +from waflib.TaskGen import before_method, feature + +lock = threading.Lock() + +gccdeps_flags = ['-MD'] +if not c_preproc.go_absolute: + gccdeps_flags = ['-MMD'] + +# Third-party tools are allowed to add extra names in here with append() +supported_compilers = ['gcc', 'icc', 'clang'] + +def scan(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).scan() + nodes = self.generator.bld.node_deps.get(self.uid(), []) + names = [] + return (nodes, names) + +re_o = re.compile(r"\.o$") +re_splitter = re.compile(r'(?= 0: + return line[sep_idx + 2:] + else: + return line + +def path_to_node(base_node, path, cached_nodes): + # Take the base node and the path and return a node + # Results are cached because searching the node tree is expensive + # The following code is executed by threads, it is not safe, so a lock is needed... + if getattr(path, '__hash__'): + node_lookup_key = (base_node, path) + else: + # Not hashable, assume it is a list and join into a string + node_lookup_key = (base_node, os.path.sep.join(path)) + try: + lock.acquire() + node = cached_nodes[node_lookup_key] + except KeyError: + node = base_node.find_resource(path) + cached_nodes[node_lookup_key] = node + finally: + lock.release() + return node + +def post_run(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).post_run() + + name = self.outputs[0].abspath() + name = re_o.sub('.d', name) + try: + txt = Utils.readf(name) + except EnvironmentError: + Logs.error('Could not find a .d dependency file, are cflags/cxxflags overwritten?') + raise + #os.remove(name) + + # Compilers have the choice to either output the file's dependencies + # as one large Makefile rule: + # + # /path/to/file.o: /path/to/dep1.h \ + # /path/to/dep2.h \ + # /path/to/dep3.h \ + # ... + # + # or as many individual rules: + # + # /path/to/file.o: /path/to/dep1.h + # /path/to/file.o: /path/to/dep2.h + # /path/to/file.o: /path/to/dep3.h + # ... + # + # So the first step is to sanitize the input by stripping out the left- + # hand side of all these lines. After that, whatever remains are the + # implicit dependencies of task.outputs[0] + txt = '\n'.join([remove_makefile_rule_lhs(line) for line in txt.splitlines()]) + + # Now join all the lines together + txt = txt.replace('\\\n', '') + + val = txt.strip() + val = [x.replace('\\ ', ' ') for x in re_splitter.split(val) if x] + + nodes = [] + bld = self.generator.bld + + # Dynamically bind to the cache + try: + cached_nodes = bld.cached_nodes + except AttributeError: + cached_nodes = bld.cached_nodes = {} + + for x in val: + + node = None + if os.path.isabs(x): + node = path_to_node(bld.root, x, cached_nodes) + else: + # TODO waf 1.9 - single cwd value + path = getattr(bld, 'cwdx', bld.bldnode) + # when calling find_resource, make sure the path does not contain '..' + x = [k for k in Utils.split_path(x) if k and k != '.'] + while '..' in x: + idx = x.index('..') + if idx == 0: + x = x[1:] + path = path.parent + else: + del x[idx] + del x[idx-1] + + node = path_to_node(path, x, cached_nodes) + + if not node: + raise ValueError('could not find %r for %r' % (x, self)) + if id(node) == id(self.inputs[0]): + # ignore the source file, it is already in the dependencies + # this way, successful config tests may be retrieved from the cache + continue + nodes.append(node) + + Logs.debug('deps: gccdeps for %s returned %s', self, nodes) + + bld.node_deps[self.uid()] = nodes + bld.raw_deps[self.uid()] = [] + + try: + del self.cache_sig + except AttributeError: + pass + + Task.Task.post_run(self) + +def sig_implicit_deps(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).sig_implicit_deps() + try: + return Task.Task.sig_implicit_deps(self) + except Errors.WafError: + return Utils.SIG_NIL + +def wrap_compiled_task(classname): + derived_class = type(classname, (Task.classes[classname],), {}) + derived_class.derived_gccdeps = derived_class + derived_class.post_run = post_run + derived_class.scan = scan + derived_class.sig_implicit_deps = sig_implicit_deps + +for k in ('c', 'cxx'): + if k in Task.classes: + wrap_compiled_task(k) + +@before_method('process_source') +@feature('force_gccdeps') +def force_gccdeps(self): + self.env.ENABLE_GCCDEPS = ['c', 'cxx'] + +def configure(conf): + # in case someone provides a --enable-gccdeps command-line option + if not getattr(conf.options, 'enable_gccdeps', True): + return + + global gccdeps_flags + flags = conf.env.GCCDEPS_FLAGS or gccdeps_flags + if conf.env.CC_NAME in supported_compilers: + try: + conf.check(fragment='int main() { return 0; }', features='c force_gccdeps', cflags=flags, msg='Checking for c flags %r' % ''.join(flags)) + except Errors.ConfigurationError: + pass + else: + conf.env.append_value('CFLAGS', flags) + conf.env.append_unique('ENABLE_GCCDEPS', 'c') + + if conf.env.CXX_NAME in supported_compilers: + try: + conf.check(fragment='int main() { return 0; }', features='cxx force_gccdeps', cxxflags=flags, msg='Checking for cxx flags %r' % ''.join(flags)) + except Errors.ConfigurationError: + pass + else: + conf.env.append_value('CXXFLAGS', flags) + conf.env.append_unique('ENABLE_GCCDEPS', 'cxx') + +def options(opt): + raise ValueError('Do not load gccdeps options') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/gdbus.py b/ldb-2.0.8/third_party/waf/waflib/extras/gdbus.py new file mode 100644 index 0000000..0e0476e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/gdbus.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Copyright Garmin International or its subsidiaries, 2018 +# +# Heavily based on dbus.py + +""" +Compiles dbus files with **gdbus-codegen** +Typical usage:: + def options(opt): + opt.load('compiler_c gdbus') + def configure(conf): + conf.load('compiler_c gdbus') + def build(bld): + tg = bld.program( + includes = '.', + source = bld.path.ant_glob('*.c'), + target = 'gnome-hello') + tg.add_gdbus_file('test.xml', 'com.example.example.', 'Example') +""" + +from waflib import Task, Errors, Utils +from waflib.TaskGen import taskgen_method, before_method + +@taskgen_method +def add_gdbus_file(self, filename, prefix, namespace, export=False): + """ + Adds a dbus file to the list of dbus files to process. Store them in the attribute *dbus_lst*. + :param filename: xml file to compile + :type filename: string + :param prefix: interface prefix (--interface-prefix=prefix) + :type prefix: string + :param mode: C namespace (--c-namespace=namespace) + :type mode: string + :param export: Export Headers? + :type export: boolean + """ + if not hasattr(self, 'gdbus_lst'): + self.gdbus_lst = [] + if not 'process_gdbus' in self.meths: + self.meths.append('process_gdbus') + self.gdbus_lst.append([filename, prefix, namespace, export]) + +@before_method('process_source') +def process_gdbus(self): + """ + Processes the dbus files stored in the attribute *gdbus_lst* to create :py:class:`gdbus_binding_tool` instances. + """ + output_node = self.path.get_bld().make_node(['gdbus', self.get_name()]) + sources = [] + + for filename, prefix, namespace, export in getattr(self, 'gdbus_lst', []): + node = self.path.find_resource(filename) + if not node: + raise Errors.WafError('file not found ' + filename) + c_file = output_node.find_or_declare(node.change_ext('.c').name) + h_file = output_node.find_or_declare(node.change_ext('.h').name) + tsk = self.create_task('gdbus_binding_tool', node, [c_file, h_file]) + tsk.cwd = output_node.abspath() + + tsk.env.GDBUS_CODEGEN_INTERFACE_PREFIX = prefix + tsk.env.GDBUS_CODEGEN_NAMESPACE = namespace + tsk.env.GDBUS_CODEGEN_OUTPUT = node.change_ext('').name + sources.append(c_file) + + if sources: + output_node.mkdir() + self.source = Utils.to_list(self.source) + sources + self.includes = [output_node] + self.to_incnodes(getattr(self, 'includes', [])) + if export: + self.export_includes = [output_node] + self.to_incnodes(getattr(self, 'export_includes', [])) + +class gdbus_binding_tool(Task.Task): + """ + Compiles a dbus file + """ + color = 'BLUE' + ext_out = ['.h', '.c'] + run_str = '${GDBUS_CODEGEN} --interface-prefix ${GDBUS_CODEGEN_INTERFACE_PREFIX} --generate-c-code ${GDBUS_CODEGEN_OUTPUT} --c-namespace ${GDBUS_CODEGEN_NAMESPACE} --c-generate-object-manager ${SRC[0].abspath()}' + shell = True + +def configure(conf): + """ + Detects the program gdbus-codegen and sets ``conf.env.GDBUS_CODEGEN`` + """ + conf.find_program('gdbus-codegen', var='GDBUS_CODEGEN') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/genpybind.py b/ldb-2.0.8/third_party/waf/waflib/extras/genpybind.py new file mode 100644 index 0000000..ac206ee --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/genpybind.py @@ -0,0 +1,194 @@ +import os +import pipes +import subprocess +import sys + +from waflib import Logs, Task, Context +from waflib.Tools.c_preproc import scan as scan_impl +# ^-- Note: waflib.extras.gccdeps.scan does not work for us, +# due to its current implementation: +# The -MD flag is injected into the {C,CXX}FLAGS environment variable and +# dependencies are read out in a separate step after compiling by reading +# the .d file saved alongside the object file. +# As the genpybind task refers to a header file that is never compiled itself, +# gccdeps will not be able to extract the list of dependencies. + +from waflib.TaskGen import feature, before_method + + +def join_args(args): + return " ".join(pipes.quote(arg) for arg in args) + + +def configure(cfg): + cfg.load("compiler_cxx") + cfg.load("python") + cfg.check_python_version(minver=(2, 7)) + if not cfg.env.LLVM_CONFIG: + cfg.find_program("llvm-config", var="LLVM_CONFIG") + if not cfg.env.GENPYBIND: + cfg.find_program("genpybind", var="GENPYBIND") + + # find clang reasource dir for builtin headers + cfg.env.GENPYBIND_RESOURCE_DIR = os.path.join( + cfg.cmd_and_log(cfg.env.LLVM_CONFIG + ["--libdir"]).strip(), + "clang", + cfg.cmd_and_log(cfg.env.LLVM_CONFIG + ["--version"]).strip()) + if os.path.exists(cfg.env.GENPYBIND_RESOURCE_DIR): + cfg.msg("Checking clang resource dir", cfg.env.GENPYBIND_RESOURCE_DIR) + else: + cfg.fatal("Clang resource dir not found") + + +@feature("genpybind") +@before_method("process_source") +def generate_genpybind_source(self): + """ + Run genpybind on the headers provided in `source` and compile/link the + generated code instead. This works by generating the code on the fly and + swapping the source node before `process_source` is run. + """ + # name of module defaults to name of target + module = getattr(self, "module", self.target) + + # create temporary source file in build directory to hold generated code + out = "genpybind-%s.%d.cpp" % (module, self.idx) + out = self.path.get_bld().find_or_declare(out) + + task = self.create_task("genpybind", self.to_nodes(self.source), out) + # used to detect whether CFLAGS or CXXFLAGS should be passed to genpybind + task.features = self.features + task.module = module + # can be used to select definitions to include in the current module + # (when header files are shared by more than one module) + task.genpybind_tags = self.to_list(getattr(self, "genpybind_tags", [])) + # additional include directories + task.includes = self.to_list(getattr(self, "includes", [])) + task.genpybind = self.env.GENPYBIND + + # Tell waf to compile/link the generated code instead of the headers + # originally passed-in via the `source` parameter. (see `process_source`) + self.source = [out] + + +class genpybind(Task.Task): # pylint: disable=invalid-name + """ + Runs genpybind on headers provided as input to this task. + Generated code will be written to the first (and only) output node. + """ + quiet = True + color = "PINK" + scan = scan_impl + + @staticmethod + def keyword(): + return "Analyzing" + + def run(self): + if not self.inputs: + return + + args = self.find_genpybind() + self._arguments( + resource_dir=self.env.GENPYBIND_RESOURCE_DIR) + + output = self.run_genpybind(args) + + # For debugging / log output + pasteable_command = join_args(args) + + # write generated code to file in build directory + # (will be compiled during process_source stage) + (output_node,) = self.outputs + output_node.write("// {}\n{}\n".format( + pasteable_command.replace("\n", "\n// "), output)) + + def find_genpybind(self): + return self.genpybind + + def run_genpybind(self, args): + bld = self.generator.bld + + kwargs = dict(cwd=bld.variant_dir) + if hasattr(bld, "log_command"): + bld.log_command(args, kwargs) + else: + Logs.debug("runner: {!r}".format(args)) + proc = subprocess.Popen( + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) + stdout, stderr = proc.communicate() + + if not isinstance(stdout, str): + stdout = stdout.decode(sys.stdout.encoding, errors="replace") + if not isinstance(stderr, str): + stderr = stderr.decode(sys.stderr.encoding, errors="replace") + + if proc.returncode != 0: + bld.fatal( + "genpybind returned {code} during the following call:" + "\n{command}\n\n{stdout}\n\n{stderr}".format( + code=proc.returncode, + command=join_args(args), + stdout=stdout, + stderr=stderr, + )) + + if stderr.strip(): + Logs.debug("non-fatal warnings during genpybind run:\n{}".format(stderr)) + + return stdout + + def _include_paths(self): + return self.generator.to_incnodes(self.includes + self.env.INCLUDES) + + def _inputs_as_relative_includes(self): + include_paths = self._include_paths() + relative_includes = [] + for node in self.inputs: + for inc in include_paths: + if node.is_child_of(inc): + relative_includes.append(node.path_from(inc)) + break + else: + self.generator.bld.fatal("could not resolve {}".format(node)) + return relative_includes + + def _arguments(self, genpybind_parse=None, resource_dir=None): + args = [] + relative_includes = self._inputs_as_relative_includes() + is_cxx = "cxx" in self.features + + # options for genpybind + args.extend(["--genpybind-module", self.module]) + if self.genpybind_tags: + args.extend(["--genpybind-tag"] + self.genpybind_tags) + if relative_includes: + args.extend(["--genpybind-include"] + relative_includes) + if genpybind_parse: + args.extend(["--genpybind-parse", genpybind_parse]) + + args.append("--") + + # headers to be processed by genpybind + args.extend(node.abspath() for node in self.inputs) + + args.append("--") + + # options for clang/genpybind-parse + args.append("-D__GENPYBIND__") + args.append("-xc++" if is_cxx else "-xc") + has_std_argument = False + for flag in self.env["CXXFLAGS" if is_cxx else "CFLAGS"]: + flag = flag.replace("-std=gnu", "-std=c") + if flag.startswith("-std=c"): + has_std_argument = True + args.append(flag) + if not has_std_argument: + args.append("-std=c++14") + args.extend("-I{}".format(n.abspath()) for n in self._include_paths()) + args.extend("-D{}".format(p) for p in self.env.DEFINES) + + # point to clang resource dir, if specified + if resource_dir: + args.append("-resource-dir={}".format(resource_dir)) + + return args diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/gob2.py b/ldb-2.0.8/third_party/waf/waflib/extras/gob2.py new file mode 100644 index 0000000..b4fa3b9 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/gob2.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Ali Sabil, 2007 + +from waflib import TaskGen + +TaskGen.declare_chain( + name = 'gob2', + rule = '${GOB2} -o ${TGT[0].bld_dir()} ${GOB2FLAGS} ${SRC}', + ext_in = '.gob', + ext_out = '.c' +) + +def configure(conf): + conf.find_program('gob2', var='GOB2') + conf.env['GOB2FLAGS'] = '' + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/halide.py b/ldb-2.0.8/third_party/waf/waflib/extras/halide.py new file mode 100644 index 0000000..6078e38 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/halide.py @@ -0,0 +1,151 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Halide code generation tool + +__author__ = __maintainer__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2014" + +""" + +Tool to run `Halide `_ code generators. + +Usage:: + + bld( + name='pipeline', + # ^ Reference this in use="..." for things using the generated code + #target=['pipeline.o', 'pipeline.h'] + # ^ by default, name.{o,h} is added, but you can set the outputs here + features='halide', + halide_env="HL_TRACE=1 HL_TARGET=host-opencl-gpu_debug", + # ^ Environment passed to the generator, + # can be a dict, k/v list, or string. + args=[], + # ^ Command-line arguments to the generator (optional), + # eg. to give parameters to the scheduling + source='pipeline_gen', + # ^ Name of the source executable + ) + + +Known issues: + + +- Currently only supports Linux (no ".exe") + +- Doesn't rerun on input modification when input is part of a build + chain, and has been modified externally. + +""" + +import os +from waflib import Task, Utils, Options, TaskGen, Errors + +class run_halide_gen(Task.Task): + color = 'CYAN' + vars = ['HALIDE_ENV', 'HALIDE_ARGS'] + run_str = "${SRC[0].abspath()} ${HALIDE_ARGS}" + def __str__(self): + stuff = "halide" + stuff += ("[%s]" % (",".join( + ('%s=%s' % (k,v)) for k, v in sorted(self.env.env.items())))) + return Task.Task.__str__(self).replace(self.__class__.__name__, + stuff) + +@TaskGen.feature('halide') +@TaskGen.before_method('process_source') +def halide(self): + Utils.def_attrs(self, + args=[], + halide_env={}, + ) + + bld = self.bld + + env = self.halide_env + try: + if isinstance(env, str): + env = dict(x.split('=') for x in env.split()) + elif isinstance(env, list): + env = dict(x.split('=') for x in env) + assert isinstance(env, dict) + except Exception as e: + if not isinstance(e, ValueError) \ + and not isinstance(e, AssertionError): + raise + raise Errors.WafError( + "halide_env must be under the form" \ + " {'HL_x':'a', 'HL_y':'b'}" \ + " or ['HL_x=y', 'HL_y=b']" \ + " or 'HL_x=y HL_y=b'") + + src = self.to_nodes(self.source) + assert len(src) == 1, "Only one source expected" + src = src[0] + + args = Utils.to_list(self.args) + + def change_ext(src, ext): + # Return a node with a new extension, in an appropriate folder + name = src.name + xpos = src.name.rfind('.') + if xpos == -1: + xpos = len(src.name) + newname = name[:xpos] + ext + if src.is_child_of(bld.bldnode): + node = src.get_src().parent.find_or_declare(newname) + else: + node = bld.bldnode.find_or_declare(newname) + return node + + def to_nodes(self, lst, path=None): + tmp = [] + path = path or self.path + find = path.find_or_declare + + if isinstance(lst, self.path.__class__): + lst = [lst] + + for x in Utils.to_list(lst): + if isinstance(x, str): + node = find(x) + else: + node = x + tmp.append(node) + return tmp + + tgt = to_nodes(self, self.target) + if not tgt: + tgt = [change_ext(src, '.o'), change_ext(src, '.h')] + cwd = tgt[0].parent.abspath() + task = self.create_task('run_halide_gen', src, tgt, cwd=cwd) + task.env.append_unique('HALIDE_ARGS', args) + if task.env.env == []: + task.env.env = {} + task.env.env.update(env) + task.env.HALIDE_ENV = " ".join(("%s=%s" % (k,v)) for (k,v) in sorted(env.items())) + task.env.HALIDE_ARGS = args + + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks = [task] + self.source = [] + +def configure(conf): + if Options.options.halide_root is None: + conf.check_cfg(package='Halide', args='--cflags --libs') + else: + halide_root = Options.options.halide_root + conf.env.INCLUDES_HALIDE = [ os.path.join(halide_root, "include") ] + conf.env.LIBPATH_HALIDE = [ os.path.join(halide_root, "lib") ] + conf.env.LIB_HALIDE = ["Halide"] + + # You might want to add this, while upstream doesn't fix it + #conf.env.LIB_HALIDE += ['ncurses', 'dl', 'pthread'] + +def options(opt): + opt.add_option('--halide-root', + help="path to Halide include and lib files", + ) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/javatest.py b/ldb-2.0.8/third_party/waf/waflib/extras/javatest.py new file mode 100755 index 0000000..979b8d8 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/javatest.py @@ -0,0 +1,118 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Federico Pellegrin, 2017 (fedepell) + +""" +Provides Java Unit test support using :py:class:`waflib.Tools.waf_unit_test.utest` +task via the **javatest** feature. + +This gives the possibility to run unit test and have them integrated into the +standard waf unit test environment. It has been tested with TestNG and JUnit +but should be easily expandable to other frameworks given the flexibility of +ut_str provided by the standard waf unit test environment. + +Example usage: + +def options(opt): + opt.load('java waf_unit_test javatest') + +def configure(conf): + conf.load('java javatest') + +def build(bld): + + [ ... mainprog is built here ... ] + + bld(features = 'javac javatest', + srcdir = 'test/', + outdir = 'test', + sourcepath = ['test'], + classpath = [ 'src' ], + basedir = 'test', + use = ['JAVATEST', 'mainprog'], # mainprog is the program being tested in src/ + ut_str = 'java -cp ${CLASSPATH} ${JTRUNNER} ${SRC}', + jtest_source = bld.path.ant_glob('test/*.xml'), + ) + + +At command line the CLASSPATH where to find the testing environment and the +test runner (default TestNG) that will then be seen in the environment as +CLASSPATH_JAVATEST (then used for use) and JTRUNNER and can be used for +dependencies and ut_str generation. + +Example configure for TestNG: + waf configure --jtpath=/tmp/testng-6.12.jar:/tmp/jcommander-1.71.jar --jtrunner=org.testng.TestNG + or as default runner is TestNG: + waf configure --jtpath=/tmp/testng-6.12.jar:/tmp/jcommander-1.71.jar + +Example configure for JUnit: + waf configure --jtpath=/tmp/junit.jar --jtrunner=org.junit.runner.JUnitCore + +The runner class presence on the system is checked for at configuration stage. + +""" + +import os +from waflib import Task, TaskGen, Options + +@TaskGen.feature('javatest') +@TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath') +def make_javatest(self): + """ + Creates a ``utest`` task with a populated environment for Java Unit test execution + + """ + tsk = self.create_task('utest') + tsk.set_run_after(self.javac_task) + + # Put test input files as waf_unit_test relies on that for some prints and log generation + # If jtest_source is there, this is specially useful for passing XML for TestNG + # that contain test specification, use that as inputs, otherwise test sources + if getattr(self, 'jtest_source', None): + tsk.inputs = self.to_nodes(self.jtest_source) + else: + if self.javac_task.srcdir[0].exists(): + tsk.inputs = self.javac_task.srcdir[0].ant_glob('**/*.java', remove=False) + + if getattr(self, 'ut_str', None): + self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) + tsk.vars = lst + tsk.vars + + if getattr(self, 'ut_cwd', None): + if isinstance(self.ut_cwd, str): + # we want a Node instance + if os.path.isabs(self.ut_cwd): + self.ut_cwd = self.bld.root.make_node(self.ut_cwd) + else: + self.ut_cwd = self.path.make_node(self.ut_cwd) + else: + self.ut_cwd = self.bld.bldnode + + # Get parent CLASSPATH and add output dir of test, we run from wscript dir + # We have to change it from list to the standard java -cp format (: separated) + tsk.env.CLASSPATH = ':'.join(self.env.CLASSPATH) + ':' + self.outdir.abspath() + + if not self.ut_cwd.exists(): + self.ut_cwd.mkdir() + + if not hasattr(self, 'ut_env'): + self.ut_env = dict(os.environ) + +def configure(ctx): + cp = ctx.env.CLASSPATH or '.' + if getattr(Options.options, 'jtpath', None): + ctx.env.CLASSPATH_JAVATEST = getattr(Options.options, 'jtpath').split(':') + cp += ':' + getattr(Options.options, 'jtpath') + + if getattr(Options.options, 'jtrunner', None): + ctx.env.JTRUNNER = getattr(Options.options, 'jtrunner') + + if ctx.check_java_class(ctx.env.JTRUNNER, with_classpath=cp): + ctx.fatal('Could not run test class %r' % ctx.env.JTRUNNER) + +def options(opt): + opt.add_option('--jtpath', action='store', default='', dest='jtpath', + help='Path to jar(s) needed for javatest execution, colon separated, if not in the system CLASSPATH') + opt.add_option('--jtrunner', action='store', default='org.testng.TestNG', dest='jtrunner', + help='Class to run javatest test [default: org.testng.TestNG]') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/kde4.py b/ldb-2.0.8/third_party/waf/waflib/extras/kde4.py new file mode 100644 index 0000000..aed9bfb --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/kde4.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2010 (ita) + +""" +Support for the KDE4 libraries and msgfmt +""" + +import os, re +from waflib import Task, Utils +from waflib.TaskGen import feature + +@feature('msgfmt') +def apply_msgfmt(self): + """ + Process all languages to create .mo files and to install them:: + + def build(bld): + bld(features='msgfmt', langs='es de fr', appname='myapp', install_path='${KDE4_LOCALE_INSTALL_DIR}') + """ + for lang in self.to_list(self.langs): + node = self.path.find_resource(lang+'.po') + task = self.create_task('msgfmt', node, node.change_ext('.mo')) + + langname = lang.split('/') + langname = langname[-1] + + inst = getattr(self, 'install_path', '${KDE4_LOCALE_INSTALL_DIR}') + + self.add_install_as( + inst_to = inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + getattr(self, 'appname', 'set_your_appname') + '.mo', + inst_from = task.outputs[0], + chmod = getattr(self, 'chmod', Utils.O644)) + +class msgfmt(Task.Task): + """ + Transform .po files into .mo files + """ + color = 'BLUE' + run_str = '${MSGFMT} ${SRC} -o ${TGT}' + +def configure(self): + """ + Detect kde4-config and set various variables for the *use* system:: + + def options(opt): + opt.load('compiler_cxx kde4') + def configure(conf): + conf.load('compiler_cxx kde4') + def build(bld): + bld.program(source='main.c', target='app', use='KDECORE KIO KHTML') + """ + kdeconfig = self.find_program('kde4-config') + prefix = self.cmd_and_log(kdeconfig + ['--prefix']).strip() + fname = '%s/share/apps/cmake/modules/KDELibsDependencies.cmake' % prefix + try: + os.stat(fname) + except OSError: + fname = '%s/share/kde4/apps/cmake/modules/KDELibsDependencies.cmake' % prefix + try: + os.stat(fname) + except OSError: + self.fatal('could not open %s' % fname) + + try: + txt = Utils.readf(fname) + except EnvironmentError: + self.fatal('could not read %s' % fname) + + txt = txt.replace('\\\n', '\n') + fu = re.compile('#(.*)\n') + txt = fu.sub('', txt) + + setregexp = re.compile(r'([sS][eE][tT]\s*\()\s*([^\s]+)\s+\"([^"]+)\"\)') + found = setregexp.findall(txt) + + for (_, key, val) in found: + #print key, val + self.env[key] = val + + # well well, i could just write an interpreter for cmake files + self.env['LIB_KDECORE']= ['kdecore'] + self.env['LIB_KDEUI'] = ['kdeui'] + self.env['LIB_KIO'] = ['kio'] + self.env['LIB_KHTML'] = ['khtml'] + self.env['LIB_KPARTS'] = ['kparts'] + + self.env['LIBPATH_KDECORE'] = [os.path.join(self.env.KDE4_LIB_INSTALL_DIR, 'kde4', 'devel'), self.env.KDE4_LIB_INSTALL_DIR] + self.env['INCLUDES_KDECORE'] = [self.env['KDE4_INCLUDE_INSTALL_DIR']] + self.env.append_value('INCLUDES_KDECORE', [self.env['KDE4_INCLUDE_INSTALL_DIR']+ os.sep + 'KDE']) + + self.find_program('msgfmt', var='MSGFMT') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/local_rpath.py b/ldb-2.0.8/third_party/waf/waflib/extras/local_rpath.py new file mode 100644 index 0000000..e3923d9 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/local_rpath.py @@ -0,0 +1,21 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011 (ita) + +import copy +from waflib.TaskGen import after_method, feature + +@after_method('propagate_uselib_vars') +@feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib', 'fcprogram', 'fcshlib') +def add_rpath_stuff(self): + all = copy.copy(self.to_list(getattr(self, 'use', []))) + while all: + name = all.pop() + try: + tg = self.bld.get_tgen_by_name(name) + except: + continue + if hasattr(tg, 'link_task'): + self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) + all.extend(self.to_list(getattr(tg, 'use', []))) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/make.py b/ldb-2.0.8/third_party/waf/waflib/extras/make.py new file mode 100644 index 0000000..933d9ca --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/make.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011 (ita) + +""" +A make-like way of executing the build, following the relationships between inputs/outputs + +This algorithm will lead to slower builds, will not be as flexible as "waf build", but +it might be useful for building data files (?) + +It is likely to break in the following cases: +- files are created dynamically (no inputs or outputs) +- headers +- building two files from different groups +""" + +import re +from waflib import Options, Task +from waflib.Build import BuildContext + +class MakeContext(BuildContext): + '''executes tasks in a step-by-step manner, following dependencies between inputs/outputs''' + cmd = 'make' + fun = 'build' + + def __init__(self, **kw): + super(MakeContext, self).__init__(**kw) + self.files = Options.options.files + + def get_build_iterator(self): + if not self.files: + while 1: + yield super(MakeContext, self).get_build_iterator() + + for g in self.groups: + for tg in g: + try: + f = tg.post + except AttributeError: + pass + else: + f() + + provides = {} + uses = {} + all_tasks = [] + tasks = [] + for pat in self.files.split(','): + matcher = self.get_matcher(pat) + for tg in g: + if isinstance(tg, Task.Task): + lst = [tg] + else: + lst = tg.tasks + for tsk in lst: + all_tasks.append(tsk) + + do_exec = False + for node in tsk.inputs: + try: + uses[node].append(tsk) + except: + uses[node] = [tsk] + + if matcher(node, output=False): + do_exec = True + break + + for node in tsk.outputs: + try: + provides[node].append(tsk) + except: + provides[node] = [tsk] + + if matcher(node, output=True): + do_exec = True + break + if do_exec: + tasks.append(tsk) + + # so we have the tasks that we need to process, the list of all tasks, + # the map of the tasks providing nodes, and the map of tasks using nodes + + if not tasks: + # if there are no tasks matching, return everything in the current group + result = all_tasks + else: + # this is like a big filter... + result = set() + seen = set() + cur = set(tasks) + while cur: + result |= cur + tosee = set() + for tsk in cur: + for node in tsk.inputs: + if node in seen: + continue + seen.add(node) + tosee |= set(provides.get(node, [])) + cur = tosee + result = list(result) + + Task.set_file_constraints(result) + Task.set_precedence_constraints(result) + yield result + + while 1: + yield [] + + def get_matcher(self, pat): + # this returns a function + inn = True + out = True + if pat.startswith('in:'): + out = False + pat = pat.replace('in:', '') + elif pat.startswith('out:'): + inn = False + pat = pat.replace('out:', '') + + anode = self.root.find_node(pat) + pattern = None + if not anode: + if not pat.startswith('^'): + pat = '^.+?%s' % pat + if not pat.endswith('$'): + pat = '%s$' % pat + pattern = re.compile(pat) + + def match(node, output): + if output and not out: + return False + if not output and not inn: + return False + + if anode: + return anode == node + else: + return pattern.match(node.abspath()) + return match + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/midl.py b/ldb-2.0.8/third_party/waf/waflib/extras/midl.py new file mode 100644 index 0000000..43e6cf9 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/midl.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# Issue 1185 ultrix gmail com + +""" +Microsoft Interface Definition Language support. Given ComObject.idl, this tool +will generate ComObject.tlb ComObject_i.h ComObject_i.c ComObject_p.c and dlldata.c + +To declare targets using midl:: + + def configure(conf): + conf.load('msvc') + conf.load('midl') + + def build(bld): + bld( + features='c cshlib', + # Note: ComObject_i.c is generated from ComObject.idl + source = 'main.c ComObject.idl ComObject_i.c', + target = 'ComObject.dll') +""" + +from waflib import Task, Utils +from waflib.TaskGen import feature, before_method +import os + +def configure(conf): + conf.find_program(['midl'], var='MIDL') + + conf.env.MIDLFLAGS = [ + '/nologo', + '/D', + '_DEBUG', + '/W1', + '/char', + 'signed', + '/Oicf', + ] + +@feature('c', 'cxx') +@before_method('process_source') +def idl_file(self): + # Do this before process_source so that the generated header can be resolved + # when scanning source dependencies. + idl_nodes = [] + src_nodes = [] + for node in Utils.to_list(self.source): + if str(node).endswith('.idl'): + idl_nodes.append(node) + else: + src_nodes.append(node) + + for node in self.to_nodes(idl_nodes): + t = node.change_ext('.tlb') + h = node.change_ext('_i.h') + c = node.change_ext('_i.c') + p = node.change_ext('_p.c') + d = node.parent.find_or_declare('dlldata.c') + self.create_task('midl', node, [t, h, c, p, d]) + + self.source = src_nodes + +class midl(Task.Task): + """ + Compile idl files + """ + color = 'YELLOW' + run_str = '${MIDL} ${MIDLFLAGS} ${CPPPATH_ST:INCLUDES} /tlb ${TGT[0].bldpath()} /header ${TGT[1].bldpath()} /iid ${TGT[2].bldpath()} /proxy ${TGT[3].bldpath()} /dlldata ${TGT[4].bldpath()} ${SRC}' + before = ['winrc'] + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/msvcdeps.py b/ldb-2.0.8/third_party/waf/waflib/extras/msvcdeps.py new file mode 100644 index 0000000..873a419 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/msvcdeps.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Copyright Garmin International or its subsidiaries, 2012-2013 + +''' +Off-load dependency scanning from Python code to MSVC compiler + +This tool is safe to load in any environment; it will only activate the +MSVC exploits when it finds that a particular taskgen uses MSVC to +compile. + +Empirical testing shows about a 10% execution time savings from using +this tool as compared to c_preproc. + +The technique of gutting scan() and pushing the dependency calculation +down to post_run() is cribbed from gccdeps.py. + +This affects the cxx class, so make sure to load Qt5 after this tool. + +Usage:: + + def options(opt): + opt.load('compiler_cxx') + def configure(conf): + conf.load('compiler_cxx msvcdeps') +''' + +import os, sys, tempfile, threading + +from waflib import Context, Errors, Logs, Task, Utils +from waflib.Tools import c_preproc, c, cxx, msvc +from waflib.TaskGen import feature, before_method + +lock = threading.Lock() +nodes = {} # Cache the path -> Node lookup + +PREPROCESSOR_FLAG = '/showIncludes' +INCLUDE_PATTERN = 'Note: including file:' + +# Extensible by outside tools +supported_compilers = ['msvc'] + +@feature('c', 'cxx') +@before_method('process_source') +def apply_msvcdeps_flags(taskgen): + if taskgen.env.CC_NAME not in supported_compilers: + return + + for flag in ('CFLAGS', 'CXXFLAGS'): + if taskgen.env.get_flat(flag).find(PREPROCESSOR_FLAG) < 0: + taskgen.env.append_value(flag, PREPROCESSOR_FLAG) + +def path_to_node(base_node, path, cached_nodes): + ''' + Take the base node and the path and return a node + Results are cached because searching the node tree is expensive + The following code is executed by threads, it is not safe, so a lock is needed... + ''' + # normalize the path because ant_glob() does not understand + # parent path components (..) + path = os.path.normpath(path) + + # normalize the path case to increase likelihood of a cache hit + path = os.path.normcase(path) + + # ant_glob interprets [] and () characters, so those must be replaced + path = path.replace('[', '?').replace(']', '?').replace('(', '[(]').replace(')', '[)]') + + node_lookup_key = (base_node, path) + + try: + node = cached_nodes[node_lookup_key] + except KeyError: + # retry with lock on cache miss + with lock: + try: + node = cached_nodes[node_lookup_key] + except KeyError: + node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True, regex=False) + node = cached_nodes[node_lookup_key] = node_list[0] if node_list else None + + return node + +def post_run(self): + if self.env.CC_NAME not in supported_compilers: + return super(self.derived_msvcdeps, self).post_run() + + # TODO this is unlikely to work with netcache + if getattr(self, 'cached', None): + return Task.Task.post_run(self) + + bld = self.generator.bld + unresolved_names = [] + resolved_nodes = [] + + # Dynamically bind to the cache + try: + cached_nodes = bld.cached_nodes + except AttributeError: + cached_nodes = bld.cached_nodes = {} + + for path in self.msvcdeps_paths: + node = None + if os.path.isabs(path): + node = path_to_node(bld.root, path, cached_nodes) + else: + # when calling find_resource, make sure the path does not begin with '..' + base_node = bld.bldnode + path = [k for k in Utils.split_path(path) if k and k != '.'] + while path[0] == '..': + path.pop(0) + base_node = base_node.parent + path = os.sep.join(path) + + node = path_to_node(base_node, path, cached_nodes) + + if not node: + raise ValueError('could not find %r for %r' % (path, self)) + else: + if not c_preproc.go_absolute: + if not (node.is_child_of(bld.srcnode) or node.is_child_of(bld.bldnode)): + # System library + Logs.debug('msvcdeps: Ignoring system include %r', node) + continue + + if id(node) == id(self.inputs[0]): + # Self-dependency + continue + + resolved_nodes.append(node) + + bld.node_deps[self.uid()] = resolved_nodes + bld.raw_deps[self.uid()] = unresolved_names + + try: + del self.cache_sig + except AttributeError: + pass + + Task.Task.post_run(self) + +def scan(self): + if self.env.CC_NAME not in supported_compilers: + return super(self.derived_msvcdeps, self).scan() + + resolved_nodes = self.generator.bld.node_deps.get(self.uid(), []) + unresolved_names = [] + return (resolved_nodes, unresolved_names) + +def sig_implicit_deps(self): + if self.env.CC_NAME not in supported_compilers: + return super(self.derived_msvcdeps, self).sig_implicit_deps() + + try: + return Task.Task.sig_implicit_deps(self) + except Errors.WafError: + return Utils.SIG_NIL + +def exec_command(self, cmd, **kw): + if self.env.CC_NAME not in supported_compilers: + return super(self.derived_msvcdeps, self).exec_command(cmd, **kw) + + if not 'cwd' in kw: + kw['cwd'] = self.get_cwd() + + if self.env.PATH: + env = kw['env'] = dict(kw.get('env') or self.env.env or os.environ) + env['PATH'] = self.env.PATH if isinstance(self.env.PATH, str) else os.pathsep.join(self.env.PATH) + + # The Visual Studio IDE adds an environment variable that causes + # the MS compiler to send its textual output directly to the + # debugging window rather than normal stdout/stderr. + # + # This is unrecoverably bad for this tool because it will cause + # all the dependency scanning to see an empty stdout stream and + # assume that the file being compiled uses no headers. + # + # See http://blogs.msdn.com/b/freik/archive/2006/04/05/569025.aspx + # + # Attempting to repair the situation by deleting the offending + # envvar at this point in tool execution will not be good enough-- + # its presence poisons the 'waf configure' step earlier. We just + # want to put a sanity check here in order to help developers + # quickly diagnose the issue if an otherwise-good Waf tree + # is then executed inside the MSVS IDE. + assert 'VS_UNICODE_OUTPUT' not in kw['env'] + + cmd, args = self.split_argfile(cmd) + try: + (fd, tmp) = tempfile.mkstemp() + os.write(fd, '\r\n'.join(args).encode()) + os.close(fd) + + self.msvcdeps_paths = [] + kw['env'] = kw.get('env', os.environ.copy()) + kw['cwd'] = kw.get('cwd', os.getcwd()) + kw['quiet'] = Context.STDOUT + kw['output'] = Context.STDOUT + + out = [] + if Logs.verbose: + Logs.debug('argfile: @%r -> %r', tmp, args) + try: + raw_out = self.generator.bld.cmd_and_log(cmd + ['@' + tmp], **kw) + ret = 0 + except Errors.WafError as e: + # Use e.msg if e.stdout is not set + raw_out = getattr(e, 'stdout', e.msg) + + # Return non-zero error code even if we didn't + # get one from the exception object + ret = getattr(e, 'returncode', 1) + + for line in raw_out.splitlines(): + if line.startswith(INCLUDE_PATTERN): + inc_path = line[len(INCLUDE_PATTERN):].strip() + Logs.debug('msvcdeps: Regex matched %s', inc_path) + self.msvcdeps_paths.append(inc_path) + else: + out.append(line) + + # Pipe through the remaining stdout content (not related to /showIncludes) + if self.generator.bld.logger: + self.generator.bld.logger.debug('out: %s' % os.linesep.join(out)) + else: + sys.stdout.write(os.linesep.join(out) + os.linesep) + + return ret + finally: + try: + os.remove(tmp) + except OSError: + # anti-virus and indexers can keep files open -_- + pass + + +def wrap_compiled_task(classname): + derived_class = type(classname, (Task.classes[classname],), {}) + derived_class.derived_msvcdeps = derived_class + derived_class.post_run = post_run + derived_class.scan = scan + derived_class.sig_implicit_deps = sig_implicit_deps + derived_class.exec_command = exec_command + +for k in ('c', 'cxx'): + if k in Task.classes: + wrap_compiled_task(k) + +def options(opt): + raise ValueError('Do not load msvcdeps options') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/msvs.py b/ldb-2.0.8/third_party/waf/waflib/extras/msvs.py new file mode 100644 index 0000000..8aa2db0 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/msvs.py @@ -0,0 +1,1048 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Avalanche Studios 2009-2011 +# Thomas Nagy 2011 + +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +""" +To add this tool to your project: +def options(conf): + opt.load('msvs') + +It can be a good idea to add the sync_exec tool too. + +To generate solution files: +$ waf configure msvs + +To customize the outputs, provide subclasses in your wscript files:: + + from waflib.extras import msvs + class vsnode_target(msvs.vsnode_target): + def get_build_command(self, props): + # likely to be required + return "waf.bat build" + def collect_source(self): + # likely to be required + ... + class msvs_bar(msvs.msvs_generator): + def init(self): + msvs.msvs_generator.init(self) + self.vsnode_target = vsnode_target + +The msvs class re-uses the same build() function for reading the targets (task generators), +you may therefore specify msvs settings on the context object:: + + def build(bld): + bld.solution_name = 'foo.sln' + bld.waf_command = 'waf.bat' + bld.projects_dir = bld.srcnode.make_node('.depproj') + bld.projects_dir.mkdir() + +For visual studio 2008, the command is called 'msvs2008', and the classes +such as vsnode_target are wrapped by a decorator class 'wrap_2008' to +provide special functionality. + +To customize platform toolsets, pass additional parameters, for example:: + + class msvs_2013(msvs.msvs_generator): + cmd = 'msvs2013' + numver = '13.00' + vsver = '2013' + platform_toolset_ver = 'v120' + +ASSUMPTIONS: +* a project can be either a directory or a target, vcxproj files are written only for targets that have source files +* each project is a vcxproj file, therefore the project uuid needs only to be a hash of the absolute path +""" + +import os, re, sys +import uuid # requires python 2.5 +from waflib.Build import BuildContext +from waflib import Utils, TaskGen, Logs, Task, Context, Node, Options + +HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' + +PROJECT_TEMPLATE = r''' + + + + ${for b in project.build_properties} + + ${b.configuration} + ${b.platform} + + ${endfor} + + + + {${project.uuid}} + MakeFileProj + ${project.name} + + + + ${for b in project.build_properties} + + Makefile + ${b.outdir} + ${project.platform_toolset_ver} + + ${endfor} + + + + + + ${for b in project.build_properties} + + + + ${endfor} + + ${for b in project.build_properties} + + ${xml:project.get_build_command(b)} + ${xml:project.get_rebuild_command(b)} + ${xml:project.get_clean_command(b)} + ${xml:b.includes_search_path} + ${xml:b.preprocessor_definitions};$(NMakePreprocessorDefinitions) + ${xml:b.includes_search_path} + $(ExecutablePath) + + ${if getattr(b, 'output_file', None)} + ${xml:b.output_file} + ${endif} + ${if getattr(b, 'deploy_dir', None)} + ${xml:b.deploy_dir} + ${endif} + + ${endfor} + + ${for b in project.build_properties} + ${if getattr(b, 'deploy_dir', None)} + + + CopyToHardDrive + + + ${endif} + ${endfor} + + + ${for x in project.source} + <${project.get_key(x)} Include='${x.win32path()}' /> + ${endfor} + + + + + +''' + +FILTER_TEMPLATE = ''' + + + ${for x in project.source} + <${project.get_key(x)} Include="${x.win32path()}"> + ${project.get_filter_name(x.parent)} + + ${endfor} + + + ${for x in project.dirs()} + + {${project.make_uuid(x.win32path())}} + + ${endfor} + + +''' + +PROJECT_2008_TEMPLATE = r''' + + + ${if project.build_properties} + ${for b in project.build_properties} + + ${endfor} + ${else} + + ${endif} + + + + + ${if project.build_properties} + ${for b in project.build_properties} + + + + ${endfor} + ${else} + + + ${endif} + + + + +${project.display_filter()} + + +''' + +SOLUTION_TEMPLATE = '''Microsoft Visual Studio Solution File, Format Version ${project.numver} +# Visual Studio ${project.vsver} +${for p in project.all_projects} +Project("{${p.ptype()}}") = "${p.name}", "${p.title}", "{${p.uuid}}" +EndProject${endfor} +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + ${if project.all_projects} + ${for (configuration, platform) in project.all_projects[0].ctx.project_configurations()} + ${configuration}|${platform} = ${configuration}|${platform} + ${endfor} + ${endif} + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + ${for p in project.all_projects} + ${if hasattr(p, 'source')} + ${for b in p.build_properties} + {${p.uuid}}.${b.configuration}|${b.platform}.ActiveCfg = ${b.configuration}|${b.platform} + ${if getattr(p, 'is_active', None)} + {${p.uuid}}.${b.configuration}|${b.platform}.Build.0 = ${b.configuration}|${b.platform} + ${endif} + ${if getattr(p, 'is_deploy', None)} + {${p.uuid}}.${b.configuration}|${b.platform}.Deploy.0 = ${b.configuration}|${b.platform} + ${endif} + ${endfor} + ${endif} + ${endfor} + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + ${for p in project.all_projects} + ${if p.parent} + {${p.uuid}} = {${p.parent.uuid}} + ${endif} + ${endfor} + EndGlobalSection +EndGlobal +''' + +COMPILE_TEMPLATE = '''def f(project): + lst = [] + def xml_escape(value): + return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") + + %s + + #f = open('cmd.txt', 'w') + #f.write(str(lst)) + #f.close() + return ''.join(lst) +''' +reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P[^}]*?)\})", re.M) +def compile_template(line): + """ + Compile a template expression into a python function (like jsps, but way shorter) + """ + extr = [] + def repl(match): + g = match.group + if g('dollar'): + return "$" + elif g('backslash'): + return "\\" + elif g('subst'): + extr.append(g('code')) + return "<<|@|>>" + return None + + line2 = reg_act.sub(repl, line) + params = line2.split('<<|@|>>') + assert(extr) + + + indent = 0 + buf = [] + app = buf.append + + def app(txt): + buf.append(indent * '\t' + txt) + + for x in range(len(extr)): + if params[x]: + app("lst.append(%r)" % params[x]) + + f = extr[x] + if f.startswith(('if', 'for')): + app(f + ':') + indent += 1 + elif f.startswith('py:'): + app(f[3:]) + elif f.startswith(('endif', 'endfor')): + indent -= 1 + elif f.startswith(('else', 'elif')): + indent -= 1 + app(f + ':') + indent += 1 + elif f.startswith('xml:'): + app('lst.append(xml_escape(%s))' % f[4:]) + else: + #app('lst.append((%s) or "cannot find %s")' % (f, f)) + app('lst.append(%s)' % f) + + if extr: + if params[-1]: + app("lst.append(%r)" % params[-1]) + + fun = COMPILE_TEMPLATE % "\n\t".join(buf) + #print(fun) + return Task.funex(fun) + + +re_blank = re.compile('(\n|\r|\\s)*\n', re.M) +def rm_blank_lines(txt): + txt = re_blank.sub('\r\n', txt) + return txt + +BOM = '\xef\xbb\xbf' +try: + BOM = bytes(BOM, 'latin-1') # python 3 +except TypeError: + pass + +def stealth_write(self, data, flags='wb'): + try: + unicode + except NameError: + data = data.encode('utf-8') # python 3 + else: + data = data.decode(sys.getfilesystemencoding(), 'replace') + data = data.encode('utf-8') + + if self.name.endswith(('.vcproj', '.vcxproj')): + data = BOM + data + + try: + txt = self.read(flags='rb') + if txt != data: + raise ValueError('must write') + except (IOError, ValueError): + self.write(data, flags=flags) + else: + Logs.debug('msvs: skipping %s', self.win32path()) +Node.Node.stealth_write = stealth_write + +re_win32 = re.compile(r'^([/\\]cygdrive)?[/\\]([a-z])([^a-z0-9_-].*)', re.I) +def win32path(self): + p = self.abspath() + m = re_win32.match(p) + if m: + return "%s:%s" % (m.group(2).upper(), m.group(3)) + return p +Node.Node.win32path = win32path + +re_quote = re.compile("[^a-zA-Z0-9-]") +def quote(s): + return re_quote.sub("_", s) + +def xml_escape(value): + return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") + +def make_uuid(v, prefix = None): + """ + simple utility function + """ + if isinstance(v, dict): + keys = list(v.keys()) + keys.sort() + tmp = str([(k, v[k]) for k in keys]) + else: + tmp = str(v) + d = Utils.md5(tmp.encode()).hexdigest().upper() + if prefix: + d = '%s%s' % (prefix, d[8:]) + gid = uuid.UUID(d, version = 4) + return str(gid).upper() + +def diff(node, fromnode): + # difference between two nodes, but with "(..)" instead of ".." + c1 = node + c2 = fromnode + + c1h = c1.height() + c2h = c2.height() + + lst = [] + up = 0 + + while c1h > c2h: + lst.append(c1.name) + c1 = c1.parent + c1h -= 1 + + while c2h > c1h: + up += 1 + c2 = c2.parent + c2h -= 1 + + while id(c1) != id(c2): + lst.append(c1.name) + up += 1 + + c1 = c1.parent + c2 = c2.parent + + for i in range(up): + lst.append('(..)') + lst.reverse() + return tuple(lst) + +class build_property(object): + pass + +class vsnode(object): + """ + Abstract class representing visual studio elements + We assume that all visual studio nodes have a uuid and a parent + """ + def __init__(self, ctx): + self.ctx = ctx # msvs context + self.name = '' # string, mandatory + self.vspath = '' # path in visual studio (name for dirs, absolute path for projects) + self.uuid = '' # string, mandatory + self.parent = None # parent node for visual studio nesting + + def get_waf(self): + """ + Override in subclasses... + """ + return 'cd /d "%s" & %s' % (self.ctx.srcnode.win32path(), getattr(self.ctx, 'waf_command', 'waf.bat')) + + def ptype(self): + """ + Return a special uuid for projects written in the solution file + """ + pass + + def write(self): + """ + Write the project file, by default, do nothing + """ + pass + + def make_uuid(self, val): + """ + Alias for creating uuid values easily (the templates cannot access global variables) + """ + return make_uuid(val) + +class vsnode_vsdir(vsnode): + """ + Nodes representing visual studio folders (which do not match the filesystem tree!) + """ + VS_GUID_SOLUTIONFOLDER = "2150E333-8FDC-42A3-9474-1A3956D46DE8" + def __init__(self, ctx, uuid, name, vspath=''): + vsnode.__init__(self, ctx) + self.title = self.name = name + self.uuid = uuid + self.vspath = vspath or name + + def ptype(self): + return self.VS_GUID_SOLUTIONFOLDER + +class vsnode_project(vsnode): + """ + Abstract class representing visual studio project elements + A project is assumed to be writable, and has a node representing the file to write to + """ + VS_GUID_VCPROJ = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" + def ptype(self): + return self.VS_GUID_VCPROJ + + def __init__(self, ctx, node): + vsnode.__init__(self, ctx) + self.path = node + self.uuid = make_uuid(node.win32path()) + self.name = node.name + self.platform_toolset_ver = getattr(ctx, 'platform_toolset_ver', None) + self.title = self.path.win32path() + self.source = [] # list of node objects + self.build_properties = [] # list of properties (nmake commands, output dir, etc) + + def dirs(self): + """ + Get the list of parent folders of the source files (header files included) + for writing the filters + """ + lst = [] + def add(x): + if x.height() > self.tg.path.height() and x not in lst: + lst.append(x) + add(x.parent) + for x in self.source: + add(x.parent) + return lst + + def write(self): + Logs.debug('msvs: creating %r', self.path) + + # first write the project file + template1 = compile_template(PROJECT_TEMPLATE) + proj_str = template1(self) + proj_str = rm_blank_lines(proj_str) + self.path.stealth_write(proj_str) + + # then write the filter + template2 = compile_template(FILTER_TEMPLATE) + filter_str = template2(self) + filter_str = rm_blank_lines(filter_str) + tmp = self.path.parent.make_node(self.path.name + '.filters') + tmp.stealth_write(filter_str) + + def get_key(self, node): + """ + required for writing the source files + """ + name = node.name + if name.endswith(('.cpp', '.c')): + return 'ClCompile' + return 'ClInclude' + + def collect_properties(self): + """ + Returns a list of triplet (configuration, platform, output_directory) + """ + ret = [] + for c in self.ctx.configurations: + for p in self.ctx.platforms: + x = build_property() + x.outdir = '' + + x.configuration = c + x.platform = p + + x.preprocessor_definitions = '' + x.includes_search_path = '' + + # can specify "deploy_dir" too + ret.append(x) + self.build_properties = ret + + def get_build_params(self, props): + opt = '--execsolution=%s' % self.ctx.get_solution_node().win32path() + return (self.get_waf(), opt) + + def get_build_command(self, props): + return "%s build %s" % self.get_build_params(props) + + def get_clean_command(self, props): + return "%s clean %s" % self.get_build_params(props) + + def get_rebuild_command(self, props): + return "%s clean build %s" % self.get_build_params(props) + + def get_filter_name(self, node): + lst = diff(node, self.tg.path) + return '\\'.join(lst) or '.' + +class vsnode_alias(vsnode_project): + def __init__(self, ctx, node, name): + vsnode_project.__init__(self, ctx, node) + self.name = name + self.output_file = '' + +class vsnode_build_all(vsnode_alias): + """ + Fake target used to emulate the behaviour of "make all" (starting one process by target is slow) + This is the only alias enabled by default + """ + def __init__(self, ctx, node, name='build_all_projects'): + vsnode_alias.__init__(self, ctx, node, name) + self.is_active = True + +class vsnode_install_all(vsnode_alias): + """ + Fake target used to emulate the behaviour of "make install" + """ + def __init__(self, ctx, node, name='install_all_projects'): + vsnode_alias.__init__(self, ctx, node, name) + + def get_build_command(self, props): + return "%s build install %s" % self.get_build_params(props) + + def get_clean_command(self, props): + return "%s clean %s" % self.get_build_params(props) + + def get_rebuild_command(self, props): + return "%s clean build install %s" % self.get_build_params(props) + +class vsnode_project_view(vsnode_alias): + """ + Fake target used to emulate a file system view + """ + def __init__(self, ctx, node, name='project_view'): + vsnode_alias.__init__(self, ctx, node, name) + self.tg = self.ctx() # fake one, cannot remove + self.exclude_files = Node.exclude_regs + ''' +waf-2* +waf3-2*/** +.waf-2* +.waf3-2*/** +**/*.sdf +**/*.suo +**/*.ncb +**/%s + ''' % Options.lockfile + + def collect_source(self): + # this is likely to be slow + self.source = self.ctx.srcnode.ant_glob('**', excl=self.exclude_files) + + def get_build_command(self, props): + params = self.get_build_params(props) + (self.ctx.cmd,) + return "%s %s %s" % params + + def get_clean_command(self, props): + return "" + + def get_rebuild_command(self, props): + return self.get_build_command(props) + +class vsnode_target(vsnode_project): + """ + Visual studio project representing a targets (programs, libraries, etc) and bound + to a task generator + """ + def __init__(self, ctx, tg): + """ + A project is more or less equivalent to a file/folder + """ + base = getattr(ctx, 'projects_dir', None) or tg.path + node = base.make_node(quote(tg.name) + ctx.project_extension) # the project file as a Node + vsnode_project.__init__(self, ctx, node) + self.name = quote(tg.name) + self.tg = tg # task generator + + def get_build_params(self, props): + """ + Override the default to add the target name + """ + opt = '--execsolution=%s' % self.ctx.get_solution_node().win32path() + if getattr(self, 'tg', None): + opt += " --targets=%s" % self.tg.name + return (self.get_waf(), opt) + + def collect_source(self): + tg = self.tg + source_files = tg.to_nodes(getattr(tg, 'source', [])) + include_dirs = Utils.to_list(getattr(tg, 'msvs_includes', [])) + include_files = [] + for x in include_dirs: + if isinstance(x, str): + x = tg.path.find_node(x) + if x: + lst = [y for y in x.ant_glob(HEADERS_GLOB, flat=False)] + include_files.extend(lst) + + # remove duplicates + self.source.extend(list(set(source_files + include_files))) + self.source.sort(key=lambda x: x.win32path()) + + def collect_properties(self): + """ + Visual studio projects are associated with platforms and configurations (for building especially) + """ + super(vsnode_target, self).collect_properties() + for x in self.build_properties: + x.outdir = self.path.parent.win32path() + x.preprocessor_definitions = '' + x.includes_search_path = '' + + try: + tsk = self.tg.link_task + except AttributeError: + pass + else: + x.output_file = tsk.outputs[0].win32path() + x.preprocessor_definitions = ';'.join(tsk.env.DEFINES) + x.includes_search_path = ';'.join(self.tg.env.INCPATHS) + +class msvs_generator(BuildContext): + '''generates a visual studio 2010 solution''' + cmd = 'msvs' + fun = 'build' + numver = '11.00' # Visual Studio Version Number + vsver = '2010' # Visual Studio Version Year + platform_toolset_ver = 'v110' # Platform Toolset Version Number + + def init(self): + """ + Some data that needs to be present + """ + if not getattr(self, 'configurations', None): + self.configurations = ['Release'] # LocalRelease, RemoteDebug, etc + if not getattr(self, 'platforms', None): + self.platforms = ['Win32'] + if not getattr(self, 'all_projects', None): + self.all_projects = [] + if not getattr(self, 'project_extension', None): + self.project_extension = '.vcxproj' + if not getattr(self, 'projects_dir', None): + self.projects_dir = self.srcnode.make_node('.depproj') + self.projects_dir.mkdir() + + # bind the classes to the object, so that subclass can provide custom generators + if not getattr(self, 'vsnode_vsdir', None): + self.vsnode_vsdir = vsnode_vsdir + if not getattr(self, 'vsnode_target', None): + self.vsnode_target = vsnode_target + if not getattr(self, 'vsnode_build_all', None): + self.vsnode_build_all = vsnode_build_all + if not getattr(self, 'vsnode_install_all', None): + self.vsnode_install_all = vsnode_install_all + if not getattr(self, 'vsnode_project_view', None): + self.vsnode_project_view = vsnode_project_view + + self.numver = self.__class__.numver + self.vsver = self.__class__.vsver + self.platform_toolset_ver = self.__class__.platform_toolset_ver + + def execute(self): + """ + Entry point + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + + # user initialization + self.init() + + # two phases for creating the solution + self.collect_projects() # add project objects into "self.all_projects" + self.write_files() # write the corresponding project and solution files + + def collect_projects(self): + """ + Fill the list self.all_projects with project objects + Fill the list of build targets + """ + self.collect_targets() + self.add_aliases() + self.collect_dirs() + default_project = getattr(self, 'default_project', None) + def sortfun(x): + if x.name == default_project: + return '' + return getattr(x, 'path', None) and x.path.win32path() or x.name + self.all_projects.sort(key=sortfun) + + def write_files(self): + """ + Write the project and solution files from the data collected + so far. It is unlikely that you will want to change this + """ + for p in self.all_projects: + p.write() + + # and finally write the solution file + node = self.get_solution_node() + node.parent.mkdir() + Logs.warn('Creating %r', node) + template1 = compile_template(SOLUTION_TEMPLATE) + sln_str = template1(self) + sln_str = rm_blank_lines(sln_str) + node.stealth_write(sln_str) + + def get_solution_node(self): + """ + The solution filename is required when writing the .vcproj files + return self.solution_node and if it does not exist, make one + """ + try: + return self.solution_node + except AttributeError: + pass + + solution_name = getattr(self, 'solution_name', None) + if not solution_name: + solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '.sln' + if os.path.isabs(solution_name): + self.solution_node = self.root.make_node(solution_name) + else: + self.solution_node = self.srcnode.make_node(solution_name) + return self.solution_node + + def project_configurations(self): + """ + Helper that returns all the pairs (config,platform) + """ + ret = [] + for c in self.configurations: + for p in self.platforms: + ret.append((c, p)) + return ret + + def collect_targets(self): + """ + Process the list of task generators + """ + for g in self.groups: + for tg in g: + if not isinstance(tg, TaskGen.task_gen): + continue + + if not hasattr(tg, 'msvs_includes'): + tg.msvs_includes = tg.to_list(getattr(tg, 'includes', [])) + tg.to_list(getattr(tg, 'export_includes', [])) + tg.post() + if not getattr(tg, 'link_task', None): + continue + + p = self.vsnode_target(self, tg) + p.collect_source() # delegate this processing + p.collect_properties() + self.all_projects.append(p) + + def add_aliases(self): + """ + Add a specific target that emulates the "make all" necessary for Visual studio when pressing F7 + We also add an alias for "make install" (disabled by default) + """ + base = getattr(self, 'projects_dir', None) or self.tg.path + + node_project = base.make_node('build_all_projects' + self.project_extension) # Node + p_build = self.vsnode_build_all(self, node_project) + p_build.collect_properties() + self.all_projects.append(p_build) + + node_project = base.make_node('install_all_projects' + self.project_extension) # Node + p_install = self.vsnode_install_all(self, node_project) + p_install.collect_properties() + self.all_projects.append(p_install) + + node_project = base.make_node('project_view' + self.project_extension) # Node + p_view = self.vsnode_project_view(self, node_project) + p_view.collect_source() + p_view.collect_properties() + self.all_projects.append(p_view) + + n = self.vsnode_vsdir(self, make_uuid(self.srcnode.win32path() + 'build_aliases'), "build_aliases") + p_build.parent = p_install.parent = p_view.parent = n + self.all_projects.append(n) + + def collect_dirs(self): + """ + Create the folder structure in the Visual studio project view + """ + seen = {} + def make_parents(proj): + # look at a project, try to make a parent + if getattr(proj, 'parent', None): + # aliases already have parents + return + x = proj.iter_path + if x in seen: + proj.parent = seen[x] + return + + # There is not vsnode_vsdir for x. + # So create a project representing the folder "x" + n = proj.parent = seen[x] = self.vsnode_vsdir(self, make_uuid(x.win32path()), x.name) + n.iter_path = x.parent + self.all_projects.append(n) + + # recurse up to the project directory + if x.height() > self.srcnode.height() + 1: + make_parents(n) + + for p in self.all_projects[:]: # iterate over a copy of all projects + if not getattr(p, 'tg', None): + # but only projects that have a task generator + continue + + # make a folder for each task generator + p.iter_path = p.tg.path + make_parents(p) + +def wrap_2008(cls): + class dec(cls): + def __init__(self, *k, **kw): + cls.__init__(self, *k, **kw) + self.project_template = PROJECT_2008_TEMPLATE + + def display_filter(self): + + root = build_property() + root.subfilters = [] + root.sourcefiles = [] + root.source = [] + root.name = '' + + @Utils.run_once + def add_path(lst): + if not lst: + return root + child = build_property() + child.subfilters = [] + child.sourcefiles = [] + child.source = [] + child.name = lst[-1] + + par = add_path(lst[:-1]) + par.subfilters.append(child) + return child + + for x in self.source: + # this crap is for enabling subclasses to override get_filter_name + tmp = self.get_filter_name(x.parent) + tmp = tmp != '.' and tuple(tmp.split('\\')) or () + par = add_path(tmp) + par.source.append(x) + + def display(n): + buf = [] + for x in n.source: + buf.append('\n' % (xml_escape(x.win32path()), self.get_key(x))) + for x in n.subfilters: + buf.append('' % xml_escape(x.name)) + buf.append(display(x)) + buf.append('') + return '\n'.join(buf) + + return display(root) + + def get_key(self, node): + """ + If you do not want to let visual studio use the default file extensions, + override this method to return a value: + 0: C/C++ Code, 1: C++ Class, 2: C++ Header File, 3: C++ Form, + 4: C++ Control, 5: Text File, 6: DEF File, 7: IDL File, + 8: Makefile, 9: RGS File, 10: RC File, 11: RES File, 12: XSD File, + 13: XML File, 14: HTML File, 15: CSS File, 16: Bitmap, 17: Icon, + 18: Resx File, 19: BSC File, 20: XSX File, 21: C++ Web Service, + 22: ASAX File, 23: Asp Page, 24: Document, 25: Discovery File, + 26: C# File, 27: eFileTypeClassDiagram, 28: MHTML Document, + 29: Property Sheet, 30: Cursor, 31: Manifest, 32: eFileTypeRDLC + """ + return '' + + def write(self): + Logs.debug('msvs: creating %r', self.path) + template1 = compile_template(self.project_template) + proj_str = template1(self) + proj_str = rm_blank_lines(proj_str) + self.path.stealth_write(proj_str) + + return dec + +class msvs_2008_generator(msvs_generator): + '''generates a visual studio 2008 solution''' + cmd = 'msvs2008' + fun = msvs_generator.fun + numver = '10.00' + vsver = '2008' + + def init(self): + if not getattr(self, 'project_extension', None): + self.project_extension = '_2008.vcproj' + if not getattr(self, 'solution_name', None): + self.solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '_2008.sln' + + if not getattr(self, 'vsnode_target', None): + self.vsnode_target = wrap_2008(vsnode_target) + if not getattr(self, 'vsnode_build_all', None): + self.vsnode_build_all = wrap_2008(vsnode_build_all) + if not getattr(self, 'vsnode_install_all', None): + self.vsnode_install_all = wrap_2008(vsnode_install_all) + if not getattr(self, 'vsnode_project_view', None): + self.vsnode_project_view = wrap_2008(vsnode_project_view) + + msvs_generator.init(self) + +def options(ctx): + """ + If the msvs option is used, try to detect if the build is made from visual studio + """ + ctx.add_option('--execsolution', action='store', help='when building with visual studio, use a build state file') + + old = BuildContext.execute + def override_build_state(ctx): + def lock(rm, add): + uns = ctx.options.execsolution.replace('.sln', rm) + uns = ctx.root.make_node(uns) + try: + uns.delete() + except OSError: + pass + + uns = ctx.options.execsolution.replace('.sln', add) + uns = ctx.root.make_node(uns) + try: + uns.write('') + except EnvironmentError: + pass + + if ctx.options.execsolution: + ctx.launch_dir = Context.top_dir # force a build for the whole project (invalid cwd when called by visual studio) + lock('.lastbuildstate', '.unsuccessfulbuild') + old(ctx) + lock('.unsuccessfulbuild', '.lastbuildstate') + else: + old(ctx) + BuildContext.execute = override_build_state + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/netcache_client.py b/ldb-2.0.8/third_party/waf/waflib/extras/netcache_client.py new file mode 100644 index 0000000..dc49048 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/netcache_client.py @@ -0,0 +1,390 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011-2015 (ita) + +""" +A client for the network cache (playground/netcache/). Launch the server with: +./netcache_server, then use it for the builds by adding the following: + + def build(bld): + bld.load('netcache_client') + +The parameters should be present in the environment in the form: + NETCACHE=host:port waf configure build + +Or in a more detailed way: + NETCACHE_PUSH=host:port NETCACHE_PULL=host:port waf configure build + +where: + host: host where the server resides, by default localhost + port: by default push on 11001 and pull on 12001 + +Use the server provided in playground/netcache/Netcache.java +""" + +import os, socket, time, atexit, sys +from waflib import Task, Logs, Utils, Build, Runner +from waflib.Configure import conf + +BUF = 8192 * 16 +HEADER_SIZE = 128 +MODES = ['PUSH', 'PULL', 'PUSH_PULL'] +STALE_TIME = 30 # seconds + +GET = 'GET' +PUT = 'PUT' +LST = 'LST' +BYE = 'BYE' + +all_sigs_in_cache = (0.0, []) + +def put_data(conn, data): + if sys.hexversion > 0x3000000: + data = data.encode('latin-1') + cnt = 0 + while cnt < len(data): + sent = conn.send(data[cnt:]) + if sent == 0: + raise RuntimeError('connection ended') + cnt += sent + +push_connections = Runner.Queue(0) +pull_connections = Runner.Queue(0) +def get_connection(push=False): + # return a new connection... do not forget to release it! + try: + if push: + ret = push_connections.get(block=False) + else: + ret = pull_connections.get(block=False) + except Exception: + ret = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if push: + ret.connect(Task.push_addr) + else: + ret.connect(Task.pull_addr) + return ret + +def release_connection(conn, msg='', push=False): + if conn: + if push: + push_connections.put(conn) + else: + pull_connections.put(conn) + +def close_connection(conn, msg=''): + if conn: + data = '%s,%s' % (BYE, msg) + try: + put_data(conn, data.ljust(HEADER_SIZE)) + except: + pass + try: + conn.close() + except: + pass + +def close_all(): + for q in (push_connections, pull_connections): + while q.qsize(): + conn = q.get() + try: + close_connection(conn) + except: + # ignore errors when cleaning up + pass +atexit.register(close_all) + +def read_header(conn): + cnt = 0 + buf = [] + while cnt < HEADER_SIZE: + data = conn.recv(HEADER_SIZE - cnt) + if not data: + #import traceback + #traceback.print_stack() + raise ValueError('connection ended when reading a header %r' % buf) + buf.append(data) + cnt += len(data) + if sys.hexversion > 0x3000000: + ret = ''.encode('latin-1').join(buf) + ret = ret.decode('latin-1') + else: + ret = ''.join(buf) + return ret + +def check_cache(conn, ssig): + """ + List the files on the server, this is an optimization because it assumes that + concurrent builds are rare + """ + global all_sigs_in_cache + if not STALE_TIME: + return + if time.time() - all_sigs_in_cache[0] > STALE_TIME: + + params = (LST,'') + put_data(conn, ','.join(params).ljust(HEADER_SIZE)) + + # read what is coming back + ret = read_header(conn) + size = int(ret.split(',')[0]) + + buf = [] + cnt = 0 + while cnt < size: + data = conn.recv(min(BUF, size-cnt)) + if not data: + raise ValueError('connection ended %r %r' % (cnt, size)) + buf.append(data) + cnt += len(data) + + if sys.hexversion > 0x3000000: + ret = ''.encode('latin-1').join(buf) + ret = ret.decode('latin-1') + else: + ret = ''.join(buf) + + all_sigs_in_cache = (time.time(), ret.splitlines()) + Logs.debug('netcache: server cache has %r entries', len(all_sigs_in_cache[1])) + + if not ssig in all_sigs_in_cache[1]: + raise ValueError('no file %s in cache' % ssig) + +class MissingFile(Exception): + pass + +def recv_file(conn, ssig, count, p): + check_cache(conn, ssig) + + params = (GET, ssig, str(count)) + put_data(conn, ','.join(params).ljust(HEADER_SIZE)) + data = read_header(conn) + + size = int(data.split(',')[0]) + + if size == -1: + raise MissingFile('no file %s - %s in cache' % (ssig, count)) + + # get the file, writing immediately + # TODO a tmp file would be better + f = open(p, 'wb') + cnt = 0 + while cnt < size: + data = conn.recv(min(BUF, size-cnt)) + if not data: + raise ValueError('connection ended %r %r' % (cnt, size)) + f.write(data) + cnt += len(data) + f.close() + +def sock_send(conn, ssig, cnt, p): + #print "pushing %r %r %r" % (ssig, cnt, p) + size = os.stat(p).st_size + params = (PUT, ssig, str(cnt), str(size)) + put_data(conn, ','.join(params).ljust(HEADER_SIZE)) + f = open(p, 'rb') + cnt = 0 + while cnt < size: + r = f.read(min(BUF, size-cnt)) + while r: + k = conn.send(r) + if not k: + raise ValueError('connection ended') + cnt += k + r = r[k:] + +def can_retrieve_cache(self): + if not Task.pull_addr: + return False + if not self.outputs: + return False + self.cached = False + + cnt = 0 + sig = self.signature() + ssig = Utils.to_hex(self.uid() + sig) + + conn = None + err = False + try: + try: + conn = get_connection() + for node in self.outputs: + p = node.abspath() + recv_file(conn, ssig, cnt, p) + cnt += 1 + except MissingFile as e: + Logs.debug('netcache: file is not in the cache %r', e) + err = True + except Exception as e: + Logs.debug('netcache: could not get the files %r', self.outputs) + if Logs.verbose > 1: + Logs.debug('netcache: exception %r', e) + err = True + + # broken connection? remove this one + close_connection(conn) + conn = None + else: + Logs.debug('netcache: obtained %r from cache', self.outputs) + + finally: + release_connection(conn) + if err: + return False + + self.cached = True + return True + +@Utils.run_once +def put_files_cache(self): + if not Task.push_addr: + return + if not self.outputs: + return + if getattr(self, 'cached', None): + return + + #print "called put_files_cache", id(self) + bld = self.generator.bld + sig = self.signature() + ssig = Utils.to_hex(self.uid() + sig) + + conn = None + cnt = 0 + try: + for node in self.outputs: + # We could re-create the signature of the task with the signature of the outputs + # in practice, this means hashing the output files + # this is unnecessary + try: + if not conn: + conn = get_connection(push=True) + sock_send(conn, ssig, cnt, node.abspath()) + Logs.debug('netcache: sent %r', node) + except Exception as e: + Logs.debug('netcache: could not push the files %r', e) + + # broken connection? remove this one + close_connection(conn) + conn = None + cnt += 1 + finally: + release_connection(conn, push=True) + + bld.task_sigs[self.uid()] = self.cache_sig + +def hash_env_vars(self, env, vars_lst): + # reimplement so that the resulting hash does not depend on local paths + if not env.table: + env = env.parent + if not env: + return Utils.SIG_NIL + + idx = str(id(env)) + str(vars_lst) + try: + cache = self.cache_env + except AttributeError: + cache = self.cache_env = {} + else: + try: + return self.cache_env[idx] + except KeyError: + pass + + v = str([env[a] for a in vars_lst]) + v = v.replace(self.srcnode.abspath().__repr__()[:-1], '') + m = Utils.md5() + m.update(v.encode()) + ret = m.digest() + + Logs.debug('envhash: %r %r', ret, v) + + cache[idx] = ret + + return ret + +def uid(self): + # reimplement so that the signature does not depend on local paths + try: + return self.uid_ + except AttributeError: + m = Utils.md5() + src = self.generator.bld.srcnode + up = m.update + up(self.__class__.__name__.encode()) + for x in self.inputs + self.outputs: + up(x.path_from(src).encode()) + self.uid_ = m.digest() + return self.uid_ + + +def make_cached(cls): + if getattr(cls, 'nocache', None): + return + + m1 = cls.run + def run(self): + if getattr(self, 'nocache', False): + return m1(self) + if self.can_retrieve_cache(): + return 0 + return m1(self) + cls.run = run + + m2 = cls.post_run + def post_run(self): + if getattr(self, 'nocache', False): + return m2(self) + bld = self.generator.bld + ret = m2(self) + if bld.cache_global: + self.put_files_cache() + if hasattr(self, 'chmod'): + for node in self.outputs: + os.chmod(node.abspath(), self.chmod) + return ret + cls.post_run = post_run + +@conf +def setup_netcache(ctx, push_addr, pull_addr): + Task.Task.can_retrieve_cache = can_retrieve_cache + Task.Task.put_files_cache = put_files_cache + Task.Task.uid = uid + Task.push_addr = push_addr + Task.pull_addr = pull_addr + Build.BuildContext.hash_env_vars = hash_env_vars + ctx.cache_global = True + + for x in Task.classes.values(): + make_cached(x) + +def build(bld): + if not 'NETCACHE' in os.environ and not 'NETCACHE_PULL' in os.environ and not 'NETCACHE_PUSH' in os.environ: + Logs.warn('Setting NETCACHE_PULL=127.0.0.1:11001 and NETCACHE_PUSH=127.0.0.1:12001') + os.environ['NETCACHE_PULL'] = '127.0.0.1:12001' + os.environ['NETCACHE_PUSH'] = '127.0.0.1:11001' + + if 'NETCACHE' in os.environ: + if not 'NETCACHE_PUSH' in os.environ: + os.environ['NETCACHE_PUSH'] = os.environ['NETCACHE'] + if not 'NETCACHE_PULL' in os.environ: + os.environ['NETCACHE_PULL'] = os.environ['NETCACHE'] + + v = os.environ['NETCACHE_PULL'] + if v: + h, p = v.split(':') + pull_addr = (h, int(p)) + else: + pull_addr = None + + v = os.environ['NETCACHE_PUSH'] + if v: + h, p = v.split(':') + push_addr = (h, int(p)) + else: + push_addr = None + + setup_netcache(bld, push_addr, pull_addr) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/objcopy.py b/ldb-2.0.8/third_party/waf/waflib/extras/objcopy.py new file mode 100644 index 0000000..bb7ca6e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/objcopy.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +# Grygoriy Fuchedzhy 2010 + +""" +Support for converting linked targets to ihex, srec or binary files using +objcopy. Use the 'objcopy' feature in conjunction with the 'cc' or 'cxx' +feature. The 'objcopy' feature uses the following attributes: + +objcopy_bfdname Target object format name (eg. ihex, srec, binary). + Defaults to ihex. +objcopy_target File name used for objcopy output. This defaults to the + target name with objcopy_bfdname as extension. +objcopy_install_path Install path for objcopy_target file. Defaults to ${PREFIX}/fw. +objcopy_flags Additional flags passed to objcopy. +""" + +from waflib.Utils import def_attrs +from waflib import Task, Options +from waflib.TaskGen import feature, after_method + +class objcopy(Task.Task): + run_str = '${OBJCOPY} -O ${TARGET_BFDNAME} ${OBJCOPYFLAGS} ${SRC} ${TGT}' + color = 'CYAN' + +@feature('objcopy') +@after_method('apply_link') +def map_objcopy(self): + def_attrs(self, + objcopy_bfdname = 'ihex', + objcopy_target = None, + objcopy_install_path = "${PREFIX}/firmware", + objcopy_flags = '') + + link_output = self.link_task.outputs[0] + if not self.objcopy_target: + self.objcopy_target = link_output.change_ext('.' + self.objcopy_bfdname).name + task = self.create_task('objcopy', src=link_output, tgt=self.path.find_or_declare(self.objcopy_target)) + + task.env.append_unique('TARGET_BFDNAME', self.objcopy_bfdname) + try: + task.env.append_unique('OBJCOPYFLAGS', getattr(self, 'objcopy_flags')) + except AttributeError: + pass + + if self.objcopy_install_path: + self.add_install_files(install_to=self.objcopy_install_path, install_from=task.outputs[0]) + +def configure(ctx): + program_name = 'objcopy' + prefix = getattr(Options.options, 'cross_prefix', None) + if prefix: + program_name = '{}-{}'.format(prefix, program_name) + ctx.find_program(program_name, var='OBJCOPY', mandatory=True) diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/ocaml.py b/ldb-2.0.8/third_party/waf/waflib/extras/ocaml.py new file mode 100644 index 0000000..7d785c6 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/ocaml.py @@ -0,0 +1,348 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2010 (ita) + +"ocaml support" + +import os, re +from waflib import Utils, Task +from waflib.Logs import error +from waflib.TaskGen import feature, before_method, after_method, extension + +EXT_MLL = ['.mll'] +EXT_MLY = ['.mly'] +EXT_MLI = ['.mli'] +EXT_MLC = ['.c'] +EXT_ML = ['.ml'] + +open_re = re.compile(r'^\s*open\s+([a-zA-Z]+)(;;){0,1}$', re.M) +foo = re.compile(r"""(\(\*)|(\*\))|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^()*"'\\]*)""", re.M) +def filter_comments(txt): + meh = [0] + def repl(m): + if m.group(1): + meh[0] += 1 + elif m.group(2): + meh[0] -= 1 + elif not meh[0]: + return m.group() + return '' + return foo.sub(repl, txt) + +def scan(self): + node = self.inputs[0] + code = filter_comments(node.read()) + + global open_re + names = [] + import_iterator = open_re.finditer(code) + if import_iterator: + for import_match in import_iterator: + names.append(import_match.group(1)) + found_lst = [] + raw_lst = [] + for name in names: + nd = None + for x in self.incpaths: + nd = x.find_resource(name.lower()+'.ml') + if not nd: + nd = x.find_resource(name+'.ml') + if nd: + found_lst.append(nd) + break + else: + raw_lst.append(name) + + return (found_lst, raw_lst) + +native_lst=['native', 'all', 'c_object'] +bytecode_lst=['bytecode', 'all'] + +@feature('ocaml') +def init_ml(self): + Utils.def_attrs(self, + type = 'all', + incpaths_lst = [], + bld_incpaths_lst = [], + mlltasks = [], + mlytasks = [], + mlitasks = [], + native_tasks = [], + bytecode_tasks = [], + linktasks = [], + bytecode_env = None, + native_env = None, + compiled_tasks = [], + includes = '', + uselib = '', + are_deps_set = 0) + +@feature('ocaml') +@after_method('init_ml') +def init_envs_ml(self): + + self.islibrary = getattr(self, 'islibrary', False) + + global native_lst, bytecode_lst + self.native_env = None + if self.type in native_lst: + self.native_env = self.env.derive() + if self.islibrary: + self.native_env['OCALINKFLAGS'] = '-a' + + self.bytecode_env = None + if self.type in bytecode_lst: + self.bytecode_env = self.env.derive() + if self.islibrary: + self.bytecode_env['OCALINKFLAGS'] = '-a' + + if self.type == 'c_object': + self.native_env.append_unique('OCALINKFLAGS_OPT', '-output-obj') + +@feature('ocaml') +@before_method('apply_vars_ml') +@after_method('init_envs_ml') +def apply_incpaths_ml(self): + inc_lst = self.includes.split() + lst = self.incpaths_lst + for dir in inc_lst: + node = self.path.find_dir(dir) + if not node: + error("node not found: " + str(dir)) + continue + if not node in lst: + lst.append(node) + self.bld_incpaths_lst.append(node) + # now the nodes are added to self.incpaths_lst + +@feature('ocaml') +@before_method('process_source') +def apply_vars_ml(self): + for i in self.incpaths_lst: + if self.bytecode_env: + app = self.bytecode_env.append_value + app('OCAMLPATH', ['-I', i.bldpath(), '-I', i.srcpath()]) + + if self.native_env: + app = self.native_env.append_value + app('OCAMLPATH', ['-I', i.bldpath(), '-I', i.srcpath()]) + + varnames = ['INCLUDES', 'OCAMLFLAGS', 'OCALINKFLAGS', 'OCALINKFLAGS_OPT'] + for name in self.uselib.split(): + for vname in varnames: + cnt = self.env[vname+'_'+name] + if cnt: + if self.bytecode_env: + self.bytecode_env.append_value(vname, cnt) + if self.native_env: + self.native_env.append_value(vname, cnt) + +@feature('ocaml') +@after_method('process_source') +def apply_link_ml(self): + + if self.bytecode_env: + ext = self.islibrary and '.cma' or '.run' + + linktask = self.create_task('ocalink') + linktask.bytecode = 1 + linktask.set_outputs(self.path.find_or_declare(self.target + ext)) + linktask.env = self.bytecode_env + self.linktasks.append(linktask) + + if self.native_env: + if self.type == 'c_object': + ext = '.o' + elif self.islibrary: + ext = '.cmxa' + else: + ext = '' + + linktask = self.create_task('ocalinkx') + linktask.set_outputs(self.path.find_or_declare(self.target + ext)) + linktask.env = self.native_env + self.linktasks.append(linktask) + + # we produce a .o file to be used by gcc + self.compiled_tasks.append(linktask) + +@extension(*EXT_MLL) +def mll_hook(self, node): + mll_task = self.create_task('ocamllex', node, node.change_ext('.ml')) + mll_task.env = self.native_env.derive() + self.mlltasks.append(mll_task) + + self.source.append(mll_task.outputs[0]) + +@extension(*EXT_MLY) +def mly_hook(self, node): + mly_task = self.create_task('ocamlyacc', node, [node.change_ext('.ml'), node.change_ext('.mli')]) + mly_task.env = self.native_env.derive() + self.mlytasks.append(mly_task) + self.source.append(mly_task.outputs[0]) + + task = self.create_task('ocamlcmi', mly_task.outputs[1], mly_task.outputs[1].change_ext('.cmi')) + task.env = self.native_env.derive() + +@extension(*EXT_MLI) +def mli_hook(self, node): + task = self.create_task('ocamlcmi', node, node.change_ext('.cmi')) + task.env = self.native_env.derive() + self.mlitasks.append(task) + +@extension(*EXT_MLC) +def mlc_hook(self, node): + task = self.create_task('ocamlcc', node, node.change_ext('.o')) + task.env = self.native_env.derive() + self.compiled_tasks.append(task) + +@extension(*EXT_ML) +def ml_hook(self, node): + if self.native_env: + task = self.create_task('ocamlx', node, node.change_ext('.cmx')) + task.env = self.native_env.derive() + task.incpaths = self.bld_incpaths_lst + self.native_tasks.append(task) + + if self.bytecode_env: + task = self.create_task('ocaml', node, node.change_ext('.cmo')) + task.env = self.bytecode_env.derive() + task.bytecode = 1 + task.incpaths = self.bld_incpaths_lst + self.bytecode_tasks.append(task) + +def compile_may_start(self): + + if not getattr(self, 'flag_deps', ''): + self.flag_deps = 1 + + # the evil part is that we can only compute the dependencies after the + # source files can be read (this means actually producing the source files) + if getattr(self, 'bytecode', ''): + alltasks = self.generator.bytecode_tasks + else: + alltasks = self.generator.native_tasks + + self.signature() # ensure that files are scanned - unfortunately + tree = self.generator.bld + for node in self.inputs: + lst = tree.node_deps[self.uid()] + for depnode in lst: + for t in alltasks: + if t == self: + continue + if depnode in t.inputs: + self.set_run_after(t) + + # TODO necessary to get the signature right - for now + delattr(self, 'cache_sig') + self.signature() + + return Task.Task.runnable_status(self) + +class ocamlx(Task.Task): + """native caml compilation""" + color = 'GREEN' + run_str = '${OCAMLOPT} ${OCAMLPATH} ${OCAMLFLAGS} ${OCAMLINCLUDES} -c -o ${TGT} ${SRC}' + scan = scan + runnable_status = compile_may_start + +class ocaml(Task.Task): + """bytecode caml compilation""" + color = 'GREEN' + run_str = '${OCAMLC} ${OCAMLPATH} ${OCAMLFLAGS} ${OCAMLINCLUDES} -c -o ${TGT} ${SRC}' + scan = scan + runnable_status = compile_may_start + +class ocamlcmi(Task.Task): + """interface generator (the .i files?)""" + color = 'BLUE' + run_str = '${OCAMLC} ${OCAMLPATH} ${OCAMLINCLUDES} -o ${TGT} -c ${SRC}' + before = ['ocamlcc', 'ocaml', 'ocamlcc'] + +class ocamlcc(Task.Task): + """ocaml to c interfaces""" + color = 'GREEN' + run_str = 'cd ${TGT[0].bld_dir()} && ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLPATH} ${OCAMLINCLUDES} -c ${SRC[0].abspath()}' + +class ocamllex(Task.Task): + """lexical generator""" + color = 'BLUE' + run_str = '${OCAMLLEX} ${SRC} -o ${TGT}' + before = ['ocamlcmi', 'ocaml', 'ocamlcc'] + +class ocamlyacc(Task.Task): + """parser generator""" + color = 'BLUE' + run_str = '${OCAMLYACC} -b ${tsk.base()} ${SRC}' + before = ['ocamlcmi', 'ocaml', 'ocamlcc'] + + def base(self): + node = self.outputs[0] + s = os.path.splitext(node.name)[0] + return node.bld_dir() + os.sep + s + +def link_may_start(self): + + if getattr(self, 'bytecode', 0): + alltasks = self.generator.bytecode_tasks + else: + alltasks = self.generator.native_tasks + + for x in alltasks: + if not x.hasrun: + return Task.ASK_LATER + + if not getattr(self, 'order', ''): + + # now reorder the inputs given the task dependencies + # this part is difficult, we do not have a total order on the tasks + # if the dependencies are wrong, this may not stop + seen = [] + pendant = []+alltasks + while pendant: + task = pendant.pop(0) + if task in seen: + continue + for x in task.run_after: + if not x in seen: + pendant.append(task) + break + else: + seen.append(task) + self.inputs = [x.outputs[0] for x in seen] + self.order = 1 + return Task.Task.runnable_status(self) + +class ocalink(Task.Task): + """bytecode caml link""" + color = 'YELLOW' + run_str = '${OCAMLC} -o ${TGT} ${OCAMLINCLUDES} ${OCALINKFLAGS} ${SRC}' + runnable_status = link_may_start + after = ['ocaml', 'ocamlcc'] + +class ocalinkx(Task.Task): + """native caml link""" + color = 'YELLOW' + run_str = '${OCAMLOPT} -o ${TGT} ${OCAMLINCLUDES} ${OCALINKFLAGS_OPT} ${SRC}' + runnable_status = link_may_start + after = ['ocamlx', 'ocamlcc'] + +def configure(conf): + opt = conf.find_program('ocamlopt', var='OCAMLOPT', mandatory=False) + occ = conf.find_program('ocamlc', var='OCAMLC', mandatory=False) + if (not opt) or (not occ): + conf.fatal('The objective caml compiler was not found:\ninstall it or make it available in your PATH') + + v = conf.env + v['OCAMLC'] = occ + v['OCAMLOPT'] = opt + v['OCAMLLEX'] = conf.find_program('ocamllex', var='OCAMLLEX', mandatory=False) + v['OCAMLYACC'] = conf.find_program('ocamlyacc', var='OCAMLYACC', mandatory=False) + v['OCAMLFLAGS'] = '' + where = conf.cmd_and_log(conf.env.OCAMLC + ['-where']).strip()+os.sep + v['OCAMLLIB'] = where + v['LIBPATH_OCAML'] = where + v['INCLUDES_OCAML'] = where + v['LIB_OCAML'] = 'camlrun' + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/package.py b/ldb-2.0.8/third_party/waf/waflib/extras/package.py new file mode 100644 index 0000000..c06498e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/package.py @@ -0,0 +1,76 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2011 + +""" +Obtain packages, unpack them in a location, and add associated uselib variables +(CFLAGS_pkgname, LIBPATH_pkgname, etc). + +The default is use a Dependencies.txt file in the source directory. + +This is a work in progress. + +Usage: + +def options(opt): + opt.load('package') + +def configure(conf): + conf.load_packages() +""" + +from waflib import Logs +from waflib.Configure import conf + +try: + from urllib import request +except ImportError: + from urllib import urlopen +else: + urlopen = request.urlopen + + +CACHEVAR = 'WAFCACHE_PACKAGE' + +@conf +def get_package_cache_dir(self): + cache = None + if CACHEVAR in conf.environ: + cache = conf.environ[CACHEVAR] + cache = self.root.make_node(cache) + elif self.env[CACHEVAR]: + cache = self.env[CACHEVAR] + cache = self.root.make_node(cache) + else: + cache = self.srcnode.make_node('.wafcache_package') + cache.mkdir() + return cache + +@conf +def download_archive(self, src, dst): + for x in self.env.PACKAGE_REPO: + url = '/'.join((x, src)) + try: + web = urlopen(url) + try: + if web.getcode() != 200: + continue + except AttributeError: + pass + except Exception: + # on python3 urlopen throws an exception + # python 2.3 does not have getcode and throws an exception to fail + continue + else: + tmp = self.root.make_node(dst) + tmp.write(web.read()) + Logs.warn('Downloaded %s from %s', tmp.abspath(), url) + break + else: + self.fatal('Could not get the package %s' % src) + +@conf +def load_packages(self): + self.get_package_cache_dir() + # read the dependencies, get the archives, .. + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/parallel_debug.py b/ldb-2.0.8/third_party/waf/waflib/extras/parallel_debug.py new file mode 100644 index 0000000..4ffec5e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/parallel_debug.py @@ -0,0 +1,462 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2007-2010 (ita) + +""" +Debugging helper for parallel compilation. + +Copy it to your project and load it with:: + + def options(opt): + opt.load('parallel_debug', tooldir='.') + def build(bld): + ... + +The build will then output a file named pdebug.svg in the source directory. +""" + +import re, sys, threading, time, traceback +try: + from Queue import Queue +except: + from queue import Queue +from waflib import Runner, Options, Task, Logs, Errors + +SVG_TEMPLATE = """ + + + + + + + + + + +${if project.title} + ${project.title} +${endif} + + +${for cls in project.groups} + + ${for rect in cls.rects} + + ${endfor} + +${endfor} + +${for info in project.infos} + + + ${info.text} + +${endfor} + +${if project.tooltip} + + + + +${endif} + + +""" + +COMPILE_TEMPLATE = '''def f(project): + lst = [] + def xml_escape(value): + return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") + + %s + return ''.join(lst) +''' +reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P[^}]*?)\})", re.M) +def compile_template(line): + + extr = [] + def repl(match): + g = match.group + if g('dollar'): + return "$" + elif g('backslash'): + return "\\" + elif g('subst'): + extr.append(g('code')) + return "<<|@|>>" + return None + + line2 = reg_act.sub(repl, line) + params = line2.split('<<|@|>>') + assert(extr) + + + indent = 0 + buf = [] + app = buf.append + + def app(txt): + buf.append(indent * '\t' + txt) + + for x in range(len(extr)): + if params[x]: + app("lst.append(%r)" % params[x]) + + f = extr[x] + if f.startswith(('if', 'for')): + app(f + ':') + indent += 1 + elif f.startswith('py:'): + app(f[3:]) + elif f.startswith(('endif', 'endfor')): + indent -= 1 + elif f.startswith(('else', 'elif')): + indent -= 1 + app(f + ':') + indent += 1 + elif f.startswith('xml:'): + app('lst.append(xml_escape(%s))' % f[4:]) + else: + #app('lst.append((%s) or "cannot find %s")' % (f, f)) + app('lst.append(str(%s))' % f) + + if extr: + if params[-1]: + app("lst.append(%r)" % params[-1]) + + fun = COMPILE_TEMPLATE % "\n\t".join(buf) + # uncomment the following to debug the template + #for i, x in enumerate(fun.splitlines()): + # print i, x + return Task.funex(fun) + +# red #ff4d4d +# green #4da74d +# lila #a751ff + +color2code = { + 'GREEN' : '#4da74d', + 'YELLOW' : '#fefe44', + 'PINK' : '#a751ff', + 'RED' : '#cc1d1d', + 'BLUE' : '#6687bb', + 'CYAN' : '#34e2e2', +} + +mp = {} +info = [] # list of (text,color) + +def map_to_color(name): + if name in mp: + return mp[name] + try: + cls = Task.classes[name] + except KeyError: + return color2code['RED'] + if cls.color in mp: + return mp[cls.color] + if cls.color in color2code: + return color2code[cls.color] + return color2code['RED'] + +def process(self): + m = self.generator.bld.producer + try: + # TODO another place for this? + del self.generator.bld.task_sigs[self.uid()] + except KeyError: + pass + + self.generator.bld.producer.set_running(1, self) + + try: + ret = self.run() + except Exception: + self.err_msg = traceback.format_exc() + self.hasrun = Task.EXCEPTION + + # TODO cleanup + m.error_handler(self) + return + + if ret: + self.err_code = ret + self.hasrun = Task.CRASHED + else: + try: + self.post_run() + except Errors.WafError: + pass + except Exception: + self.err_msg = traceback.format_exc() + self.hasrun = Task.EXCEPTION + else: + self.hasrun = Task.SUCCESS + if self.hasrun != Task.SUCCESS: + m.error_handler(self) + + self.generator.bld.producer.set_running(-1, self) + +Task.Task.process_back = Task.Task.process +Task.Task.process = process + +old_start = Runner.Parallel.start +def do_start(self): + try: + Options.options.dband + except AttributeError: + self.bld.fatal('use def options(opt): opt.load("parallel_debug")!') + + self.taskinfo = Queue() + old_start(self) + if self.dirty: + make_picture(self) +Runner.Parallel.start = do_start + +lock_running = threading.Lock() +def set_running(self, by, tsk): + with lock_running: + try: + cache = self.lock_cache + except AttributeError: + cache = self.lock_cache = {} + + i = 0 + if by > 0: + vals = cache.values() + for i in range(self.numjobs): + if i not in vals: + cache[tsk] = i + break + else: + i = cache[tsk] + del cache[tsk] + + self.taskinfo.put( (i, id(tsk), time.time(), tsk.__class__.__name__, self.processed, self.count, by, ",".join(map(str, tsk.outputs))) ) +Runner.Parallel.set_running = set_running + +def name2class(name): + return name.replace(' ', '_').replace('.', '_') + +def make_picture(producer): + # first, cast the parameters + if not hasattr(producer.bld, 'path'): + return + + tmp = [] + try: + while True: + tup = producer.taskinfo.get(False) + tmp.append(list(tup)) + except: + pass + + try: + ini = float(tmp[0][2]) + except: + return + + if not info: + seen = [] + for x in tmp: + name = x[3] + if not name in seen: + seen.append(name) + else: + continue + + info.append((name, map_to_color(name))) + info.sort(key=lambda x: x[0]) + + thread_count = 0 + acc = [] + for x in tmp: + thread_count += x[6] + acc.append("%d %d %f %r %d %d %d %s" % (x[0], x[1], x[2] - ini, x[3], x[4], x[5], thread_count, x[7])) + + data_node = producer.bld.path.make_node('pdebug.dat') + data_node.write('\n'.join(acc)) + + tmp = [lst[:2] + [float(lst[2]) - ini] + lst[3:] for lst in tmp] + + st = {} + for l in tmp: + if not l[0] in st: + st[l[0]] = len(st.keys()) + tmp = [ [st[lst[0]]] + lst[1:] for lst in tmp ] + THREAD_AMOUNT = len(st.keys()) + + st = {} + for l in tmp: + if not l[1] in st: + st[l[1]] = len(st.keys()) + tmp = [ [lst[0]] + [st[lst[1]]] + lst[2:] for lst in tmp ] + + + BAND = Options.options.dband + + seen = {} + acc = [] + for x in range(len(tmp)): + line = tmp[x] + id = line[1] + + if id in seen: + continue + seen[id] = True + + begin = line[2] + thread_id = line[0] + for y in range(x + 1, len(tmp)): + line = tmp[y] + if line[1] == id: + end = line[2] + #print id, thread_id, begin, end + #acc.append( ( 10*thread_id, 10*(thread_id+1), 10*begin, 10*end ) ) + acc.append( (BAND * begin, BAND*thread_id, BAND*end - BAND*begin, BAND, line[3], line[7]) ) + break + + if Options.options.dmaxtime < 0.1: + gwidth = 1 + for x in tmp: + m = BAND * x[2] + if m > gwidth: + gwidth = m + else: + gwidth = BAND * Options.options.dmaxtime + + ratio = float(Options.options.dwidth) / gwidth + gwidth = Options.options.dwidth + gheight = BAND * (THREAD_AMOUNT + len(info) + 1.5) + + + # simple data model for our template + class tobject(object): + pass + + model = tobject() + model.x = 0 + model.y = 0 + model.width = gwidth + 4 + model.height = gheight + 4 + + model.tooltip = not Options.options.dnotooltip + + model.title = Options.options.dtitle + model.title_x = gwidth / 2 + model.title_y = gheight + - 5 + + groups = {} + for (x, y, w, h, clsname, name) in acc: + try: + groups[clsname].append((x, y, w, h, name)) + except: + groups[clsname] = [(x, y, w, h, name)] + + # groups of rectangles (else js highlighting is slow) + model.groups = [] + for cls in groups: + g = tobject() + model.groups.append(g) + g.classname = name2class(cls) + g.rects = [] + for (x, y, w, h, name) in groups[cls]: + r = tobject() + g.rects.append(r) + r.x = 2 + x * ratio + r.y = 2 + y + r.width = w * ratio + r.height = h + r.name = name + r.color = map_to_color(cls) + + cnt = THREAD_AMOUNT + + # caption + model.infos = [] + for (text, color) in info: + inf = tobject() + model.infos.append(inf) + inf.classname = name2class(text) + inf.x = 2 + BAND + inf.y = 5 + (cnt + 0.5) * BAND + inf.width = BAND/2 + inf.height = BAND/2 + inf.color = color + + inf.text = text + inf.text_x = 2 + 2 * BAND + inf.text_y = 5 + (cnt + 0.5) * BAND + 10 + + cnt += 1 + + # write the file... + template1 = compile_template(SVG_TEMPLATE) + txt = template1(model) + + node = producer.bld.path.make_node('pdebug.svg') + node.write(txt) + Logs.warn('Created the diagram %r', node) + +def options(opt): + opt.add_option('--dtitle', action='store', default='Parallel build representation for %r' % ' '.join(sys.argv), + help='title for the svg diagram', dest='dtitle') + opt.add_option('--dwidth', action='store', type='int', help='diagram width', default=800, dest='dwidth') + opt.add_option('--dtime', action='store', type='float', help='recording interval in seconds', default=0.009, dest='dtime') + opt.add_option('--dband', action='store', type='int', help='band width', default=22, dest='dband') + opt.add_option('--dmaxtime', action='store', type='float', help='maximum time, for drawing fair comparisons', default=0, dest='dmaxtime') + opt.add_option('--dnotooltip', action='store_true', help='disable tooltips', default=False, dest='dnotooltip') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/pch.py b/ldb-2.0.8/third_party/waf/waflib/extras/pch.py new file mode 100644 index 0000000..103e752 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/pch.py @@ -0,0 +1,148 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Alexander Afanasyev (UCLA), 2014 + +""" +Enable precompiled C++ header support (currently only clang++ and g++ are supported) + +To use this tool, wscript should look like: + + def options(opt): + opt.load('pch') + # This will add `--with-pch` configure option. + # Unless --with-pch during configure stage specified, the precompiled header support is disabled + + def configure(conf): + conf.load('pch') + # this will set conf.env.WITH_PCH if --with-pch is specified and the supported compiler is used + # Unless conf.env.WITH_PCH is set, the precompiled header support is disabled + + def build(bld): + bld(features='cxx pch', + target='precompiled-headers', + name='precompiled-headers', + headers='a.h b.h c.h', # headers to pre-compile into `precompiled-headers` + + # Other parameters to compile precompiled headers + # includes=..., + # export_includes=..., + # use=..., + # ... + + # Exported parameters will be propagated even if precompiled headers are disabled + ) + + bld( + target='test', + features='cxx cxxprogram', + source='a.cpp b.cpp d.cpp main.cpp', + use='precompiled-headers', + ) + + # or + + bld( + target='test', + features='pch cxx cxxprogram', + source='a.cpp b.cpp d.cpp main.cpp', + headers='a.h b.h c.h', + ) + +Note that precompiled header must have multiple inclusion guards. If the guards are missing, any benefit of precompiled header will be voided and compilation may fail in some cases. +""" + +import os +from waflib import Task, TaskGen, Utils +from waflib.Tools import c_preproc, cxx + + +PCH_COMPILER_OPTIONS = { + 'clang++': [['-include'], '.pch', ['-x', 'c++-header']], + 'g++': [['-include'], '.gch', ['-x', 'c++-header']], +} + + +def options(opt): + opt.add_option('--without-pch', action='store_false', default=True, dest='with_pch', help='''Try to use precompiled header to speed up compilation (only g++ and clang++)''') + +def configure(conf): + if (conf.options.with_pch and conf.env['COMPILER_CXX'] in PCH_COMPILER_OPTIONS.keys()): + conf.env.WITH_PCH = True + flags = PCH_COMPILER_OPTIONS[conf.env['COMPILER_CXX']] + conf.env.CXXPCH_F = flags[0] + conf.env.CXXPCH_EXT = flags[1] + conf.env.CXXPCH_FLAGS = flags[2] + + +@TaskGen.feature('pch') +@TaskGen.before('process_source') +def apply_pch(self): + if not self.env.WITH_PCH: + return + + if getattr(self.bld, 'pch_tasks', None) is None: + self.bld.pch_tasks = {} + + if getattr(self, 'headers', None) is None: + return + + self.headers = self.to_nodes(self.headers) + + if getattr(self, 'name', None): + try: + task = self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] + self.bld.fatal("Duplicated 'pch' task with name %r" % "%s.%s" % (self.name, self.idx)) + except KeyError: + pass + + out = '%s.%d%s' % (self.target, self.idx, self.env['CXXPCH_EXT']) + out = self.path.find_or_declare(out) + task = self.create_task('gchx', self.headers, out) + + # target should be an absolute path of `out`, but without precompiled header extension + task.target = out.abspath()[:-len(out.suffix())] + + self.pch_task = task + if getattr(self, 'name', None): + self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] = task + +@TaskGen.feature('cxx') +@TaskGen.after_method('process_source', 'propagate_uselib_vars') +def add_pch(self): + if not (self.env['WITH_PCH'] and getattr(self, 'use', None) and getattr(self, 'compiled_tasks', None) and getattr(self.bld, 'pch_tasks', None)): + return + + pch = None + # find pch task, if any + + if getattr(self, 'pch_task', None): + pch = self.pch_task + else: + for use in Utils.to_list(self.use): + try: + pch = self.bld.pch_tasks[use] + except KeyError: + pass + + if pch: + for x in self.compiled_tasks: + x.env.append_value('CXXFLAGS', self.env['CXXPCH_F'] + [pch.target]) + +class gchx(Task.Task): + run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CXXPCH_FLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXXPCH_F:SRC} ${CXX_SRC_F}${SRC[0].abspath()} ${CXX_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' + scan = c_preproc.scan + color = 'BLUE' + ext_out=['.h'] + + def runnable_status(self): + try: + node_deps = self.generator.bld.node_deps[self.uid()] + except KeyError: + node_deps = [] + ret = Task.Task.runnable_status(self) + if ret == Task.SKIP_ME and self.env.CXX_NAME == 'clang': + t = os.stat(self.outputs[0].abspath()).st_mtime + for n in self.inputs + node_deps: + if os.stat(n.abspath()).st_mtime > t: + return Task.RUN_ME + return ret diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/pep8.py b/ldb-2.0.8/third_party/waf/waflib/extras/pep8.py new file mode 100644 index 0000000..676beed --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/pep8.py @@ -0,0 +1,106 @@ +#! /usr/bin/env python +# encoding: utf-8 +# +# written by Sylvain Rouquette, 2011 + +''' +Install pep8 module: +$ easy_install pep8 + or +$ pip install pep8 + +To add the pep8 tool to the waf file: +$ ./waf-light --tools=compat15,pep8 + or, if you have waf >= 1.6.2 +$ ./waf update --files=pep8 + + +Then add this to your wscript: + +[at]extension('.py', 'wscript') +def run_pep8(self, node): + self.create_task('Pep8', node) + +''' + +import threading +from waflib import Task, Options + +pep8 = __import__('pep8') + + +class Pep8(Task.Task): + color = 'PINK' + lock = threading.Lock() + + def check_options(self): + if pep8.options: + return + pep8.options = Options.options + pep8.options.prog = 'pep8' + excl = pep8.options.exclude.split(',') + pep8.options.exclude = [s.rstrip('/') for s in excl] + if pep8.options.filename: + pep8.options.filename = pep8.options.filename.split(',') + if pep8.options.select: + pep8.options.select = pep8.options.select.split(',') + else: + pep8.options.select = [] + if pep8.options.ignore: + pep8.options.ignore = pep8.options.ignore.split(',') + elif pep8.options.select: + # Ignore all checks which are not explicitly selected + pep8.options.ignore = [''] + elif pep8.options.testsuite or pep8.options.doctest: + # For doctest and testsuite, all checks are required + pep8.options.ignore = [] + else: + # The default choice: ignore controversial checks + pep8.options.ignore = pep8.DEFAULT_IGNORE.split(',') + pep8.options.physical_checks = pep8.find_checks('physical_line') + pep8.options.logical_checks = pep8.find_checks('logical_line') + pep8.options.counters = dict.fromkeys(pep8.BENCHMARK_KEYS, 0) + pep8.options.messages = {} + + def run(self): + with Pep8.lock: + self.check_options() + pep8.input_file(self.inputs[0].abspath()) + return 0 if not pep8.get_count() else -1 + + +def options(opt): + opt.add_option('-q', '--quiet', default=0, action='count', + help="report only file names, or nothing with -qq") + opt.add_option('-r', '--repeat', action='store_true', + help="show all occurrences of the same error") + opt.add_option('--exclude', metavar='patterns', + default=pep8.DEFAULT_EXCLUDE, + help="exclude files or directories which match these " + "comma separated patterns (default: %s)" % + pep8.DEFAULT_EXCLUDE, + dest='exclude') + opt.add_option('--filename', metavar='patterns', default='*.py', + help="when parsing directories, only check filenames " + "matching these comma separated patterns (default: " + "*.py)") + opt.add_option('--select', metavar='errors', default='', + help="select errors and warnings (e.g. E,W6)") + opt.add_option('--ignore', metavar='errors', default='', + help="skip errors and warnings (e.g. E4,W)") + opt.add_option('--show-source', action='store_true', + help="show source code for each error") + opt.add_option('--show-pep8', action='store_true', + help="show text of PEP 8 for each error") + opt.add_option('--statistics', action='store_true', + help="count errors and warnings") + opt.add_option('--count', action='store_true', + help="print total number of errors and warnings " + "to standard error and set exit code to 1 if " + "total is not null") + opt.add_option('--benchmark', action='store_true', + help="measure processing speed") + opt.add_option('--testsuite', metavar='dir', + help="run regression tests from dir") + opt.add_option('--doctest', action='store_true', + help="run doctest on myself") diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/pgicc.py b/ldb-2.0.8/third_party/waf/waflib/extras/pgicc.py new file mode 100644 index 0000000..f8068d5 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/pgicc.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Antoine Dechaume 2011 + +""" +Detect the PGI C compiler +""" + +import sys, re +from waflib import Errors +from waflib.Configure import conf +from waflib.Tools.compiler_c import c_compiler +c_compiler['linux'].append('pgicc') + +@conf +def find_pgi_compiler(conf, var, name): + """ + Find the program name, and execute it to ensure it really is itself. + """ + if sys.platform == 'cygwin': + conf.fatal('The PGI compiler does not work on Cygwin') + + v = conf.env + cc = None + if v[var]: + cc = v[var] + elif var in conf.environ: + cc = conf.environ[var] + if not cc: + cc = conf.find_program(name, var=var) + if not cc: + conf.fatal('PGI Compiler (%s) was not found' % name) + + v[var + '_VERSION'] = conf.get_pgi_version(cc) + v[var] = cc + v[var + '_NAME'] = 'pgi' + +@conf +def get_pgi_version(conf, cc): + """Find the version of a pgi compiler.""" + version_re = re.compile(r"The Portland Group", re.I).search + cmd = cc + ['-V', '-E'] # Issue 1078, prevent wrappers from linking + + try: + out, err = conf.cmd_and_log(cmd, output=0) + except Errors.WafError: + conf.fatal('Could not find pgi compiler %r' % cmd) + + if out: + match = version_re(out) + else: + match = version_re(err) + + if not match: + conf.fatal('Could not verify PGI signature') + + cmd = cc + ['-help=variable'] + try: + out, err = conf.cmd_and_log(cmd, output=0) + except Errors.WafError: + conf.fatal('Could not find pgi compiler %r' % cmd) + + version = re.findall(r'^COMPVER\s*=(.*)', out, re.M) + if len(version) != 1: + conf.fatal('Could not determine the compiler version') + return version[0] + +def configure(conf): + conf.find_pgi_compiler('CC', 'pgcc') + conf.find_ar() + conf.gcc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/pgicxx.py b/ldb-2.0.8/third_party/waf/waflib/extras/pgicxx.py new file mode 100644 index 0000000..eae121c --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/pgicxx.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Antoine Dechaume 2011 + +""" +Detect the PGI C++ compiler +""" + +from waflib.Tools.compiler_cxx import cxx_compiler +cxx_compiler['linux'].append('pgicxx') + +from waflib.extras import pgicc + +def configure(conf): + conf.find_pgi_compiler('CXX', 'pgCC') + conf.find_ar() + conf.gxx_common_flags() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/proc.py b/ldb-2.0.8/third_party/waf/waflib/extras/proc.py new file mode 100644 index 0000000..764abec --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/proc.py @@ -0,0 +1,54 @@ +#! /usr/bin/env python +# per rosengren 2011 + +from os import environ, path +from waflib import TaskGen, Utils + +def options(opt): + grp = opt.add_option_group('Oracle ProC Options') + grp.add_option('--oracle_home', action='store', default=environ.get('PROC_ORACLE'), help='Path to Oracle installation home (has bin/lib)') + grp.add_option('--tns_admin', action='store', default=environ.get('TNS_ADMIN'), help='Directory containing server list (TNS_NAMES.ORA)') + grp.add_option('--connection', action='store', default='dummy-user/dummy-password@dummy-server', help='Format: user/password@server') + +def configure(cnf): + env = cnf.env + if not env.PROC_ORACLE: + env.PROC_ORACLE = cnf.options.oracle_home + if not env.PROC_TNS_ADMIN: + env.PROC_TNS_ADMIN = cnf.options.tns_admin + if not env.PROC_CONNECTION: + env.PROC_CONNECTION = cnf.options.connection + cnf.find_program('proc', var='PROC', path_list=env.PROC_ORACLE + path.sep + 'bin') + +def proc(tsk): + env = tsk.env + gen = tsk.generator + inc_nodes = gen.to_incnodes(Utils.to_list(getattr(gen,'includes',[])) + env['INCLUDES']) + + cmd = ( + [env.PROC] + + ['SQLCHECK=SEMANTICS'] + + (['SYS_INCLUDE=(' + ','.join(env.PROC_INCLUDES) + ')'] + if env.PROC_INCLUDES else []) + + ['INCLUDE=(' + ','.join( + [i.bldpath() for i in inc_nodes] + ) + ')'] + + ['userid=' + env.PROC_CONNECTION] + + ['INAME=' + tsk.inputs[0].bldpath()] + + ['ONAME=' + tsk.outputs[0].bldpath()] + ) + exec_env = { + 'ORACLE_HOME': env.PROC_ORACLE, + 'LD_LIBRARY_PATH': env.PROC_ORACLE + path.sep + 'lib', + } + if env.PROC_TNS_ADMIN: + exec_env['TNS_ADMIN'] = env.PROC_TNS_ADMIN + return tsk.exec_command(cmd, env=exec_env) + +TaskGen.declare_chain( + name = 'proc', + rule = proc, + ext_in = '.pc', + ext_out = '.c', +) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/protoc.py b/ldb-2.0.8/third_party/waf/waflib/extras/protoc.py new file mode 100644 index 0000000..4a519cc --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/protoc.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Philipp Bender, 2012 +# Matt Clarkson, 2012 + +import re, os +from waflib.Task import Task +from waflib.TaskGen import extension +from waflib import Errors, Context, Logs + +""" +A simple tool to integrate protocol buffers into your build system. + +Example for C++: + + def configure(conf): + conf.load('compiler_cxx cxx protoc') + + def build(bld): + bld( + features = 'cxx cxxprogram' + source = 'main.cpp file1.proto proto/file2.proto', + includes = '. proto', + target = 'executable') + +Example for Python: + + def configure(conf): + conf.load('python protoc') + + def build(bld): + bld( + features = 'py' + source = 'main.py file1.proto proto/file2.proto', + protoc_includes = 'proto') + +Example for both Python and C++ at same time: + + def configure(conf): + conf.load('cxx python protoc') + + def build(bld): + bld( + features = 'cxx py' + source = 'file1.proto proto/file2.proto', + protoc_includes = 'proto') # or includes + + +Example for Java: + + def options(opt): + opt.load('java') + + def configure(conf): + conf.load('python java protoc') + # Here you have to point to your protobuf-java JAR and have it in classpath + conf.env.CLASSPATH_PROTOBUF = ['protobuf-java-2.5.0.jar'] + + def build(bld): + bld( + features = 'javac protoc', + name = 'pbjava', + srcdir = 'inc/ src', # directories used by javac + source = ['inc/message_inc.proto', 'inc/message.proto'], + # source is used by protoc for .proto files + use = 'PROTOBUF', + protoc_includes = ['inc']) # for protoc to search dependencies + + +Protoc includes passed via protoc_includes are either relative to the taskgen +or to the project and are searched in this order. + +Include directories external to the waf project can also be passed to the +extra by using protoc_extincludes + + protoc_extincludes = ['/usr/include/pblib'] + + +Notes when using this tool: + +- protoc command line parsing is tricky. + + The generated files can be put in subfolders which depend on + the order of the include paths. + + Try to be simple when creating task generators + containing protoc stuff. + +""" + +class protoc(Task): + run_str = '${PROTOC} ${PROTOC_FL:PROTOC_FLAGS} ${PROTOC_ST:INCPATHS} ${PROTOC_ST:PROTOC_INCPATHS} ${PROTOC_ST:PROTOC_EXTINCPATHS} ${SRC[0].bldpath()}' + color = 'BLUE' + ext_out = ['.h', 'pb.cc', '.py', '.java'] + def scan(self): + """ + Scan .proto dependencies + """ + node = self.inputs[0] + + nodes = [] + names = [] + seen = [] + search_nodes = [] + + if not node: + return (nodes, names) + + if 'cxx' in self.generator.features: + search_nodes = self.generator.includes_nodes + + if 'py' in self.generator.features or 'javac' in self.generator.features: + for incpath in getattr(self.generator, 'protoc_includes', []): + incpath_node = self.generator.path.find_node(incpath) + if incpath_node: + search_nodes.append(incpath_node) + else: + # Check if relative to top-level for extra tg dependencies + incpath_node = self.generator.bld.path.find_node(incpath) + if incpath_node: + search_nodes.append(incpath_node) + else: + raise Errors.WafError('protoc: include path %r does not exist' % incpath) + + + def parse_node(node): + if node in seen: + return + seen.append(node) + code = node.read().splitlines() + for line in code: + m = re.search(r'^import\s+"(.*)";.*(//)?.*', line) + if m: + dep = m.groups()[0] + for incnode in search_nodes: + found = incnode.find_resource(dep) + if found: + nodes.append(found) + parse_node(found) + else: + names.append(dep) + + parse_node(node) + # Add also dependencies path to INCPATHS so protoc will find the included file + for deppath in nodes: + self.env.append_unique('INCPATHS', deppath.parent.bldpath()) + return (nodes, names) + +@extension('.proto') +def process_protoc(self, node): + incdirs = [] + out_nodes = [] + protoc_flags = [] + + # ensure PROTOC_FLAGS is a list; a copy is used below anyway + self.env.PROTOC_FLAGS = self.to_list(self.env.PROTOC_FLAGS) + + if 'cxx' in self.features: + cpp_node = node.change_ext('.pb.cc') + hpp_node = node.change_ext('.pb.h') + self.source.append(cpp_node) + out_nodes.append(cpp_node) + out_nodes.append(hpp_node) + protoc_flags.append('--cpp_out=%s' % node.parent.get_bld().bldpath()) + + if 'py' in self.features: + py_node = node.change_ext('_pb2.py') + self.source.append(py_node) + out_nodes.append(py_node) + protoc_flags.append('--python_out=%s' % node.parent.get_bld().bldpath()) + + if 'javac' in self.features: + # Make javac get also pick java code generated in build + if not node.parent.get_bld() in self.javac_task.srcdir: + self.javac_task.srcdir.append(node.parent.get_bld()) + + protoc_flags.append('--java_out=%s' % node.parent.get_bld().bldpath()) + node.parent.get_bld().mkdir() + + tsk = self.create_task('protoc', node, out_nodes) + tsk.env.append_value('PROTOC_FLAGS', protoc_flags) + + if 'javac' in self.features: + self.javac_task.set_run_after(tsk) + + # Instruct protoc where to search for .proto included files. + # For C++ standard include files dirs are used, + # but this doesn't apply to Python for example + for incpath in getattr(self, 'protoc_includes', []): + incpath_node = self.path.find_node(incpath) + if incpath_node: + incdirs.append(incpath_node.bldpath()) + else: + # Check if relative to top-level for extra tg dependencies + incpath_node = self.bld.path.find_node(incpath) + if incpath_node: + incdirs.append(incpath_node.bldpath()) + else: + raise Errors.WafError('protoc: include path %r does not exist' % incpath) + + tsk.env.PROTOC_INCPATHS = incdirs + + # Include paths external to the waf project (ie. shared pb repositories) + tsk.env.PROTOC_EXTINCPATHS = getattr(self, 'protoc_extincludes', []) + + # PR2115: protoc generates output of .proto files in nested + # directories by canonicalizing paths. To avoid this we have to pass + # as first include the full directory file of the .proto file + tsk.env.prepend_value('INCPATHS', node.parent.bldpath()) + + use = getattr(self, 'use', '') + if not 'PROTOBUF' in use: + self.use = self.to_list(use) + ['PROTOBUF'] + +def configure(conf): + conf.check_cfg(package='protobuf', uselib_store='PROTOBUF', args=['--cflags', '--libs']) + conf.find_program('protoc', var='PROTOC') + conf.start_msg('Checking for protoc version') + protocver = conf.cmd_and_log(conf.env.PROTOC + ['--version'], output=Context.BOTH) + protocver = ''.join(protocver).strip()[protocver[0].rfind(' ')+1:] + conf.end_msg(protocver) + conf.env.PROTOC_MAJOR = protocver[:protocver.find('.')] + conf.env.PROTOC_ST = '-I%s' + conf.env.PROTOC_FL = '%s' diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/pyqt5.py b/ldb-2.0.8/third_party/waf/waflib/extras/pyqt5.py new file mode 100644 index 0000000..9c94176 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/pyqt5.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Federico Pellegrin, 2016-2019 (fedepell) adapted for Python + +""" +This tool helps with finding Python Qt5 tools and libraries, +and provides translation from QT5 files to Python code. + +The following snippet illustrates the tool usage:: + + def options(opt): + opt.load('py pyqt5') + + def configure(conf): + conf.load('py pyqt5') + + def build(bld): + bld( + features = 'py pyqt5', + source = 'main.py textures.qrc aboutDialog.ui', + ) + +Here, the UI description and resource files will be processed +to generate code. + +Usage +===== + +Load the "pyqt5" tool. + +Add into the sources list also the qrc resources files or ui5 +definition files and they will be translated into python code +with the system tools (PyQt5, PySide2, PyQt4 are searched in this +order) and then compiled +""" + +try: + from xml.sax import make_parser + from xml.sax.handler import ContentHandler +except ImportError: + has_xml = False + ContentHandler = object +else: + has_xml = True + +import os +from waflib.Tools import python +from waflib import Task, Options +from waflib.TaskGen import feature, extension +from waflib.Configure import conf +from waflib import Logs + +EXT_RCC = ['.qrc'] +""" +File extension for the resource (.qrc) files +""" + +EXT_UI = ['.ui'] +""" +File extension for the user interface (.ui) files +""" + + +class XMLHandler(ContentHandler): + """ + Parses ``.qrc`` files + """ + def __init__(self): + self.buf = [] + self.files = [] + def startElement(self, name, attrs): + if name == 'file': + self.buf = [] + def endElement(self, name): + if name == 'file': + self.files.append(str(''.join(self.buf))) + def characters(self, cars): + self.buf.append(cars) + +@extension(*EXT_RCC) +def create_pyrcc_task(self, node): + "Creates rcc and py task for ``.qrc`` files" + rcnode = node.change_ext('.py') + self.create_task('pyrcc', node, rcnode) + if getattr(self, 'install_from', None): + self.install_from = self.install_from.get_bld() + else: + self.install_from = self.path.get_bld() + self.install_path = getattr(self, 'install_path', '${PYTHONDIR}') + self.process_py(rcnode) + +@extension(*EXT_UI) +def create_pyuic_task(self, node): + "Create uic tasks and py for user interface ``.ui`` definition files" + uinode = node.change_ext('.py') + self.create_task('ui5py', node, uinode) + if getattr(self, 'install_from', None): + self.install_from = self.install_from.get_bld() + else: + self.install_from = self.path.get_bld() + self.install_path = getattr(self, 'install_path', '${PYTHONDIR}') + self.process_py(uinode) + +@extension('.ts') +def add_pylang(self, node): + """Adds all the .ts file into ``self.lang``""" + self.lang = self.to_list(getattr(self, 'lang', [])) + [node] + +@feature('pyqt5') +def apply_pyqt5(self): + """ + The additional parameters are: + + :param lang: list of translation files (\\*.ts) to process + :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension + :param langname: if given, transform the \\*.ts files into a .qrc files to include in the binary file + :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension + """ + if getattr(self, 'lang', None): + qmtasks = [] + for x in self.to_list(self.lang): + if isinstance(x, str): + x = self.path.find_resource(x + '.ts') + qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.qm'))) + + + if getattr(self, 'langname', None): + qmnodes = [k.outputs[0] for k in qmtasks] + rcnode = self.langname + if isinstance(rcnode, str): + rcnode = self.path.find_or_declare(rcnode + '.qrc') + t = self.create_task('qm2rcc', qmnodes, rcnode) + create_pyrcc_task(self, t.outputs[0]) + +class pyrcc(Task.Task): + """ + Processes ``.qrc`` files + """ + color = 'BLUE' + run_str = '${QT_PYRCC} ${SRC} -o ${TGT}' + ext_out = ['.py'] + + def rcname(self): + return os.path.splitext(self.inputs[0].name)[0] + + def scan(self): + """Parse the *.qrc* files""" + if not has_xml: + Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') + return ([], []) + + parser = make_parser() + curHandler = XMLHandler() + parser.setContentHandler(curHandler) + fi = open(self.inputs[0].abspath(), 'r') + try: + parser.parse(fi) + finally: + fi.close() + + nodes = [] + names = [] + root = self.inputs[0].parent + for x in curHandler.files: + nd = root.find_resource(x) + if nd: + nodes.append(nd) + else: + names.append(x) + return (nodes, names) + + +class ui5py(Task.Task): + """ + Processes ``.ui`` files for python + """ + color = 'BLUE' + run_str = '${QT_PYUIC} ${SRC} -o ${TGT}' + ext_out = ['.py'] + +class ts2qm(Task.Task): + """ + Generates ``.qm`` files from ``.ts`` files + """ + color = 'BLUE' + run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' + +class qm2rcc(Task.Task): + """ + Generates ``.qrc`` files from ``.qm`` files + """ + color = 'BLUE' + after = 'ts2qm' + def run(self): + """Create a qrc file including the inputs""" + txt = '\n'.join(['%s' % k.path_from(self.outputs[0].parent) for k in self.inputs]) + code = '\n\n%s\n\n' % txt + self.outputs[0].write(code) + +def configure(self): + self.find_pyqt5_binaries() + + # warn about this during the configuration too + if not has_xml: + Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') + +@conf +def find_pyqt5_binaries(self): + """ + Detects PyQt5 or PySide2 programs such as pyuic5/pyside2-uic, pyrcc5/pyside2-rcc + """ + env = self.env + + if getattr(Options.options, 'want_pyqt5', True): + self.find_program(['pyuic5'], var='QT_PYUIC') + self.find_program(['pyrcc5'], var='QT_PYRCC') + self.find_program(['pylupdate5'], var='QT_PYLUPDATE') + elif getattr(Options.options, 'want_pyside2', True): + self.find_program(['pyside2-uic'], var='QT_PYUIC') + self.find_program(['pyside2-rcc'], var='QT_PYRCC') + self.find_program(['pyside2-lupdate'], var='QT_PYLUPDATE') + elif getattr(Options.options, 'want_pyqt4', True): + self.find_program(['pyuic4'], var='QT_PYUIC') + self.find_program(['pyrcc4'], var='QT_PYRCC') + self.find_program(['pylupdate4'], var='QT_PYLUPDATE') + else: + self.find_program(['pyuic5','pyside2-uic','pyuic4'], var='QT_PYUIC') + self.find_program(['pyrcc5','pyside2-rcc','pyrcc4'], var='QT_PYRCC') + self.find_program(['pylupdate5', 'pyside2-lupdate','pylupdate4'], var='QT_PYLUPDATE') + + if not env.QT_PYUIC: + self.fatal('cannot find the uic compiler for python for qt5') + + if not env.QT_PYRCC: + self.fatal('cannot find the rcc compiler for python for qt5') + + self.find_program(['lrelease-qt5', 'lrelease'], var='QT_LRELEASE') + +def options(opt): + """ + Command-line options + """ + pyqt5opt=opt.add_option_group("Python QT5 Options") + pyqt5opt.add_option('--pyqt5-pyqt5', action='store_true', default=False, dest='want_pyqt5', help='use PyQt5 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') + pyqt5opt.add_option('--pyqt5-pyside2', action='store_true', default=False, dest='want_pyside2', help='use PySide2 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') + pyqt5opt.add_option('--pyqt5-pyqt4', action='store_true', default=False, dest='want_pyqt4', help='use PyQt4 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/pytest.py b/ldb-2.0.8/third_party/waf/waflib/extras/pytest.py new file mode 100644 index 0000000..7dd5a1a --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/pytest.py @@ -0,0 +1,225 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Calle Rosenquist, 2016-2018 (xbreak) + +""" +Provides Python unit test support using :py:class:`waflib.Tools.waf_unit_test.utest` +task via the **pytest** feature. + +To use pytest the following is needed: + +1. Load `pytest` and the dependency `waf_unit_test` tools. +2. Create a task generator with feature `pytest` (not `test`) and customize behaviour with + the following attributes: + + - `pytest_source`: Test input files. + - `ut_str`: Test runner command, e.g. ``${PYTHON} -B -m unittest discover`` or + if nose is used: ``${NOSETESTS} --no-byte-compile ${SRC}``. + - `ut_shell`: Determines if ``ut_str`` is executed in a shell. Default: False. + - `ut_cwd`: Working directory for test runner. Defaults to directory of + first ``pytest_source`` file. + + Additionally the following `pytest` specific attributes are used in dependent taskgens: + + - `pytest_path`: Node or string list of additional Python paths. + - `pytest_libpath`: Node or string list of additional library paths. + +The `use` dependencies are used for both update calculation and to populate +the following environment variables for the `pytest` test runner: + +1. `PYTHONPATH` (`sys.path`) of any dependent taskgen that has the feature `py`: + + - `install_from` attribute is used to determine where the root of the Python sources + are located. If `install_from` is not specified the default is to use the taskgen path + as the root. + + - `pytest_path` attribute is used to manually specify additional Python paths. + +2. Dynamic linker search path variable (e.g. `LD_LIBRARY_PATH`) of any dependent taskgen with + non-static link_task. + + - `pytest_libpath` attribute is used to manually specify additional linker paths. + +Note: `pytest` cannot automatically determine the correct `PYTHONPATH` for `pyext` taskgens + because the extension might be part of a Python package or used standalone: + + - When used as part of another `py` package, the `PYTHONPATH` is provided by + that taskgen so no additional action is required. + + - When used as a standalone module, the user needs to specify the `PYTHONPATH` explicitly + via the `pytest_path` attribute on the `pyext` taskgen. + + For details c.f. the pytest playground examples. + + +For example:: + + # A standalone Python C extension that demonstrates unit test environment population + # of PYTHONPATH and LD_LIBRARY_PATH/PATH/DYLD_LIBRARY_PATH. + # + # Note: `pytest_path` is provided here because pytest cannot automatically determine + # if the extension is part of another Python package or is used standalone. + bld(name = 'foo_ext', + features = 'c cshlib pyext', + source = 'src/foo_ext.c', + target = 'foo_ext', + pytest_path = [ bld.path.get_bld() ]) + + # Python package under test that also depend on the Python module `foo_ext` + # + # Note: `install_from` is added automatically to `PYTHONPATH`. + bld(name = 'foo', + features = 'py', + use = 'foo_ext', + source = bld.path.ant_glob('src/foo/*.py'), + install_from = 'src') + + # Unit test example using the built in module unittest and let that discover + # any test cases. + bld(name = 'foo_test', + features = 'pytest', + use = 'foo', + pytest_source = bld.path.ant_glob('test/*.py'), + ut_str = '${PYTHON} -B -m unittest discover') + +""" + +import os +from waflib import Task, TaskGen, Errors, Utils, Logs +from waflib.Tools import ccroot + +def _process_use_rec(self, name): + """ + Recursively process ``use`` for task generator with name ``name``.. + Used by pytest_process_use. + """ + if name in self.pytest_use_not or name in self.pytest_use_seen: + return + try: + tg = self.bld.get_tgen_by_name(name) + except Errors.WafError: + self.pytest_use_not.add(name) + return + + self.pytest_use_seen.append(name) + tg.post() + + for n in self.to_list(getattr(tg, 'use', [])): + _process_use_rec(self, n) + + +@TaskGen.feature('pytest') +@TaskGen.after_method('process_source', 'apply_link') +def pytest_process_use(self): + """ + Process the ``use`` attribute which contains a list of task generator names and store + paths that later is used to populate the unit test runtime environment. + """ + self.pytest_use_not = set() + self.pytest_use_seen = [] + self.pytest_paths = [] # strings or Nodes + self.pytest_libpaths = [] # strings or Nodes + self.pytest_dep_nodes = [] + + names = self.to_list(getattr(self, 'use', [])) + for name in names: + _process_use_rec(self, name) + + def extend_unique(lst, varlst): + ext = [] + for x in varlst: + if x not in lst: + ext.append(x) + lst.extend(ext) + + # Collect type specific info needed to construct a valid runtime environment + # for the test. + for name in self.pytest_use_seen: + tg = self.bld.get_tgen_by_name(name) + + extend_unique(self.pytest_paths, Utils.to_list(getattr(tg, 'pytest_path', []))) + extend_unique(self.pytest_libpaths, Utils.to_list(getattr(tg, 'pytest_libpath', []))) + + if 'py' in tg.features: + # Python dependencies are added to PYTHONPATH + pypath = getattr(tg, 'install_from', tg.path) + + if 'buildcopy' in tg.features: + # Since buildcopy is used we assume that PYTHONPATH in build should be used, + # not source + extend_unique(self.pytest_paths, [pypath.get_bld().abspath()]) + + # Add buildcopy output nodes to dependencies + extend_unique(self.pytest_dep_nodes, [o for task in getattr(tg, 'tasks', []) \ + for o in getattr(task, 'outputs', [])]) + else: + # If buildcopy is not used, depend on sources instead + extend_unique(self.pytest_dep_nodes, tg.source) + extend_unique(self.pytest_paths, [pypath.abspath()]) + + if getattr(tg, 'link_task', None): + # For tasks with a link_task (C, C++, D et.c.) include their library paths: + if not isinstance(tg.link_task, ccroot.stlink_task): + extend_unique(self.pytest_dep_nodes, tg.link_task.outputs) + extend_unique(self.pytest_libpaths, tg.link_task.env.LIBPATH) + + if 'pyext' in tg.features: + # If the taskgen is extending Python we also want to add the interpreter libpath. + extend_unique(self.pytest_libpaths, tg.link_task.env.LIBPATH_PYEXT) + else: + # Only add to libpath if the link task is not a Python extension + extend_unique(self.pytest_libpaths, [tg.link_task.outputs[0].parent.abspath()]) + + +@TaskGen.feature('pytest') +@TaskGen.after_method('pytest_process_use') +def make_pytest(self): + """ + Creates a ``utest`` task with a populated environment for Python if not specified in ``ut_env``: + + - Paths in `pytest_paths` attribute are used to populate PYTHONPATH + - Paths in `pytest_libpaths` attribute are used to populate the system library path (e.g. LD_LIBRARY_PATH) + """ + nodes = self.to_nodes(self.pytest_source) + tsk = self.create_task('utest', nodes) + + tsk.dep_nodes.extend(self.pytest_dep_nodes) + if getattr(self, 'ut_str', None): + self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) + tsk.vars = lst + tsk.vars + + if getattr(self, 'ut_cwd', None): + if isinstance(self.ut_cwd, str): + # we want a Node instance + if os.path.isabs(self.ut_cwd): + self.ut_cwd = self.bld.root.make_node(self.ut_cwd) + else: + self.ut_cwd = self.path.make_node(self.ut_cwd) + else: + if tsk.inputs: + self.ut_cwd = tsk.inputs[0].parent + else: + raise Errors.WafError("no valid input files for pytest task, check pytest_source value") + + if not self.ut_cwd.exists(): + self.ut_cwd.mkdir() + + if not hasattr(self, 'ut_env'): + self.ut_env = dict(os.environ) + def add_paths(var, lst): + # Add list of paths to a variable, lst can contain strings or nodes + lst = [ str(n) for n in lst ] + Logs.debug("ut: %s: Adding paths %s=%s", self, var, lst) + self.ut_env[var] = os.pathsep.join(lst) + os.pathsep + self.ut_env.get(var, '') + + # Prepend dependency paths to PYTHONPATH and LD_LIBRARY_PATH + add_paths('PYTHONPATH', self.pytest_paths) + + if Utils.is_win32: + add_paths('PATH', self.pytest_libpaths) + elif Utils.unversioned_sys_platform() == 'darwin': + add_paths('DYLD_LIBRARY_PATH', self.pytest_libpaths) + add_paths('LD_LIBRARY_PATH', self.pytest_libpaths) + else: + add_paths('LD_LIBRARY_PATH', self.pytest_libpaths) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/qnxnto.py b/ldb-2.0.8/third_party/waf/waflib/extras/qnxnto.py new file mode 100644 index 0000000..1158124 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/qnxnto.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Jérôme Carretero 2011 (zougloub) +# QNX neutrino compatibility functions + +import sys, os +from waflib import Utils + +class Popen(object): + """ + Popen cannot work on QNX from a threaded program: + Forking in threads is not implemented in neutrino. + + Python's os.popen / spawn / fork won't work when running in threads (they will if in the main program thread) + + In waf, this happens mostly in build. + And the use cases can be replaced by os.system() calls. + """ + __slots__ = ["prog", "kw", "popen", "verbose"] + verbose = 0 + def __init__(self, prog, **kw): + try: + self.prog = prog + self.kw = kw + self.popen = None + if Popen.verbose: + sys.stdout.write("Popen created: %r, kw=%r..." % (prog, kw)) + + do_delegate = kw.get('stdout') == -1 and kw.get('stderr') == -1 + if do_delegate: + if Popen.verbose: + print("Delegating to real Popen") + self.popen = self.real_Popen(prog, **kw) + else: + if Popen.verbose: + print("Emulating") + except Exception as e: + if Popen.verbose: + print("Exception: %s" % e) + raise + + def __getattr__(self, name): + if Popen.verbose: + sys.stdout.write("Getattr: %s..." % name) + if name in Popen.__slots__: + return object.__getattribute__(self, name) + else: + if self.popen is not None: + if Popen.verbose: + print("from Popen") + return getattr(self.popen, name) + else: + if name == "wait": + return self.emu_wait + else: + raise Exception("subprocess emulation: not implemented: %s" % name) + + def emu_wait(self): + if Popen.verbose: + print("emulated wait (%r kw=%r)" % (self.prog, self.kw)) + if isinstance(self.prog, str): + cmd = self.prog + else: + cmd = " ".join(self.prog) + if 'cwd' in self.kw: + cmd = 'cd "%s" && %s' % (self.kw['cwd'], cmd) + return os.system(cmd) + +if sys.platform == "qnx6": + Popen.real_Popen = Utils.subprocess.Popen + Utils.subprocess.Popen = Popen + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/qt4.py b/ldb-2.0.8/third_party/waf/waflib/extras/qt4.py new file mode 100644 index 0000000..d19a4dd --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/qt4.py @@ -0,0 +1,695 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2010 (ita) + +""" + +Tool Description +================ + +This tool helps with finding Qt4 tools and libraries, +and also provides syntactic sugar for using Qt4 tools. + +The following snippet illustrates the tool usage:: + + def options(opt): + opt.load('compiler_cxx qt4') + + def configure(conf): + conf.load('compiler_cxx qt4') + + def build(bld): + bld( + features = 'qt4 cxx cxxprogram', + uselib = 'QTCORE QTGUI QTOPENGL QTSVG', + source = 'main.cpp textures.qrc aboutDialog.ui', + target = 'window', + ) + +Here, the UI description and resource files will be processed +to generate code. + +Usage +===== + +Load the "qt4" tool. + +You also need to edit your sources accordingly: + +- the normal way of doing things is to have your C++ files + include the .moc file. + This is regarded as the best practice (and provides much faster + compilations). + It also implies that the include paths have beenset properly. + +- to have the include paths added automatically, use the following:: + + from waflib.TaskGen import feature, before_method, after_method + @feature('cxx') + @after_method('process_source') + @before_method('apply_incpaths') + def add_includes_paths(self): + incs = set(self.to_list(getattr(self, 'includes', ''))) + for x in self.compiled_tasks: + incs.add(x.inputs[0].parent.path_from(self.path)) + self.includes = sorted(incs) + +Note: another tool provides Qt processing that does not require +.moc includes, see 'playground/slow_qt/'. + +A few options (--qt{dir,bin,...}) and environment variables +(QT4_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool, +tool path selection, etc; please read the source for more info. + +""" + +try: + from xml.sax import make_parser + from xml.sax.handler import ContentHandler +except ImportError: + has_xml = False + ContentHandler = object +else: + has_xml = True + +import os, sys +from waflib.Tools import cxx +from waflib import Task, Utils, Options, Errors, Context +from waflib.TaskGen import feature, after_method, extension +from waflib.Configure import conf +from waflib import Logs + +MOC_H = ['.h', '.hpp', '.hxx', '.hh'] +""" +File extensions associated to the .moc files +""" + +EXT_RCC = ['.qrc'] +""" +File extension for the resource (.qrc) files +""" + +EXT_UI = ['.ui'] +""" +File extension for the user interface (.ui) files +""" + +EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C'] +""" +File extensions of C++ files that may require a .moc processing +""" + +QT4_LIBS = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtXmlPatterns QtWebKit Qt3Support QtHelp QtScript QtDeclarative QtDesigner" + +class qxx(Task.classes['cxx']): + """ + Each C++ file can have zero or several .moc files to create. + They are known only when the files are scanned (preprocessor) + To avoid scanning the c++ files each time (parsing C/C++), the results + are retrieved from the task cache (bld.node_deps/bld.raw_deps). + The moc tasks are also created *dynamically* during the build. + """ + + def __init__(self, *k, **kw): + Task.Task.__init__(self, *k, **kw) + self.moc_done = 0 + + def runnable_status(self): + """ + Compute the task signature to make sure the scanner was executed. Create the + moc tasks by using :py:meth:`waflib.Tools.qt4.qxx.add_moc_tasks` (if necessary), + then postpone the task execution (there is no need to recompute the task signature). + """ + if self.moc_done: + return Task.Task.runnable_status(self) + else: + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + self.add_moc_tasks() + return Task.Task.runnable_status(self) + + def create_moc_task(self, h_node, m_node): + """ + If several libraries use the same classes, it is possible that moc will run several times (Issue 1318) + It is not possible to change the file names, but we can assume that the moc transformation will be identical, + and the moc tasks can be shared in a global cache. + + The defines passed to moc will then depend on task generator order. If this is not acceptable, then + use the tool slow_qt4 instead (and enjoy the slow builds... :-( ) + """ + try: + moc_cache = self.generator.bld.moc_cache + except AttributeError: + moc_cache = self.generator.bld.moc_cache = {} + + try: + return moc_cache[h_node] + except KeyError: + tsk = moc_cache[h_node] = Task.classes['moc'](env=self.env, generator=self.generator) + tsk.set_inputs(h_node) + tsk.set_outputs(m_node) + + if self.generator: + self.generator.tasks.append(tsk) + + # direct injection in the build phase (safe because called from the main thread) + gen = self.generator.bld.producer + gen.outstanding.append(tsk) + gen.total += 1 + + return tsk + + def moc_h_ext(self): + ext = [] + try: + ext = Options.options.qt_header_ext.split() + except AttributeError: + pass + if not ext: + ext = MOC_H + return ext + + def add_moc_tasks(self): + """ + Create the moc tasks by looking in ``bld.raw_deps[self.uid()]`` + """ + node = self.inputs[0] + bld = self.generator.bld + + try: + # compute the signature once to know if there is a moc file to create + self.signature() + except KeyError: + # the moc file may be referenced somewhere else + pass + else: + # remove the signature, it must be recomputed with the moc task + delattr(self, 'cache_sig') + + include_nodes = [node.parent] + self.generator.includes_nodes + + moctasks = [] + mocfiles = set() + for d in bld.raw_deps.get(self.uid(), []): + if not d.endswith('.moc'): + continue + + # process that base.moc only once + if d in mocfiles: + continue + mocfiles.add(d) + + # find the source associated with the moc file + h_node = None + + base2 = d[:-4] + for x in include_nodes: + for e in self.moc_h_ext(): + h_node = x.find_node(base2 + e) + if h_node: + break + if h_node: + m_node = h_node.change_ext('.moc') + break + else: + # foo.cpp -> foo.cpp.moc + for k in EXT_QT4: + if base2.endswith(k): + for x in include_nodes: + h_node = x.find_node(base2) + if h_node: + break + if h_node: + m_node = h_node.change_ext(k + '.moc') + break + + if not h_node: + raise Errors.WafError('No source found for %r which is a moc file' % d) + + # create the moc task + task = self.create_moc_task(h_node, m_node) + moctasks.append(task) + + # simple scheduler dependency: run the moc task before others + self.run_after.update(set(moctasks)) + self.moc_done = 1 + +class trans_update(Task.Task): + """Update a .ts files from a list of C++ files""" + run_str = '${QT_LUPDATE} ${SRC} -ts ${TGT}' + color = 'BLUE' + +class XMLHandler(ContentHandler): + """ + Parser for *.qrc* files + """ + def __init__(self): + self.buf = [] + self.files = [] + def startElement(self, name, attrs): + if name == 'file': + self.buf = [] + def endElement(self, name): + if name == 'file': + self.files.append(str(''.join(self.buf))) + def characters(self, cars): + self.buf.append(cars) + +@extension(*EXT_RCC) +def create_rcc_task(self, node): + "Create rcc and cxx tasks for *.qrc* files" + rcnode = node.change_ext('_rc.cpp') + self.create_task('rcc', node, rcnode) + cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) + try: + self.compiled_tasks.append(cpptask) + except AttributeError: + self.compiled_tasks = [cpptask] + return cpptask + +@extension(*EXT_UI) +def create_uic_task(self, node): + "hook for uic tasks" + uictask = self.create_task('ui4', node) + uictask.outputs = [self.path.find_or_declare(self.env['ui_PATTERN'] % node.name[:-3])] + +@extension('.ts') +def add_lang(self, node): + """add all the .ts file into self.lang""" + self.lang = self.to_list(getattr(self, 'lang', [])) + [node] + +@feature('qt4') +@after_method('apply_link') +def apply_qt4(self): + """ + Add MOC_FLAGS which may be necessary for moc:: + + def build(bld): + bld.program(features='qt4', source='main.cpp', target='app', use='QTCORE') + + The additional parameters are: + + :param lang: list of translation files (\\*.ts) to process + :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension + :param update: whether to process the C++ files to update the \\*.ts files (use **waf --translate**) + :type update: bool + :param langname: if given, transform the \\*.ts files into a .qrc files to include in the binary file + :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension + """ + if getattr(self, 'lang', None): + qmtasks = [] + for x in self.to_list(self.lang): + if isinstance(x, str): + x = self.path.find_resource(x + '.ts') + qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.qm'))) + + if getattr(self, 'update', None) and Options.options.trans_qt4: + cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [ + a.inputs[0] for a in self.tasks if getattr(a, 'inputs', None) and a.inputs[0].name.endswith('.ui')] + for x in qmtasks: + self.create_task('trans_update', cxxnodes, x.inputs) + + if getattr(self, 'langname', None): + qmnodes = [x.outputs[0] for x in qmtasks] + rcnode = self.langname + if isinstance(rcnode, str): + rcnode = self.path.find_or_declare(rcnode + '.qrc') + t = self.create_task('qm2rcc', qmnodes, rcnode) + k = create_rcc_task(self, t.outputs[0]) + self.link_task.inputs.append(k.outputs[0]) + + lst = [] + for flag in self.to_list(self.env['CXXFLAGS']): + if len(flag) < 2: + continue + f = flag[0:2] + if f in ('-D', '-I', '/D', '/I'): + if (f[0] == '/'): + lst.append('-' + flag[1:]) + else: + lst.append(flag) + self.env.append_value('MOC_FLAGS', lst) + +@extension(*EXT_QT4) +def cxx_hook(self, node): + """ + Re-map C++ file extensions to the :py:class:`waflib.Tools.qt4.qxx` task. + """ + return self.create_compiled_task('qxx', node) + +class rcc(Task.Task): + """ + Process *.qrc* files + """ + color = 'BLUE' + run_str = '${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' + ext_out = ['.h'] + + def rcname(self): + return os.path.splitext(self.inputs[0].name)[0] + + def scan(self): + """Parse the *.qrc* files""" + if not has_xml: + Logs.error('no xml support was found, the rcc dependencies will be incomplete!') + return ([], []) + + parser = make_parser() + curHandler = XMLHandler() + parser.setContentHandler(curHandler) + fi = open(self.inputs[0].abspath(), 'r') + try: + parser.parse(fi) + finally: + fi.close() + + nodes = [] + names = [] + root = self.inputs[0].parent + for x in curHandler.files: + nd = root.find_resource(x) + if nd: + nodes.append(nd) + else: + names.append(x) + return (nodes, names) + +class moc(Task.Task): + """ + Create *.moc* files + """ + color = 'BLUE' + run_str = '${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' + def keyword(self): + return "Creating" + def __str__(self): + return self.outputs[0].path_from(self.generator.bld.launch_node()) + +class ui4(Task.Task): + """ + Process *.ui* files + """ + color = 'BLUE' + run_str = '${QT_UIC} ${SRC} -o ${TGT}' + ext_out = ['.h'] + +class ts2qm(Task.Task): + """ + Create *.qm* files from *.ts* files + """ + color = 'BLUE' + run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' + +class qm2rcc(Task.Task): + """ + Transform *.qm* files into *.rc* files + """ + color = 'BLUE' + after = 'ts2qm' + + def run(self): + """Create a qrc file including the inputs""" + txt = '\n'.join(['%s' % k.path_from(self.outputs[0].parent) for k in self.inputs]) + code = '\n\n%s\n\n' % txt + self.outputs[0].write(code) + +def configure(self): + """ + Besides the configuration options, the environment variable QT4_ROOT may be used + to give the location of the qt4 libraries (absolute path). + + The detection will use the program *pkg-config* through :py:func:`waflib.Tools.config_c.check_cfg` + """ + self.find_qt4_binaries() + self.set_qt4_libs_to_check() + self.set_qt4_defines() + self.find_qt4_libraries() + self.add_qt4_rpath() + self.simplify_qt4_libs() + +@conf +def find_qt4_binaries(self): + env = self.env + opt = Options.options + + qtdir = getattr(opt, 'qtdir', '') + qtbin = getattr(opt, 'qtbin', '') + + paths = [] + + if qtdir: + qtbin = os.path.join(qtdir, 'bin') + + # the qt directory has been given from QT4_ROOT - deduce the qt binary path + if not qtdir: + qtdir = os.environ.get('QT4_ROOT', '') + qtbin = os.environ.get('QT4_BIN') or os.path.join(qtdir, 'bin') + + if qtbin: + paths = [qtbin] + + # no qtdir, look in the path and in /usr/local/Trolltech + if not qtdir: + paths = os.environ.get('PATH', '').split(os.pathsep) + paths.append('/usr/share/qt4/bin/') + try: + lst = Utils.listdir('/usr/local/Trolltech/') + except OSError: + pass + else: + if lst: + lst.sort() + lst.reverse() + + # keep the highest version + qtdir = '/usr/local/Trolltech/%s/' % lst[0] + qtbin = os.path.join(qtdir, 'bin') + paths.append(qtbin) + + # at the end, try to find qmake in the paths given + # keep the one with the highest version + cand = None + prev_ver = ['4', '0', '0'] + for qmk in ('qmake-qt4', 'qmake4', 'qmake'): + try: + qmake = self.find_program(qmk, path_list=paths) + except self.errors.ConfigurationError: + pass + else: + try: + version = self.cmd_and_log(qmake + ['-query', 'QT_VERSION']).strip() + except self.errors.WafError: + pass + else: + if version: + new_ver = version.split('.') + if new_ver > prev_ver: + cand = qmake + prev_ver = new_ver + if cand: + self.env.QMAKE = cand + else: + self.fatal('Could not find qmake for qt4') + + qtbin = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_BINS']).strip() + os.sep + + def find_bin(lst, var): + if var in env: + return + for f in lst: + try: + ret = self.find_program(f, path_list=paths) + except self.errors.ConfigurationError: + pass + else: + env[var]=ret + break + + find_bin(['uic-qt3', 'uic3'], 'QT_UIC3') + find_bin(['uic-qt4', 'uic'], 'QT_UIC') + if not env.QT_UIC: + self.fatal('cannot find the uic compiler for qt4') + + self.start_msg('Checking for uic version') + uicver = self.cmd_and_log(env.QT_UIC + ["-version"], output=Context.BOTH) + uicver = ''.join(uicver).strip() + uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '') + self.end_msg(uicver) + if uicver.find(' 3.') != -1: + self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') + + find_bin(['moc-qt4', 'moc'], 'QT_MOC') + find_bin(['rcc-qt4', 'rcc'], 'QT_RCC') + find_bin(['lrelease-qt4', 'lrelease'], 'QT_LRELEASE') + find_bin(['lupdate-qt4', 'lupdate'], 'QT_LUPDATE') + + env['UIC3_ST']= '%s -o %s' + env['UIC_ST'] = '%s -o %s' + env['MOC_ST'] = '-o' + env['ui_PATTERN'] = 'ui_%s.h' + env['QT_LRELEASE_FLAGS'] = ['-silent'] + env.MOCCPPPATH_ST = '-I%s' + env.MOCDEFINES_ST = '-D%s' + +@conf +def find_qt4_libraries(self): + qtlibs = getattr(Options.options, 'qtlibs', None) or os.environ.get("QT4_LIBDIR") + if not qtlibs: + try: + qtlibs = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_LIBS']).strip() + except Errors.WafError: + qtdir = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip() + os.sep + qtlibs = os.path.join(qtdir, 'lib') + self.msg('Found the Qt4 libraries in', qtlibs) + + qtincludes = os.environ.get("QT4_INCLUDES") or self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_HEADERS']).strip() + env = self.env + if not 'PKG_CONFIG_PATH' in os.environ: + os.environ['PKG_CONFIG_PATH'] = '%s:%s/pkgconfig:/usr/lib/qt4/lib/pkgconfig:/opt/qt4/lib/pkgconfig:/usr/lib/qt4/lib:/opt/qt4/lib' % (qtlibs, qtlibs) + + try: + if os.environ.get("QT4_XCOMPILE"): + raise self.errors.ConfigurationError() + self.check_cfg(atleast_pkgconfig_version='0.1') + except self.errors.ConfigurationError: + for i in self.qt4_vars: + uselib = i.upper() + if Utils.unversioned_sys_platform() == "darwin": + # Since at least qt 4.7.3 each library locates in separate directory + frameworkName = i + ".framework" + qtDynamicLib = os.path.join(qtlibs, frameworkName, i) + if os.path.exists(qtDynamicLib): + env.append_unique('FRAMEWORK_' + uselib, i) + self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') + else: + self.msg('Checking for %s' % i, False, 'YELLOW') + env.append_unique('INCLUDES_' + uselib, os.path.join(qtlibs, frameworkName, 'Headers')) + elif env.DEST_OS != "win32": + qtDynamicLib = os.path.join(qtlibs, "lib" + i + ".so") + qtStaticLib = os.path.join(qtlibs, "lib" + i + ".a") + if os.path.exists(qtDynamicLib): + env.append_unique('LIB_' + uselib, i) + self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') + elif os.path.exists(qtStaticLib): + env.append_unique('LIB_' + uselib, i) + self.msg('Checking for %s' % i, qtStaticLib, 'GREEN') + else: + self.msg('Checking for %s' % i, False, 'YELLOW') + + env.append_unique('LIBPATH_' + uselib, qtlibs) + env.append_unique('INCLUDES_' + uselib, qtincludes) + env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) + else: + # Release library names are like QtCore4 + for k in ("lib%s.a", "lib%s4.a", "%s.lib", "%s4.lib"): + lib = os.path.join(qtlibs, k % i) + if os.path.exists(lib): + env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) + self.msg('Checking for %s' % i, lib, 'GREEN') + break + else: + self.msg('Checking for %s' % i, False, 'YELLOW') + + env.append_unique('LIBPATH_' + uselib, qtlibs) + env.append_unique('INCLUDES_' + uselib, qtincludes) + env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) + + # Debug library names are like QtCore4d + uselib = i.upper() + "_debug" + for k in ("lib%sd.a", "lib%sd4.a", "%sd.lib", "%sd4.lib"): + lib = os.path.join(qtlibs, k % i) + if os.path.exists(lib): + env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) + self.msg('Checking for %s' % i, lib, 'GREEN') + break + else: + self.msg('Checking for %s' % i, False, 'YELLOW') + + env.append_unique('LIBPATH_' + uselib, qtlibs) + env.append_unique('INCLUDES_' + uselib, qtincludes) + env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) + else: + for i in self.qt4_vars_debug + self.qt4_vars: + self.check_cfg(package=i, args='--cflags --libs', mandatory=False) + +@conf +def simplify_qt4_libs(self): + # the libpaths make really long command-lines + # remove the qtcore ones from qtgui, etc + env = self.env + def process_lib(vars_, coreval): + for d in vars_: + var = d.upper() + if var == 'QTCORE': + continue + + value = env['LIBPATH_'+var] + if value: + core = env[coreval] + accu = [] + for lib in value: + if lib in core: + continue + accu.append(lib) + env['LIBPATH_'+var] = accu + + process_lib(self.qt4_vars, 'LIBPATH_QTCORE') + process_lib(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') + +@conf +def add_qt4_rpath(self): + # rpath if wanted + env = self.env + if getattr(Options.options, 'want_rpath', False): + def process_rpath(vars_, coreval): + for d in vars_: + var = d.upper() + value = env['LIBPATH_'+var] + if value: + core = env[coreval] + accu = [] + for lib in value: + if var != 'QTCORE': + if lib in core: + continue + accu.append('-Wl,--rpath='+lib) + env['RPATH_'+var] = accu + process_rpath(self.qt4_vars, 'LIBPATH_QTCORE') + process_rpath(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') + +@conf +def set_qt4_libs_to_check(self): + if not hasattr(self, 'qt4_vars'): + self.qt4_vars = QT4_LIBS + self.qt4_vars = Utils.to_list(self.qt4_vars) + if not hasattr(self, 'qt4_vars_debug'): + self.qt4_vars_debug = [a + '_debug' for a in self.qt4_vars] + self.qt4_vars_debug = Utils.to_list(self.qt4_vars_debug) + +@conf +def set_qt4_defines(self): + if sys.platform != 'win32': + return + for x in self.qt4_vars: + y = x[2:].upper() + self.env.append_unique('DEFINES_%s' % x.upper(), 'QT_%s_LIB' % y) + self.env.append_unique('DEFINES_%s_DEBUG' % x.upper(), 'QT_%s_LIB' % y) + +def options(opt): + """ + Command-line options + """ + opt.add_option('--want-rpath', action='store_true', default=False, dest='want_rpath', help='enable the rpath for qt libraries') + + opt.add_option('--header-ext', + type='string', + default='', + help='header extension for moc files', + dest='qt_header_ext') + + for i in 'qtdir qtbin qtlibs'.split(): + opt.add_option('--'+i, type='string', default='', dest=i) + + opt.add_option('--translate', action="store_true", help="collect translation strings", dest="trans_qt4", default=False) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/relocation.py b/ldb-2.0.8/third_party/waf/waflib/extras/relocation.py new file mode 100644 index 0000000..7e821f4 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/relocation.py @@ -0,0 +1,85 @@ +#! /usr/bin/env python +# encoding: utf-8 + +""" +Waf 1.6 + +Try to detect if the project directory was relocated, and if it was, +change the node representing the project directory. Just call: + + waf configure build + +Note that if the project directory name changes, the signatures for the tasks using +files in that directory will change, causing a partial build. +""" + +import os +from waflib import Build, ConfigSet, Task, Utils, Errors +from waflib.TaskGen import feature, after_method + +EXTRA_LOCK = '.old_srcdir' + +old1 = Build.BuildContext.store +def store(self): + old1(self) + db = os.path.join(self.variant_dir, EXTRA_LOCK) + env = ConfigSet.ConfigSet() + env.SRCDIR = self.srcnode.abspath() + env.store(db) +Build.BuildContext.store = store + +old2 = Build.BuildContext.init_dirs +def init_dirs(self): + + if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): + raise Errors.WafError('The project was not configured: run "waf configure" first!') + + srcdir = None + db = os.path.join(self.variant_dir, EXTRA_LOCK) + env = ConfigSet.ConfigSet() + try: + env.load(db) + srcdir = env.SRCDIR + except: + pass + + if srcdir: + d = self.root.find_node(srcdir) + if d and srcdir != self.top_dir and getattr(d, 'children', ''): + srcnode = self.root.make_node(self.top_dir) + print("relocating the source directory %r -> %r" % (srcdir, self.top_dir)) + srcnode.children = {} + + for (k, v) in d.children.items(): + srcnode.children[k] = v + v.parent = srcnode + d.children = {} + + old2(self) + +Build.BuildContext.init_dirs = init_dirs + + +def uid(self): + try: + return self.uid_ + except AttributeError: + # this is not a real hot zone, but we want to avoid surprises here + m = Utils.md5() + up = m.update + up(self.__class__.__name__.encode()) + for x in self.inputs + self.outputs: + up(x.path_from(x.ctx.srcnode).encode()) + self.uid_ = m.digest() + return self.uid_ +Task.Task.uid = uid + +@feature('c', 'cxx', 'd', 'go', 'asm', 'fc', 'includes') +@after_method('propagate_uselib_vars', 'process_source') +def apply_incpaths(self): + lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES']) + self.includes_nodes = lst + bld = self.bld + self.env['INCPATHS'] = [x.is_child_of(bld.srcnode) and x.path_from(bld.bldnode) or x.abspath() for x in lst] + + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/remote.py b/ldb-2.0.8/third_party/waf/waflib/extras/remote.py new file mode 100644 index 0000000..f43b600 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/remote.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Remote Builds tool using rsync+ssh + +__author__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2013" + +""" +Simple Remote Builds +******************** + +This tool is an *experimental* tool (meaning, do not even try to pollute +the waf bug tracker with bugs in here, contact me directly) providing simple +remote builds. + +It uses rsync and ssh to perform the remote builds. +It is intended for performing cross-compilation on platforms where +a cross-compiler is either unavailable (eg. MacOS, QNX) a specific product +does not exist (eg. Windows builds using Visual Studio) or simply not installed. +This tool sends the sources and the waf script to the remote host, +and commands the usual waf execution. + +There are alternatives to using this tool, such as setting up shared folders, +logging on to remote machines, and building on the shared folders. +Electing one method or another depends on the size of the program. + + +Usage +===== + +1. Set your wscript file so it includes a list of variants, + e.g.:: + + from waflib import Utils + top = '.' + out = 'build' + + variants = [ + 'linux_64_debug', + 'linux_64_release', + 'linux_32_debug', + 'linux_32_release', + ] + + from waflib.extras import remote + + def options(opt): + # normal stuff from here on + opt.load('compiler_c') + + def configure(conf): + if not conf.variant: + return + # normal stuff from here on + conf.load('compiler_c') + + def build(bld): + if not bld.variant: + return + # normal stuff from here on + bld(features='c cprogram', target='app', source='main.c') + + +2. Build the waf file, so it includes this tool, and put it in the current + directory + + .. code:: bash + + ./waf-light --tools=remote + +3. Set the host names to access the hosts: + + .. code:: bash + + export REMOTE_QNX=user@kiunix + +4. Setup the ssh server and ssh keys + + The ssh key should not be protected by a password, or it will prompt for it every time. + Create the key on the client: + + .. code:: bash + + ssh-keygen -t rsa -f foo.rsa + + Then copy foo.rsa.pub to the remote machine (user@kiunix:/home/user/.ssh/authorized_keys), + and make sure the permissions are correct (chmod go-w ~ ~/.ssh ~/.ssh/authorized_keys) + + A separate key for the build processes can be set in the environment variable WAF_SSH_KEY. + The tool will then use 'ssh-keyscan' to avoid prompting for remote hosts, so + be warned to use this feature on internal networks only (MITM). + + .. code:: bash + + export WAF_SSH_KEY=~/foo.rsa + +5. Perform the build: + + .. code:: bash + + waf configure_all build_all --remote + +""" + + +import getpass, os, re, sys +from collections import OrderedDict +from waflib import Context, Options, Utils, ConfigSet + +from waflib.Build import BuildContext, CleanContext, InstallContext, UninstallContext +from waflib.Configure import ConfigurationContext + + +is_remote = False +if '--remote' in sys.argv: + is_remote = True + sys.argv.remove('--remote') + +class init(Context.Context): + """ + Generates the *_all commands + """ + cmd = 'init' + fun = 'init' + def execute(self): + for x in list(Context.g_module.variants): + self.make_variant(x) + lst = ['remote'] + for k in Options.commands: + if k.endswith('_all'): + name = k.replace('_all', '') + for x in Context.g_module.variants: + lst.append('%s_%s' % (name, x)) + else: + lst.append(k) + del Options.commands[:] + Options.commands += lst + + def make_variant(self, x): + for y in (BuildContext, CleanContext, InstallContext, UninstallContext): + name = y.__name__.replace('Context','').lower() + class tmp(y): + cmd = name + '_' + x + fun = 'build' + variant = x + class tmp(ConfigurationContext): + cmd = 'configure_' + x + fun = 'configure' + variant = x + def __init__(self, **kw): + ConfigurationContext.__init__(self, **kw) + self.setenv(x) + +class remote(BuildContext): + cmd = 'remote' + fun = 'build' + + def get_ssh_hosts(self): + lst = [] + for v in Context.g_module.variants: + self.env.HOST = self.login_to_host(self.variant_to_login(v)) + cmd = Utils.subst_vars('${SSH_KEYSCAN} -t rsa,ecdsa ${HOST}', self.env) + out, err = self.cmd_and_log(cmd, output=Context.BOTH, quiet=Context.BOTH) + lst.append(out.strip()) + return lst + + def setup_private_ssh_key(self): + """ + When WAF_SSH_KEY points to a private key, a .ssh directory will be created in the build directory + Make sure that the ssh key does not prompt for a password + """ + key = os.environ.get('WAF_SSH_KEY', '') + if not key: + return + if not os.path.isfile(key): + self.fatal('Key in WAF_SSH_KEY must point to a valid file') + self.ssh_dir = os.path.join(self.path.abspath(), 'build', '.ssh') + self.ssh_hosts = os.path.join(self.ssh_dir, 'known_hosts') + self.ssh_key = os.path.join(self.ssh_dir, os.path.basename(key)) + self.ssh_config = os.path.join(self.ssh_dir, 'config') + for x in self.ssh_hosts, self.ssh_key, self.ssh_config: + if not os.path.isfile(x): + if not os.path.isdir(self.ssh_dir): + os.makedirs(self.ssh_dir) + Utils.writef(self.ssh_key, Utils.readf(key), 'wb') + os.chmod(self.ssh_key, 448) + + Utils.writef(self.ssh_hosts, '\n'.join(self.get_ssh_hosts())) + os.chmod(self.ssh_key, 448) + + Utils.writef(self.ssh_config, 'UserKnownHostsFile %s' % self.ssh_hosts, 'wb') + os.chmod(self.ssh_config, 448) + self.env.SSH_OPTS = ['-F', self.ssh_config, '-i', self.ssh_key] + self.env.append_value('RSYNC_SEND_OPTS', '--exclude=build/.ssh') + + def skip_unbuildable_variant(self): + # skip variants that cannot be built on this OS + for k in Options.commands: + a, _, b = k.partition('_') + if b in Context.g_module.variants: + c, _, _ = b.partition('_') + if c != Utils.unversioned_sys_platform(): + Options.commands.remove(k) + + def login_to_host(self, login): + return re.sub(r'(\w+@)', '', login) + + def variant_to_login(self, variant): + """linux_32_debug -> search env.LINUX_32 and then env.LINUX""" + x = variant[:variant.rfind('_')] + ret = os.environ.get('REMOTE_' + x.upper(), '') + if not ret: + x = x[:x.find('_')] + ret = os.environ.get('REMOTE_' + x.upper(), '') + if not ret: + ret = '%s@localhost' % getpass.getuser() + return ret + + def execute(self): + global is_remote + if not is_remote: + self.skip_unbuildable_variant() + else: + BuildContext.execute(self) + + def restore(self): + self.top_dir = os.path.abspath(Context.g_module.top) + self.srcnode = self.root.find_node(self.top_dir) + self.path = self.srcnode + + self.out_dir = os.path.join(self.top_dir, Context.g_module.out) + self.bldnode = self.root.make_node(self.out_dir) + self.bldnode.mkdir() + + self.env = ConfigSet.ConfigSet() + + def extract_groups_of_builds(self): + """Return a dict mapping each variants to the commands to build""" + self.vgroups = {} + for x in reversed(Options.commands): + _, _, variant = x.partition('_') + if variant in Context.g_module.variants: + try: + dct = self.vgroups[variant] + except KeyError: + dct = self.vgroups[variant] = OrderedDict() + try: + dct[variant].append(x) + except KeyError: + dct[variant] = [x] + Options.commands.remove(x) + + def custom_options(self, login): + try: + return Context.g_module.host_options[login] + except (AttributeError, KeyError): + return {} + + def recurse(self, *k, **kw): + self.env.RSYNC = getattr(Context.g_module, 'rsync', 'rsync -a --chmod=u+rwx') + self.env.SSH = getattr(Context.g_module, 'ssh', 'ssh') + self.env.SSH_KEYSCAN = getattr(Context.g_module, 'ssh_keyscan', 'ssh-keyscan') + try: + self.env.WAF = getattr(Context.g_module, 'waf') + except AttributeError: + try: + os.stat('waf') + except KeyError: + self.fatal('Put a waf file in the directory (./waf-light --tools=remote)') + else: + self.env.WAF = './waf' + + self.extract_groups_of_builds() + self.setup_private_ssh_key() + for k, v in self.vgroups.items(): + task = self(rule=rsync_and_ssh, always=True) + task.env.login = self.variant_to_login(k) + + task.env.commands = [] + for opt, value in v.items(): + task.env.commands += value + task.env.variant = task.env.commands[0].partition('_')[2] + for opt, value in self.custom_options(k): + task.env[opt] = value + self.jobs = len(self.vgroups) + + def make_mkdir_command(self, task): + return Utils.subst_vars('${SSH} ${SSH_OPTS} ${login} "rm -fr ${remote_dir} && mkdir -p ${remote_dir}"', task.env) + + def make_send_command(self, task): + return Utils.subst_vars('${RSYNC} ${RSYNC_SEND_OPTS} -e "${SSH} ${SSH_OPTS}" ${local_dir} ${login}:${remote_dir}', task.env) + + def make_exec_command(self, task): + txt = '''${SSH} ${SSH_OPTS} ${login} "cd ${remote_dir} && ${WAF} ${commands}"''' + return Utils.subst_vars(txt, task.env) + + def make_save_command(self, task): + return Utils.subst_vars('${RSYNC} ${RSYNC_SAVE_OPTS} -e "${SSH} ${SSH_OPTS}" ${login}:${remote_dir_variant} ${build_dir}', task.env) + +def rsync_and_ssh(task): + + # remove a warning + task.uid_ = id(task) + + bld = task.generator.bld + + task.env.user, _, _ = task.env.login.partition('@') + task.env.hdir = Utils.to_hex(Utils.h_list((task.generator.path.abspath(), task.env.variant))) + task.env.remote_dir = '~%s/wafremote/%s' % (task.env.user, task.env.hdir) + task.env.local_dir = bld.srcnode.abspath() + '/' + + task.env.remote_dir_variant = '%s/%s/%s' % (task.env.remote_dir, Context.g_module.out, task.env.variant) + task.env.build_dir = bld.bldnode.abspath() + + ret = task.exec_command(bld.make_mkdir_command(task)) + if ret: + return ret + ret = task.exec_command(bld.make_send_command(task)) + if ret: + return ret + ret = task.exec_command(bld.make_exec_command(task)) + if ret: + return ret + ret = task.exec_command(bld.make_save_command(task)) + if ret: + return ret + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/resx.py b/ldb-2.0.8/third_party/waf/waflib/extras/resx.py new file mode 100644 index 0000000..caf4d31 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/resx.py @@ -0,0 +1,35 @@ +#! /usr/bin/env python +# encoding: utf-8 + +import os +from waflib import Task +from waflib.TaskGen import extension + +def configure(conf): + conf.find_program(['resgen'], var='RESGEN') + conf.env.RESGENFLAGS = '/useSourcePath' + +@extension('.resx') +def resx_file(self, node): + """ + Bind the .resx extension to a resgen task + """ + if not getattr(self, 'cs_task', None): + self.bld.fatal('resx_file has no link task for use %r' % self) + + # Given assembly 'Foo' and file 'Sub/Dir/File.resx', create 'Foo.Sub.Dir.File.resources' + assembly = getattr(self, 'namespace', os.path.splitext(self.gen)[0]) + res = os.path.splitext(node.path_from(self.path))[0].replace('/', '.').replace('\\', '.') + out = self.path.find_or_declare(assembly + '.' + res + '.resources') + + tsk = self.create_task('resgen', node, out) + + self.cs_task.dep_nodes.extend(tsk.outputs) # dependency + self.env.append_value('RESOURCES', tsk.outputs[0].bldpath()) + +class resgen(Task.Task): + """ + Compile C# resource files + """ + color = 'YELLOW' + run_str = '${RESGEN} ${RESGENFLAGS} ${SRC} ${TGT}' diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/review.py b/ldb-2.0.8/third_party/waf/waflib/extras/review.py new file mode 100644 index 0000000..561e062 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/review.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Laurent Birtz, 2011 +# moved the code into a separate tool (ita) + +""" +There are several things here: +- a different command-line option management making options persistent +- the review command to display the options set + +Assumptions: +- configuration options are not always added to the right group (and do not count on the users to do it...) +- the options are persistent between the executions (waf options are NOT persistent by design), even for the configuration +- when the options change, the build is invalidated (forcing a reconfiguration) +""" + +import os, textwrap, shutil +from waflib import Logs, Context, ConfigSet, Options, Build, Configure + +class Odict(dict): + """Ordered dictionary""" + def __init__(self, data=None): + self._keys = [] + dict.__init__(self) + if data: + # we were provided a regular dict + if isinstance(data, dict): + self.append_from_dict(data) + + # we were provided a tuple list + elif type(data) == list: + self.append_from_plist(data) + + # we were provided invalid input + else: + raise Exception("expected a dict or a tuple list") + + def append_from_dict(self, dict): + map(self.__setitem__, dict.keys(), dict.values()) + + def append_from_plist(self, plist): + for pair in plist: + if len(pair) != 2: + raise Exception("invalid pairs list") + for (k, v) in plist: + self.__setitem__(k, v) + + def __delitem__(self, key): + if not key in self._keys: + raise KeyError(key) + dict.__delitem__(self, key) + self._keys.remove(key) + + def __setitem__(self, key, item): + dict.__setitem__(self, key, item) + if key not in self._keys: + self._keys.append(key) + + def clear(self): + dict.clear(self) + self._keys = [] + + def copy(self): + return Odict(self.plist()) + + def items(self): + return zip(self._keys, self.values()) + + def keys(self): + return list(self._keys) # return a copy of the list + + def values(self): + return map(self.get, self._keys) + + def plist(self): + p = [] + for k, v in self.items(): + p.append( (k, v) ) + return p + + def __str__(self): + buf = [] + buf.append("{ ") + for k, v in self.items(): + buf.append('%r : %r, ' % (k, v)) + buf.append("}") + return ''.join(buf) + +review_options = Odict() +""" +Ordered dictionary mapping configuration option names to their optparse option. +""" + +review_defaults = {} +""" +Dictionary mapping configuration option names to their default value. +""" + +old_review_set = None +""" +Review set containing the configuration values before parsing the command line. +""" + +new_review_set = None +""" +Review set containing the configuration values after parsing the command line. +""" + +class OptionsReview(Options.OptionsContext): + def __init__(self, **kw): + super(self.__class__, self).__init__(**kw) + + def prepare_config_review(self): + """ + Find the configuration options that are reviewable, detach + their default value from their optparse object and store them + into the review dictionaries. + """ + gr = self.get_option_group('configure options') + for opt in gr.option_list: + if opt.action != 'store' or opt.dest in ("out", "top"): + continue + review_options[opt.dest] = opt + review_defaults[opt.dest] = opt.default + if gr.defaults.has_key(opt.dest): + del gr.defaults[opt.dest] + opt.default = None + + def parse_args(self): + self.prepare_config_review() + self.parser.get_option('--prefix').help = 'installation prefix' + super(OptionsReview, self).parse_args() + Context.create_context('review').refresh_review_set() + +class ReviewContext(Context.Context): + '''reviews the configuration values''' + + cmd = 'review' + + def __init__(self, **kw): + super(self.__class__, self).__init__(**kw) + + out = Options.options.out + if not out: + out = getattr(Context.g_module, Context.OUT, None) + if not out: + out = Options.lockfile.replace('.lock-waf', '') + self.build_path = (os.path.isabs(out) and self.root or self.path).make_node(out).abspath() + """Path to the build directory""" + + self.cache_path = os.path.join(self.build_path, Build.CACHE_DIR) + """Path to the cache directory""" + + self.review_path = os.path.join(self.cache_path, 'review.cache') + """Path to the review cache file""" + + def execute(self): + """ + Display and store the review set. Invalidate the cache as required. + """ + if not self.compare_review_set(old_review_set, new_review_set): + self.invalidate_cache() + self.store_review_set(new_review_set) + print(self.display_review_set(new_review_set)) + + def invalidate_cache(self): + """Invalidate the cache to prevent bad builds.""" + try: + Logs.warn("Removing the cached configuration since the options have changed") + shutil.rmtree(self.cache_path) + except: + pass + + def refresh_review_set(self): + """ + Obtain the old review set and the new review set, and import the new set. + """ + global old_review_set, new_review_set + old_review_set = self.load_review_set() + new_review_set = self.update_review_set(old_review_set) + self.import_review_set(new_review_set) + + def load_review_set(self): + """ + Load and return the review set from the cache if it exists. + Otherwise, return an empty set. + """ + if os.path.isfile(self.review_path): + return ConfigSet.ConfigSet(self.review_path) + return ConfigSet.ConfigSet() + + def store_review_set(self, review_set): + """ + Store the review set specified in the cache. + """ + if not os.path.isdir(self.cache_path): + os.makedirs(self.cache_path) + review_set.store(self.review_path) + + def update_review_set(self, old_set): + """ + Merge the options passed on the command line with those imported + from the previous review set and return the corresponding + preview set. + """ + + # Convert value to string. It's important that 'None' maps to + # the empty string. + def val_to_str(val): + if val == None or val == '': + return '' + return str(val) + + new_set = ConfigSet.ConfigSet() + opt_dict = Options.options.__dict__ + + for name in review_options.keys(): + # the option is specified explicitly on the command line + if name in opt_dict: + # if the option is the default, pretend it was never specified + if val_to_str(opt_dict[name]) != val_to_str(review_defaults[name]): + new_set[name] = opt_dict[name] + # the option was explicitly specified in a previous command + elif name in old_set: + new_set[name] = old_set[name] + + return new_set + + def import_review_set(self, review_set): + """ + Import the actual value of the reviewable options in the option + dictionary, given the current review set. + """ + for name in review_options.keys(): + if name in review_set: + value = review_set[name] + else: + value = review_defaults[name] + setattr(Options.options, name, value) + + def compare_review_set(self, set1, set2): + """ + Return true if the review sets specified are equal. + """ + if len(set1.keys()) != len(set2.keys()): + return False + for key in set1.keys(): + if not key in set2 or set1[key] != set2[key]: + return False + return True + + def display_review_set(self, review_set): + """ + Return the string representing the review set specified. + """ + term_width = Logs.get_term_cols() + lines = [] + for dest in review_options.keys(): + opt = review_options[dest] + name = ", ".join(opt._short_opts + opt._long_opts) + help = opt.help + actual = None + if dest in review_set: + actual = review_set[dest] + default = review_defaults[dest] + lines.append(self.format_option(name, help, actual, default, term_width)) + return "Configuration:\n\n" + "\n\n".join(lines) + "\n" + + def format_option(self, name, help, actual, default, term_width): + """ + Return the string representing the option specified. + """ + def val_to_str(val): + if val == None or val == '': + return "(void)" + return str(val) + + max_name_len = 20 + sep_len = 2 + + w = textwrap.TextWrapper() + w.width = term_width - 1 + if w.width < 60: + w.width = 60 + + out = "" + + # format the help + out += w.fill(help) + "\n" + + # format the name + name_len = len(name) + out += Logs.colors.CYAN + name + Logs.colors.NORMAL + + # set the indentation used when the value wraps to the next line + w.subsequent_indent = " ".rjust(max_name_len + sep_len) + w.width -= (max_name_len + sep_len) + + # the name string is too long, switch to the next line + if name_len > max_name_len: + out += "\n" + w.subsequent_indent + + # fill the remaining of the line with spaces + else: + out += " ".rjust(max_name_len + sep_len - name_len) + + # format the actual value, if there is one + if actual != None: + out += Logs.colors.BOLD + w.fill(val_to_str(actual)) + Logs.colors.NORMAL + "\n" + w.subsequent_indent + + # format the default value + default_fmt = val_to_str(default) + if actual != None: + default_fmt = "default: " + default_fmt + out += Logs.colors.NORMAL + w.fill(default_fmt) + Logs.colors.NORMAL + + return out + +# Monkey-patch ConfigurationContext.execute() to have it store the review set. +old_configure_execute = Configure.ConfigurationContext.execute +def new_configure_execute(self): + old_configure_execute(self) + Context.create_context('review').store_review_set(new_review_set) +Configure.ConfigurationContext.execute = new_configure_execute + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/rst.py b/ldb-2.0.8/third_party/waf/waflib/extras/rst.py new file mode 100644 index 0000000..f3c3a5e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/rst.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Jérôme Carretero, 2013 (zougloub) + +""" +reStructuredText support (experimental) + +Example:: + + def configure(conf): + conf.load('rst') + if not conf.env.RST2HTML: + conf.fatal('The program rst2html is required') + + def build(bld): + bld( + features = 'rst', + type = 'rst2html', # rst2html, rst2pdf, ... + source = 'index.rst', # mandatory, the source + deps = 'image.png', # to give additional non-trivial dependencies + ) + +By default the tool looks for a set of programs in PATH. +The tools are defined in `rst_progs`. +To configure with a special program use:: + + $ RST2HTML=/path/to/rst2html waf configure + +This tool is experimental; don't hesitate to contribute to it. + +""" + +import re +from waflib import Node, Utils, Task, Errors, Logs +from waflib.TaskGen import feature, before_method + +rst_progs = "rst2html rst2xetex rst2latex rst2xml rst2pdf rst2s5 rst2man rst2odt rst2rtf".split() + +def parse_rst_node(task, node, nodes, names, seen, dirs=None): + # TODO add extensibility, to handle custom rst include tags... + if dirs is None: + dirs = (node.parent,node.get_bld().parent) + + if node in seen: + return + seen.append(node) + code = node.read() + re_rst = re.compile(r'^\s*.. ((?P\|\S+\|) )?(?Pinclude|image|figure):: (?P.*)$', re.M) + for match in re_rst.finditer(code): + ipath = match.group('file') + itype = match.group('type') + Logs.debug('rst: visiting %s: %s', itype, ipath) + found = False + for d in dirs: + Logs.debug('rst: looking for %s in %s', ipath, d.abspath()) + found = d.find_node(ipath) + if found: + Logs.debug('rst: found %s as %s', ipath, found.abspath()) + nodes.append((itype, found)) + if itype == 'include': + parse_rst_node(task, found, nodes, names, seen) + break + if not found: + names.append((itype, ipath)) + +class docutils(Task.Task): + """ + Compile a rst file. + """ + + def scan(self): + """ + A recursive regex-based scanner that finds rst dependencies. + """ + + nodes = [] + names = [] + seen = [] + + node = self.inputs[0] + + if not node: + return (nodes, names) + + parse_rst_node(self, node, nodes, names, seen) + + Logs.debug('rst: %r: found the following file deps: %r', self, nodes) + if names: + Logs.warn('rst: %r: could not find the following file deps: %r', self, names) + + return ([v for (t,v) in nodes], [v for (t,v) in names]) + + def check_status(self, msg, retcode): + """ + Check an exit status and raise an error with a particular message + + :param msg: message to display if the code is non-zero + :type msg: string + :param retcode: condition + :type retcode: boolean + """ + if retcode != 0: + raise Errors.WafError('%r command exit status %r' % (msg, retcode)) + + def run(self): + """ + Runs the rst compilation using docutils + """ + raise NotImplementedError() + +class rst2html(docutils): + color = 'BLUE' + + def __init__(self, *args, **kw): + docutils.__init__(self, *args, **kw) + self.command = self.generator.env.RST2HTML + self.attributes = ['stylesheet'] + + def scan(self): + nodes, names = docutils.scan(self) + + for attribute in self.attributes: + stylesheet = getattr(self.generator, attribute, None) + if stylesheet is not None: + ssnode = self.generator.to_nodes(stylesheet)[0] + nodes.append(ssnode) + Logs.debug('rst: adding dep to %s %s', attribute, stylesheet) + + return nodes, names + + def run(self): + cwdn = self.outputs[0].parent + src = self.inputs[0].path_from(cwdn) + dst = self.outputs[0].path_from(cwdn) + + cmd = self.command + [src, dst] + cmd += Utils.to_list(getattr(self.generator, 'options', [])) + for attribute in self.attributes: + stylesheet = getattr(self.generator, attribute, None) + if stylesheet is not None: + stylesheet = self.generator.to_nodes(stylesheet)[0] + cmd += ['--%s' % attribute, stylesheet.path_from(cwdn)] + + return self.exec_command(cmd, cwd=cwdn.abspath()) + +class rst2s5(rst2html): + def __init__(self, *args, **kw): + rst2html.__init__(self, *args, **kw) + self.command = self.generator.env.RST2S5 + self.attributes = ['stylesheet'] + +class rst2latex(rst2html): + def __init__(self, *args, **kw): + rst2html.__init__(self, *args, **kw) + self.command = self.generator.env.RST2LATEX + self.attributes = ['stylesheet'] + +class rst2xetex(rst2html): + def __init__(self, *args, **kw): + rst2html.__init__(self, *args, **kw) + self.command = self.generator.env.RST2XETEX + self.attributes = ['stylesheet'] + +class rst2pdf(docutils): + color = 'BLUE' + def run(self): + cwdn = self.outputs[0].parent + src = self.inputs[0].path_from(cwdn) + dst = self.outputs[0].path_from(cwdn) + + cmd = self.generator.env.RST2PDF + [src, '-o', dst] + cmd += Utils.to_list(getattr(self.generator, 'options', [])) + + return self.exec_command(cmd, cwd=cwdn.abspath()) + + +@feature('rst') +@before_method('process_source') +def apply_rst(self): + """ + Create :py:class:`rst` or other rst-related task objects + """ + + if self.target: + if isinstance(self.target, Node.Node): + tgt = self.target + elif isinstance(self.target, str): + tgt = self.path.get_bld().make_node(self.target) + else: + self.bld.fatal("rst: Don't know how to build target name %s which is not a string or Node for %s" % (self.target, self)) + else: + tgt = None + + tsk_type = getattr(self, 'type', None) + + src = self.to_nodes(self.source) + assert len(src) == 1 + src = src[0] + + if tsk_type is not None and tgt is None: + if tsk_type.startswith('rst2'): + ext = tsk_type[4:] + else: + self.bld.fatal("rst: Could not detect the output file extension for %s" % self) + tgt = src.change_ext('.%s' % ext) + elif tsk_type is None and tgt is not None: + out = tgt.name + ext = out[out.rfind('.')+1:] + self.type = 'rst2' + ext + elif tsk_type is not None and tgt is not None: + # the user knows what he wants + pass + else: + self.bld.fatal("rst: Need to indicate task type or target name for %s" % self) + + deps_lst = [] + + if getattr(self, 'deps', None): + deps = self.to_list(self.deps) + for filename in deps: + n = self.path.find_resource(filename) + if not n: + self.bld.fatal('Could not find %r for %r' % (filename, self)) + if not n in deps_lst: + deps_lst.append(n) + + try: + task = self.create_task(self.type, src, tgt) + except KeyError: + self.bld.fatal("rst: Task of type %s not implemented (created by %s)" % (self.type, self)) + + task.env = self.env + + # add the manual dependencies + if deps_lst: + try: + lst = self.bld.node_deps[task.uid()] + for n in deps_lst: + if not n in lst: + lst.append(n) + except KeyError: + self.bld.node_deps[task.uid()] = deps_lst + + inst_to = getattr(self, 'install_path', None) + if inst_to: + self.install_task = self.add_install_files(install_to=inst_to, install_from=task.outputs[:]) + + self.source = [] + +def configure(self): + """ + Try to find the rst programs. + + Do not raise any error if they are not found. + You'll have to use additional code in configure() to die + if programs were not found. + """ + for p in rst_progs: + self.find_program(p, mandatory=False) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/run_do_script.py b/ldb-2.0.8/third_party/waf/waflib/extras/run_do_script.py new file mode 100644 index 0000000..07e3aa2 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/run_do_script.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Hans-Martin von Gaudecker, 2012 + +""" +Run a Stata do-script in the directory specified by **ctx.bldnode**. The +first and only argument will be the name of the do-script (no extension), +which can be accessed inside the do-script by the local macro `1'. Useful +for keeping a log file. + +The tool uses the log file that is automatically kept by Stata only +for error-catching purposes, it will be destroyed if the task finished +without error. In case of an error in **some_script.do**, you can inspect +it as **some_script.log** in the **ctx.bldnode** directory. + +Note that Stata will not return an error code if it exits abnormally -- +catching errors relies on parsing the log file mentioned before. Should +the parser behave incorrectly please send an email to hmgaudecker [at] gmail. + +**WARNING** + + The tool will not work if multiple do-scripts of the same name---but in + different directories---are run at the same time! Avoid this situation. + +Usage:: + + ctx(features='run_do_script', + source='some_script.do', + target=['some_table.tex', 'some_figure.eps'], + deps='some_data.csv') +""" + + +import os, re, sys +from waflib import Task, TaskGen, Logs + +if sys.platform == 'darwin': + STATA_COMMANDS = ['Stata64MP', 'StataMP', + 'Stata64SE', 'StataSE', + 'Stata64', 'Stata'] + STATAFLAGS = '-e -q do' + STATAENCODING = 'MacRoman' +elif sys.platform.startswith('linux'): + STATA_COMMANDS = ['stata-mp', 'stata-se', 'stata'] + STATAFLAGS = '-b -q do' + # Not sure whether this is correct... + STATAENCODING = 'Latin-1' +elif sys.platform.lower().startswith('win'): + STATA_COMMANDS = ['StataMP-64', 'StataMP-ia', + 'StataMP', 'StataSE-64', + 'StataSE-ia', 'StataSE', + 'Stata-64', 'Stata-ia', + 'Stata.e', 'WMPSTATA', + 'WSESTATA', 'WSTATA'] + STATAFLAGS = '/e do' + STATAENCODING = 'Latin-1' +else: + raise Exception("Unknown sys.platform: %s " % sys.platform) + +def configure(ctx): + ctx.find_program(STATA_COMMANDS, var='STATACMD', errmsg="""\n +No Stata executable found!\n\n +If Stata is needed:\n + 1) Check the settings of your system path. + 2) Note we are looking for Stata executables called: %s + If yours has a different name, please report to hmgaudecker [at] gmail\n +Else:\n + Do not load the 'run_do_script' tool in the main wscript.\n\n""" % STATA_COMMANDS) + ctx.env.STATAFLAGS = STATAFLAGS + ctx.env.STATAENCODING = STATAENCODING + +class run_do_script_base(Task.Task): + """Run a Stata do-script from the bldnode directory.""" + run_str = '"${STATACMD}" ${STATAFLAGS} "${SRC[0].abspath()}" "${DOFILETRUNK}"' + shell = True + +class run_do_script(run_do_script_base): + """Use the log file automatically kept by Stata for error-catching. + Erase it if the task finished without error. If not, it will show + up as do_script.log in the bldnode directory. + """ + def run(self): + run_do_script_base.run(self) + ret, log_tail = self.check_erase_log_file() + if ret: + Logs.error("""Running Stata on %r failed with code %r.\n\nCheck the log file %s, last 10 lines\n\n%s\n\n\n""", + self.inputs[0], ret, self.env.LOGFILEPATH, log_tail) + return ret + + def check_erase_log_file(self): + """Parse Stata's default log file and erase it if everything okay. + + Parser is based on Brendan Halpin's shell script found here: + http://teaching.sociology.ul.ie/bhalpin/wordpress/?p=122 + """ + + if sys.version_info.major >= 3: + kwargs = {'file': self.env.LOGFILEPATH, 'mode': 'r', 'encoding': self.env.STATAENCODING} + else: + kwargs = {'name': self.env.LOGFILEPATH, 'mode': 'r'} + with open(**kwargs) as log: + log_tail = log.readlines()[-10:] + for line in log_tail: + error_found = re.match(r"r\(([0-9]+)\)", line) + if error_found: + return error_found.group(1), ''.join(log_tail) + else: + pass + # Only end up here if the parser did not identify an error. + os.remove(self.env.LOGFILEPATH) + return None, None + + +@TaskGen.feature('run_do_script') +@TaskGen.before_method('process_source') +def apply_run_do_script(tg): + """Task generator customising the options etc. to call Stata in batch + mode for running a do-script. + """ + + # Convert sources and targets to nodes + src_node = tg.path.find_resource(tg.source) + tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] + + tsk = tg.create_task('run_do_script', src=src_node, tgt=tgt_nodes) + tsk.env.DOFILETRUNK = os.path.splitext(src_node.name)[0] + tsk.env.LOGFILEPATH = os.path.join(tg.bld.bldnode.abspath(), '%s.log' % (tsk.env.DOFILETRUNK)) + + # dependencies (if the attribute 'deps' changes, trigger a recompilation) + for x in tg.to_list(getattr(tg, 'deps', [])): + node = tg.path.find_resource(x) + if not node: + tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.abspath())) + tsk.dep_nodes.append(node) + Logs.debug('deps: found dependencies %r for running %r', tsk.dep_nodes, src_node.abspath()) + + # Bypass the execution of process_source by setting the source to an empty list + tg.source = [] + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/run_m_script.py b/ldb-2.0.8/third_party/waf/waflib/extras/run_m_script.py new file mode 100644 index 0000000..b5f27eb --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/run_m_script.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Hans-Martin von Gaudecker, 2012 + +""" +Run a Matlab script. + +Note that the script is run in the directory where it lives -- Matlab won't +allow it any other way. + +For error-catching purposes, keep an own log-file that is destroyed if the +task finished without error. If not, it will show up as mscript_[index].log +in the bldnode directory. + +Usage:: + + ctx(features='run_m_script', + source='some_script.m', + target=['some_table.tex', 'some_figure.eps'], + deps='some_data.mat') +""" + +import os, sys +from waflib import Task, TaskGen, Logs + +MATLAB_COMMANDS = ['matlab'] + +def configure(ctx): + ctx.find_program(MATLAB_COMMANDS, var='MATLABCMD', errmsg = """\n +No Matlab executable found!\n\n +If Matlab is needed:\n + 1) Check the settings of your system path. + 2) Note we are looking for Matlab executables called: %s + If yours has a different name, please report to hmgaudecker [at] gmail\n +Else:\n + Do not load the 'run_m_script' tool in the main wscript.\n\n""" % MATLAB_COMMANDS) + ctx.env.MATLABFLAGS = '-wait -nojvm -nosplash -minimize' + +class run_m_script_base(Task.Task): + """Run a Matlab script.""" + run_str = '"${MATLABCMD}" ${MATLABFLAGS} -logfile "${LOGFILEPATH}" -r "try, ${MSCRIPTTRUNK}, exit(0), catch err, disp(err.getReport()), exit(1), end"' + shell = True + +class run_m_script(run_m_script_base): + """Erase the Matlab overall log file if everything went okay, else raise an + error and print its 10 last lines. + """ + def run(self): + ret = run_m_script_base.run(self) + logfile = self.env.LOGFILEPATH + if ret: + mode = 'r' + if sys.version_info.major >= 3: + mode = 'rb' + with open(logfile, mode=mode) as f: + tail = f.readlines()[-10:] + Logs.error("""Running Matlab on %r returned the error %r\n\nCheck the log file %s, last 10 lines\n\n%s\n\n\n""", + self.inputs[0], ret, logfile, '\n'.join(tail)) + else: + os.remove(logfile) + return ret + +@TaskGen.feature('run_m_script') +@TaskGen.before_method('process_source') +def apply_run_m_script(tg): + """Task generator customising the options etc. to call Matlab in batch + mode for running a m-script. + """ + + # Convert sources and targets to nodes + src_node = tg.path.find_resource(tg.source) + tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] + + tsk = tg.create_task('run_m_script', src=src_node, tgt=tgt_nodes) + tsk.cwd = src_node.parent.abspath() + tsk.env.MSCRIPTTRUNK = os.path.splitext(src_node.name)[0] + tsk.env.LOGFILEPATH = os.path.join(tg.bld.bldnode.abspath(), '%s_%d.log' % (tsk.env.MSCRIPTTRUNK, tg.idx)) + + # dependencies (if the attribute 'deps' changes, trigger a recompilation) + for x in tg.to_list(getattr(tg, 'deps', [])): + node = tg.path.find_resource(x) + if not node: + tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.abspath())) + tsk.dep_nodes.append(node) + Logs.debug('deps: found dependencies %r for running %r', tsk.dep_nodes, src_node.abspath()) + + # Bypass the execution of process_source by setting the source to an empty list + tg.source = [] diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/run_py_script.py b/ldb-2.0.8/third_party/waf/waflib/extras/run_py_script.py new file mode 100644 index 0000000..3670381 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/run_py_script.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Hans-Martin von Gaudecker, 2012 + +""" +Run a Python script in the directory specified by **ctx.bldnode**. + +Select a Python version by specifying the **version** keyword for +the task generator instance as integer 2 or 3. Default is 3. + +If the build environment has an attribute "PROJECT_PATHS" with +a key "PROJECT_ROOT", its value will be appended to the PYTHONPATH. +Same a string passed to the optional **add_to_pythonpath** +keyword (appended after the PROJECT_ROOT). + +Usage:: + + ctx(features='run_py_script', version=3, + source='some_script.py', + target=['some_table.tex', 'some_figure.eps'], + deps='some_data.csv', + add_to_pythonpath='src/some/library') +""" + +import os, re +from waflib import Task, TaskGen, Logs + + +def configure(conf): + """TODO: Might need to be updated for Windows once + "PEP 397":http://www.python.org/dev/peps/pep-0397/ is settled. + """ + conf.find_program('python', var='PY2CMD', mandatory=False) + conf.find_program('python3', var='PY3CMD', mandatory=False) + if not conf.env.PY2CMD and not conf.env.PY3CMD: + conf.fatal("No Python interpreter found!") + +class run_py_2_script(Task.Task): + """Run a Python 2 script.""" + run_str = '${PY2CMD} ${SRC[0].abspath()}' + shell=True + +class run_py_3_script(Task.Task): + """Run a Python 3 script.""" + run_str = '${PY3CMD} ${SRC[0].abspath()}' + shell=True + +@TaskGen.feature('run_py_script') +@TaskGen.before_method('process_source') +def apply_run_py_script(tg): + """Task generator for running either Python 2 or Python 3 on a single + script. + + Attributes: + + * source -- A **single** source node or string. (required) + * target -- A single target or list of targets (nodes or strings) + * deps -- A single dependency or list of dependencies (nodes or strings) + * add_to_pythonpath -- A string that will be appended to the PYTHONPATH environment variable + + If the build environment has an attribute "PROJECT_PATHS" with + a key "PROJECT_ROOT", its value will be appended to the PYTHONPATH. + """ + + # Set the Python version to use, default to 3. + v = getattr(tg, 'version', 3) + if v not in (2, 3): + raise ValueError("Specify the 'version' attribute for run_py_script task generator as integer 2 or 3.\n Got: %s" %v) + + # Convert sources and targets to nodes + src_node = tg.path.find_resource(tg.source) + tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] + + # Create the task. + tsk = tg.create_task('run_py_%d_script' %v, src=src_node, tgt=tgt_nodes) + + # custom execution environment + # TODO use a list and os.sep.join(lst) at the end instead of concatenating strings + tsk.env.env = dict(os.environ) + tsk.env.env['PYTHONPATH'] = tsk.env.env.get('PYTHONPATH', '') + project_paths = getattr(tsk.env, 'PROJECT_PATHS', None) + if project_paths and 'PROJECT_ROOT' in project_paths: + tsk.env.env['PYTHONPATH'] += os.pathsep + project_paths['PROJECT_ROOT'].abspath() + if getattr(tg, 'add_to_pythonpath', None): + tsk.env.env['PYTHONPATH'] += os.pathsep + tg.add_to_pythonpath + + # Clean up the PYTHONPATH -- replace double occurrences of path separator + tsk.env.env['PYTHONPATH'] = re.sub(os.pathsep + '+', os.pathsep, tsk.env.env['PYTHONPATH']) + + # Clean up the PYTHONPATH -- doesn't like starting with path separator + if tsk.env.env['PYTHONPATH'].startswith(os.pathsep): + tsk.env.env['PYTHONPATH'] = tsk.env.env['PYTHONPATH'][1:] + + # dependencies (if the attribute 'deps' changes, trigger a recompilation) + for x in tg.to_list(getattr(tg, 'deps', [])): + node = tg.path.find_resource(x) + if not node: + tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.abspath())) + tsk.dep_nodes.append(node) + Logs.debug('deps: found dependencies %r for running %r', tsk.dep_nodes, src_node.abspath()) + + # Bypass the execution of process_source by setting the source to an empty list + tg.source = [] + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/run_r_script.py b/ldb-2.0.8/third_party/waf/waflib/extras/run_r_script.py new file mode 100644 index 0000000..b0d8f2b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/run_r_script.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Hans-Martin von Gaudecker, 2012 + +""" +Run a R script in the directory specified by **ctx.bldnode**. + +For error-catching purposes, keep an own log-file that is destroyed if the +task finished without error. If not, it will show up as rscript_[index].log +in the bldnode directory. + +Usage:: + + ctx(features='run_r_script', + source='some_script.r', + target=['some_table.tex', 'some_figure.eps'], + deps='some_data.csv') +""" + + +import os, sys +from waflib import Task, TaskGen, Logs + +R_COMMANDS = ['RTerm', 'R', 'r'] + +def configure(ctx): + ctx.find_program(R_COMMANDS, var='RCMD', errmsg = """\n +No R executable found!\n\n +If R is needed:\n + 1) Check the settings of your system path. + 2) Note we are looking for R executables called: %s + If yours has a different name, please report to hmgaudecker [at] gmail\n +Else:\n + Do not load the 'run_r_script' tool in the main wscript.\n\n""" % R_COMMANDS) + ctx.env.RFLAGS = 'CMD BATCH --slave' + +class run_r_script_base(Task.Task): + """Run a R script.""" + run_str = '"${RCMD}" ${RFLAGS} "${SRC[0].abspath()}" "${LOGFILEPATH}"' + shell = True + +class run_r_script(run_r_script_base): + """Erase the R overall log file if everything went okay, else raise an + error and print its 10 last lines. + """ + def run(self): + ret = run_r_script_base.run(self) + logfile = self.env.LOGFILEPATH + if ret: + mode = 'r' + if sys.version_info.major >= 3: + mode = 'rb' + with open(logfile, mode=mode) as f: + tail = f.readlines()[-10:] + Logs.error("""Running R on %r returned the error %r\n\nCheck the log file %s, last 10 lines\n\n%s\n\n\n""", + self.inputs[0], ret, logfile, '\n'.join(tail)) + else: + os.remove(logfile) + return ret + + +@TaskGen.feature('run_r_script') +@TaskGen.before_method('process_source') +def apply_run_r_script(tg): + """Task generator customising the options etc. to call R in batch + mode for running a R script. + """ + + # Convert sources and targets to nodes + src_node = tg.path.find_resource(tg.source) + tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] + + tsk = tg.create_task('run_r_script', src=src_node, tgt=tgt_nodes) + tsk.env.LOGFILEPATH = os.path.join(tg.bld.bldnode.abspath(), '%s_%d.log' % (os.path.splitext(src_node.name)[0], tg.idx)) + + # dependencies (if the attribute 'deps' changes, trigger a recompilation) + for x in tg.to_list(getattr(tg, 'deps', [])): + node = tg.path.find_resource(x) + if not node: + tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.abspath())) + tsk.dep_nodes.append(node) + Logs.debug('deps: found dependencies %r for running %r', tsk.dep_nodes, src_node.abspath()) + + # Bypass the execution of process_source by setting the source to an empty list + tg.source = [] + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/sas.py b/ldb-2.0.8/third_party/waf/waflib/extras/sas.py new file mode 100644 index 0000000..754c614 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/sas.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Mark Coggeshall, 2010 + +"SAS support" + +import os +from waflib import Task, Errors, Logs +from waflib.TaskGen import feature, before_method + +sas_fun, _ = Task.compile_fun('sas -sysin ${SRCFILE} -log ${LOGFILE} -print ${LSTFILE}', shell=False) + +class sas(Task.Task): + vars = ['SAS', 'SASFLAGS'] + def run(task): + command = 'SAS' + fun = sas_fun + + node = task.inputs[0] + logfilenode = node.change_ext('.log') + lstfilenode = node.change_ext('.lst') + + # set the cwd + task.cwd = task.inputs[0].parent.get_src().abspath() + Logs.debug('runner: %r on %r', command, node) + + SASINPUTS = node.parent.get_bld().abspath() + os.pathsep + node.parent.get_src().abspath() + os.pathsep + task.env.env = {'SASINPUTS': SASINPUTS} + + task.env.SRCFILE = node.abspath() + task.env.LOGFILE = logfilenode.abspath() + task.env.LSTFILE = lstfilenode.abspath() + ret = fun(task) + if ret: + Logs.error('Running %s on %r returned a non-zero exit', command, node) + Logs.error('SRCFILE = %r', node) + Logs.error('LOGFILE = %r', logfilenode) + Logs.error('LSTFILE = %r', lstfilenode) + return ret + +@feature('sas') +@before_method('process_source') +def apply_sas(self): + if not getattr(self, 'type', None) in ('sas',): + self.type = 'sas' + + self.env['logdir'] = getattr(self, 'logdir', 'log') + self.env['lstdir'] = getattr(self, 'lstdir', 'lst') + + deps_lst = [] + + if getattr(self, 'deps', None): + deps = self.to_list(self.deps) + for filename in deps: + n = self.path.find_resource(filename) + if not n: + n = self.bld.root.find_resource(filename) + if not n: + raise Errors.WafError('cannot find input file %s for processing' % filename) + if not n in deps_lst: + deps_lst.append(n) + + for node in self.to_nodes(self.source): + if self.type == 'sas': + task = self.create_task('sas', src=node) + task.dep_nodes = deps_lst + self.source = [] + +def configure(self): + self.find_program('sas', var='SAS', mandatory=False) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/satellite_assembly.py b/ldb-2.0.8/third_party/waf/waflib/extras/satellite_assembly.py new file mode 100644 index 0000000..005eb07 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/satellite_assembly.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +# encoding: utf-8 +# vim: tabstop=4 noexpandtab + +""" +Create a satellite assembly from "*.??.txt" files. ?? stands for a language code. + +The projects Resources subfolder contains resources.??.txt string files for several languages. +The build folder will hold the satellite assemblies as ./??/ExeName.resources.dll + +#gen becomes template (It is called gen because it also uses resx.py). +bld(source='Resources/resources.de.txt',gen=ExeName) +""" + +import os, re +from waflib import Task +from waflib.TaskGen import feature,before_method + +class al(Task.Task): + run_str = '${AL} ${ALFLAGS}' + +@feature('satellite_assembly') +@before_method('process_source') +def satellite_assembly(self): + if not getattr(self, 'gen', None): + self.bld.fatal('satellite_assembly needs a template assembly provided with the "gen" parameter') + res_lang = re.compile(r'(.*)\.(\w\w)\.(?:resx|txt)',flags=re.I) + + # self.source can contain node objects, so this will break in one way or another + self.source = self.to_list(self.source) + for i, x in enumerate(self.source): + #x = 'resources/resources.de.resx' + #x = 'resources/resources.de.txt' + mo = res_lang.match(x) + if mo: + template = os.path.splitext(self.gen)[0] + templatedir, templatename = os.path.split(template) + res = mo.group(1) + lang = mo.group(2) + #./Resources/resources.de.resources + resources = self.path.find_or_declare(res+ '.' + lang + '.resources') + self.create_task('resgen', self.to_nodes(x), [resources]) + #./de/Exename.resources.dll + satellite = self.path.find_or_declare(os.path.join(templatedir,lang,templatename) + '.resources.dll') + tsk = self.create_task('al',[resources],[satellite]) + tsk.env.append_value('ALFLAGS','/template:'+os.path.join(self.path.relpath(),self.gen)) + tsk.env.append_value('ALFLAGS','/embed:'+resources.relpath()) + tsk.env.append_value('ALFLAGS','/culture:'+lang) + tsk.env.append_value('ALFLAGS','/out:'+satellite.relpath()) + self.source[i] = None + # remove the None elements that we just substituted + self.source = list(filter(lambda x:x, self.source)) + +def configure(ctx): + ctx.find_program('al', var='AL', mandatory=True) + ctx.load('resx') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/scala.py b/ldb-2.0.8/third_party/waf/waflib/extras/scala.py new file mode 100644 index 0000000..a9880f0 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/scala.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010 (ita) + +""" +Scala support + +scalac outputs files a bit where it wants to +""" + +import os +from waflib import Task, Utils, Node +from waflib.TaskGen import feature, before_method, after_method + +from waflib.Tools import ccroot +ccroot.USELIB_VARS['scalac'] = set(['CLASSPATH', 'SCALACFLAGS']) + +from waflib.Tools import javaw + +@feature('scalac') +@before_method('process_source') +def apply_scalac(self): + + Utils.def_attrs(self, jarname='', classpath='', + sourcepath='.', srcdir='.', + jar_mf_attributes={}, jar_mf_classpath=[]) + + outdir = getattr(self, 'outdir', None) + if outdir: + if not isinstance(outdir, Node.Node): + outdir = self.path.get_bld().make_node(self.outdir) + else: + outdir = self.path.get_bld() + outdir.mkdir() + self.env['OUTDIR'] = outdir.abspath() + + self.scalac_task = tsk = self.create_task('scalac') + tmp = [] + + srcdir = getattr(self, 'srcdir', '') + if isinstance(srcdir, Node.Node): + srcdir = [srcdir] + for x in Utils.to_list(srcdir): + if isinstance(x, Node.Node): + y = x + else: + y = self.path.find_dir(x) + if not y: + self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) + tmp.append(y) + tsk.srcdir = tmp + +# reuse some code +feature('scalac')(javaw.use_javac_files) +after_method('apply_scalac')(javaw.use_javac_files) + +feature('scalac')(javaw.set_classpath) +after_method('apply_scalac', 'use_scalac_files')(javaw.set_classpath) + + +SOURCE_RE = '**/*.scala' +class scalac(javaw.javac): + color = 'GREEN' + vars = ['CLASSPATH', 'SCALACFLAGS', 'SCALAC', 'OUTDIR'] + + def runnable_status(self): + """ + Wait for dependent tasks to be complete, then read the file system to find the input nodes. + """ + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + + if not self.inputs: + global SOURCE_RE + self.inputs = [] + for x in self.srcdir: + self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) + return super(javaw.javac, self).runnable_status() + + def run(self): + """ + Execute the scalac compiler + """ + env = self.env + gen = self.generator + bld = gen.bld + wd = bld.bldnode.abspath() + def to_list(xx): + if isinstance(xx, str): + return [xx] + return xx + self.last_cmd = lst = [] + lst.extend(to_list(env['SCALAC'])) + lst.extend(['-classpath']) + lst.extend(to_list(env['CLASSPATH'])) + lst.extend(['-d']) + lst.extend(to_list(env['OUTDIR'])) + lst.extend(to_list(env['SCALACFLAGS'])) + lst.extend([a.abspath() for a in self.inputs]) + lst = [x for x in lst if x] + try: + self.out = self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None, output=0, quiet=0)[1] + except: + self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None) + +def configure(self): + """ + Detect the scalac program + """ + # If SCALA_HOME is set, we prepend it to the path list + java_path = self.environ['PATH'].split(os.pathsep) + v = self.env + + if 'SCALA_HOME' in self.environ: + java_path = [os.path.join(self.environ['SCALA_HOME'], 'bin')] + java_path + self.env['SCALA_HOME'] = [self.environ['SCALA_HOME']] + + for x in 'scalac scala'.split(): + self.find_program(x, var=x.upper(), path_list=java_path) + + if 'CLASSPATH' in self.environ: + v['CLASSPATH'] = self.environ['CLASSPATH'] + + v.SCALACFLAGS = ['-verbose'] + if not v['SCALAC']: + self.fatal('scalac is required for compiling scala classes') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/slow_qt4.py b/ldb-2.0.8/third_party/waf/waflib/extras/slow_qt4.py new file mode 100644 index 0000000..ec7880b --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/slow_qt4.py @@ -0,0 +1,96 @@ +#! /usr/bin/env python +# Thomas Nagy, 2011 (ita) + +""" +Create _moc.cpp files + +The builds are 30-40% faster when .moc files are included, +you should NOT use this tool. If you really +really want it: + +def configure(conf): + conf.load('compiler_cxx qt4') + conf.load('slow_qt4') + +See playground/slow_qt/wscript for a complete example. +""" + +from waflib.TaskGen import extension +from waflib import Task +import waflib.Tools.qt4 +import waflib.Tools.cxx + +@extension(*waflib.Tools.qt4.EXT_QT4) +def cxx_hook(self, node): + return self.create_compiled_task('cxx_qt', node) + +class cxx_qt(Task.classes['cxx']): + def runnable_status(self): + ret = Task.classes['cxx'].runnable_status(self) + if ret != Task.ASK_LATER and not getattr(self, 'moc_done', None): + + try: + cache = self.generator.moc_cache + except AttributeError: + cache = self.generator.moc_cache = {} + + deps = self.generator.bld.node_deps[self.uid()] + for x in [self.inputs[0]] + deps: + if x.read().find('Q_OBJECT') > 0: + + # process "foo.h -> foo.moc" only if "foo.cpp" is in the sources for the current task generator + # this code will work because it is in the main thread (runnable_status) + if x.name.rfind('.') > -1: # a .h file... + name = x.name[:x.name.rfind('.')] + for tsk in self.generator.compiled_tasks: + if tsk.inputs and tsk.inputs[0].name.startswith(name): + break + else: + # no corresponding file, continue + continue + + # the file foo.cpp could be compiled for a static and a shared library - hence the %number in the name + cxx_node = x.parent.get_bld().make_node(x.name.replace('.', '_') + '_%d_moc.cpp' % self.generator.idx) + if cxx_node in cache: + continue + cache[cxx_node] = self + + tsk = Task.classes['moc'](env=self.env, generator=self.generator) + tsk.set_inputs(x) + tsk.set_outputs(cxx_node) + + if x.name.endswith('.cpp'): + # moc is trying to be too smart but it is too dumb: + # why forcing the #include when Q_OBJECT is in the cpp file? + gen = self.generator.bld.producer + gen.outstanding.append(tsk) + gen.total += 1 + self.set_run_after(tsk) + else: + cxxtsk = Task.classes['cxx'](env=self.env, generator=self.generator) + cxxtsk.set_inputs(tsk.outputs) + cxxtsk.set_outputs(cxx_node.change_ext('.o')) + cxxtsk.set_run_after(tsk) + + try: + self.more_tasks.extend([tsk, cxxtsk]) + except AttributeError: + self.more_tasks = [tsk, cxxtsk] + + try: + link = self.generator.link_task + except AttributeError: + pass + else: + link.set_run_after(cxxtsk) + link.inputs.extend(cxxtsk.outputs) + link.inputs.sort(key=lambda x: x.abspath()) + + self.moc_done = True + + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + + return ret + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/softlink_libs.py b/ldb-2.0.8/third_party/waf/waflib/extras/softlink_libs.py new file mode 100644 index 0000000..50c777f --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/softlink_libs.py @@ -0,0 +1,76 @@ +#! /usr/bin/env python +# per rosengren 2011 + +from waflib.TaskGen import feature, after_method +from waflib.Task import Task, always_run +from os.path import basename, isabs +from os import tmpfile, linesep + +def options(opt): + grp = opt.add_option_group('Softlink Libraries Options') + grp.add_option('--exclude', default='/usr/lib,/lib', help='No symbolic links are created for libs within [%default]') + +def configure(cnf): + cnf.find_program('ldd') + if not cnf.env.SOFTLINK_EXCLUDE: + cnf.env.SOFTLINK_EXCLUDE = cnf.options.exclude.split(',') + +@feature('softlink_libs') +@after_method('process_rule') +def add_finder(self): + tgt = self.path.find_or_declare(self.target) + self.create_task('sll_finder', tgt=tgt) + self.create_task('sll_installer', tgt=tgt) + always_run(sll_installer) + +class sll_finder(Task): + ext_out = 'softlink_libs' + def run(self): + bld = self.generator.bld + linked=[] + target_paths = [] + for g in bld.groups: + for tgen in g: + # FIXME it might be better to check if there is a link_task (getattr?) + target_paths += [tgen.path.get_bld().bldpath()] + linked += [t.outputs[0].bldpath() + for t in getattr(tgen, 'tasks', []) + if t.__class__.__name__ in + ['cprogram', 'cshlib', 'cxxprogram', 'cxxshlib']] + lib_list = [] + if len(linked): + cmd = [self.env.LDD] + linked + # FIXME add DYLD_LIBRARY_PATH+PATH for osx+win32 + ldd_env = {'LD_LIBRARY_PATH': ':'.join(target_paths + self.env.LIBPATH)} + # FIXME the with syntax will not work in python 2 + with tmpfile() as result: + self.exec_command(cmd, env=ldd_env, stdout=result) + result.seek(0) + for line in result.readlines(): + words = line.split() + if len(words) < 3 or words[1] != '=>': + continue + lib = words[2] + if lib == 'not': + continue + if any([lib.startswith(p) for p in + [bld.bldnode.abspath(), '('] + + self.env.SOFTLINK_EXCLUDE]): + continue + if not isabs(lib): + continue + lib_list.append(lib) + lib_list = sorted(set(lib_list)) + self.outputs[0].write(linesep.join(lib_list + self.env.DYNAMIC_LIBS)) + return 0 + +class sll_installer(Task): + ext_in = 'softlink_libs' + def run(self): + tgt = self.outputs[0] + self.generator.bld.install_files('${LIBDIR}', tgt, postpone=False) + lib_list=tgt.read().split() + for lib in lib_list: + self.generator.bld.symlink_as('${LIBDIR}/'+basename(lib), lib, postpone=False) + return 0 + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/sphinx.py b/ldb-2.0.8/third_party/waf/waflib/extras/sphinx.py new file mode 100644 index 0000000..ce11110 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/sphinx.py @@ -0,0 +1,81 @@ +"""Support for Sphinx documentation + +This is a wrapper for sphinx-build program. Please note that sphinx-build supports only one output format which can +passed to build via sphinx_output_format attribute. The default output format is html. + +Example wscript: + +def configure(cnf): + conf.load('sphinx') + +def build(bld): + bld( + features='sphinx', + sphinx_source='sources', # path to source directory + sphinx_options='-a -v', # sphinx-build program additional options + sphinx_output_format='man' # output format of sphinx documentation + ) + +""" + +from waflib.Node import Node +from waflib import Utils +from waflib.Task import Task +from waflib.TaskGen import feature, after_method + + +def configure(cnf): + """Check if sphinx-build program is available and loads gnu_dirs tool.""" + cnf.find_program('sphinx-build', var='SPHINX_BUILD', mandatory=False) + cnf.load('gnu_dirs') + + +@feature('sphinx') +def build_sphinx(self): + """Builds sphinx sources. + """ + if not self.env.SPHINX_BUILD: + self.bld.fatal('Program SPHINX_BUILD not defined.') + if not getattr(self, 'sphinx_source', None): + self.bld.fatal('Attribute sphinx_source not defined.') + if not isinstance(self.sphinx_source, Node): + self.sphinx_source = self.path.find_node(self.sphinx_source) + if not self.sphinx_source: + self.bld.fatal('Can\'t find sphinx_source: %r' % self.sphinx_source) + + Utils.def_attrs(self, sphinx_output_format='html') + self.env.SPHINX_OUTPUT_FORMAT = self.sphinx_output_format + self.env.SPHINX_OPTIONS = getattr(self, 'sphinx_options', []) + + for source_file in self.sphinx_source.ant_glob('**/*'): + self.bld.add_manual_dependency(self.sphinx_source, source_file) + + sphinx_build_task = self.create_task('SphinxBuildingTask') + sphinx_build_task.set_inputs(self.sphinx_source) + sphinx_build_task.set_outputs(self.path.get_bld()) + + # the sphinx-build results are in directory + sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT) + sphinx_output_directory.mkdir() + Utils.def_attrs(self, install_path=get_install_path(self)) + self.add_install_files(install_to=self.install_path, + install_from=sphinx_output_directory.ant_glob('**/*'), + cwd=sphinx_output_directory, + relative_trick=True) + + +def get_install_path(tg): + if tg.env.SPHINX_OUTPUT_FORMAT == 'man': + return tg.env.MANDIR + elif tg.env.SPHINX_OUTPUT_FORMAT == 'info': + return tg.env.INFODIR + else: + return tg.env.DOCDIR + + +class SphinxBuildingTask(Task): + color = 'BOLD' + run_str = '${SPHINX_BUILD} -M ${SPHINX_OUTPUT_FORMAT} ${SRC} ${TGT} ${SPHINX_OPTIONS}' + + def keyword(self): + return 'Compiling (%s)' % self.env.SPHINX_OUTPUT_FORMAT diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/stale.py b/ldb-2.0.8/third_party/waf/waflib/extras/stale.py new file mode 100644 index 0000000..cac3f46 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/stale.py @@ -0,0 +1,98 @@ +#! /usr/bin/env python +# encoding: UTF-8 +# Thomas Nagy, 2006-2015 (ita) + +""" +Add a pre-build hook to remove build files (declared in the system) +that do not have a corresponding target + +This can be used for example to remove the targets +that have changed name without performing +a full 'waf clean' + +Of course, it will only work if there are no dynamically generated +nodes/tasks, in which case the method will have to be modified +to exclude some folders for example. + +Make sure to set bld.post_mode = waflib.Build.POST_AT_ONCE +""" + +from waflib import Logs, Build +from waflib.Runner import Parallel + +DYNAMIC_EXT = [] # add your non-cleanable files/extensions here +MOC_H_EXTS = '.cpp .cxx .hpp .hxx .h'.split() + +def can_delete(node): + """Imperfect moc cleanup which does not look for a Q_OBJECT macro in the files""" + if not node.name.endswith('.moc'): + return True + base = node.name[:-4] + p1 = node.parent.get_src() + p2 = node.parent.get_bld() + for k in MOC_H_EXTS: + h_name = base + k + n = p1.search_node(h_name) + if n: + return False + n = p2.search_node(h_name) + if n: + return False + + # foo.cpp.moc, foo.h.moc, etc. + if base.endswith(k): + return False + + return True + +# recursion over the nodes to find the stale files +def stale_rec(node, nodes): + if node.abspath() in node.ctx.env[Build.CFG_FILES]: + return + + if getattr(node, 'children', []): + for x in node.children.values(): + if x.name != "c4che": + stale_rec(x, nodes) + else: + for ext in DYNAMIC_EXT: + if node.name.endswith(ext): + break + else: + if not node in nodes: + if can_delete(node): + Logs.warn('Removing stale file -> %r', node) + node.delete() + +old = Parallel.refill_task_list +def refill_task_list(self): + iit = old(self) + bld = self.bld + + # execute this operation only once + if getattr(self, 'stale_done', False): + return iit + self.stale_done = True + + # this does not work in partial builds + if bld.targets != '*': + return iit + + # this does not work in dynamic builds + if getattr(bld, 'post_mode') == Build.POST_AT_ONCE: + return iit + + # obtain the nodes to use during the build + nodes = [] + for tasks in bld.groups: + for x in tasks: + try: + nodes.extend(x.outputs) + except AttributeError: + pass + + stale_rec(bld.bldnode, nodes) + return iit + +Parallel.refill_task_list = refill_task_list + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/stracedeps.py b/ldb-2.0.8/third_party/waf/waflib/extras/stracedeps.py new file mode 100644 index 0000000..37d82cb --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/stracedeps.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2015 (ita) + +""" +Execute tasks through strace to obtain dependencies after the process is run. This +scheme is similar to that of the Fabricate script. + +To use:: + + def configure(conf): + conf.load('strace') + +WARNING: +* This will not work when advanced scanners are needed (qt4/qt5) +* The overhead of running 'strace' is significant (56s -> 1m29s) +* It will not work on Windows :-) +""" + +import os, re, threading +from waflib import Task, Logs, Utils + +#TRACECALLS = 'trace=access,chdir,clone,creat,execve,exit_group,fork,lstat,lstat64,mkdir,open,rename,stat,stat64,symlink,vfork' +TRACECALLS = 'trace=process,file' + +BANNED = ('/tmp', '/proc', '/sys', '/dev') + +s_process = r'(?:clone|fork|vfork)\(.*?(?P\d+)' +s_file = r'(?P\w+)\("(?P([^"\\]|\\.)*)"(.*)' +re_lines = re.compile(r'^(?P\d+)\s+(?:(?:%s)|(?:%s))\r*$' % (s_file, s_process), re.IGNORECASE | re.MULTILINE) +strace_lock = threading.Lock() + +def configure(conf): + conf.find_program('strace') + +def task_method(func): + # Decorator function to bind/replace methods on the base Task class + # + # The methods Task.exec_command and Task.sig_implicit_deps already exists and are rarely overridden + # we thus expect that we are the only ones doing this + try: + setattr(Task.Task, 'nostrace_%s' % func.__name__, getattr(Task.Task, func.__name__)) + except AttributeError: + pass + setattr(Task.Task, func.__name__, func) + return func + +@task_method +def get_strace_file(self): + try: + return self.strace_file + except AttributeError: + pass + + if self.outputs: + ret = self.outputs[0].abspath() + '.strace' + else: + ret = '%s%s%d%s' % (self.generator.bld.bldnode.abspath(), os.sep, id(self), '.strace') + self.strace_file = ret + return ret + +@task_method +def get_strace_args(self): + return (self.env.STRACE or ['strace']) + ['-e', TRACECALLS, '-f', '-o', self.get_strace_file()] + +@task_method +def exec_command(self, cmd, **kw): + bld = self.generator.bld + if not 'cwd' in kw: + kw['cwd'] = self.get_cwd() + + args = self.get_strace_args() + fname = self.get_strace_file() + if isinstance(cmd, list): + cmd = args + cmd + else: + cmd = '%s %s' % (' '.join(args), cmd) + + try: + ret = bld.exec_command(cmd, **kw) + finally: + if not ret: + self.parse_strace_deps(fname, kw['cwd']) + return ret + +@task_method +def sig_implicit_deps(self): + # bypass the scanner functions + return + +@task_method +def parse_strace_deps(self, path, cwd): + # uncomment the following line to disable the dependencies and force a file scan + # return + try: + cnt = Utils.readf(path) + finally: + try: + os.remove(path) + except OSError: + pass + + if not isinstance(cwd, str): + cwd = cwd.abspath() + + nodes = [] + bld = self.generator.bld + try: + cache = bld.strace_cache + except AttributeError: + cache = bld.strace_cache = {} + + # chdir and relative paths + pid_to_cwd = {} + + global BANNED + done = set() + for m in re.finditer(re_lines, cnt): + # scraping the output of strace + pid = m.group('pid') + if m.group('npid'): + npid = m.group('npid') + pid_to_cwd[npid] = pid_to_cwd.get(pid, cwd) + continue + + p = m.group('path').replace('\\"', '"') + + if p == '.' or m.group().find('= -1 ENOENT') > -1: + # just to speed it up a bit + continue + + if not os.path.isabs(p): + p = os.path.join(pid_to_cwd.get(pid, cwd), p) + + call = m.group('call') + if call == 'chdir': + pid_to_cwd[pid] = p + continue + + if p in done: + continue + done.add(p) + + for x in BANNED: + if p.startswith(x): + break + else: + if p.endswith('/') or os.path.isdir(p): + continue + + try: + node = cache[p] + except KeyError: + strace_lock.acquire() + try: + cache[p] = node = bld.root.find_node(p) + if not node: + continue + finally: + strace_lock.release() + nodes.append(node) + + # record the dependencies then force the task signature recalculation for next time + if Logs.verbose: + Logs.debug('deps: real scanner for %r returned %r', self, nodes) + bld = self.generator.bld + bld.node_deps[self.uid()] = nodes + bld.raw_deps[self.uid()] = [] + try: + del self.cache_sig + except AttributeError: + pass + self.signature() + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/swig.py b/ldb-2.0.8/third_party/waf/waflib/extras/swig.py new file mode 100644 index 0000000..740ab46 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/swig.py @@ -0,0 +1,237 @@ +#! /usr/bin/env python +# encoding: UTF-8 +# Petar Forai +# Thomas Nagy 2008-2010 (ita) + +import re +from waflib import Task, Logs +from waflib.TaskGen import extension, feature, after_method +from waflib.Configure import conf +from waflib.Tools import c_preproc + +""" +tasks have to be added dynamically: +- swig interface files may be created at runtime +- the module name may be unknown in advance +""" + +SWIG_EXTS = ['.swig', '.i'] + +re_module = re.compile(r'%module(?:\s*\(.*\))?\s+(.+)', re.M) + +re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) +re_2 = re.compile(r'[#%](?:include|import(?:\(module=".*"\))+|python(?:begin|code)) [<"](.*)[">]', re.M) + +class swig(Task.Task): + color = 'BLUE' + run_str = '${SWIG} ${SWIGFLAGS} ${SWIGPATH_ST:INCPATHS} ${SWIGDEF_ST:DEFINES} ${SRC}' + ext_out = ['.h'] # might produce .h files although it is not mandatory + vars = ['SWIG_VERSION', 'SWIGDEPS'] + + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + + if not getattr(self, 'init_outputs', None): + self.init_outputs = True + if not getattr(self, 'module', None): + # search the module name + txt = self.inputs[0].read() + m = re_module.search(txt) + if not m: + raise ValueError("could not find the swig module name") + self.module = m.group(1) + + swig_c(self) + + # add the language-specific output files as nodes + # call funs in the dict swig_langs + for x in self.env['SWIGFLAGS']: + # obtain the language + x = x[1:] + try: + fun = swig_langs[x] + except KeyError: + pass + else: + fun(self) + + return super(swig, self).runnable_status() + + def scan(self): + "scan for swig dependencies, climb the .i files" + lst_src = [] + + seen = [] + missing = [] + to_see = [self.inputs[0]] + + while to_see: + node = to_see.pop(0) + if node in seen: + continue + seen.append(node) + lst_src.append(node) + + # read the file + code = node.read() + code = c_preproc.re_nl.sub('', code) + code = c_preproc.re_cpp.sub(c_preproc.repl, code) + + # find .i files and project headers + names = re_2.findall(code) + for n in names: + for d in self.generator.includes_nodes + [node.parent]: + u = d.find_resource(n) + if u: + to_see.append(u) + break + else: + missing.append(n) + return (lst_src, missing) + +# provide additional language processing +swig_langs = {} +def swigf(fun): + swig_langs[fun.__name__.replace('swig_', '')] = fun + return fun +swig.swigf = swigf + +def swig_c(self): + ext = '.swigwrap_%d.c' % self.generator.idx + flags = self.env['SWIGFLAGS'] + if '-c++' in flags: + ext += 'xx' + out_node = self.inputs[0].parent.find_or_declare(self.module + ext) + + if '-c++' in flags: + c_tsk = self.generator.cxx_hook(out_node) + else: + c_tsk = self.generator.c_hook(out_node) + + c_tsk.set_run_after(self) + + # transfer weights from swig task to c task + if getattr(self, 'weight', None): + c_tsk.weight = self.weight + if getattr(self, 'tree_weight', None): + c_tsk.tree_weight = self.tree_weight + + try: + self.more_tasks.append(c_tsk) + except AttributeError: + self.more_tasks = [c_tsk] + + try: + ltask = self.generator.link_task + except AttributeError: + pass + else: + ltask.set_run_after(c_tsk) + # setting input nodes does not declare the build order + # because the build already started, but it sets + # the dependency to enable rebuilds + ltask.inputs.append(c_tsk.outputs[0]) + + self.outputs.append(out_node) + + if not '-o' in self.env['SWIGFLAGS']: + self.env.append_value('SWIGFLAGS', ['-o', self.outputs[0].abspath()]) + +@swigf +def swig_python(tsk): + node = tsk.inputs[0].parent + if tsk.outdir: + node = tsk.outdir + tsk.set_outputs(node.find_or_declare(tsk.module+'.py')) + +@swigf +def swig_ocaml(tsk): + node = tsk.inputs[0].parent + if tsk.outdir: + node = tsk.outdir + tsk.set_outputs(node.find_or_declare(tsk.module+'.ml')) + tsk.set_outputs(node.find_or_declare(tsk.module+'.mli')) + +@extension(*SWIG_EXTS) +def i_file(self, node): + # the task instance + tsk = self.create_task('swig') + tsk.set_inputs(node) + tsk.module = getattr(self, 'swig_module', None) + + flags = self.to_list(getattr(self, 'swig_flags', [])) + tsk.env.append_value('SWIGFLAGS', flags) + + tsk.outdir = None + if '-outdir' in flags: + outdir = flags[flags.index('-outdir')+1] + outdir = tsk.generator.bld.bldnode.make_node(outdir) + outdir.mkdir() + tsk.outdir = outdir + +@feature('c', 'cxx', 'd', 'fc', 'asm') +@after_method('apply_link', 'process_source') +def enforce_swig_before_link(self): + try: + link_task = self.link_task + except AttributeError: + pass + else: + for x in self.tasks: + if x.__class__.__name__ == 'swig': + link_task.run_after.add(x) + +@conf +def check_swig_version(conf, minver=None): + """ + Check if the swig tool is found matching a given minimum version. + minver should be a tuple, eg. to check for swig >= 1.3.28 pass (1,3,28) as minver. + + If successful, SWIG_VERSION is defined as 'MAJOR.MINOR' + (eg. '1.3') of the actual swig version found. + + :param minver: minimum version + :type minver: tuple of int + :return: swig version + :rtype: tuple of int + """ + assert minver is None or isinstance(minver, tuple) + swigbin = conf.env['SWIG'] + if not swigbin: + conf.fatal('could not find the swig executable') + + # Get swig version string + cmd = swigbin + ['-version'] + Logs.debug('swig: Running swig command %r', cmd) + reg_swig = re.compile(r'SWIG Version\s(.*)', re.M) + swig_out = conf.cmd_and_log(cmd) + swigver_tuple = tuple([int(s) for s in reg_swig.findall(swig_out)[0].split('.')]) + + # Compare swig version with the minimum required + result = (minver is None) or (swigver_tuple >= minver) + + if result: + # Define useful environment variables + swigver = '.'.join([str(x) for x in swigver_tuple[:2]]) + conf.env['SWIG_VERSION'] = swigver + + # Feedback + swigver_full = '.'.join(map(str, swigver_tuple[:3])) + if minver is None: + conf.msg('Checking for swig version', swigver_full) + else: + minver_str = '.'.join(map(str, minver)) + conf.msg('Checking for swig version >= %s' % (minver_str,), swigver_full, color=result and 'GREEN' or 'YELLOW') + + if not result: + conf.fatal('The swig version is too old, expecting %r' % (minver,)) + + return swigver_tuple + +def configure(conf): + conf.find_program('swig', var='SWIG') + conf.env.SWIGPATH_ST = '-I%s' + conf.env.SWIGDEF_ST = '-D%s' + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/syms.py b/ldb-2.0.8/third_party/waf/waflib/extras/syms.py new file mode 100644 index 0000000..562f708 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/syms.py @@ -0,0 +1,84 @@ +#! /usr/bin/env python +# encoding: utf-8 + +""" +This tool supports the export_symbols_regex to export the symbols in a shared library. +by default, all symbols are exported by gcc, and nothing by msvc. +to use the tool, do something like: + +def build(ctx): + ctx(features='c cshlib syms', source='a.c b.c', export_symbols_regex='mylib_.*', target='testlib') + +only the symbols starting with 'mylib_' will be exported. +""" + +import re +from waflib.Context import STDOUT +from waflib.Task import Task +from waflib.Errors import WafError +from waflib.TaskGen import feature, after_method + +class gen_sym(Task): + def run(self): + obj = self.inputs[0] + kw = {} + + reg = getattr(self.generator, 'export_symbols_regex', '.+?') + if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): + re_nm = re.compile(r'External\s+\|\s+_(?P%s)\b' % reg) + cmd = (self.env.DUMPBIN or ['dumpbin']) + ['/symbols', obj.abspath()] + else: + if self.env.DEST_BINFMT == 'pe': #gcc uses nm, and has a preceding _ on windows + re_nm = re.compile(r'(T|D)\s+_(?P%s)\b' % reg) + elif self.env.DEST_BINFMT=='mac-o': + re_nm=re.compile(r'(T|D)\s+(?P_?(%s))\b' % reg) + else: + re_nm = re.compile(r'(T|D)\s+(?P%s)\b' % reg) + cmd = (self.env.NM or ['nm']) + ['-g', obj.abspath()] + syms = [m.group('symbol') for m in re_nm.finditer(self.generator.bld.cmd_and_log(cmd, quiet=STDOUT, **kw))] + self.outputs[0].write('%r' % syms) + +class compile_sym(Task): + def run(self): + syms = {} + for x in self.inputs: + slist = eval(x.read()) + for s in slist: + syms[s] = 1 + lsyms = list(syms.keys()) + lsyms.sort() + if self.env.DEST_BINFMT == 'pe': + self.outputs[0].write('EXPORTS\n' + '\n'.join(lsyms)) + elif self.env.DEST_BINFMT == 'elf': + self.outputs[0].write('{ global:\n' + ';\n'.join(lsyms) + ";\nlocal: *; };\n") + elif self.env.DEST_BINFMT=='mac-o': + self.outputs[0].write('\n'.join(lsyms) + '\n') + else: + raise WafError('NotImplemented') + +@feature('syms') +@after_method('process_source', 'process_use', 'apply_link', 'process_uselib_local', 'propagate_uselib_vars') +def do_the_symbol_stuff(self): + def_node = self.path.find_or_declare(getattr(self, 'sym_file', self.target + '.def')) + compiled_tasks = getattr(self, 'compiled_tasks', None) + if compiled_tasks: + ins = [x.outputs[0] for x in compiled_tasks] + self.gen_sym_tasks = [self.create_task('gen_sym', x, x.change_ext('.%d.sym' % self.idx)) for x in ins] + self.create_task('compile_sym', [x.outputs[0] for x in self.gen_sym_tasks], def_node) + + link_task = getattr(self, 'link_task', None) + if link_task: + self.link_task.dep_nodes.append(def_node) + + if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): + self.link_task.env.append_value('LINKFLAGS', ['/def:' + def_node.bldpath()]) + elif self.env.DEST_BINFMT == 'pe': + # gcc on windows takes *.def as an additional input + self.link_task.inputs.append(def_node) + elif self.env.DEST_BINFMT == 'elf': + self.link_task.env.append_value('LINKFLAGS', ['-Wl,-version-script', '-Wl,' + def_node.bldpath()]) + elif self.env.DEST_BINFMT=='mac-o': + self.link_task.env.append_value('LINKFLAGS',['-Wl,-exported_symbols_list,' + def_node.bldpath()]) + else: + raise WafError('NotImplemented') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/ticgt.py b/ldb-2.0.8/third_party/waf/waflib/extras/ticgt.py new file mode 100644 index 0000000..f43a7ea --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/ticgt.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python +# encoding: utf-8 + +# Texas Instruments code generator support (experimental) +# When reporting issues, please directly assign the bug to the maintainer. + +__author__ = __maintainer__ = "Jérôme Carretero " +__copyright__ = "Jérôme Carretero, 2012" + +""" +TI cgt6x is a compiler suite for TI DSPs. + +The toolchain does pretty weird things, and I'm sure I'm missing some of them. +But still, the tool saves time. + +What this tool does is: + +- create a TI compiler environment +- create TI compiler features, to handle some specifics about this compiler + It has a few idiosyncracies, such as not giving the liberty of the .o file names +- automatically activate them when using the TI compiler +- handle the tconf tool + The tool + +TODO: + +- the set_platform_flags() function is not nice +- more tests +- broaden tool scope, if needed + +""" + +import os, re + +from waflib import Options, Utils, Task, TaskGen +from waflib.Tools import c, ccroot, c_preproc +from waflib.Configure import conf +from waflib.TaskGen import feature, before_method +from waflib.Tools.c import cprogram + +opj = os.path.join + +@conf +def find_ticc(conf): + conf.find_program(['cl6x'], var='CC', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin')) + conf.env.CC_NAME = 'ticc' + +@conf +def find_tild(conf): + conf.find_program(['lnk6x'], var='LINK_CC', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin')) + conf.env.LINK_CC_NAME = 'tild' + +@conf +def find_tiar(conf): + conf.find_program(['ar6x'], var='AR', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin')) + conf.env.AR_NAME = 'tiar' + conf.env.ARFLAGS = 'qru' + +@conf +def ticc_common_flags(conf): + v = conf.env + + if not v['LINK_CC']: + v['LINK_CC'] = v['CC'] + v['CCLNK_SRC_F'] = [] + v['CCLNK_TGT_F'] = ['-o'] + v['CPPPATH_ST'] = '-I%s' + v['DEFINES_ST'] = '-d%s' + + v['LIB_ST'] = '-l%s' # template for adding libs + v['LIBPATH_ST'] = '-i%s' # template for adding libpaths + v['STLIB_ST'] = '-l=%s.lib' + v['STLIBPATH_ST'] = '-i%s' + + # program + v['cprogram_PATTERN'] = '%s.out' + + # static lib + #v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic'] + v['cstlib_PATTERN'] = '%s.lib' + +def configure(conf): + v = conf.env + v.TI_CGT_DIR = getattr(Options.options, 'ti-cgt-dir', "") + v.TI_DSPLINK_DIR = getattr(Options.options, 'ti-dsplink-dir', "") + v.TI_BIOSUTILS_DIR = getattr(Options.options, 'ti-biosutils-dir', "") + v.TI_DSPBIOS_DIR = getattr(Options.options, 'ti-dspbios-dir', "") + v.TI_XDCTOOLS_DIR = getattr(Options.options, 'ti-xdctools-dir', "") + conf.find_ticc() + conf.find_tiar() + conf.find_tild() + conf.ticc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + conf.find_program(['tconf'], var='TCONF', path_list=v.TI_XDCTOOLS_DIR) + + conf.env.TCONF_INCLUDES += [ + opj(conf.env.TI_DSPBIOS_DIR, 'packages'), + ] + + conf.env.INCLUDES += [ + opj(conf.env.TI_CGT_DIR, 'include'), + ] + + conf.env.LIBPATH += [ + opj(conf.env.TI_CGT_DIR, "lib"), + ] + + conf.env.INCLUDES_DSPBIOS += [ + opj(conf.env.TI_DSPBIOS_DIR, 'packages', 'ti', 'bios', 'include'), + ] + + conf.env.LIBPATH_DSPBIOS += [ + opj(conf.env.TI_DSPBIOS_DIR, 'packages', 'ti', 'bios', 'lib'), + ] + + conf.env.INCLUDES_DSPLINK += [ + opj(conf.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc'), + ] + +@conf +def ti_set_debug(cfg, debug=1): + """ + Sets debug flags for the compiler. + + TODO: + - for each TI CFLAG/INCLUDES/LINKFLAGS/LIBPATH replace RELEASE by DEBUG + - -g --no_compress + """ + if debug: + cfg.env.CFLAGS += "-d_DEBUG -dDEBUG -dDDSP_DEBUG".split() + +@conf +def ti_dsplink_set_platform_flags(cfg, splat, dsp, dspbios_ver, board): + """ + Sets the INCLUDES, LINKFLAGS for DSPLINK and TCONF_INCLUDES + For the specific hardware. + + Assumes that DSPLINK was built in its own folder. + + :param splat: short platform name (eg. OMAPL138) + :param dsp: DSP name (eg. 674X) + :param dspbios_ver: string identifying DspBios version (eg. 5.XX) + :param board: board name (eg. OMAPL138GEM) + + """ + d1 = opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', 'DspBios', dspbios_ver) + d = opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', 'DspBios', dspbios_ver, board) + cfg.env.TCONF_INCLUDES += [d1, d] + cfg.env.INCLUDES_DSPLINK += [ + opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', dsp), + d, + ] + + cfg.env.LINKFLAGS_DSPLINK += [ + opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'export', 'BIN', 'DspBios', splat, board+'_0', 'RELEASE', 'dsplink%s.lib' % x) + for x in ('', 'pool', 'mpcs', 'mplist', 'msg', 'data', 'notify', 'ringio') + ] + + +def options(opt): + opt.add_option('--with-ti-cgt', type='string', dest='ti-cgt-dir', help = 'Specify alternate cgt root folder', default="") + opt.add_option('--with-ti-biosutils', type='string', dest='ti-biosutils-dir', help = 'Specify alternate biosutils folder', default="") + opt.add_option('--with-ti-dspbios', type='string', dest='ti-dspbios-dir', help = 'Specify alternate dspbios folder', default="") + opt.add_option('--with-ti-dsplink', type='string', dest='ti-dsplink-dir', help = 'Specify alternate dsplink folder', default="") + opt.add_option('--with-ti-xdctools', type='string', dest='ti-xdctools-dir', help = 'Specify alternate xdctools folder', default="") + +class ti_cprogram(cprogram): + """ + Link object files into a c program + + Changes: + + - the linked executable to have a relative path (because we can) + - put the LIBPATH first + """ + run_str = '${LINK_CC} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].bldpath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ' + +@feature("c") +@before_method('apply_link') +def use_ti_cprogram(self): + """ + Automatically uses ti_cprogram link process + """ + if 'cprogram' in self.features and self.env.CC_NAME == 'ticc': + self.features.insert(0, "ti_cprogram") + +class ti_c(Task.Task): + """ + Compile task for the TI codegen compiler + + This compiler does not allow specifying the output file name, only the output path. + + """ + "Compile C files into object files" + run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${SRC} -c ${OUT} ${CPPFLAGS}' + vars = ['CCDEPS'] # unused variable to depend on, just in case + ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] + scan = c_preproc.scan + +def create_compiled_task(self, name, node): + """ + Overrides ccroot.create_compiled_task to support ti_c + """ + out = '%s' % (node.change_ext('.obj').name) + if self.env.CC_NAME == 'ticc': + name = 'ti_c' + task = self.create_task(name, node, node.parent.find_or_declare(out)) + self.env.OUT = '-fr%s' % (node.parent.get_bld().abspath()) + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks = [task] + return task + +@TaskGen.extension('.c') +def c_hook(self, node): + "Bind the c file extension to the creation of a :py:class:`waflib.Tools.c.c` instance" + if self.env.CC_NAME == 'ticc': + return create_compiled_task(self, 'ti_c', node) + else: + return self.create_compiled_task('c', node) + + +@feature("ti-tconf") +@before_method('process_source') +def apply_tconf(self): + sources = [x.get_src() for x in self.to_nodes(self.source, path=self.path.get_src())] + node = sources[0] + assert(sources[0].name.endswith(".tcf")) + if len(sources) > 1: + assert(sources[1].name.endswith(".cmd")) + + target = getattr(self, 'target', self.source) + target_node = node.get_bld().parent.find_or_declare(node.name) + + procid = "%d" % int(getattr(self, 'procid', 0)) + + importpaths = [] + includes = Utils.to_list(getattr(self, 'includes', [])) + for x in includes + self.env.TCONF_INCLUDES: + if x == os.path.abspath(x): + importpaths.append(x) + else: + relpath = self.path.find_node(x).path_from(target_node.parent) + importpaths.append(relpath) + + task = self.create_task('ti_tconf', sources, target_node.change_ext('.cdb')) + task.path = self.path + task.includes = includes + task.cwd = target_node.parent.abspath() + task.env = self.env.derive() + task.env["TCONFSRC"] = node.path_from(target_node.parent) + task.env["TCONFINC"] = '-Dconfig.importPath=%s' % ";".join(importpaths) + task.env['TCONFPROGNAME'] = '-Dconfig.programName=%s' % target + task.env['PROCID'] = procid + task.outputs = [ + target_node.change_ext("cfg_c.c"), + target_node.change_ext("cfg.s62"), + target_node.change_ext("cfg.cmd"), + ] + + create_compiled_task(self, 'ti_c', task.outputs[1]) + ctask = create_compiled_task(self, 'ti_c', task.outputs[0]) + ctask.env = self.env.derive() + + self.add_those_o_files(target_node.change_ext("cfg.cmd")) + if len(sources) > 1: + self.add_those_o_files(sources[1]) + self.source = [] + +re_tconf_include = re.compile(r'(?Putils\.importFile)\("(?P.*)"\)',re.M) +class ti_tconf(Task.Task): + run_str = '${TCONF} ${TCONFINC} ${TCONFPROGNAME} ${TCONFSRC} ${PROCID}' + color = 'PINK' + + def scan(self): + includes = Utils.to_list(getattr(self, 'includes', [])) + + def deps(node): + nodes, names = [], [] + if node: + code = Utils.readf(node.abspath()) + for match in re_tconf_include.finditer(code): + path = match.group('file') + if path: + for x in includes: + filename = opj(x, path) + fi = self.path.find_resource(filename) + if fi: + subnodes, subnames = deps(fi) + nodes += subnodes + names += subnames + nodes.append(fi) + names.append(path) + break + return nodes, names + return deps(self.inputs[0]) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/unity.py b/ldb-2.0.8/third_party/waf/waflib/extras/unity.py new file mode 100644 index 0000000..78128ed --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/unity.py @@ -0,0 +1,108 @@ +#! /usr/bin/env python +# encoding: utf-8 + +""" +Compile whole groups of C/C++ files at once +(C and C++ files are processed independently though). + +To enable globally:: + + def options(opt): + opt.load('compiler_cxx') + def build(bld): + bld.load('compiler_cxx unity') + +To enable for specific task generators only:: + + def build(bld): + bld(features='c cprogram unity', source='main.c', ...) + +The file order is often significant in such builds, so it can be +necessary to adjust the order of source files and the batch sizes. +To control the amount of files processed in a batch per target +(the default is 50):: + + def build(bld): + bld(features='c cprogram', unity_size=20) + +""" + +from waflib import Task, Options +from waflib.Tools import c_preproc +from waflib import TaskGen + +MAX_BATCH = 50 + +EXTS_C = ('.c',) +EXTS_CXX = ('.cpp','.cc','.cxx','.C','.c++') + +def options(opt): + global MAX_BATCH + opt.add_option('--batchsize', action='store', dest='batchsize', type='int', default=MAX_BATCH, + help='default unity batch size (0 disables unity builds)') + +@TaskGen.taskgen_method +def batch_size(self): + default = getattr(Options.options, 'batchsize', MAX_BATCH) + if default < 1: + return 0 + return getattr(self, 'unity_size', default) + + +class unity(Task.Task): + color = 'BLUE' + scan = c_preproc.scan + def to_include(self, node): + ret = node.path_from(self.outputs[0].parent) + ret = ret.replace('\\', '\\\\').replace('"', '\\"') + return ret + def run(self): + lst = ['#include "%s"\n' % self.to_include(node) for node in self.inputs] + txt = ''.join(lst) + self.outputs[0].write(txt) + def __str__(self): + node = self.outputs[0] + return node.path_from(node.ctx.launch_node()) + +def bind_unity(obj, cls_name, exts): + if not 'mappings' in obj.__dict__: + obj.mappings = dict(obj.mappings) + + for j in exts: + fun = obj.mappings[j] + if fun.__name__ == 'unity_fun': + raise ValueError('Attempt to bind unity mappings multiple times %r' % j) + + def unity_fun(self, node): + cnt = self.batch_size() + if cnt <= 1: + return fun(self, node) + x = getattr(self, 'master_%s' % cls_name, None) + if not x or len(x.inputs) >= cnt: + x = self.create_task('unity') + setattr(self, 'master_%s' % cls_name, x) + + cnt_cur = getattr(self, 'cnt_%s' % cls_name, 0) + c_node = node.parent.find_or_declare('unity_%s_%d_%d.%s' % (self.idx, cnt_cur, cnt, cls_name)) + x.outputs = [c_node] + setattr(self, 'cnt_%s' % cls_name, cnt_cur + 1) + fun(self, c_node) + x.inputs.append(node) + + obj.mappings[j] = unity_fun + +@TaskGen.feature('unity') +@TaskGen.before('process_source') +def single_unity(self): + lst = self.to_list(self.features) + if 'c' in lst: + bind_unity(self, 'c', EXTS_C) + if 'cxx' in lst: + bind_unity(self, 'cxx', EXTS_CXX) + +def build(bld): + if bld.env.CC_NAME: + bind_unity(TaskGen.task_gen, 'c', EXTS_C) + if bld.env.CXX_NAME: + bind_unity(TaskGen.task_gen, 'cxx', EXTS_CXX) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/use_config.py b/ldb-2.0.8/third_party/waf/waflib/extras/use_config.py new file mode 100644 index 0000000..ef5129f --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/use_config.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python +# coding=utf-8 +# Mathieu Courtois - EDF R&D, 2013 - http://www.code-aster.org + +""" +When a project has a lot of options the 'waf configure' command line can be +very long and it becomes a cause of error. +This tool provides a convenient way to load a set of configuration parameters +from a local file or from a remote url. + +The configuration parameters are stored in a Python file that is imported as +an extra waf tool can be. + +Example: +$ waf configure --use-config-dir=http://www.anywhere.org --use-config=myconf1 ... + +The file 'myconf1' will be downloaded from 'http://www.anywhere.org' +(or 'http://www.anywhere.org/wafcfg'). +If the files are available locally, it could be: +$ waf configure --use-config-dir=/somewhere/myconfigurations --use-config=myconf1 ... + +The configuration of 'myconf1.py' is automatically loaded by calling +its 'configure' function. In this example, it defines environment variables and +set options: + +def configure(self): + self.env['CC'] = 'gcc-4.8' + self.env.append_value('LIBPATH', [...]) + self.options.perlbinary = '/usr/local/bin/perl' + self.options.pyc = False + +The corresponding command line should have been: +$ CC=gcc-4.8 LIBPATH=... waf configure --nopyc --with-perl-binary=/usr/local/bin/perl + + +This is an extra tool, not bundled with the default waf binary. +To add the use_config tool to the waf file: +$ ./waf-light --tools=use_config + +When using this tool, the wscript will look like: + + def options(opt): + opt.load('use_config') + + def configure(conf): + conf.load('use_config') +""" + +import sys +import os.path as osp +import os + +local_repo = '' +"""Local repository containing additional Waf tools (plugins)""" +remote_repo = 'https://gitlab.com/ita1024/waf/raw/master/' +""" +Remote directory containing downloadable waf tools. The missing tools can be downloaded by using:: + + $ waf configure --download +""" + +remote_locs = ['waflib/extras', 'waflib/Tools'] +""" +Remote directories for use with :py:const:`waflib.extras.use_config.remote_repo` +""" + + +try: + from urllib import request +except ImportError: + from urllib import urlopen +else: + urlopen = request.urlopen + + +from waflib import Errors, Context, Logs, Utils, Options, Configure + +try: + from urllib.parse import urlparse +except ImportError: + from urlparse import urlparse + + + + +DEFAULT_DIR = 'wafcfg' +# add first the current wafcfg subdirectory +sys.path.append(osp.abspath(DEFAULT_DIR)) + +def options(self): + group = self.add_option_group('configure options') + group.add_option('--download', dest='download', default=False, action='store_true', help='try to download the tools if missing') + + group.add_option('--use-config', action='store', default=None, + metavar='CFG', dest='use_config', + help='force the configuration parameters by importing ' + 'CFG.py. Several modules may be provided (comma ' + 'separated).') + group.add_option('--use-config-dir', action='store', default=DEFAULT_DIR, + metavar='CFG_DIR', dest='use_config_dir', + help='path or url where to find the configuration file') + +def download_check(node): + """ + Hook to check for the tools which are downloaded. Replace with your function if necessary. + """ + pass + + +def download_tool(tool, force=False, ctx=None): + """ + Download a Waf tool from the remote repository defined in :py:const:`waflib.extras.use_config.remote_repo`:: + + $ waf configure --download + """ + for x in Utils.to_list(remote_repo): + for sub in Utils.to_list(remote_locs): + url = '/'.join((x, sub, tool + '.py')) + try: + web = urlopen(url) + try: + if web.getcode() != 200: + continue + except AttributeError: + pass + except Exception: + # on python3 urlopen throws an exception + # python 2.3 does not have getcode and throws an exception to fail + continue + else: + tmp = ctx.root.make_node(os.sep.join((Context.waf_dir, 'waflib', 'extras', tool + '.py'))) + tmp.write(web.read(), 'wb') + Logs.warn('Downloaded %s from %s', tool, url) + download_check(tmp) + try: + module = Context.load_tool(tool) + except Exception: + Logs.warn('The tool %s from %s is unusable', tool, url) + try: + tmp.delete() + except Exception: + pass + continue + return module + + raise Errors.WafError('Could not load the Waf tool') + +def load_tool(tool, tooldir=None, ctx=None, with_sys_path=True): + try: + module = Context.load_tool_default(tool, tooldir, ctx, with_sys_path) + except ImportError as e: + if not ctx or not hasattr(Options.options, 'download'): + Logs.error('Could not load %r during options phase (download unavailable at this point)' % tool) + raise + if Options.options.download: + module = download_tool(tool, ctx=ctx) + if not module: + ctx.fatal('Could not load the Waf tool %r or download a suitable replacement from the repository (sys.path %r)\n%s' % (tool, sys.path, e)) + else: + ctx.fatal('Could not load the Waf tool %r from %r (try the --download option?):\n%s' % (tool, sys.path, e)) + return module + +Context.load_tool_default = Context.load_tool +Context.load_tool = load_tool +Configure.download_tool = download_tool + +def configure(self): + opts = self.options + use_cfg = opts.use_config + if use_cfg is None: + return + url = urlparse(opts.use_config_dir) + kwargs = {} + if url.scheme: + kwargs['download'] = True + kwargs['remote_url'] = url.geturl() + # search first with the exact url, else try with +'/wafcfg' + kwargs['remote_locs'] = ['', DEFAULT_DIR] + tooldir = url.geturl() + ' ' + DEFAULT_DIR + for cfg in use_cfg.split(','): + Logs.pprint('NORMAL', "Searching configuration '%s'..." % cfg) + self.load(cfg, tooldir=tooldir, **kwargs) + self.start_msg('Checking for configuration') + self.end_msg(use_cfg) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/valadoc.py b/ldb-2.0.8/third_party/waf/waflib/extras/valadoc.py new file mode 100644 index 0000000..c50f69e --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/valadoc.py @@ -0,0 +1,140 @@ +#! /usr/bin/env python +# encoding: UTF-8 +# Nicolas Joseph 2009 + +""" +ported from waf 1.5: +TODO: tabs vs spaces +""" + +from waflib import Task, Utils, Errors, Logs +from waflib.TaskGen import feature + +VALADOC_STR = '${VALADOC}' + +class valadoc(Task.Task): + vars = ['VALADOC', 'VALADOCFLAGS'] + color = 'BLUE' + after = ['cprogram', 'cstlib', 'cshlib', 'cxxprogram', 'cxxstlib', 'cxxshlib'] + quiet = True # no outputs .. this is weird + + def __init__(self, *k, **kw): + Task.Task.__init__(self, *k, **kw) + self.output_dir = '' + self.doclet = '' + self.package_name = '' + self.package_version = '' + self.files = [] + self.vapi_dirs = [] + self.protected = True + self.private = False + self.inherit = False + self.deps = False + self.vala_defines = [] + self.vala_target_glib = None + self.enable_non_null_experimental = False + self.force = False + + def run(self): + if not self.env['VALADOCFLAGS']: + self.env['VALADOCFLAGS'] = '' + cmd = [Utils.subst_vars(VALADOC_STR, self.env)] + cmd.append ('-o %s' % self.output_dir) + if getattr(self, 'doclet', None): + cmd.append ('--doclet %s' % self.doclet) + cmd.append ('--package-name %s' % self.package_name) + if getattr(self, 'package_version', None): + cmd.append ('--package-version %s' % self.package_version) + if getattr(self, 'packages', None): + for package in self.packages: + cmd.append ('--pkg %s' % package) + if getattr(self, 'vapi_dirs', None): + for vapi_dir in self.vapi_dirs: + cmd.append ('--vapidir %s' % vapi_dir) + if not getattr(self, 'protected', None): + cmd.append ('--no-protected') + if getattr(self, 'private', None): + cmd.append ('--private') + if getattr(self, 'inherit', None): + cmd.append ('--inherit') + if getattr(self, 'deps', None): + cmd.append ('--deps') + if getattr(self, 'vala_defines', None): + for define in self.vala_defines: + cmd.append ('--define %s' % define) + if getattr(self, 'vala_target_glib', None): + cmd.append ('--target-glib=%s' % self.vala_target_glib) + if getattr(self, 'enable_non_null_experimental', None): + cmd.append ('--enable-non-null-experimental') + if getattr(self, 'force', None): + cmd.append ('--force') + cmd.append (' '.join ([x.abspath() for x in self.files])) + return self.generator.bld.exec_command(' '.join(cmd)) + +@feature('valadoc') +def process_valadoc(self): + """ + Generate API documentation from Vala source code with valadoc + + doc = bld( + features = 'valadoc', + output_dir = '../doc/html', + package_name = 'vala-gtk-example', + package_version = '1.0.0', + packages = 'gtk+-2.0', + vapi_dirs = '../vapi', + force = True + ) + + path = bld.path.find_dir ('../src') + doc.files = path.ant_glob (incl='**/*.vala') + """ + + task = self.create_task('valadoc') + if getattr(self, 'output_dir', None): + task.output_dir = self.path.find_or_declare(self.output_dir).abspath() + else: + Errors.WafError('no output directory') + if getattr(self, 'doclet', None): + task.doclet = self.doclet + else: + Errors.WafError('no doclet directory') + if getattr(self, 'package_name', None): + task.package_name = self.package_name + else: + Errors.WafError('no package name') + if getattr(self, 'package_version', None): + task.package_version = self.package_version + if getattr(self, 'packages', None): + task.packages = Utils.to_list(self.packages) + if getattr(self, 'vapi_dirs', None): + vapi_dirs = Utils.to_list(self.vapi_dirs) + for vapi_dir in vapi_dirs: + try: + task.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath()) + except AttributeError: + Logs.warn('Unable to locate Vala API directory: %r', vapi_dir) + if getattr(self, 'files', None): + task.files = self.files + else: + Errors.WafError('no input file') + if getattr(self, 'protected', None): + task.protected = self.protected + if getattr(self, 'private', None): + task.private = self.private + if getattr(self, 'inherit', None): + task.inherit = self.inherit + if getattr(self, 'deps', None): + task.deps = self.deps + if getattr(self, 'vala_defines', None): + task.vala_defines = Utils.to_list(self.vala_defines) + if getattr(self, 'vala_target_glib', None): + task.vala_target_glib = self.vala_target_glib + if getattr(self, 'enable_non_null_experimental', None): + task.enable_non_null_experimental = self.enable_non_null_experimental + if getattr(self, 'force', None): + task.force = self.force + +def configure(conf): + conf.find_program('valadoc', errmsg='You must install valadoc for generate the API documentation') + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/waf_xattr.py b/ldb-2.0.8/third_party/waf/waflib/extras/waf_xattr.py new file mode 100644 index 0000000..351dd63 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/waf_xattr.py @@ -0,0 +1,150 @@ +#! /usr/bin/env python +# encoding: utf-8 + +""" +Use extended attributes instead of database files + +1. Input files will be made writable +2. This is only for systems providing extended filesystem attributes +3. By default, hashes are calculated only if timestamp/size change (HASH_CACHE below) +4. The module enables "deep_inputs" on all tasks by propagating task signatures +5. This module also skips task signature comparisons for task code changes due to point 4. +6. This module is for Python3/Linux only, but it could be extended to Python2/other systems + using the xattr library +7. For projects in which tasks always declare output files, it should be possible to + store the rest of build context attributes on output files (imp_sigs, raw_deps and node_deps) + but this is not done here + +On a simple C++ project benchmark, the variations before and after adding waf_xattr.py were observed: +total build time: 20s -> 22s +no-op build time: 2.4s -> 1.8s +pickle file size: 2.9MB -> 2.6MB +""" + +import os +from waflib import Logs, Node, Task, Utils, Errors +from waflib.Task import SKIP_ME, RUN_ME, CANCEL_ME, ASK_LATER, SKIPPED, MISSING + +HASH_CACHE = True +SIG_VAR = 'user.waf.sig' +SEP = ','.encode() +TEMPLATE = '%b%d,%d'.encode() + +try: + PermissionError +except NameError: + PermissionError = IOError + +def getxattr(self): + return os.getxattr(self.abspath(), SIG_VAR) + +def setxattr(self, val): + os.setxattr(self.abspath(), SIG_VAR, val) + +def h_file(self): + try: + ret = getxattr(self) + except OSError: + if HASH_CACHE: + st = os.stat(self.abspath()) + mtime = st.st_mtime + size = st.st_size + else: + if len(ret) == 16: + # for build directory files + return ret + + if HASH_CACHE: + # check if timestamp and mtime match to avoid re-hashing + st = os.stat(self.abspath()) + mtime, size = ret[16:].split(SEP) + if int(1000 * st.st_mtime) == int(mtime) and st.st_size == int(size): + return ret[:16] + + ret = Utils.h_file(self.abspath()) + if HASH_CACHE: + val = TEMPLATE % (ret, int(1000 * st.st_mtime), int(st.st_size)) + try: + setxattr(self, val) + except PermissionError: + os.chmod(self.abspath(), st.st_mode | 128) + setxattr(self, val) + return ret + +def runnable_status(self): + bld = self.generator.bld + if bld.is_install < 0: + return SKIP_ME + + for t in self.run_after: + if not t.hasrun: + return ASK_LATER + elif t.hasrun < SKIPPED: + # a dependency has an error + return CANCEL_ME + + # first compute the signature + try: + new_sig = self.signature() + except Errors.TaskNotReady: + return ASK_LATER + + if not self.outputs: + # compare the signature to a signature computed previously + # this part is only for tasks with no output files + key = self.uid() + try: + prev_sig = bld.task_sigs[key] + except KeyError: + Logs.debug('task: task %r must run: it was never run before or the task code changed', self) + return RUN_ME + if new_sig != prev_sig: + Logs.debug('task: task %r must run: the task signature changed', self) + return RUN_ME + + # compare the signatures of the outputs to make a decision + for node in self.outputs: + try: + sig = node.h_file() + except EnvironmentError: + Logs.debug('task: task %r must run: an output node does not exist', self) + return RUN_ME + if sig != new_sig: + Logs.debug('task: task %r must run: an output node is stale', self) + return RUN_ME + + return (self.always_run and RUN_ME) or SKIP_ME + +def post_run(self): + bld = self.generator.bld + sig = self.signature() + for node in self.outputs: + if not node.exists(): + self.hasrun = MISSING + self.err_msg = '-> missing file: %r' % node.abspath() + raise Errors.WafError(self.err_msg) + os.setxattr(node.abspath(), 'user.waf.sig', sig) + if not self.outputs: + # only for task with no outputs + bld.task_sigs[self.uid()] = sig + if not self.keep_last_cmd: + try: + del self.last_cmd + except AttributeError: + pass + +try: + os.getxattr +except AttributeError: + pass +else: + h_file.__doc__ = Node.Node.h_file.__doc__ + + # keep file hashes as file attributes + Node.Node.h_file = h_file + + # enable "deep_inputs" on all tasks + Task.Task.runnable_status = runnable_status + Task.Task.post_run = post_run + Task.Task.sig_deep_inputs = Utils.nada + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/why.py b/ldb-2.0.8/third_party/waf/waflib/extras/why.py new file mode 100644 index 0000000..1bb941f --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/why.py @@ -0,0 +1,78 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010 (ita) + +""" +This tool modifies the task signature scheme to store and obtain +information about the task execution (why it must run, etc):: + + def configure(conf): + conf.load('why') + +After adding the tool, a full rebuild is necessary: +waf clean build --zones=task +""" + +from waflib import Task, Utils, Logs, Errors + +def signature(self): + # compute the result one time, and suppose the scan_signature will give the good result + try: + return self.cache_sig + except AttributeError: + pass + + self.m = Utils.md5() + self.m.update(self.hcode) + id_sig = self.m.digest() + + # explicit deps + self.m = Utils.md5() + self.sig_explicit_deps() + exp_sig = self.m.digest() + + # env vars + self.m = Utils.md5() + self.sig_vars() + var_sig = self.m.digest() + + # implicit deps / scanner results + self.m = Utils.md5() + if self.scan: + try: + self.sig_implicit_deps() + except Errors.TaskRescan: + return self.signature() + impl_sig = self.m.digest() + + ret = self.cache_sig = impl_sig + id_sig + exp_sig + var_sig + return ret + + +Task.Task.signature = signature + +old = Task.Task.runnable_status +def runnable_status(self): + ret = old(self) + if ret == Task.RUN_ME: + try: + old_sigs = self.generator.bld.task_sigs[self.uid()] + except (KeyError, AttributeError): + Logs.debug("task: task must run as no previous signature exists") + else: + new_sigs = self.cache_sig + def v(x): + return Utils.to_hex(x) + + Logs.debug('Task %r', self) + msgs = ['* Implicit or scanner dependency', '* Task code', '* Source file, explicit or manual dependency', '* Configuration data variable'] + tmp = 'task: -> %s: %s %s' + for x in range(len(msgs)): + l = len(Utils.SIG_NIL) + a = new_sigs[x*l : (x+1)*l] + b = old_sigs[x*l : (x+1)*l] + if (a != b): + Logs.debug(tmp, msgs[x].ljust(35), v(a), v(b)) + return ret +Task.Task.runnable_status = runnable_status + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/win32_opts.py b/ldb-2.0.8/third_party/waf/waflib/extras/win32_opts.py new file mode 100644 index 0000000..9f7443c --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/win32_opts.py @@ -0,0 +1,170 @@ +#! /usr/bin/env python +# encoding: utf-8 + +""" +Windows-specific optimizations + +This module can help reducing the overhead of listing files on windows +(more than 10000 files). Python 3.5 already provides the listdir +optimization though. +""" + +import os +from waflib import Utils, Build, Node, Logs + +try: + TP = '%s\\*'.decode('ascii') +except AttributeError: + TP = '%s\\*' + +if Utils.is_win32: + from waflib.Tools import md5_tstamp + import ctypes, ctypes.wintypes + + FindFirstFile = ctypes.windll.kernel32.FindFirstFileW + FindNextFile = ctypes.windll.kernel32.FindNextFileW + FindClose = ctypes.windll.kernel32.FindClose + FILE_ATTRIBUTE_DIRECTORY = 0x10 + INVALID_HANDLE_VALUE = -1 + UPPER_FOLDERS = ('.', '..') + try: + UPPER_FOLDERS = [unicode(x) for x in UPPER_FOLDERS] + except NameError: + pass + + def cached_hash_file(self): + try: + cache = self.ctx.cache_listdir_cache_hash_file + except AttributeError: + cache = self.ctx.cache_listdir_cache_hash_file = {} + + if id(self.parent) in cache: + try: + t = cache[id(self.parent)][self.name] + except KeyError: + raise IOError('Not a file') + else: + # an opportunity to list the files and the timestamps at once + findData = ctypes.wintypes.WIN32_FIND_DATAW() + find = FindFirstFile(TP % self.parent.abspath(), ctypes.byref(findData)) + + if find == INVALID_HANDLE_VALUE: + cache[id(self.parent)] = {} + raise IOError('Not a file') + + cache[id(self.parent)] = lst_files = {} + try: + while True: + if findData.cFileName not in UPPER_FOLDERS: + thatsadir = findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY + if not thatsadir: + ts = findData.ftLastWriteTime + d = (ts.dwLowDateTime << 32) | ts.dwHighDateTime + lst_files[str(findData.cFileName)] = d + if not FindNextFile(find, ctypes.byref(findData)): + break + except Exception: + cache[id(self.parent)] = {} + raise IOError('Not a file') + finally: + FindClose(find) + t = lst_files[self.name] + + fname = self.abspath() + if fname in Build.hashes_md5_tstamp: + if Build.hashes_md5_tstamp[fname][0] == t: + return Build.hashes_md5_tstamp[fname][1] + + try: + fd = os.open(fname, os.O_BINARY | os.O_RDONLY | os.O_NOINHERIT) + except OSError: + raise IOError('Cannot read from %r' % fname) + f = os.fdopen(fd, 'rb') + m = Utils.md5() + rb = 1 + try: + while rb: + rb = f.read(200000) + m.update(rb) + finally: + f.close() + + # ensure that the cache is overwritten + Build.hashes_md5_tstamp[fname] = (t, m.digest()) + return m.digest() + Node.Node.cached_hash_file = cached_hash_file + + def get_bld_sig_win32(self): + try: + return self.ctx.hash_cache[id(self)] + except KeyError: + pass + except AttributeError: + self.ctx.hash_cache = {} + self.ctx.hash_cache[id(self)] = ret = Utils.h_file(self.abspath()) + return ret + Node.Node.get_bld_sig = get_bld_sig_win32 + + def isfile_cached(self): + # optimize for nt.stat calls, assuming there are many files for few folders + try: + cache = self.__class__.cache_isfile_cache + except AttributeError: + cache = self.__class__.cache_isfile_cache = {} + + try: + c1 = cache[id(self.parent)] + except KeyError: + c1 = cache[id(self.parent)] = [] + + curpath = self.parent.abspath() + findData = ctypes.wintypes.WIN32_FIND_DATAW() + find = FindFirstFile(TP % curpath, ctypes.byref(findData)) + + if find == INVALID_HANDLE_VALUE: + Logs.error("invalid win32 handle isfile_cached %r", self.abspath()) + return os.path.isfile(self.abspath()) + + try: + while True: + if findData.cFileName not in UPPER_FOLDERS: + thatsadir = findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY + if not thatsadir: + c1.append(str(findData.cFileName)) + if not FindNextFile(find, ctypes.byref(findData)): + break + except Exception as e: + Logs.error('exception while listing a folder %r %r', self.abspath(), e) + return os.path.isfile(self.abspath()) + finally: + FindClose(find) + return self.name in c1 + Node.Node.isfile_cached = isfile_cached + + def find_or_declare_win32(self, lst): + # assuming that "find_or_declare" is called before the build starts, remove the calls to os.path.isfile + if isinstance(lst, str): + lst = [x for x in Utils.split_path(lst) if x and x != '.'] + + node = self.get_bld().search_node(lst) + if node: + if not node.isfile_cached(): + try: + node.parent.mkdir() + except OSError: + pass + return node + self = self.get_src() + node = self.find_node(lst) + if node: + if not node.isfile_cached(): + try: + node.parent.mkdir() + except OSError: + pass + return node + node = self.get_bld().make_node(lst) + node.parent.mkdir() + return node + Node.Node.find_or_declare = find_or_declare_win32 + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/wix.py b/ldb-2.0.8/third_party/waf/waflib/extras/wix.py new file mode 100644 index 0000000..d87bfbb --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/wix.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# encoding: utf-8 +# vim: tabstop=4 noexpandtab + +""" +Windows Installer XML Tool (WiX) + +.wxs --- candle ---> .wxobj --- light ---> .msi + +bld(features='wix', some.wxs, gen='some.msi', candleflags=[..], lightflags=[..]) + +bld(features='wix', source=['bundle.wxs','WixBalExtension'], gen='setup.exe', candleflags=[..]) +""" + +import os, copy +from waflib import TaskGen +from waflib import Task +from waflib.Utils import winreg + +class candle(Task.Task): + run_str = '${CANDLE} -nologo ${CANDLEFLAGS} -out ${TGT} ${SRC[0].abspath()}', + +class light(Task.Task): + run_str = "${LIGHT} -nologo -b ${SRC[0].parent.abspath()} ${LIGHTFLAGS} -out ${TGT} ${SRC[0].abspath()}" + +@TaskGen.feature('wix') +@TaskGen.before_method('process_source') +def wix(self): + #X.wxs -> ${SRC} for CANDLE + #X.wxobj -> ${SRC} for LIGHT + #X.dll -> -ext X in ${LIGHTFLAGS} + #X.wxl -> wixui.wixlib -loc X.wxl in ${LIGHTFLAGS} + wxobj = [] + wxs = [] + exts = [] + wxl = [] + rest = [] + for x in self.source: + if x.endswith('.wxobj'): + wxobj.append(x) + elif x.endswith('.wxs'): + wxobj.append(self.path.find_or_declare(x[:-4]+'.wxobj')) + wxs.append(x) + elif x.endswith('.dll'): + exts.append(x[:-4]) + elif '.' not in x: + exts.append(x) + elif x.endswith('.wxl'): + wxl.append(x) + else: + rest.append(x) + self.source = self.to_nodes(rest) #.wxs + + cndl = self.create_task('candle', self.to_nodes(wxs), self.to_nodes(wxobj)) + lght = self.create_task('light', self.to_nodes(wxobj), self.path.find_or_declare(self.gen)) + + cndl.env.CANDLEFLAGS = copy.copy(getattr(self,'candleflags',[])) + lght.env.LIGHTFLAGS = copy.copy(getattr(self,'lightflags',[])) + + for x in wxl: + lght.env.append_value('LIGHTFLAGS','wixui.wixlib') + lght.env.append_value('LIGHTFLAGS','-loc') + lght.env.append_value('LIGHTFLAGS',x) + for x in exts: + cndl.env.append_value('CANDLEFLAGS','-ext') + cndl.env.append_value('CANDLEFLAGS',x) + lght.env.append_value('LIGHTFLAGS','-ext') + lght.env.append_value('LIGHTFLAGS',x) + +#wix_bin_path() +def wix_bin_path(): + basekey = r"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders" + query = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, basekey) + cnt=winreg.QueryInfoKey(query)[0] + thiskey = r'C:\Program Files (x86)\WiX Toolset v3.10\SDK' + for i in range(cnt-1,-1,-1): + thiskey = winreg.EnumKey(query,i) + if 'WiX' in thiskey: + break + winreg.CloseKey(query) + return os.path.normpath(winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE, basekey+r'\\'+thiskey)+'..\\bin') + +def configure(ctx): + path_list=[wix_bin_path()] + ctx.find_program('candle', var='CANDLE', mandatory=True, path_list = path_list) + ctx.find_program('light', var='LIGHT', mandatory=True, path_list = path_list) + diff --git a/ldb-2.0.8/third_party/waf/waflib/extras/xcode6.py b/ldb-2.0.8/third_party/waf/waflib/extras/xcode6.py new file mode 100644 index 0000000..91bbff1 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/extras/xcode6.py @@ -0,0 +1,727 @@ +#! /usr/bin/env python +# encoding: utf-8 +# XCode 3/XCode 4/XCode 6/Xcode 7 generator for Waf +# Based on work by Nicolas Mercier 2011 +# Extended by Simon Warg 2015, https://github.com/mimon +# XCode project file format based on http://www.monobjc.net/xcode-project-file-format.html + +""" +See playground/xcode6/ for usage examples. + +""" + +from waflib import Context, TaskGen, Build, Utils, Errors, Logs +import os, sys + +# FIXME too few extensions +XCODE_EXTS = ['.c', '.cpp', '.m', '.mm'] + +HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' + +MAP_EXT = { + '': "folder", + '.h' : "sourcecode.c.h", + + '.hh': "sourcecode.cpp.h", + '.inl': "sourcecode.cpp.h", + '.hpp': "sourcecode.cpp.h", + + '.c': "sourcecode.c.c", + + '.m': "sourcecode.c.objc", + + '.mm': "sourcecode.cpp.objcpp", + + '.cc': "sourcecode.cpp.cpp", + + '.cpp': "sourcecode.cpp.cpp", + '.C': "sourcecode.cpp.cpp", + '.cxx': "sourcecode.cpp.cpp", + '.c++': "sourcecode.cpp.cpp", + + '.l': "sourcecode.lex", # luthor + '.ll': "sourcecode.lex", + + '.y': "sourcecode.yacc", + '.yy': "sourcecode.yacc", + + '.plist': "text.plist.xml", + ".nib": "wrapper.nib", + ".xib": "text.xib", +} + +# Used in PBXNativeTarget elements +PRODUCT_TYPE_APPLICATION = 'com.apple.product-type.application' +PRODUCT_TYPE_FRAMEWORK = 'com.apple.product-type.framework' +PRODUCT_TYPE_EXECUTABLE = 'com.apple.product-type.tool' +PRODUCT_TYPE_LIB_STATIC = 'com.apple.product-type.library.static' +PRODUCT_TYPE_LIB_DYNAMIC = 'com.apple.product-type.library.dynamic' +PRODUCT_TYPE_EXTENSION = 'com.apple.product-type.kernel-extension' +PRODUCT_TYPE_IOKIT = 'com.apple.product-type.kernel-extension.iokit' + +# Used in PBXFileReference elements +FILE_TYPE_APPLICATION = 'wrapper.cfbundle' +FILE_TYPE_FRAMEWORK = 'wrapper.framework' +FILE_TYPE_LIB_DYNAMIC = 'compiled.mach-o.dylib' +FILE_TYPE_LIB_STATIC = 'archive.ar' +FILE_TYPE_EXECUTABLE = 'compiled.mach-o.executable' + +# Tuple packs of the above +TARGET_TYPE_FRAMEWORK = (PRODUCT_TYPE_FRAMEWORK, FILE_TYPE_FRAMEWORK, '.framework') +TARGET_TYPE_APPLICATION = (PRODUCT_TYPE_APPLICATION, FILE_TYPE_APPLICATION, '.app') +TARGET_TYPE_DYNAMIC_LIB = (PRODUCT_TYPE_LIB_DYNAMIC, FILE_TYPE_LIB_DYNAMIC, '.dylib') +TARGET_TYPE_STATIC_LIB = (PRODUCT_TYPE_LIB_STATIC, FILE_TYPE_LIB_STATIC, '.a') +TARGET_TYPE_EXECUTABLE = (PRODUCT_TYPE_EXECUTABLE, FILE_TYPE_EXECUTABLE, '') + +# Maps target type string to its data +TARGET_TYPES = { + 'framework': TARGET_TYPE_FRAMEWORK, + 'app': TARGET_TYPE_APPLICATION, + 'dylib': TARGET_TYPE_DYNAMIC_LIB, + 'stlib': TARGET_TYPE_STATIC_LIB, + 'exe' :TARGET_TYPE_EXECUTABLE, +} + +def delete_invalid_values(dct): + """ Deletes entries that are dictionaries or sets """ + for k, v in list(dct.items()): + if isinstance(v, dict) or isinstance(v, set): + del dct[k] + return dct + +""" +Configuration of the global project settings. Sets an environment variable 'PROJ_CONFIGURATION' +which is a dictionary of configuration name and buildsettings pair. +E.g.: +env.PROJ_CONFIGURATION = { + 'Debug': { + 'ARCHS': 'x86', + ... + } + 'Release': { + 'ARCHS' x86_64' + ... + } +} +The user can define a completely customized dictionary in configure() stage. Otherwise a default Debug/Release will be created +based on env variable +""" +def configure(self): + if not self.env.PROJ_CONFIGURATION: + self.to_log("A default project configuration was created since no custom one was given in the configure(conf) stage. Define your custom project settings by adding PROJ_CONFIGURATION to env. The env.PROJ_CONFIGURATION must be a dictionary with at least one key, where each key is the configuration name, and the value is a dictionary of key/value settings.\n") + + # Check for any added config files added by the tool 'c_config'. + if 'cfg_files' in self.env: + self.env.INCLUDES = Utils.to_list(self.env.INCLUDES) + [os.path.abspath(os.path.dirname(f)) for f in self.env.cfg_files] + + # Create default project configuration? + if 'PROJ_CONFIGURATION' not in self.env: + defaults = delete_invalid_values(self.env.get_merged_dict()) + self.env.PROJ_CONFIGURATION = { + "Debug": defaults, + "Release": defaults, + } + + # Some build settings are required to be present by XCode. We will supply default values + # if user hasn't defined any. + defaults_required = [('PRODUCT_NAME', '$(TARGET_NAME)')] + for cfgname,settings in self.env.PROJ_CONFIGURATION.items(): + for default_var, default_val in defaults_required: + if default_var not in settings: + settings[default_var] = default_val + + # Error check customization + if not isinstance(self.env.PROJ_CONFIGURATION, dict): + raise Errors.ConfigurationError("The env.PROJ_CONFIGURATION must be a dictionary with at least one key, where each key is the configuration name, and the value is a dictionary of key/value settings.") + +part1 = 0 +part2 = 10000 +part3 = 0 +id = 562000999 +def newid(): + global id + id += 1 + return "%04X%04X%04X%012d" % (0, 10000, 0, id) + +""" +Represents a tree node in the XCode project plist file format. +When written to a file, all attributes of XCodeNode are stringified together with +its value. However, attributes starting with an underscore _ are ignored +during that process and allows you to store arbitrary values that are not supposed +to be written out. +""" +class XCodeNode(object): + def __init__(self): + self._id = newid() + self._been_written = False + + def tostring(self, value): + if isinstance(value, dict): + result = "{\n" + for k,v in value.items(): + result = result + "\t\t\t%s = %s;\n" % (k, self.tostring(v)) + result = result + "\t\t}" + return result + elif isinstance(value, str): + return "\"%s\"" % value + elif isinstance(value, list): + result = "(\n" + for i in value: + result = result + "\t\t\t%s,\n" % self.tostring(i) + result = result + "\t\t)" + return result + elif isinstance(value, XCodeNode): + return value._id + else: + return str(value) + + def write_recursive(self, value, file): + if isinstance(value, dict): + for k,v in value.items(): + self.write_recursive(v, file) + elif isinstance(value, list): + for i in value: + self.write_recursive(i, file) + elif isinstance(value, XCodeNode): + value.write(file) + + def write(self, file): + if not self._been_written: + self._been_written = True + for attribute,value in self.__dict__.items(): + if attribute[0] != '_': + self.write_recursive(value, file) + w = file.write + w("\t%s = {\n" % self._id) + w("\t\tisa = %s;\n" % self.__class__.__name__) + for attribute,value in self.__dict__.items(): + if attribute[0] != '_': + w("\t\t%s = %s;\n" % (attribute, self.tostring(value))) + w("\t};\n\n") + +# Configurations +class XCBuildConfiguration(XCodeNode): + def __init__(self, name, settings = {}, env=None): + XCodeNode.__init__(self) + self.baseConfigurationReference = "" + self.buildSettings = settings + self.name = name + if env and env.ARCH: + settings['ARCHS'] = " ".join(env.ARCH) + + +class XCConfigurationList(XCodeNode): + def __init__(self, configlst): + """ :param configlst: list of XCConfigurationList """ + XCodeNode.__init__(self) + self.buildConfigurations = configlst + self.defaultConfigurationIsVisible = 0 + self.defaultConfigurationName = configlst and configlst[0].name or "" + +# Group/Files +class PBXFileReference(XCodeNode): + def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"): + + XCodeNode.__init__(self) + self.fileEncoding = 4 + if not filetype: + _, ext = os.path.splitext(name) + filetype = MAP_EXT.get(ext, 'text') + self.lastKnownFileType = filetype + self.explicitFileType = filetype + self.name = name + self.path = path + self.sourceTree = sourcetree + + def __hash__(self): + return (self.path+self.name).__hash__() + + def __eq__(self, other): + return (self.path, self.name) == (other.path, other.name) + +class PBXBuildFile(XCodeNode): + """ This element indicate a file reference that is used in a PBXBuildPhase (either as an include or resource). """ + def __init__(self, fileRef, settings={}): + XCodeNode.__init__(self) + + # fileRef is a reference to a PBXFileReference object + self.fileRef = fileRef + + # A map of key/value pairs for additional settings. + self.settings = settings + + def __hash__(self): + return (self.fileRef).__hash__() + + def __eq__(self, other): + return self.fileRef == other.fileRef + +class PBXGroup(XCodeNode): + def __init__(self, name, sourcetree = 'SOURCE_TREE'): + XCodeNode.__init__(self) + self.children = [] + self.name = name + self.sourceTree = sourcetree + + # Maintain a lookup table for all PBXFileReferences + # that are contained in this group. + self._filerefs = {} + + def add(self, sources): + """ + Add a list of PBXFileReferences to this group + + :param sources: list of PBXFileReferences objects + """ + self._filerefs.update(dict(zip(sources, sources))) + self.children.extend(sources) + + def get_sub_groups(self): + """ + Returns all child PBXGroup objects contained in this group + """ + return list(filter(lambda x: isinstance(x, PBXGroup), self.children)) + + def find_fileref(self, fileref): + """ + Recursively search this group for an existing PBXFileReference. Returns None + if none were found. + + The reason you'd want to reuse existing PBXFileReferences from a PBXGroup is that XCode doesn't like PBXFileReferences that aren't part of a PBXGroup hierarchy. + If it isn't, the consequence is that certain UI features like 'Reveal in Finder' + stops working. + """ + if fileref in self._filerefs: + return self._filerefs[fileref] + elif self.children: + for childgroup in self.get_sub_groups(): + f = childgroup.find_fileref(fileref) + if f: + return f + return None + +class PBXContainerItemProxy(XCodeNode): + """ This is the element for to decorate a target item. """ + def __init__(self, containerPortal, remoteGlobalIDString, remoteInfo='', proxyType=1): + XCodeNode.__init__(self) + self.containerPortal = containerPortal # PBXProject + self.remoteGlobalIDString = remoteGlobalIDString # PBXNativeTarget + self.remoteInfo = remoteInfo # Target name + self.proxyType = proxyType + +class PBXTargetDependency(XCodeNode): + """ This is the element for referencing other target through content proxies. """ + def __init__(self, native_target, proxy): + XCodeNode.__init__(self) + self.target = native_target + self.targetProxy = proxy + +class PBXFrameworksBuildPhase(XCodeNode): + """ This is the element for the framework link build phase, i.e. linking to frameworks """ + def __init__(self, pbxbuildfiles): + XCodeNode.__init__(self) + self.buildActionMask = 2147483647 + self.runOnlyForDeploymentPostprocessing = 0 + self.files = pbxbuildfiles #List of PBXBuildFile (.o, .framework, .dylib) + +class PBXHeadersBuildPhase(XCodeNode): + """ This is the element for adding header files to be packaged into the .framework """ + def __init__(self, pbxbuildfiles): + XCodeNode.__init__(self) + self.buildActionMask = 2147483647 + self.runOnlyForDeploymentPostprocessing = 0 + self.files = pbxbuildfiles #List of PBXBuildFile (.o, .framework, .dylib) + +class PBXCopyFilesBuildPhase(XCodeNode): + """ + Represents the PBXCopyFilesBuildPhase section. PBXBuildFile + can be added to this node to copy files after build is done. + """ + def __init__(self, pbxbuildfiles, dstpath, dstSubpathSpec=0, *args, **kwargs): + XCodeNode.__init__(self) + self.files = pbxbuildfiles + self.dstPath = dstpath + self.dstSubfolderSpec = dstSubpathSpec + +class PBXSourcesBuildPhase(XCodeNode): + """ Represents the 'Compile Sources' build phase in a Xcode target """ + def __init__(self, buildfiles): + XCodeNode.__init__(self) + self.files = buildfiles # List of PBXBuildFile objects + +class PBXLegacyTarget(XCodeNode): + def __init__(self, action, target=''): + XCodeNode.__init__(self) + self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) + if not target: + self.buildArgumentsString = "%s %s" % (sys.argv[0], action) + else: + self.buildArgumentsString = "%s %s --targets=%s" % (sys.argv[0], action, target) + self.buildPhases = [] + self.buildToolPath = sys.executable + self.buildWorkingDirectory = "" + self.dependencies = [] + self.name = target or action + self.productName = target or action + self.passBuildSettingsInEnvironment = 0 + +class PBXShellScriptBuildPhase(XCodeNode): + def __init__(self, action, target): + XCodeNode.__init__(self) + self.buildActionMask = 2147483647 + self.files = [] + self.inputPaths = [] + self.outputPaths = [] + self.runOnlyForDeploymentPostProcessing = 0 + self.shellPath = "/bin/sh" + self.shellScript = "%s %s %s --targets=%s" % (sys.executable, sys.argv[0], action, target) + +class PBXNativeTarget(XCodeNode): + """ Represents a target in XCode, e.g. App, DyLib, Framework etc. """ + def __init__(self, target, node, target_type=TARGET_TYPE_APPLICATION, configlist=[], buildphases=[]): + XCodeNode.__init__(self) + product_type = target_type[0] + file_type = target_type[1] + + self.buildConfigurationList = XCConfigurationList(configlist) + self.buildPhases = buildphases + self.buildRules = [] + self.dependencies = [] + self.name = target + self.productName = target + self.productType = product_type # See TARGET_TYPE_ tuples constants + self.productReference = PBXFileReference(node.name, node.abspath(), file_type, '') + + def add_configuration(self, cf): + """ :type cf: XCBuildConfiguration """ + self.buildConfigurationList.buildConfigurations.append(cf) + + def add_build_phase(self, phase): + # Some build phase types may appear only once. If a phase type already exists, then merge them. + if ( (phase.__class__ == PBXFrameworksBuildPhase) + or (phase.__class__ == PBXSourcesBuildPhase) ): + for b in self.buildPhases: + if b.__class__ == phase.__class__: + b.files.extend(phase.files) + return + self.buildPhases.append(phase) + + def add_dependency(self, depnd): + self.dependencies.append(depnd) + +# Root project object +class PBXProject(XCodeNode): + def __init__(self, name, version, env): + XCodeNode.__init__(self) + + if not isinstance(env.PROJ_CONFIGURATION, dict): + raise Errors.WafError("Error: env.PROJ_CONFIGURATION must be a dictionary. This is done for you if you do not define one yourself. However, did you load the xcode module at the end of your wscript configure() ?") + + # Retrieve project configuration + configurations = [] + for config_name, settings in env.PROJ_CONFIGURATION.items(): + cf = XCBuildConfiguration(config_name, settings) + configurations.append(cf) + + self.buildConfigurationList = XCConfigurationList(configurations) + self.compatibilityVersion = version[0] + self.hasScannedForEncodings = 1 + self.mainGroup = PBXGroup(name) + self.projectRoot = "" + self.projectDirPath = "" + self.targets = [] + self._objectVersion = version[1] + + def create_target_dependency(self, target, name): + """ : param target : PXBNativeTarget """ + proxy = PBXContainerItemProxy(self, target, name) + dependency = PBXTargetDependency(target, proxy) + return dependency + + def write(self, file): + + # Make sure this is written only once + if self._been_written: + return + + w = file.write + w("// !$*UTF8*$!\n") + w("{\n") + w("\tarchiveVersion = 1;\n") + w("\tclasses = {\n") + w("\t};\n") + w("\tobjectVersion = %d;\n" % self._objectVersion) + w("\tobjects = {\n\n") + + XCodeNode.write(self, file) + + w("\t};\n") + w("\trootObject = %s;\n" % self._id) + w("}\n") + + def add_target(self, target): + self.targets.append(target) + + def get_target(self, name): + """ Get a reference to PBXNativeTarget if it exists """ + for t in self.targets: + if t.name == name: + return t + return None + +@TaskGen.feature('c', 'cxx') +@TaskGen.after('propagate_uselib_vars', 'apply_incpaths') +def process_xcode(self): + bld = self.bld + try: + p = bld.project + except AttributeError: + return + + if not hasattr(self, 'target_type'): + return + + products_group = bld.products_group + + target_group = PBXGroup(self.name) + p.mainGroup.children.append(target_group) + + # Determine what type to build - framework, app bundle etc. + target_type = getattr(self, 'target_type', 'app') + if target_type not in TARGET_TYPES: + raise Errors.WafError("Target type '%s' does not exists. Available options are '%s'. In target '%s'" % (target_type, "', '".join(TARGET_TYPES.keys()), self.name)) + else: + target_type = TARGET_TYPES[target_type] + file_ext = target_type[2] + + # Create the output node + target_node = self.path.find_or_declare(self.name+file_ext) + target = PBXNativeTarget(self.name, target_node, target_type, [], []) + + products_group.children.append(target.productReference) + + # Pull source files from the 'source' attribute and assign them to a UI group. + # Use a default UI group named 'Source' unless the user + # provides a 'group_files' dictionary to customize the UI grouping. + sources = getattr(self, 'source', []) + if hasattr(self, 'group_files'): + group_files = getattr(self, 'group_files', []) + for grpname,files in group_files.items(): + group = bld.create_group(grpname, files) + target_group.children.append(group) + else: + group = bld.create_group('Source', sources) + target_group.children.append(group) + + # Create a PBXFileReference for each source file. + # If the source file already exists as a PBXFileReference in any of the UI groups, then + # reuse that PBXFileReference object (XCode does not like it if we don't reuse) + for idx, path in enumerate(sources): + fileref = PBXFileReference(path.name, path.abspath()) + existing_fileref = target_group.find_fileref(fileref) + if existing_fileref: + sources[idx] = existing_fileref + else: + sources[idx] = fileref + + # If the 'source' attribute contains any file extension that XCode can't work with, + # then remove it. The allowed file extensions are defined in XCODE_EXTS. + is_valid_file_extension = lambda file: os.path.splitext(file.path)[1] in XCODE_EXTS + sources = list(filter(is_valid_file_extension, sources)) + + buildfiles = [bld.unique_buildfile(PBXBuildFile(x)) for x in sources] + target.add_build_phase(PBXSourcesBuildPhase(buildfiles)) + + # Check if any framework to link against is some other target we've made + libs = getattr(self, 'tmp_use_seen', []) + for lib in libs: + use_target = p.get_target(lib) + if use_target: + # Create an XCode dependency so that XCode knows to build the other target before this target + dependency = p.create_target_dependency(use_target, use_target.name) + target.add_dependency(dependency) + + buildphase = PBXFrameworksBuildPhase([PBXBuildFile(use_target.productReference)]) + target.add_build_phase(buildphase) + if lib in self.env.LIB: + self.env.LIB = list(filter(lambda x: x != lib, self.env.LIB)) + + # If 'export_headers' is present, add files to the Headers build phase in xcode. + # These are files that'll get packed into the Framework for instance. + exp_hdrs = getattr(self, 'export_headers', []) + hdrs = bld.as_nodes(Utils.to_list(exp_hdrs)) + files = [p.mainGroup.find_fileref(PBXFileReference(n.name, n.abspath())) for n in hdrs] + files = [PBXBuildFile(f, {'ATTRIBUTES': ('Public',)}) for f in files] + buildphase = PBXHeadersBuildPhase(files) + target.add_build_phase(buildphase) + + # Merge frameworks and libs into one list, and prefix the frameworks + frameworks = Utils.to_list(self.env.FRAMEWORK) + frameworks = ' '.join(['-framework %s' % (f.split('.framework')[0]) for f in frameworks]) + + libs = Utils.to_list(self.env.STLIB) + Utils.to_list(self.env.LIB) + libs = ' '.join(bld.env['STLIB_ST'] % t for t in libs) + + # Override target specific build settings + bldsettings = { + 'HEADER_SEARCH_PATHS': ['$(inherited)'] + self.env['INCPATHS'], + 'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.LIBPATH) + Utils.to_list(self.env.STLIBPATH) + Utils.to_list(self.env.LIBDIR) , + 'FRAMEWORK_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.FRAMEWORKPATH), + 'OTHER_LDFLAGS': libs + ' ' + frameworks, + 'OTHER_LIBTOOLFLAGS': bld.env['LINKFLAGS'], + 'OTHER_CPLUSPLUSFLAGS': Utils.to_list(self.env['CXXFLAGS']), + 'OTHER_CFLAGS': Utils.to_list(self.env['CFLAGS']), + 'INSTALL_PATH': [] + } + + # Install path + installpaths = Utils.to_list(getattr(self, 'install', [])) + prodbuildfile = PBXBuildFile(target.productReference) + for instpath in installpaths: + bldsettings['INSTALL_PATH'].append(instpath) + target.add_build_phase(PBXCopyFilesBuildPhase([prodbuildfile], instpath)) + + if not bldsettings['INSTALL_PATH']: + del bldsettings['INSTALL_PATH'] + + # Create build settings which can override the project settings. Defaults to none if user + # did not pass argument. This will be filled up with target specific + # search paths, libs to link etc. + settings = getattr(self, 'settings', {}) + + # The keys represents different build configuration, e.g. Debug, Release and so on.. + # Insert our generated build settings to all configuration names + keys = set(settings.keys() + bld.env.PROJ_CONFIGURATION.keys()) + for k in keys: + if k in settings: + settings[k].update(bldsettings) + else: + settings[k] = bldsettings + + for k,v in settings.items(): + target.add_configuration(XCBuildConfiguration(k, v)) + + p.add_target(target) + + +class xcode(Build.BuildContext): + cmd = 'xcode6' + fun = 'build' + + def as_nodes(self, files): + """ Returns a list of waflib.Nodes from a list of string of file paths """ + nodes = [] + for x in files: + if not isinstance(x, str): + d = x + else: + d = self.srcnode.find_node(x) + if not d: + raise Errors.WafError('File \'%s\' was not found' % x) + nodes.append(d) + return nodes + + def create_group(self, name, files): + """ + Returns a new PBXGroup containing the files (paths) passed in the files arg + :type files: string + """ + group = PBXGroup(name) + """ + Do not use unique file reference here, since XCode seem to allow only one file reference + to be referenced by a group. + """ + files_ = [] + for d in self.as_nodes(Utils.to_list(files)): + fileref = PBXFileReference(d.name, d.abspath()) + files_.append(fileref) + group.add(files_) + return group + + def unique_buildfile(self, buildfile): + """ + Returns a unique buildfile, possibly an existing one. + Use this after you've constructed a PBXBuildFile to make sure there is + only one PBXBuildFile for the same file in the same project. + """ + try: + build_files = self.build_files + except AttributeError: + build_files = self.build_files = {} + + if buildfile not in build_files: + build_files[buildfile] = buildfile + return build_files[buildfile] + + def execute(self): + """ + Entry point + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + + appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) + + p = PBXProject(appname, ('Xcode 3.2', 46), self.env) + + # If we don't create a Products group, then + # XCode will create one, which entails that + # we'll start to see duplicate files in the UI + # for some reason. + products_group = PBXGroup('Products') + p.mainGroup.children.append(products_group) + + self.project = p + self.products_group = products_group + + # post all task generators + # the process_xcode method above will be called for each target + if self.targets and self.targets != '*': + (self._min_grp, self._exact_tg) = self.get_targets() + + self.current_group = 0 + while self.current_group < len(self.groups): + self.post_group() + self.current_group += 1 + + node = self.bldnode.make_node('%s.xcodeproj' % appname) + node.mkdir() + node = node.make_node('project.pbxproj') + with open(node.abspath(), 'w') as f: + p.write(f) + Logs.pprint('GREEN', 'Wrote %r' % node.abspath()) + +def bind_fun(tgtype): + def fun(self, *k, **kw): + tgtype = fun.__name__ + if tgtype == 'shlib' or tgtype == 'dylib': + features = 'cxx cxxshlib' + tgtype = 'dylib' + elif tgtype == 'framework': + features = 'cxx cxxshlib' + tgtype = 'framework' + elif tgtype == 'program': + features = 'cxx cxxprogram' + tgtype = 'exe' + elif tgtype == 'app': + features = 'cxx cxxprogram' + tgtype = 'app' + elif tgtype == 'stlib': + features = 'cxx cxxstlib' + tgtype = 'stlib' + lst = kw['features'] = Utils.to_list(kw.get('features', [])) + for x in features.split(): + if not x in kw['features']: + lst.append(x) + + kw['target_type'] = tgtype + return self(*k, **kw) + fun.__name__ = tgtype + setattr(Build.BuildContext, tgtype, fun) + return fun + +for xx in 'app framework dylib shlib stlib program'.split(): + bind_fun(xx) + diff --git a/ldb-2.0.8/third_party/waf/waflib/fixpy2.py b/ldb-2.0.8/third_party/waf/waflib/fixpy2.py new file mode 100644 index 0000000..24176e0 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/fixpy2.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2010-2018 (ita) + +from __future__ import with_statement + +import os + +all_modifs = {} + +def fixdir(dir): + """Call all substitution functions on Waf folders""" + for k in all_modifs: + for v in all_modifs[k]: + modif(os.path.join(dir, 'waflib'), k, v) + +def modif(dir, name, fun): + """Call a substitution function""" + if name == '*': + lst = [] + for y in '. Tools extras'.split(): + for x in os.listdir(os.path.join(dir, y)): + if x.endswith('.py'): + lst.append(y + os.sep + x) + for x in lst: + modif(dir, x, fun) + return + + filename = os.path.join(dir, name) + with open(filename, 'r') as f: + txt = f.read() + + txt = fun(txt) + + with open(filename, 'w') as f: + f.write(txt) + +def subst(*k): + """register a substitution function""" + def do_subst(fun): + for x in k: + try: + all_modifs[x].append(fun) + except KeyError: + all_modifs[x] = [fun] + return fun + return do_subst + +@subst('*') +def r1(code): + "utf-8 fixes for python < 2.6" + code = code.replace('as e:', ',e:') + code = code.replace(".decode(sys.stdout.encoding or'latin-1',errors='replace')", '') + return code.replace('.encode()', '') + +@subst('Runner.py') +def r4(code): + "generator syntax" + return code.replace('next(self.biter)', 'self.biter.next()') + +@subst('Context.py') +def r5(code): + return code.replace("('Execution failure: %s'%str(e),ex=e)", "('Execution failure: %s'%str(e),ex=e),None,sys.exc_info()[2]") + diff --git a/ldb-2.0.8/third_party/waf/waflib/processor.py b/ldb-2.0.8/third_party/waf/waflib/processor.py new file mode 100755 index 0000000..eff2e69 --- /dev/null +++ b/ldb-2.0.8/third_party/waf/waflib/processor.py @@ -0,0 +1,68 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2016-2018 (ita) + +import os, sys, traceback, base64, signal +try: + import cPickle +except ImportError: + import pickle as cPickle + +try: + import subprocess32 as subprocess +except ImportError: + import subprocess + +try: + TimeoutExpired = subprocess.TimeoutExpired +except AttributeError: + class TimeoutExpired(Exception): + pass + +def run(): + txt = sys.stdin.readline().strip() + if not txt: + # parent process probably ended + sys.exit(1) + [cmd, kwargs, cargs] = cPickle.loads(base64.b64decode(txt)) + cargs = cargs or {} + + if not 'close_fds' in kwargs: + # workers have no fds + kwargs['close_fds'] = False + + ret = 1 + out, err, ex, trace = (None, None, None, None) + try: + proc = subprocess.Popen(cmd, **kwargs) + try: + out, err = proc.communicate(**cargs) + except TimeoutExpired: + if kwargs.get('start_new_session') and hasattr(os, 'killpg'): + os.killpg(proc.pid, signal.SIGKILL) + else: + proc.kill() + out, err = proc.communicate() + exc = TimeoutExpired(proc.args, timeout=cargs['timeout'], output=out) + exc.stderr = err + raise exc + ret = proc.returncode + except Exception as e: + exc_type, exc_value, tb = sys.exc_info() + exc_lines = traceback.format_exception(exc_type, exc_value, tb) + trace = str(cmd) + '\n' + ''.join(exc_lines) + ex = e.__class__.__name__ + + # it is just text so maybe we do not need to pickle() + tmp = [ret, out, err, ex, trace] + obj = base64.b64encode(cPickle.dumps(tmp)) + sys.stdout.write(obj.decode()) + sys.stdout.write('\n') + sys.stdout.flush() + +while 1: + try: + run() + except KeyboardInterrupt: + break + diff --git a/ldb-2.0.8/tools/cmdline.c b/ldb-2.0.8/tools/cmdline.c new file mode 100644 index 0000000..a2fe97e --- /dev/null +++ b/ldb-2.0.8/tools/cmdline.c @@ -0,0 +1,521 @@ +/* + ldb database library - command line handling for ldb tools + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb.h" +#include "ldb_module.h" +#include "tools/cmdline.h" + +static struct ldb_cmdline options; /* needs to be static for older compilers */ + +enum ldb_cmdline_options { CMDLINE_RELAX=1 }; + +static struct poptOption builtin_popt_options[] = { + POPT_AUTOHELP + { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" }, + { "basedn", 'b', POPT_ARG_STRING, &options.basedn, 0, "base DN", "DN" }, + { "editor", 'e', POPT_ARG_STRING, &options.editor, 0, "external editor", "PROGRAM" }, + { "scope", 's', POPT_ARG_STRING, NULL, 's', "search scope", "SCOPE" }, + { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "increase verbosity", NULL }, + { "trace", 0, POPT_ARG_NONE, &options.tracing, 0, "enable tracing", NULL }, + { "interactive", 'i', POPT_ARG_NONE, &options.interactive, 0, "input from stdin", NULL }, + { "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL }, + { "modules-path", 0, POPT_ARG_STRING, &options.modules_path, 0, "modules path", "PATH" }, + { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL }, + { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL }, + { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "(|(objectClass=*)(distinguishedName=*))", NULL }, + { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL }, + { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, + { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" }, + { "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL }, + { "show-binary", 0, POPT_ARG_NONE, &options.show_binary, 0, "display binary LDIF", NULL }, + { "paged", 0, POPT_ARG_NONE, NULL, 'P', "use a paged search", NULL }, + { "show-deleted", 0, POPT_ARG_NONE, NULL, 'D', "show deleted objects", NULL }, + { "show-recycled", 0, POPT_ARG_NONE, NULL, 'R', "show recycled objects", NULL }, + { "show-deactivated-link", 0, POPT_ARG_NONE, NULL, 'd', "show deactivated links", NULL }, + { "reveal", 0, POPT_ARG_NONE, NULL, 'r', "reveal ldb internals", NULL }, + { "relax", 0, POPT_ARG_NONE, NULL, CMDLINE_RELAX, "pass relax control", NULL }, + { "cross-ncs", 0, POPT_ARG_NONE, NULL, 'N', "search across NC boundaries", NULL }, + { "extended-dn", 0, POPT_ARG_NONE, NULL, 'E', "show extended DNs", NULL }, + { NULL } +}; + +void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f) +{ + poptContext pc; + struct poptOption **popt_options = ldb_module_popt_options(ldb); + pc = poptGetContext(cmdname, 0, NULL, *popt_options, + POPT_CONTEXT_KEEP_FIRST); + poptPrintHelp(pc, f, 0); +} + +/* + add a control to the options structure + */ +static bool add_control(TALLOC_CTX *mem_ctx, const char *control) +{ + unsigned int i; + + /* count how many controls we already have */ + for (i=0; options.controls && options.controls[i]; i++) ; + + options.controls = talloc_realloc(mem_ctx, options.controls, const char *, i + 2); + if (options.controls == NULL) { + return false; + } + options.controls[i] = control; + options.controls[i+1] = NULL; + return true; +} + +/** + process command line options +*/ +static struct ldb_cmdline *ldb_cmdline_process_internal(struct ldb_context *ldb, + int argc, const char **argv, + void (*usage)(struct ldb_context *), + bool search) +{ + struct ldb_cmdline *ret=NULL; + poptContext pc; + int num_options = 0; + int opt; + unsigned int flags = 0; + int rc; + struct poptOption **popt_options; + + /* make the ldb utilities line buffered */ + setlinebuf(stdout); + + ret = talloc_zero(ldb, struct ldb_cmdline); + if (ret == NULL) { + fprintf(stderr, "Out of memory!\n"); + goto failed; + } + + options = *ret; + + /* pull in URL */ + options.url = getenv("LDB_URL"); + + /* and editor (used by ldbedit) */ + options.editor = getenv("VISUAL"); + if (!options.editor) { + options.editor = getenv("EDITOR"); + } + if (!options.editor) { + options.editor = "vi"; + } + + options.scope = LDB_SCOPE_DEFAULT; + + popt_options = ldb_module_popt_options(ldb); + (*popt_options) = builtin_popt_options; + + rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_OPTIONS); + if (rc != LDB_SUCCESS) { + fprintf(stderr, "ldb: failed to run command line hooks : %s\n", ldb_strerror(rc)); + goto failed; + } + + pc = poptGetContext(argv[0], argc, argv, *popt_options, + POPT_CONTEXT_KEEP_FIRST); + + while((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case 's': { + const char *arg = poptGetOptArg(pc); + if (strcmp(arg, "base") == 0) { + options.scope = LDB_SCOPE_BASE; + } else if (strcmp(arg, "sub") == 0) { + options.scope = LDB_SCOPE_SUBTREE; + } else if (strcmp(arg, "one") == 0) { + options.scope = LDB_SCOPE_ONELEVEL; + } else { + fprintf(stderr, "Invalid scope '%s'\n", arg); + goto failed; + } + break; + } + + case 'v': + options.verbose++; + break; + + case 'o': + options.options = talloc_realloc(ret, options.options, + const char *, num_options+3); + if (options.options == NULL) { + fprintf(stderr, "Out of memory!\n"); + goto failed; + } + options.options[num_options] = poptGetOptArg(pc); + options.options[num_options+1] = NULL; + num_options++; + break; + + case 'c': { + const char *cs = poptGetOptArg(pc); + const char *p; + + for (p = cs; p != NULL; ) { + const char *t, *c; + + t = strchr(p, ','); + if (t == NULL) { + c = talloc_strdup(options.controls, p); + p = NULL; + } else { + c = talloc_strndup(options.controls, p, t-p); + p = t + 1; + } + if (c == NULL || !add_control(ret, c)) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + } + + break; + } + case 'P': + if (!add_control(ret, "paged_results:1:1024")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + case 'D': + if (!add_control(ret, "show_deleted:1")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + case 'R': + if (!add_control(ret, "show_recycled:0")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + case 'd': + if (!add_control(ret, "show_deactivated_link:0")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + case 'r': + if (!add_control(ret, "reveal_internals:0")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + case CMDLINE_RELAX: + if (!add_control(ret, "relax:0")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + case 'N': + if (!add_control(ret, "search_options:1:2")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + case 'E': + if (!add_control(ret, "extended_dn:1:1")) { + fprintf(stderr, __location__ ": out of memory\n"); + goto failed; + } + break; + default: + fprintf(stderr, "Invalid option %s: %s\n", + poptBadOption(pc, 0), poptStrerror(opt)); + if (usage) usage(ldb); + goto failed; + } + } + + /* setup the remaining options for the main program to use */ + options.argv = poptGetArgs(pc); + if (options.argv) { + options.argv++; + while (options.argv[options.argc]) options.argc++; + } + + *ret = options; + + /* all utils need some option */ + if (ret->url == NULL) { + fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); + if (usage) usage(ldb); + goto failed; + } + + if (strcmp(ret->url, "NONE") == 0) { + return ret; + } + + if (options.nosync) { + flags |= LDB_FLG_NOSYNC; + } + + if (search) { + flags |= LDB_FLG_DONT_CREATE_DB; + + if (options.show_binary) { + flags |= LDB_FLG_SHOW_BINARY; + } + } + + if (options.tracing) { + flags |= LDB_FLG_ENABLE_TRACING; + } + + if (options.modules_path != NULL) { + ldb_set_modules_dir(ldb, options.modules_path); + } + + rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT); + if (rc != LDB_SUCCESS) { + fprintf(stderr, "ldb: failed to run preconnect hooks : %s\n", ldb_strerror(rc)); + goto failed; + } + + /* now connect to the ldb */ + if (ldb_connect(ldb, ret->url, flags, ret->options) != LDB_SUCCESS) { + fprintf(stderr, "Failed to connect to %s - %s\n", + ret->url, ldb_errstring(ldb)); + goto failed; + } + + rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_POSTCONNECT); + if (rc != LDB_SUCCESS) { + fprintf(stderr, "ldb: failed to run post connect hooks : %s\n", ldb_strerror(rc)); + goto failed; + } + + return ret; + +failed: + talloc_free(ret); + exit(LDB_ERR_OPERATIONS_ERROR); + return NULL; +} + +struct ldb_cmdline *ldb_cmdline_process_search(struct ldb_context *ldb, + int argc, const char **argv, + void (*usage)(struct ldb_context *)) +{ + return ldb_cmdline_process_internal(ldb, argc, argv, usage, true); +} + +struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, + int argc, const char **argv, + void (*usage)(struct ldb_context *)) +{ + return ldb_cmdline_process_internal(ldb, argc, argv, usage, false); +} + +/* this function check controls reply and determines if more + * processing is needed setting up the request controls correctly + * + * returns: + * -1 error + * 0 all ok + * 1 all ok, more processing required + */ +int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request) +{ + unsigned int i, j; + int ret = 0; + + if (reply == NULL || request == NULL) return -1; + + for (i = 0; reply[i]; i++) { + if (strcmp(LDB_CONTROL_VLV_RESP_OID, reply[i]->oid) == 0) { + struct ldb_vlv_resp_control *rep_control; + + rep_control = talloc_get_type(reply[i]->data, struct ldb_vlv_resp_control); + + /* check we have a matching control in the request */ + for (j = 0; request[j]; j++) { + if (strcmp(LDB_CONTROL_VLV_REQ_OID, request[j]->oid) == 0) + break; + } + if (! request[j]) { + fprintf(stderr, "Warning VLV reply received but no request have been made\n"); + continue; + } + + /* check the result */ + if (rep_control->vlv_result != 0) { + fprintf(stderr, "Warning: VLV not performed with error: %d\n", rep_control->vlv_result); + } else { + fprintf(stderr, "VLV Info: target position = %d, content count = %d\n", rep_control->targetPosition, rep_control->contentCount); + } + + continue; + } + + if (strcmp(LDB_CONTROL_ASQ_OID, reply[i]->oid) == 0) { + struct ldb_asq_control *rep_control; + + rep_control = talloc_get_type(reply[i]->data, struct ldb_asq_control); + + /* check the result */ + if (rep_control->result != 0) { + fprintf(stderr, "Warning: ASQ not performed with error: %d\n", rep_control->result); + } + + continue; + } + + if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, reply[i]->oid) == 0) { + struct ldb_paged_control *rep_control, *req_control; + + rep_control = talloc_get_type(reply[i]->data, struct ldb_paged_control); + if (rep_control->cookie_len == 0) /* we are done */ + break; + + /* more processing required */ + /* let's fill in the request control with the new cookie */ + + for (j = 0; request[j]; j++) { + if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, request[j]->oid) == 0) + break; + } + /* if there's a reply control we must find a request + * control matching it */ + if (! request[j]) return -1; + + req_control = talloc_get_type(request[j]->data, struct ldb_paged_control); + + if (req_control->cookie) + talloc_free(req_control->cookie); + req_control->cookie = (char *)talloc_memdup( + req_control, rep_control->cookie, + rep_control->cookie_len); + req_control->cookie_len = rep_control->cookie_len; + + ret = 1; + + continue; + } + + if (strcmp(LDB_CONTROL_SORT_RESP_OID, reply[i]->oid) == 0) { + struct ldb_sort_resp_control *rep_control; + + rep_control = talloc_get_type(reply[i]->data, struct ldb_sort_resp_control); + + /* check we have a matching control in the request */ + for (j = 0; request[j]; j++) { + if (strcmp(LDB_CONTROL_SERVER_SORT_OID, request[j]->oid) == 0) + break; + } + if (! request[j]) { + fprintf(stderr, "Warning Server Sort reply received but no request found\n"); + continue; + } + + /* check the result */ + if (rep_control->result != 0) { + fprintf(stderr, "Warning: Sorting not performed with error: %d\n", rep_control->result); + } + + continue; + } + + if (strcmp(LDB_CONTROL_DIRSYNC_OID, reply[i]->oid) == 0) { + struct ldb_dirsync_control *rep_control, *req_control; + char *cookie; + + rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control); + if (rep_control->cookie_len == 0) /* we are done */ + break; + + /* more processing required */ + /* let's fill in the request control with the new cookie */ + + for (j = 0; request[j]; j++) { + if (strcmp(LDB_CONTROL_DIRSYNC_OID, request[j]->oid) == 0) + break; + } + /* if there's a reply control we must find a request + * control matching it */ + if (! request[j]) return -1; + + req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control); + + if (req_control->cookie) + talloc_free(req_control->cookie); + req_control->cookie = (char *)talloc_memdup( + req_control, rep_control->cookie, + rep_control->cookie_len); + req_control->cookie_len = rep_control->cookie_len; + + cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len); + printf("# DIRSYNC cookie returned was:\n# %s\n", cookie); + + continue; + } + if (strcmp(LDB_CONTROL_DIRSYNC_EX_OID, reply[i]->oid) == 0) { + struct ldb_dirsync_control *rep_control, *req_control; + char *cookie; + + rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control); + if (rep_control->cookie_len == 0) /* we are done */ + break; + + /* more processing required */ + /* let's fill in the request control with the new cookie */ + + for (j = 0; request[j]; j++) { + if (strcmp(LDB_CONTROL_DIRSYNC_EX_OID, request[j]->oid) == 0) + break; + } + /* if there's a reply control we must find a request + * control matching it */ + if (! request[j]) return -1; + + req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control); + + if (req_control->cookie) + talloc_free(req_control->cookie); + req_control->cookie = (char *)talloc_memdup( + req_control, rep_control->cookie, + rep_control->cookie_len); + req_control->cookie_len = rep_control->cookie_len; + + cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len); + printf("# DIRSYNC_EX cookie returned was:\n# %s\n", cookie); + + continue; + } + + /* no controls matched, throw a warning */ + fprintf(stderr, "Unknown reply control oid: %s\n", reply[i]->oid); + } + + return ret; +} + diff --git a/ldb-2.0.8/tools/cmdline.h b/ldb-2.0.8/tools/cmdline.h new file mode 100644 index 0000000..9af0ea1 --- /dev/null +++ b/ldb-2.0.8/tools/cmdline.h @@ -0,0 +1,59 @@ +/* + ldb database library - command line handling for ldb tools + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +#include + +struct ldb_cmdline { + const char *url; + enum ldb_scope scope; + const char *basedn; + const char *modules_path; + int interactive; + int sorted; + const char *editor; + int verbose; + int recursive; + int all_records; + int nosync; + const char **options; + int argc; + const char **argv; + int num_records; + int num_searches; + const char *sasl_mechanism; + const char **controls; + int show_binary; + int tracing; +}; + +struct ldb_cmdline *ldb_cmdline_process_search(struct ldb_context *ldb, + int argc, const char **argv, + void (*usage)(struct ldb_context *)); +struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, + const char **argv, + void (*usage)(struct ldb_context *)); + + +int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request); +void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f); + diff --git a/ldb-2.0.8/tools/ldbadd.c b/ldb-2.0.8/tools/ldbadd.c new file mode 100644 index 0000000..e6cea29 --- /dev/null +++ b/ldb-2.0.8/tools/ldbadd.c @@ -0,0 +1,186 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldbadd + * + * Description: utility to add records - modelled on ldapadd + * + * Author: Andrew Tridgell + */ + +#include "replace.h" +#include "ldb.h" +#include "tools/cmdline.h" +#include "ldbutil.h" +#include "include/ldb_private.h" + +static struct ldb_cmdline *options; + +static void usage(struct ldb_context *ldb) +{ + printf("Usage: ldbadd \n"); + printf("Adds records to a ldb, reading ldif the specified list of files\n\n"); + ldb_cmdline_help(ldb, "ldbadd", stdout); + exit(LDB_ERR_OPERATIONS_ERROR); +} + + +/* + add records from an opened file +*/ +static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) +{ + struct ldb_ldif *ldif; + int fun_ret = LDB_SUCCESS, ret; + struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); + struct ldif_read_file_state state = { + .f = f + }; + + if (options->controls != NULL && req_ctrls== NULL) { + printf("parsing controls failed: %s\n", ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + fun_ret = ldb_transaction_start(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction start\n", + ldb_errstring(ldb)); + return fun_ret; + } + + while ((ldif = ldb_ldif_read_file_state(ldb, &state))) { + if (ldif->changetype != LDB_CHANGETYPE_ADD && + ldif->changetype != LDB_CHANGETYPE_NONE) { + fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); + break; + } + + ret = ldb_msg_normalize(ldb, ldif, ldif->msg, &ldif->msg); + if (ret != LDB_SUCCESS) { + fprintf(stderr, + "ERR: Message canonicalize failed - %s\n", + ldb_strerror(ret)); + fun_ret = ret; + ldb_ldif_read_free(ldb, ldif); + continue; + } + + ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls); + if (ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: %s : \"%s\" on DN %s at block before line %llu\n", + ldb_strerror(ret), ldb_errstring(ldb), + ldb_dn_get_linearized(ldif->msg->dn), + (unsigned long long)state.line_no); + fun_ret = ret; + } else { + (*count)++; + if (options->verbose) { + printf("Added %s\n", ldb_dn_get_linearized(ldif->msg->dn)); + } + } + ldb_ldif_read_free(ldb, ldif); + if (ret) { + break; + } + } + + if (fun_ret == LDB_SUCCESS && !feof(f)) { + fprintf(stderr, "Failed to parse ldif\n"); + fun_ret = LDB_ERR_OPERATIONS_ERROR; + } + + if (fun_ret == LDB_SUCCESS) { + fun_ret = ldb_transaction_commit(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction commit\n", + ldb_errstring(ldb)); + } + } else { + ldb_transaction_cancel(ldb); + } + + return fun_ret; +} + + + +int main(int argc, const char **argv) +{ + struct ldb_context *ldb; + unsigned int i, count = 0; + int ret = LDB_SUCCESS; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + ldb = ldb_init(mem_ctx, NULL); + if (ldb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + options = ldb_cmdline_process(ldb, argc, argv, usage); + + ret = ldb_transaction_start(ldb); + if (ret != LDB_SUCCESS) { + printf("Failed to start transaction: %s\n", ldb_errstring(ldb)); + return ret; + } + + if (options->argc == 0) { + ret = process_file(ldb, stdin, &count); + } else { + for (i=0;iargc;i++) { + const char *fname = options->argv[i]; + FILE *f; + f = fopen(fname, "r"); + if (!f) { + perror(fname); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = process_file(ldb, f, &count); + fclose(f); + } + } + + if (count != 0) { + ret = ldb_transaction_commit(ldb); + if (ret != LDB_SUCCESS) { + printf("Failed to commit transaction: %s\n", ldb_errstring(ldb)); + return ret; + } + } else { + ldb_transaction_cancel(ldb); + } + + talloc_free(mem_ctx); + + if (ret) { + printf("Add failed after processing %u records\n", count); + } else { + printf("Added %u records successfully\n", count); + } + + return ret; +} diff --git a/ldb-2.0.8/tools/ldbdel.c b/ldb-2.0.8/tools/ldbdel.c new file mode 100644 index 0000000..8036d09 --- /dev/null +++ b/ldb-2.0.8/tools/ldbdel.c @@ -0,0 +1,135 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldbdel + * + * Description: utility to delete records - modelled on ldapdelete + * + * Author: Andrew Tridgell + */ + +#include "replace.h" +#include "ldb.h" +#include "tools/cmdline.h" +#include "ldbutil.h" + +static int dn_cmp(struct ldb_message **msg1, struct ldb_message **msg2) +{ + return ldb_dn_compare((*msg1)->dn, (*msg2)->dn); +} + +static int ldb_delete_recursive(struct ldb_context *ldb, struct ldb_dn *dn,struct ldb_control **req_ctrls) +{ + int ret; + unsigned int i, total=0; + const char *attrs[] = { NULL }; + struct ldb_result *res; + + ret = ldb_search(ldb, ldb, &res, dn, LDB_SCOPE_SUBTREE, attrs, "distinguishedName=*"); + if (ret != LDB_SUCCESS) return ret; + + /* sort the DNs, deepest first */ + TYPESAFE_QSORT(res->msgs, res->count, dn_cmp); + + for (i = 0; i < res->count; i++) { + if (ldb_delete_ctrl(ldb, res->msgs[i]->dn,req_ctrls) == LDB_SUCCESS) { + total++; + } else { + printf("Failed to delete '%s' - %s\n", + ldb_dn_get_linearized(res->msgs[i]->dn), + ldb_errstring(ldb)); + } + } + + talloc_free(res); + + if (total == 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + printf("Deleted %u records\n", total); + return LDB_SUCCESS; +} + +static void usage(struct ldb_context *ldb) +{ + printf("Usage: ldbdel \n"); + printf("Deletes records from a ldb\n\n"); + ldb_cmdline_help(ldb, "ldbdel", stdout); + exit(LDB_ERR_OPERATIONS_ERROR); +} + +int main(int argc, const char **argv) +{ + struct ldb_control **req_ctrls; + struct ldb_cmdline *options; + struct ldb_context *ldb; + int ret = 0, i; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + ldb = ldb_init(mem_ctx, NULL); + if (ldb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + options = ldb_cmdline_process(ldb, argc, argv, usage); + + if (options->argc < 1) { + usage(ldb); + } + + req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); + if (options->controls != NULL && req_ctrls== NULL) { + printf("parsing controls failed: %s\n", ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + for (i=0;iargc;i++) { + struct ldb_dn *dn; + + dn = ldb_dn_new(ldb, ldb, options->argv[i]); + if (dn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + if (options->recursive) { + ret = ldb_delete_recursive(ldb, dn,req_ctrls); + } else { + ret = ldb_delete_ctrl(ldb, dn,req_ctrls); + if (ret == LDB_SUCCESS) { + printf("Deleted 1 record\n"); + } + } + if (ret != LDB_SUCCESS) { + printf("delete of '%s' failed - (%s) %s\n", + ldb_dn_get_linearized(dn), + ldb_strerror(ret), + ldb_errstring(ldb)); + } + } + + talloc_free(mem_ctx); + + return ret; +} diff --git a/ldb-2.0.8/tools/ldbdump.c b/ldb-2.0.8/tools/ldbdump.c new file mode 100644 index 0000000..5cdb7d8 --- /dev/null +++ b/ldb-2.0.8/tools/ldbdump.c @@ -0,0 +1,383 @@ +/* + Unix SMB/CIFS implementation. + simple ldb tdb dump util + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2012 + + 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 . +*/ + +#include "replace.h" +#include "system/locale.h" +#include "system/time.h" +#include "system/filesys.h" +#include "system/wait.h" +#include +#include +#include + +#ifdef HAVE_LMDB +#include +#endif /* ifdef HAVE_LMDB */ + + +static struct ldb_context *ldb; +bool show_index = false; +bool validate_contents = false; + +static void print_data(TDB_DATA d) +{ + unsigned char *p = (unsigned char *)d.dptr; + int len = d.dsize; + while (len--) { + if (isprint(*p) && !strchr("\"\\", *p)) { + fputc(*p, stdout); + } else { + printf("\\%02X", *p); + } + p++; + } +} + +static unsigned int pull_uint32(uint8_t *p) +{ + return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); +} + + +static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA _dbuf, void *state) +{ + int ret, i, j; + struct ldb_dn *dn = state; + struct ldb_message *msg = ldb_msg_new(NULL); + struct ldb_val dbuf = { + .data = _dbuf.dptr, + .length = _dbuf.dsize, + }; + struct ldb_ldif ldif = { + .msg = msg, + .changetype = LDB_CHANGETYPE_NONE + }; + if (!msg) { + return -1; + } + + ret = ldb_unpack_data(ldb, &dbuf, msg); + if (ret != 0) { + fprintf(stderr, "Failed to parse record %*.*s as an LDB record\n", (int)key.dsize, (int)key.dsize, (char *)key.dptr); + TALLOC_FREE(msg); + return 0; + } + + if (dn && ldb_dn_compare(msg->dn, dn) != 0) { + TALLOC_FREE(msg); + return 0; + } + + if (!show_index && ldb_dn_is_special(msg->dn)) { + const char *dn_lin = ldb_dn_get_linearized(msg->dn); + if ((strcmp(dn_lin, "@BASEINFO") == 0) || (strncmp(dn_lin, "@INDEX:", strlen("@INDEX:")) == 0)) { + /* + the user has asked not to show index + records. Also exclude BASEINFO as it + contains meta-data which will be re-created + if this database is restored + */ + TALLOC_FREE(msg); + return 0; + } + } + + printf("# key: "); + print_data(key); + printf("\n# pack format: %#010x\n", pull_uint32(_dbuf.dptr)); + + if (!validate_contents || ldb_dn_is_special(msg->dn)) { + ldb_ldif_write_file(ldb, stdout, &ldif); + TALLOC_FREE(msg); + return 0; + } + + for (i=0;inum_elements;i++) { + const struct ldb_schema_attribute *a; + + a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name); + for (j=0;jelements[i].num_values;j++) { + struct ldb_val v; + ret = a->syntax->ldif_write_fn(ldb, msg, &msg->elements[i].values[j], &v); + if (ret != 0) { + v = msg->elements[i].values[j]; + if (ldb_should_b64_encode(ldb, &v)) { + v.data = (uint8_t *)ldb_base64_encode(ldb, (char *)v.data, v.length); + v.length = strlen((char *)v.data); + } + fprintf(stderr, "On %s element %s value %d (%*.*s) failed to convert to LDIF correctly, skipping possibly corrupt record\n", + ldb_dn_get_linearized(msg->dn), + msg->elements[i].name, + j, (int)v.length, (int)v.length, + v.data); + TALLOC_FREE(msg); + return 0; + } + } + } + ldb_ldif_write_file(ldb, stdout, &ldif); + TALLOC_FREE(msg); + + return 0; +} + +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; + const char *name = tdb_name(tdb); + const char *prefix = ""; + + if (!name) + name = "unnamed"; + + switch (level) { + case TDB_DEBUG_ERROR: + prefix = "ERROR: "; + break; + case TDB_DEBUG_WARNING: + prefix = "WARNING: "; + break; + case TDB_DEBUG_TRACE: + return; + + default: + case TDB_DEBUG_FATAL: + prefix = "FATAL: "; + break; + } + + va_start(ap, fmt); + fprintf(stderr, "tdb(%s): %s", name, prefix); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static void emergency_walk(TDB_DATA key, TDB_DATA dbuf, void *keyname) +{ + traverse_fn(NULL, key, dbuf, keyname); +} + +static int dump_tdb(const char *fname, struct ldb_dn *dn, bool emergency) +{ + TDB_CONTEXT *tdb; + struct tdb_logging_context logfn = { + .log_fn = log_stderr, + }; + + tdb = tdb_open_ex(fname, 0, 0, O_RDONLY, 0, &logfn, NULL); + if (!tdb) { + fprintf(stderr, "Failed to open %s\n", fname); + return 1; + } + + if (emergency) { + return tdb_rescue(tdb, emergency_walk, dn) == 0; + } + return tdb_traverse(tdb, traverse_fn, dn) == -1 ? 1 : 0; +} + +#ifdef HAVE_LMDB +static int dump_lmdb(const char *fname, struct ldb_dn *dn, bool emergency) +{ + int ret; + struct MDB_env *env = NULL; + struct MDB_txn *txn = NULL; + MDB_dbi dbi; + struct MDB_cursor *cursor = NULL; + struct MDB_val key; + struct MDB_val data; + + ret = mdb_env_create(&env); + if (ret != 0) { + fprintf(stderr, + "Could not create MDB environment: (%d) %s\n", + ret, + mdb_strerror(ret)); + goto close_env; + } + + ret = mdb_env_open(env, + fname, + MDB_NOSUBDIR|MDB_NOTLS|MDB_RDONLY, + 0600); + if (ret != 0) { + fprintf(stderr, + "Could not open environment for %s: (%d) %s\n", + fname, + ret, + mdb_strerror(ret)); + goto close_env; + } + + ret = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); + if (ret != 0) { + fprintf(stderr, + "Could not start transaction: (%d) %s\n", + ret, + mdb_strerror(ret)); + goto close_env; + } + + ret = mdb_dbi_open(txn, NULL, 0, &dbi); + if (ret != 0) { + fprintf(stderr, + "Could not open database: (%d) %s\n", + ret, + mdb_strerror(ret)); + goto close_txn; + } + + ret = mdb_cursor_open(txn, dbi, &cursor); + if (ret != 0) { + fprintf(stderr, + "Could not open cursor: (%d) %s\n", + ret, + mdb_strerror(ret)); + goto close_txn; + } + + ret = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); + if (ret != 0 && ret != MDB_NOTFOUND) { + fprintf(stderr, + "Could not find first record: (%d) %s\n", + ret, + mdb_strerror(ret)); + goto close_cursor; + } + while (ret != MDB_NOTFOUND) { + struct TDB_DATA tkey = { + .dptr = key.mv_data, + .dsize = key.mv_size + }; + struct TDB_DATA tdata = { + .dptr = data.mv_data, + .dsize = data.mv_size + }; + traverse_fn(NULL, tkey, tdata, dn); + ret = mdb_cursor_get(cursor, &key, &data, MDB_NEXT); + if (ret != 0 && ret != MDB_NOTFOUND) { + fprintf(stderr, + "Could not read next record: (%d) %s\n", + ret, + mdb_strerror(ret)); + goto close_cursor; + } + } + ret = 0; + +close_cursor: + mdb_cursor_close(cursor); +close_txn: + mdb_txn_commit(txn); +close_env: + mdb_env_close(env); + + if (ret != 0) { + return 1; + } + return 0; + +} +#else +static int dump_lmdb(const char *fname, struct ldb_dn *dn, bool emergency) +{ + /* not built with lmdb support */ + return 1; +} +#endif /* #ifdef HAVE_LMDB */ + +static void usage( void) +{ + printf( "Usage: ldbdump [options] \n\n"); + printf( " -h this help message\n"); + printf( " -d DN dumps DN only\n"); + printf( " -e emergency dump, for corrupt databases\n"); + printf( " -i include index and @BASEINFO records in dump\n"); + printf( " -c validate contents of the records\n"); +} + + int main(int argc, char *argv[]) +{ + bool emergency = false; + int c, rc; + char *fname; + struct ldb_dn *dn = NULL; + + ldb = ldb_init(NULL, NULL); + if (ldb == NULL) { + fprintf(stderr, "ldb: ldb_init failed()"); + exit(1); + } + + rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT); + if (rc != LDB_SUCCESS) { + fprintf(stderr, "ldb: failed to run preconnect hooks (needed to get Samba LDIF handlers): %s\n", ldb_strerror(rc)); + exit(1); + } + + if (argc < 2) { + printf("Usage: ldbdump \n"); + exit(1); + } + + while ((c = getopt( argc, argv, "hd:eic")) != -1) { + switch (c) { + case 'h': + usage(); + exit( 0); + case 'd': + dn = ldb_dn_new(ldb, ldb, optarg); + if (!dn) { + fprintf(stderr, "ldb failed to parse %s as a DN\n", optarg); + exit(1); + } + break; + case 'e': + emergency = true; + break; + case 'i': + show_index = true; + break; + case 'c': + validate_contents = true; + break; + default: + usage(); + exit( 1); + } + } + + fname = argv[optind]; + + rc = dump_lmdb(fname, dn, emergency); + if (rc != 0) { + rc = dump_tdb(fname, dn, emergency); + if (rc != 0) { + fprintf(stderr, "Failed to open %s\n", fname); + return 1; + } + } + return 0; + +} diff --git a/ldb-2.0.8/tools/ldbedit.c b/ldb-2.0.8/tools/ldbedit.c new file mode 100644 index 0000000..5b83783 --- /dev/null +++ b/ldb-2.0.8/tools/ldbedit.c @@ -0,0 +1,383 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldbedit + * + * Description: utility for ldb database editing + * + * Author: Andrew Tridgell + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "system/filesys.h" +#include "ldb.h" +#include "tools/cmdline.h" +#include "tools/ldbutil.h" + +static struct ldb_cmdline *options; + +/* + debug routine +*/ +static void ldif_write_msg(struct ldb_context *ldb, + FILE *f, + enum ldb_changetype changetype, + struct ldb_message *msg) +{ + struct ldb_ldif ldif; + ldif.changetype = changetype; + ldif.msg = msg; + ldb_ldif_write_file(ldb, f, &ldif); +} + +/* + modify a database record so msg1 becomes msg2 + returns the number of modified elements +*/ +static int modify_record(struct ldb_context *ldb, + struct ldb_message *msg1, + struct ldb_message *msg2, + struct ldb_control **req_ctrls) +{ + int ret; + struct ldb_message *mod; + + if (ldb_msg_difference(ldb, ldb, msg1, msg2, &mod) != LDB_SUCCESS) { + fprintf(stderr, "Failed to calculate message differences\n"); + return -1; + } + + ret = mod->num_elements; + if (ret == 0) { + goto done; + } + + if (options->verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod); + } + + if (ldb_modify_ctrl(ldb, mod, req_ctrls) != LDB_SUCCESS) { + fprintf(stderr, "failed to modify %s - %s\n", + ldb_dn_get_linearized(msg1->dn), ldb_errstring(ldb)); + ret = -1; + goto done; + } + +done: + talloc_free(mod); + return ret; +} + +/* + find dn in msgs[] +*/ +static struct ldb_message *msg_find(struct ldb_context *ldb, + struct ldb_message **msgs, + unsigned int count, + struct ldb_dn *dn) +{ + unsigned int i; + for (i=0;idn) == 0) { + return msgs[i]; + } + } + return NULL; +} + +/* + merge the changes in msgs2 into the messages from msgs1 +*/ +static int merge_edits(struct ldb_context *ldb, + struct ldb_message **msgs1, unsigned int count1, + struct ldb_message **msgs2, unsigned int count2) +{ + unsigned int i; + struct ldb_message *msg; + int ret; + unsigned int adds=0, modifies=0, deletes=0; + struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); + if (options->controls != NULL && req_ctrls == NULL) { + fprintf(stderr, "parsing controls failed: %s\n", ldb_errstring(ldb)); + return -1; + } + + if (ldb_transaction_start(ldb) != LDB_SUCCESS) { + fprintf(stderr, "Failed to start transaction: %s\n", ldb_errstring(ldb)); + return -1; + } + + /* do the adds and modifies */ + for (i=0;idn); + if (!msg) { + if (options->verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]); + } + if (ldb_add_ctrl(ldb, msgs2[i], req_ctrls) != LDB_SUCCESS) { + fprintf(stderr, "failed to add %s - %s\n", + ldb_dn_get_linearized(msgs2[i]->dn), + ldb_errstring(ldb)); + ldb_transaction_cancel(ldb); + return -1; + } + adds++; + } else { + ret = modify_record(ldb, msg, msgs2[i], req_ctrls); + if (ret != -1) { + modifies += (unsigned int) ret; + } else { + ldb_transaction_cancel(ldb); + return -1; + } + } + } + + /* do the deletes */ + for (i=0;idn); + if (!msg) { + if (options->verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]); + } + if (ldb_delete_ctrl(ldb, msgs1[i]->dn, req_ctrls) != LDB_SUCCESS) { + fprintf(stderr, "failed to delete %s - %s\n", + ldb_dn_get_linearized(msgs1[i]->dn), + ldb_errstring(ldb)); + ldb_transaction_cancel(ldb); + return -1; + } + deletes++; + } + } + + if (ldb_transaction_commit(ldb) != LDB_SUCCESS) { + fprintf(stderr, "Failed to commit transaction: %s\n", ldb_errstring(ldb)); + return -1; + } + + printf("# %u adds %u modifies %u deletes\n", adds, modifies, deletes); + + return 0; +} + +/* + save a set of messages as ldif to a file +*/ +static int save_ldif(struct ldb_context *ldb, + FILE *f, struct ldb_message **msgs, unsigned int count) +{ + unsigned int i; + + fprintf(f, "# editing %u records\n", count); + + for (i=0;imsg; + } + + /* the feof() test works here, even for the last line of the + * file, as we parse ldif files character by character, and + * feof() is only true if we have failed to read a character + * from the file. So if the last line is bad, we don't get + * feof() set, so we know the record was bad. Only if we + * attempt to go to the next record will we get feof() and + * thus consider that the ldif has ended without errors + */ + if (!feof(f)) { + fprintf(stderr, "Error parsing ldif - aborting\n"); + fclose(f); + unlink(file_template); + return -1; + } + + fclose(f); + unlink(file_template); + + return merge_edits(ldb, msgs1, count1, msgs2, count2); +} + +static void usage(struct ldb_context *ldb) +{ + printf("Usage: ldbedit \n"); + ldb_cmdline_help(ldb, "ldbedit", stdout); + exit(LDB_ERR_OPERATIONS_ERROR); +} + +int main(int argc, const char **argv) +{ + struct ldb_context *ldb; + struct ldb_result *result = NULL; + struct ldb_dn *basedn = NULL; + int ret; + const char *expression = "(|(objectClass=*)(distinguishedName=*))"; + const char * const * attrs = NULL; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + struct ldb_control **req_ctrls; + unsigned int i; + + ldb = ldb_init(mem_ctx, NULL); + if (ldb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + options = ldb_cmdline_process(ldb, argc, argv, usage); + + /* the check for '=' is for compatibility with ldapsearch */ + if (options->argc > 0 && + strchr(options->argv[0], '=')) { + expression = options->argv[0]; + options->argv++; + options->argc--; + } + + if (options->argc > 0) { + attrs = (const char * const *)(options->argv); + } + + if (options->basedn != NULL) { + basedn = ldb_dn_new(ldb, ldb, options->basedn); + if (basedn == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + for (i = 0; options->controls != NULL && options->controls[i] != NULL; i++) { + if (strncmp(options->controls[i], "reveal_internals:", 17) == 0) { + printf("Using reveal internals has unintended consequences.\n"); + printf("If this is your intent, manually perform the search," + " and use ldbmodify directly.\n"); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); + if (options->controls != NULL && req_ctrls== NULL) { + printf("parsing controls failed: %s\n", ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_search_ctrl(ldb, ldb, &result, basedn, options->scope, attrs, req_ctrls, "%s", expression); + if (ret != LDB_SUCCESS) { + printf("search failed - %s\n", ldb_errstring(ldb)); + return ret; + } + + if (result->count == 0) { + printf("no matching records - cannot edit\n"); + talloc_free(mem_ctx); + return LDB_SUCCESS; + } + + ret = do_edit(ldb, result->msgs, result->count, options->editor); + + talloc_free(mem_ctx); + + return ret == 0 ? LDB_SUCCESS : LDB_ERR_OPERATIONS_ERROR; +} diff --git a/ldb-2.0.8/tools/ldbmodify.c b/ldb-2.0.8/tools/ldbmodify.c new file mode 100644 index 0000000..9b4d7b7 --- /dev/null +++ b/ldb-2.0.8/tools/ldbmodify.c @@ -0,0 +1,184 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldbmodify + * + * Description: utility to modify records - modelled on ldapmodify + * + * Author: Andrew Tridgell + */ + +#include "replace.h" +#include "ldb.h" +#include "tools/cmdline.h" +#include "ldbutil.h" +#include "include/ldb_private.h" + +static struct ldb_cmdline *options; + +static void usage(struct ldb_context *ldb) +{ + printf("Usage: ldbmodify \n"); + printf("Modifies a ldb based upon ldif change records\n\n"); + ldb_cmdline_help(ldb, "ldbmodify", stdout); + exit(LDB_ERR_OPERATIONS_ERROR); +} + +/* + process modifies for one file +*/ +static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) +{ + struct ldb_ldif *ldif; + int fun_ret = LDB_SUCCESS, ret; + struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); + struct ldif_read_file_state state = { + .f = f + }; + + if (options->controls != NULL && req_ctrls== NULL) { + printf("parsing controls failed: %s\n", ldb_errstring(ldb)); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + fun_ret = ldb_transaction_start(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction start\n", + ldb_errstring(ldb)); + return fun_ret; + } + + while ((ldif = ldb_ldif_read_file_state(ldb, &state))) { + struct ldb_dn *olddn; + bool deleteoldrdn = false; + struct ldb_dn *newdn; + const char *errstr = NULL; + + switch (ldif->changetype) { + case LDB_CHANGETYPE_NONE: + case LDB_CHANGETYPE_ADD: + ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls); + break; + case LDB_CHANGETYPE_DELETE: + ret = ldb_delete_ctrl(ldb, ldif->msg->dn,req_ctrls); + break; + case LDB_CHANGETYPE_MODIFY: + ret = ldb_modify_ctrl(ldb, ldif->msg,req_ctrls); + break; + case LDB_CHANGETYPE_MODRDN: + ret = ldb_ldif_parse_modrdn(ldb, ldif, ldif, &olddn, + NULL, &deleteoldrdn, + NULL, &newdn); + if (ret == LDB_SUCCESS) { + if (deleteoldrdn) { + ret = ldb_rename(ldb, olddn, newdn); + } else { + errstr = "modrdn: deleteoldrdn=0 " + "not supported."; + ret = LDB_ERR_CONSTRAINT_VIOLATION; + } + } + break; + } + if (ret != LDB_SUCCESS) { + if (errstr == NULL) { + errstr = ldb_errstring(ldb); + } + fprintf(stderr, "ERR: (%s) \"%s\" on DN %s at block before line %llu\n", + ldb_strerror(ret), + errstr, ldb_dn_get_linearized(ldif->msg->dn), + (unsigned long long)state.line_no); + fun_ret = ret; + } else { + (*count)++; + if (options->verbose) { + printf("Modified %s\n", ldb_dn_get_linearized(ldif->msg->dn)); + } + } + ldb_ldif_read_free(ldb, ldif); + if (ret) { + break; + } + } + + if (fun_ret == LDB_SUCCESS && !feof(f)) { + fprintf(stderr, "Failed to parse ldif\n"); + fun_ret = LDB_ERR_OPERATIONS_ERROR; + } + + if (fun_ret == LDB_SUCCESS) { + fun_ret = ldb_transaction_commit(ldb); + if (fun_ret != LDB_SUCCESS) { + fprintf(stderr, "ERR: (%s) on transaction commit\n", + ldb_errstring(ldb)); + } + } else { + ldb_transaction_cancel(ldb); + } + + return fun_ret; +} + +int main(int argc, const char **argv) +{ + struct ldb_context *ldb; + unsigned int i, count = 0; + int ret = LDB_SUCCESS; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + ldb = ldb_init(mem_ctx, NULL); + if (ldb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + options = ldb_cmdline_process(ldb, argc, argv, usage); + + if (options->argc == 0) { + ret = process_file(ldb, stdin, &count); + } else { + for (i=0;iargc;i++) { + const char *fname = options->argv[i]; + FILE *f; + f = fopen(fname, "r"); + if (!f) { + perror(fname); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = process_file(ldb, f, &count); + fclose(f); + } + } + + talloc_free(mem_ctx); + + if (ret) { + printf("Modify failed after processing %u records\n", count); + } else { + printf("Modified %u records successfully\n", count); + } + + return ret; +} diff --git a/ldb-2.0.8/tools/ldbrename.c b/ldb-2.0.8/tools/ldbrename.c new file mode 100644 index 0000000..ab2be4d --- /dev/null +++ b/ldb-2.0.8/tools/ldbrename.c @@ -0,0 +1,85 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldbrename + * + * Description: utility to rename records - modelled on ldapmodrdn + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + */ + +#include "replace.h" +#include "ldb.h" +#include "tools/cmdline.h" + +static void usage(struct ldb_context *ldb) +{ + printf("Usage: ldbrename [] \n"); + printf("Renames records in a ldb\n\n"); + ldb_cmdline_help(ldb, "ldbmodify", stdout); + exit(LDB_ERR_OPERATIONS_ERROR); +} + + +int main(int argc, const char **argv) +{ + struct ldb_context *ldb; + int ret; + struct ldb_cmdline *options; + struct ldb_dn *dn1, *dn2; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + ldb = ldb_init(mem_ctx, NULL); + if (ldb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + options = ldb_cmdline_process(ldb, argc, argv, usage); + + if (options->argc < 2) { + usage(ldb); + } + + dn1 = ldb_dn_new(ldb, ldb, options->argv[0]); + dn2 = ldb_dn_new(ldb, ldb, options->argv[1]); + if ((dn1 == NULL) || (dn2 == NULL)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_rename(ldb, dn1, dn2); + if (ret == LDB_SUCCESS) { + printf("Renamed 1 record\n"); + } else { + printf("rename of '%s' to '%s' failed - %s\n", + options->argv[0], options->argv[1], ldb_errstring(ldb)); + } + + talloc_free(mem_ctx); + + return ret; +} diff --git a/ldb-2.0.8/tools/ldbsearch.c b/ldb-2.0.8/tools/ldbsearch.c new file mode 100644 index 0000000..374f240 --- /dev/null +++ b/ldb-2.0.8/tools/ldbsearch.c @@ -0,0 +1,342 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldbsearch + * + * Description: utility for ldb search - modelled on ldapsearch + * + * Author: Andrew Tridgell + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb.h" +#include "tools/cmdline.h" + +static void usage(struct ldb_context *ldb) +{ + printf("Usage: ldbsearch \n"); + ldb_cmdline_help(ldb, "ldbsearch", stdout); + exit(LDB_ERR_OPERATIONS_ERROR); +} + +static int do_compare_msg(struct ldb_message **el1, + struct ldb_message **el2, + void *opaque) +{ + return ldb_dn_compare((*el1)->dn, (*el2)->dn); +} + +struct search_context { + struct ldb_context *ldb; + struct ldb_control **req_ctrls; + + int sort; + unsigned int num_stored; + struct ldb_message **store; + unsigned int refs_stored; + char **refs_store; + + unsigned int entries; + unsigned int refs; + + unsigned int pending; + int status; +}; + +static int store_message(struct ldb_message *msg, struct search_context *sctx) { + + sctx->store = talloc_realloc(sctx, sctx->store, struct ldb_message *, sctx->num_stored + 2); + if (!sctx->store) { + fprintf(stderr, "talloc_realloc failed while storing messages\n"); + return -1; + } + + sctx->store[sctx->num_stored] = talloc_move(sctx->store, &msg); + sctx->num_stored++; + sctx->store[sctx->num_stored] = NULL; + + return 0; +} + +static int store_referral(char *referral, struct search_context *sctx) { + + sctx->refs_store = talloc_realloc(sctx, sctx->refs_store, char *, sctx->refs_stored + 2); + if (!sctx->refs_store) { + fprintf(stderr, "talloc_realloc failed while storing referrals\n"); + return -1; + } + + sctx->refs_store[sctx->refs_stored] = talloc_move(sctx->refs_store, &referral); + sctx->refs_stored++; + sctx->refs_store[sctx->refs_stored] = NULL; + + return 0; +} + +static int display_message(struct ldb_message *msg, struct search_context *sctx) { + struct ldb_ldif ldif; + + sctx->entries++; + printf("# record %d\n", sctx->entries); + + ldif.changetype = LDB_CHANGETYPE_NONE; + ldif.msg = msg; + + if (sctx->sort) { + /* + * Ensure attributes are always returned in the same + * order. For testing, this makes comparison of old + * vs. new much easier. + */ + ldb_msg_sort_elements(ldif.msg); + } + + ldb_ldif_write_file(sctx->ldb, stdout, &ldif); + + return 0; +} + +static int display_referral(char *referral, struct search_context *sctx) +{ + + sctx->refs++; + printf("# Referral\nref: %s\n\n", referral); + + return 0; +} + +static int search_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct search_context *sctx; + int ret = LDB_SUCCESS; + + sctx = talloc_get_type(req->context, struct search_context); + + if (!ares) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_request_done(req, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + if (sctx->sort) { + ret = store_message(ares->message, sctx); + } else { + ret = display_message(ares->message, sctx); + } + break; + + case LDB_REPLY_REFERRAL: + if (sctx->sort) { + ret = store_referral(ares->referral, sctx); + } else { + ret = display_referral(ares->referral, sctx); + } + if (ret) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + break; + + case LDB_REPLY_DONE: + if (ares->controls) { + if (handle_controls_reply(ares->controls, sctx->req_ctrls) == 1) + sctx->pending = 1; + } + talloc_free(ares); + return ldb_request_done(req, LDB_SUCCESS); + } + + talloc_free(ares); + if (ret != LDB_SUCCESS) { + return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); + } + + return LDB_SUCCESS; +} + +static int do_search(struct ldb_context *ldb, + struct ldb_dn *basedn, + struct ldb_cmdline *options, + const char *expression, + const char * const *attrs) +{ + struct ldb_request *req; + struct search_context *sctx; + int ret; + + req = NULL; + + sctx = talloc_zero(ldb, struct search_context); + if (!sctx) return LDB_ERR_OPERATIONS_ERROR; + + sctx->ldb = ldb; + sctx->sort = options->sorted; + sctx->req_ctrls = ldb_parse_control_strings(ldb, sctx, (const char **)options->controls); + if (options->controls != NULL && sctx->req_ctrls== NULL) { + printf("parsing controls failed: %s\n", ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + +again: + /* free any previous requests */ + if (req) talloc_free(req); + + ret = ldb_build_search_req(&req, ldb, ldb, + basedn, options->scope, + expression, attrs, + sctx->req_ctrls, + sctx, search_callback, + NULL); + if (ret != LDB_SUCCESS) { + talloc_free(sctx); + printf("allocating request failed: %s\n", ldb_errstring(ldb)); + return ret; + } + + if (basedn == NULL) { + /* + we need to use a NULL base DN when doing a cross-ncs + search so we find results on all partitions in a + forest. When doing a domain-local search, default to + the default basedn + */ + struct ldb_control *ctrl; + struct ldb_search_options_control *search_options = NULL; + + ctrl = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID); + if (ctrl) { + search_options = talloc_get_type(ctrl->data, struct ldb_search_options_control); + } + + if (ctrl == NULL || search_options == NULL || + !(search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) { + struct ldb_dn *base = ldb_get_default_basedn(ldb); + if (base != NULL) { + req->op.search.base = base; + } + } + } + + sctx->pending = 0; + + ret = ldb_request(ldb, req); + if (ret != LDB_SUCCESS) { + talloc_free(sctx); + talloc_free(req); + printf("search failed - %s\n", ldb_errstring(ldb)); + return ret; + } + + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + if (ret != LDB_SUCCESS) { + talloc_free(sctx); + talloc_free(req); + printf("search error - %s\n", ldb_errstring(ldb)); + return ret; + } + + if (sctx->pending) + goto again; + + if (sctx->sort && (sctx->num_stored != 0 || sctx->refs != 0)) { + unsigned int i; + + if (sctx->num_stored) { + LDB_TYPESAFE_QSORT(sctx->store, sctx->num_stored, ldb, do_compare_msg); + } + for (i = 0; i < sctx->num_stored; i++) { + display_message(sctx->store[i], sctx); + } + + for (i = 0; i < sctx->refs_stored; i++) { + display_referral(sctx->refs_store[i], sctx); + } + } + + printf("# returned %u records\n# %u entries\n# %u referrals\n", + sctx->entries + sctx->refs, sctx->entries, sctx->refs); + + talloc_free(sctx); + talloc_free(req); + + return LDB_SUCCESS; +} + +int main(int argc, const char **argv) +{ + struct ldb_context *ldb; + struct ldb_dn *basedn = NULL; + const char * const * attrs = NULL; + struct ldb_cmdline *options; + int ret = -1; + const char *expression = "(|(objectClass=*)(distinguishedName=*))"; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + ldb = ldb_init(mem_ctx, NULL); + if (ldb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + options = ldb_cmdline_process_search(ldb, argc, argv, usage); + + /* the check for '=' is for compatibility with ldapsearch */ + if (!options->interactive && + options->argc > 0 && + strpbrk(options->argv[0], "=<>~:")) { + expression = options->argv[0]; + options->argv++; + options->argc--; + } + + if (options->argc > 0) { + attrs = (const char * const *)(options->argv); + } + + if (options->basedn != NULL) { + basedn = ldb_dn_new(ldb, ldb, options->basedn); + if (basedn == NULL) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + if (options->interactive) { + char line[1024]; + while (fgets(line, sizeof(line), stdin)) { + ret = do_search(ldb, basedn, options, line, attrs); + } + } else { + ret = do_search(ldb, basedn, options, expression, attrs); + } + + talloc_free(mem_ctx); + + return ret; +} diff --git a/ldb-2.0.8/tools/ldbtest.c b/ldb-2.0.8/tools/ldbtest.c new file mode 100644 index 0000000..64b6baa --- /dev/null +++ b/ldb-2.0.8/tools/ldbtest.c @@ -0,0 +1,438 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Component: ldbtest + * + * Description: utility to test ldb + * + * Author: Andrew Tridgell + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/time.h" +#include "ldb.h" +#include "tools/cmdline.h" + +static struct timespec tp1,tp2; +static struct ldb_cmdline *options; + +static void _start_timer(void) +{ + if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp1) != 0) { + clock_gettime(CLOCK_REALTIME, &tp1); + } +} + +static double _end_timer(void) +{ + if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp2) != 0) { + clock_gettime(CLOCK_REALTIME, &tp2); + } + return((tp2.tv_sec - tp1.tv_sec) + + (tp2.tv_nsec - tp1.tv_nsec)*1.0e-9); +} + +static void add_records(struct ldb_context *ldb, + struct ldb_dn *basedn, + unsigned int count) +{ + struct ldb_message msg = {0}; + unsigned int i; + +#if 0 + if (ldb_lock(ldb, "transaction") != 0) { + printf("transaction lock failed\n"); + exit(LDB_ERR_OPERATIONS_ERROR); + } +#endif + for (i=0;icount != 1)) { + printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb)); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + if (uid >= nrecords && res->count > 0) { + printf("Found %s !? - %d\n", expr, ret); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + printf("Testing uid %d/%d - %d \r", i, uid, res->count); + fflush(stdout); + + talloc_free(res); + talloc_free(expr); + } + + printf("\n"); +} + +static void start_test(struct ldb_context *ldb, unsigned int nrecords, + unsigned int nsearches) +{ + struct ldb_dn *basedn; + + basedn = ldb_dn_new(ldb, ldb, options->basedn); + if ( ! ldb_dn_validate(basedn)) { + printf("Invalid base DN format\n"); + exit(LDB_ERR_INVALID_DN_SYNTAX); + } + + printf("Adding %d records\n", nrecords); + add_records(ldb, basedn, nrecords); + + printf("Starting search on uid\n"); + _start_timer(); + search_uid(ldb, basedn, nrecords, nsearches); + printf("uid search took %.2f seconds\n", _end_timer()); + + printf("Modifying records\n"); + modify_records(ldb, basedn, nrecords); + + printf("Deleting records\n"); + delete_records(ldb, basedn, nrecords); +} + + +/* + 2) Store an @indexlist record + + 3) Store a record that contains fields that should be index according +to @index + + 4) disconnection from database + + 5) connect to same database + + 6) search for record added in step 3 using a search key that should +be indexed +*/ +static void start_test_index(struct ldb_context **ldb) +{ + struct ldb_message *msg; + struct ldb_result *res = NULL; + struct ldb_dn *indexlist; + struct ldb_dn *basedn; + int ret; + unsigned int flags = 0; + const char *specials; + + specials = getenv("LDB_SPECIALS"); + if (specials && atoi(specials) == 0) { + printf("LDB_SPECIALS disabled - skipping index test\n"); + return; + } + + if (options->nosync) { + flags |= LDB_FLG_NOSYNC; + } + + printf("Starting index test\n"); + + indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST"); + + ldb_delete(*ldb, indexlist); + + msg = ldb_msg_new(NULL); + if (msg == NULL) { + printf("ldb_msg_new failed\n"); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + msg->dn = indexlist; + ldb_msg_add_string(msg, "@IDXATTR", strdup("uid")); + + if (ldb_add(*ldb, msg) != 0) { + printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb)); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + basedn = ldb_dn_new(*ldb, *ldb, options->basedn); + + memset(msg, 0, sizeof(*msg)); + msg->dn = ldb_dn_copy(msg, basedn); + ldb_dn_add_child_fmt(msg->dn, "cn=test"); + ldb_msg_add_string(msg, "cn", strdup("test")); + ldb_msg_add_string(msg, "sn", strdup("test")); + ldb_msg_add_string(msg, "uid", strdup("test")); + ldb_msg_add_string(msg, "objectClass", strdup("OpenLDAPperson")); + + if (ldb_add(*ldb, msg) != LDB_SUCCESS) { + printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb)); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + if (talloc_free(*ldb) != 0) { + printf("failed to free/close ldb database"); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + (*ldb) = ldb_init(options, NULL); + + ret = ldb_connect(*ldb, options->url, flags, NULL); + if (ret != LDB_SUCCESS) { + printf("failed to connect to %s\n", options->url); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + basedn = ldb_dn_new(*ldb, *ldb, options->basedn); + msg->dn = basedn; + ldb_dn_add_child_fmt(msg->dn, "cn=test"); + + ret = ldb_search(*ldb, *ldb, &res, basedn, LDB_SCOPE_SUBTREE, NULL, "uid=test"); + if (ret != LDB_SUCCESS) { + printf("Search with (uid=test) filter failed!\n"); + exit(LDB_ERR_OPERATIONS_ERROR); + } + if(res->count != 1) { + printf("Should have found 1 record - found %d\n", res->count); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST"); + + if (ldb_delete(*ldb, msg->dn) != 0 || + ldb_delete(*ldb, indexlist) != 0) { + printf("cleanup failed - %s\n", ldb_errstring(*ldb)); + exit(LDB_ERR_OPERATIONS_ERROR); + } + + printf("Finished index test\n"); +} + + +static void usage(struct ldb_context *ldb) +{ + printf("Usage: ldbtest \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" --num-records nrecords database size to use\n"); + printf(" --num-searches nsearches number of searches to do\n"); + printf("\n"); + printf("tests ldb API\n\n"); + exit(LDB_ERR_OPERATIONS_ERROR); +} + +int main(int argc, const char **argv) +{ + TALLOC_CTX *mem_ctx = talloc_new(NULL); + struct ldb_context *ldb; + + ldb = ldb_init(mem_ctx, NULL); + if (ldb == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + options = ldb_cmdline_process(ldb, argc, argv, usage); + + talloc_steal(mem_ctx, options); + + if (options->basedn == NULL) { + options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST"; + } + + srandom(1); + + printf("Testing with num-records=%d and num-searches=%d\n", + options->num_records, options->num_searches); + + start_test(ldb, + (unsigned int) options->num_records, + (unsigned int) options->num_searches); + + start_test_index(&ldb); + + talloc_free(mem_ctx); + + return LDB_SUCCESS; +} diff --git a/ldb-2.0.8/tools/ldbutil.c b/ldb-2.0.8/tools/ldbutil.c new file mode 100644 index 0000000..9ff7fad --- /dev/null +++ b/ldb-2.0.8/tools/ldbutil.c @@ -0,0 +1,220 @@ +/* + ldb database library utility + + Copyright (C) Matthieu Patou 2009 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Description: Common function used by ldb_add/ldb_modify/ldb_delete + * + * Author: Matthieu Patou + */ + +#include "replace.h" +#include "ldb.h" +#include "ldb_module.h" +#include "ldbutil.h" + + +/* autostarts a transacion if none active */ +static int ldb_do_autotransaction(struct ldb_context *ldb, + struct ldb_request *req) +{ + int ret; + + ret = ldb_transaction_start(ldb); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_request(ldb, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret == LDB_SUCCESS) { + return ldb_transaction_commit(ldb); + } + ldb_transaction_cancel(ldb); + + if (ldb_errstring(ldb) == NULL) { + /* no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, "%s (%d)", ldb_strerror(ret), ret); + } + + return ret; +} +/* + Same as ldb_add but accept control +*/ +int ldb_add_ctrl(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_control **controls) +{ + struct ldb_request *req; + int ret; + + ret = ldb_msg_sanity_check(ldb, message); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_add_req(&req, ldb, ldb, + message, + controls, + NULL, + ldb_op_default_callback, + NULL); + + if (ret != LDB_SUCCESS) return ret; + + /* do request and autostart a transaction */ + ret = ldb_do_autotransaction(ldb, req); + + talloc_free(req); + return ret; +} + +/* + same as ldb_delete but accept control +*/ +int ldb_delete_ctrl(struct ldb_context *ldb, struct ldb_dn *dn, + struct ldb_control **controls) +{ + struct ldb_request *req; + int ret; + + ret = ldb_build_del_req(&req, ldb, ldb, + dn, + controls, + NULL, + ldb_op_default_callback, + NULL); + + if (ret != LDB_SUCCESS) return ret; + + /* do request and autostart a transaction */ + ret = ldb_do_autotransaction(ldb, req); + + talloc_free(req); + return ret; +} + + +/* + same as ldb_modify, but accepts controls +*/ +int ldb_modify_ctrl(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_control **controls) +{ + struct ldb_request *req; + int ret; + + ret = ldb_msg_sanity_check(ldb, message); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_mod_req(&req, ldb, ldb, + message, + controls, + NULL, + ldb_op_default_callback, + NULL); + + if (ret != LDB_SUCCESS) return ret; + + /* do request and autostart a transaction */ + ret = ldb_do_autotransaction(ldb, req); + + talloc_free(req); + return ret; +} + + +/* + ldb_search with controls +*/ +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, ...) +{ + struct ldb_request *req; + struct ldb_result *res; + char *expression; + va_list ap; + int ret; + + expression = NULL; + *result = NULL; + req = NULL; + + res = talloc_zero(mem_ctx, struct ldb_result); + if (!res) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (exp_fmt) { + va_start(ap, exp_fmt); + expression = talloc_vasprintf(mem_ctx, exp_fmt, ap); + va_end(ap); + + if (!expression) { + talloc_free(res); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + ret = ldb_build_search_req(&req, ldb, mem_ctx, + base?base:ldb_get_default_basedn(ldb), + scope, + expression, + attrs, + controls, + res, + ldb_search_default_callback, + NULL); + ldb_req_set_location(req, "ldb_search_ctrl"); + + if (ret != LDB_SUCCESS) goto done; + + ret = ldb_request(ldb, req); + + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + +done: + if (ret != LDB_SUCCESS) { + talloc_free(res); + res = NULL; + } + + talloc_free(expression); + talloc_free(req); + + *result = res; + return ret; +} diff --git a/ldb-2.0.8/tools/ldbutil.h b/ldb-2.0.8/tools/ldbutil.h new file mode 100644 index 0000000..6723863 --- /dev/null +++ b/ldb-2.0.8/tools/ldbutil.h @@ -0,0 +1,46 @@ +/* + ldb database library utility header file + + Copyright (C) Matthieu Patou 2009 + + ** NOTE! The following LGPL license applies to the ldb + ** 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 + Lesser 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 . +*/ + +/* + * Name: ldb + * + * Description: Common function used by ldb_add/ldb_modify/ldb_delete + * + * Author: Matthieu Patou + */ + +#include "ldb.h" + +int ldb_add_ctrl(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_control **controls); +int ldb_delete_ctrl(struct ldb_context *ldb, struct ldb_dn *dn, + struct ldb_control **controls); +int ldb_modify_ctrl(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_control **controls); +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, ...) PRINTF_ATTRIBUTE(8,9); diff --git a/ldb-2.0.8/web/index.html b/ldb-2.0.8/web/index.html new file mode 100644 index 0000000..7f50cdc --- /dev/null +++ b/ldb-2.0.8/web/index.html @@ -0,0 +1,74 @@ + + + +ldb + + + +

ldb

+ +ldb is a LDAP-like embedded database. It is not at all +LDAP +standards compliant, so if you want a standards compliant database then please +see the excellent OpenLDAP +project.

+ +What ldb does is provide a fast database with an LDAP-like API +designed to be used within an application. In some ways it can be seen +as a intermediate solution between key-value pair databases and a real +LDAP database.

+ +ldb is the database engine used in Samba4. + +

Features

+ +The main features that separate ldb from other solutions are: + +
    +
  • Safe multi-reader, multi-writer, using byte range locking +
  • LDAP-like API +
  • fast operation +
  • choice of local tdb or remote LDAP backends +
  • integration with talloc +
  • schema-less operation, for trivial setup +
  • modules for extensions (such as schema support) +
  • easy setup of indexes and attribute properties +
  • LDIF for import/export +
  • ldbedit tool for database (via LDIF) editing (reminiscent of 'vipw') +
+ +

Documentation

+ +Currently ldb is completely lacking in programmer or user +documentation. This is your opportunity to make a contribution! Start +with the public functions declared in ldb.h +and the example code in the tools +directory. Documentation in the same docbook format used by Samba +would be preferred. + +

Discussion and bug reports

+ +ldb does not have its own mailing list or bug tracking system. Please +use +the samba-technical +mailing list, and the Samba +bugzilla bug tracking system. + +

Download

+ +You can download the latest release here:
+ http://samba.org/ftp/pub/ldb + +Alternatively, you can fetch via git. See the following guide:
+Using Git for Samba Development
+ +
+ +Andrew Tridgell
+ldb AT tridgell.net +
+ + + diff --git a/ldb-2.0.8/wscript b/ldb-2.0.8/wscript new file mode 100644 index 0000000..5b5c42d --- /dev/null +++ b/ldb-2.0.8/wscript @@ -0,0 +1,650 @@ +#!/usr/bin/env python + +APPNAME = 'ldb' +VERSION = '2.0.8' + +import sys, os + +# find the buildtools directory +top = '.' +while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5: + top = top + '/..' +sys.path.insert(0, top + '/buildtools/wafsamba') + +out = 'bin' + +import wafsamba +from wafsamba import samba_dist, samba_utils +from waflib import Errors, Options, Logs, Context +import shutil + +samba_dist.DIST_DIRS('''lib/ldb:. lib/replace:lib/replace lib/talloc:lib/talloc + lib/tdb:lib/tdb lib/tdb:lib/tdb lib/tevent:lib/tevent + third_party/popt:third_party/popt + third_party/cmocka:third_party/cmocka + buildtools:buildtools third_party/waf:third_party/waf''') + +samba_dist.DIST_FILES('''lib/util/binsearch.h:lib/util/binsearch.h + lib/util/attr.h:lib/util/attr.h''') + +def options(opt): + opt.BUILTIN_DEFAULT('replace') + opt.PRIVATE_EXTENSION_DEFAULT('ldb', noextension='ldb') + opt.RECURSE('lib/tdb') + opt.RECURSE('lib/tevent') + opt.RECURSE('lib/replace') + opt.load('python') # options for disabling pyc or pyo compilation + + opt.add_option('--without-ldb-lmdb', + help='disable new LMDB backend for LDB', + action='store_true', dest='without_ldb_lmdb', default=False) + + +def configure(conf): + conf.RECURSE('lib/tdb') + conf.RECURSE('lib/tevent') + + if conf.CHECK_FOR_THIRD_PARTY(): + conf.RECURSE('third_party/popt') + conf.RECURSE('third_party/cmocka') + else: + if not conf.CHECK_POPT(): + raise Errors.WafError('popt development packages have not been found.\nIf third_party is installed, check that it is in the proper place.') + else: + conf.define('USING_SYSTEM_POPT', 1) + + if not conf.CHECK_CMOCKA(): + raise Errors.WafError('cmocka development package have not been found.\nIf third_party is installed, check that it is in the proper place.') + else: + conf.define('USING_SYSTEM_CMOCKA', 1) + + conf.RECURSE('lib/replace') + conf.find_program('xsltproc', var='XSLTPROC') + conf.SAMBA_CHECK_PYTHON() + conf.SAMBA_CHECK_PYTHON_HEADERS() + + # where does the default LIBDIR end up? in conf.env somewhere? + # + conf.CONFIG_PATH('LDB_MODULESDIR', conf.SUBST_ENV_VAR('MODULESDIR') + '/ldb') + + conf.env.standalone_ldb = conf.IN_LAUNCH_DIR() + + if not conf.env.standalone_ldb: + max_ldb_version = [int(x) for x in VERSION.split(".")] + max_ldb_version[2] = 999 + max_ldb_version_dots = "%d.%d.%d" % tuple(max_ldb_version) + + if conf.env.disable_python: + if conf.CHECK_BUNDLED_SYSTEM_PKG('ldb', + minversion=VERSION, + maxversion=max_ldb_version_dots, + onlyif='talloc tdb tevent', + implied_deps='replace talloc tdb tevent'): + conf.define('USING_SYSTEM_LDB', 1) + else: + using_system_pyldb_util = True + dflt_name = 'pyldb-util' + conf.all_envs['default']['PYTHON_SO_ABI_FLAG'] + if not conf.CHECK_BUNDLED_SYSTEM_PKG(dflt_name, + minversion=VERSION, + maxversion=max_ldb_version_dots, + onlyif='talloc tdb tevent', + implied_deps='replace talloc tdb tevent ldb'): + using_system_pyldb_util = False + + if using_system_pyldb_util: + conf.define('USING_SYSTEM_PYLDB_UTIL', 1) + + if conf.CHECK_BUNDLED_SYSTEM_PKG('ldb', + minversion=VERSION, + maxversion=max_ldb_version_dots, + onlyif='talloc tdb tevent %s' % dflt_name, + implied_deps='replace talloc tdb tevent'): + conf.define('USING_SYSTEM_LDB', 1) + + if not conf.CHECK_CODE('return !(sizeof(size_t) >= 8)', + "HAVE_64_BIT_SIZE_T_FOR_LMDB", + execute=True, + msg='Checking for a 64-bit host to ' + 'support lmdb'): + Logs.warn("--without-ldb-lmdb implied as this " + "host is not 64-bit") + + if not conf.env.standalone_ldb and \ + not Options.options.without_ad_dc and \ + conf.CONFIG_GET('ENABLE_SELFTEST'): + Logs.warn("NOTE: Some AD DC parts of selftest will fail") + + conf.env.REQUIRE_LMDB = False + else: + if conf.env.standalone_ldb: + if Options.options.without_ldb_lmdb: + conf.env.REQUIRE_LMDB = False + else: + conf.env.REQUIRE_LMDB = True + elif Options.options.without_ad_dc: + conf.env.REQUIRE_LMDB = False + else: + if Options.options.without_ldb_lmdb: + if not Options.options.without_ad_dc and \ + conf.CONFIG_GET('ENABLE_SELFTEST'): + raise Errors.WafError('--without-ldb-lmdb conflicts ' + 'with --enable-selftest while ' + 'building the AD DC') + + conf.env.REQUIRE_LMDB = False + else: + conf.env.REQUIRE_LMDB = True + + + if conf.CONFIG_SET('USING_SYSTEM_LDB'): + v = VERSION.split('.') + conf.DEFINE('EXPECTED_SYSTEM_LDB_VERSION_MAJOR', int(v[0])) + conf.DEFINE('EXPECTED_SYSTEM_LDB_VERSION_MINOR', int(v[1])) + conf.DEFINE('EXPECTED_SYSTEM_LDB_VERSION_RELEASE', int(v[2])) + + if conf.env.standalone_ldb: + conf.CHECK_XSLTPROC_MANPAGES() + + # we need this for the ldap backend + if conf.CHECK_FUNCS_IN('ber_flush ldap_open ldap_initialize', 'lber ldap', headers='lber.h ldap.h'): + conf.env.ENABLE_LDAP_BACKEND = True + + # we don't want any libraries or modules to rely on runtime + # resolution of symbols + if not sys.platform.startswith("openbsd"): + conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True) + + # if lmdb support is enabled then we require lmdb + # is present, build the mdb back end and enable lmdb support in + # the tools. + if conf.env.REQUIRE_LMDB and \ + not conf.CONFIG_SET('USING_SYSTEM_LDB'): + if not conf.CHECK_CFG(package='lmdb', + args='"lmdb >= 0.9.16" --cflags --libs', + msg='Checking for lmdb >= 0.9.16', + mandatory=False): + if not conf.CHECK_CODE(''' + #if MDB_VERSION_MAJOR == 0 \ + && MDB_VERSION_MINOR <= 9 \ + && MDB_VERSION_PATCH < 16 + #error LMDB too old + #endif + ''', + 'HAVE_GOOD_LMDB_VERSION', + headers='lmdb.h', + msg='Checking for lmdb >= 0.9.16 via header check'): + + if conf.env.standalone_ldb: + raise Errors.WafError('ldb build (unless --without-ldb-lmdb) ' + 'requires ' + 'lmdb 0.9.16 or later') + elif not Options.options.without_ad_dc: + raise Errors.WafError('Samba AD DC and --enable-selftest ' + 'requires ' + 'lmdb 0.9.16 or later') + + if conf.CHECK_FUNCS_IN('mdb_env_create', 'lmdb', headers='lmdb.h'): + conf.DEFINE('HAVE_LMDB', '1') + conf.env.HAVE_LMDB = True + + + conf.DEFINE('HAVE_CONFIG_H', 1, add_to_cflags=True) + + conf.SAMBA_CONFIG_H() + + conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS() + +def build(bld): + bld.RECURSE('lib/tevent') + + if bld.CHECK_FOR_THIRD_PARTY(): + bld.RECURSE('third_party/popt') + bld.RECURSE('third_party/cmocka') + + bld.RECURSE('lib/replace') + bld.RECURSE('lib/tdb') + + if bld.env.standalone_ldb: + if not 'PACKAGE_VERSION' in bld.env: + bld.env.PACKAGE_VERSION = VERSION + bld.env.PKGCONFIGDIR = '${LIBDIR}/pkgconfig' + private_library = False + else: + private_library = True + # we're not currently linking against the ldap libs, but ldb.pc.in + # has @LDAP_LIBS@ + bld.env.LDAP_LIBS = '' + + LDB_MAP_SRC = bld.SUBDIR('ldb_map', + 'ldb_map.c ldb_map_inbound.c ldb_map_outbound.c') + + COMMON_SRC = bld.SUBDIR('common', + '''ldb_modules.c ldb_ldif.c ldb_parse.c ldb_msg.c ldb_utf8.c + ldb_debug.c ldb_dn.c ldb_match.c ldb_options.c ldb_pack.c + ldb_attributes.c attrib_handlers.c ldb_controls.c qsort.c''') + + bld.SAMBA_MODULE('ldb_ldap', 'ldb_ldap/ldb_ldap.c', + init_function='ldb_ldap_init', + module_init_name='ldb_init_module', + deps='talloc lber ldap ldb', + enabled=bld.env.ENABLE_LDAP_BACKEND, + internal_module=False, + subsystem='ldb') + + if bld.PYTHON_BUILD_IS_ENABLED(): + if not bld.CONFIG_SET('USING_SYSTEM_PYLDB_UTIL'): + name = bld.pyembed_libname('pyldb-util') + bld.SAMBA_LIBRARY(name, + deps='replace ldb', + source='pyldb_util.c', + public_headers=('' if private_library else 'pyldb.h'), + public_headers_install=not private_library, + vnum=VERSION, + private_library=private_library, + pc_files='pyldb-util.pc', + pyembed=True, + enabled=bld.PYTHON_BUILD_IS_ENABLED(), + abi_directory='ABI', + abi_match='pyldb_*') + + if not bld.CONFIG_SET('USING_SYSTEM_LDB'): + bld.SAMBA_PYTHON('pyldb', 'pyldb.c', + deps='replace ldb ' + name, + realname='ldb.so', + cflags='-DPACKAGE_VERSION=\"%s\"' % VERSION) + + # Do only install this file as part of the Samba build if we do not + # use the system libldb! + if not bld.CONFIG_SET('USING_SYSTEM_PYLDB_UTIL'): + bld.SAMBA_SCRIPT('_ldb_text.py', + pattern='_ldb_text.py', + installdir='python') + + bld.INSTALL_FILES('${PYTHONARCHDIR}', '_ldb_text.py') + + if not bld.CONFIG_SET('USING_SYSTEM_LDB'): + if bld.is_install: + modules_dir = bld.EXPAND_VARIABLES('${LDB_MODULESDIR}') + else: + # when we run from the source directory, we want to use + # the current modules, not the installed ones + modules_dir = os.path.join(os.getcwd(), 'bin/modules/ldb') + + abi_match = '!ldb_*module_ops !ldb_*backend_ops ldb_*' + + ldb_headers = ('include/ldb.h include/ldb_errors.h ' + 'include/ldb_module.h include/ldb_handlers.h') + + bld.SAMBA_LIBRARY('ldb', + COMMON_SRC + ' ' + LDB_MAP_SRC, + deps='tevent LIBLDB_MAIN replace', + includes='include', + public_headers=('' if private_library else ldb_headers), + public_headers_install=not private_library, + pc_files='ldb.pc', + vnum=VERSION, + private_library=private_library, + manpages='man/ldb.3', + abi_directory='ABI', + abi_match = abi_match) + + # generate a include/ldb_version.h + def generate_ldb_version_h(t): + '''generate a vscript file for our public libraries''' + + tgt = t.outputs[0].bldpath(t.env) + + v = t.env.LDB_VERSION.split('.') + + f = open(tgt, mode='w') + try: + f.write('#define LDB_VERSION "%s"\n' % t.env.LDB_VERSION) + f.write('#define LDB_VERSION_MAJOR %d\n' % int(v[0])) + f.write('#define LDB_VERSION_MINOR %d\n' % int(v[1])) + f.write('#define LDB_VERSION_RELEASE %d\n' % int(v[2])) + finally: + f.close() + return + t = bld.SAMBA_GENERATOR('ldb_version.h', + rule=generate_ldb_version_h, + dep_vars=['LDB_VERSION'], + target='include/ldb_version.h', + public_headers='include/ldb_version.h', + public_headers_install=not private_library) + t.env.LDB_VERSION = VERSION + + bld.SAMBA_MODULE('ldb_asq', + 'modules/asq.c', + init_function='ldb_asq_init', + module_init_name='ldb_init_module', + internal_module=False, + deps='ldb', + subsystem='ldb') + + bld.SAMBA_MODULE('ldb_server_sort', + 'modules/sort.c', + init_function='ldb_server_sort_init', + internal_module=False, + module_init_name='ldb_init_module', + deps='ldb', + subsystem='ldb') + + bld.SAMBA_MODULE('ldb_paged_searches', + 'modules/paged_searches.c', + init_function='ldb_paged_searches_init', + internal_module=False, + module_init_name='ldb_init_module', + deps='ldb', + subsystem='ldb') + + bld.SAMBA_MODULE('ldb_rdn_name', + 'modules/rdn_name.c', + init_function='ldb_rdn_name_init', + internal_module=False, + module_init_name='ldb_init_module', + deps='ldb', + subsystem='ldb') + + bld.SAMBA_MODULE('ldb_sample', + 'tests/sample_module.c', + init_function='ldb_sample_init', + internal_module=False, + module_init_name='ldb_init_module', + deps='ldb', + subsystem='ldb') + + bld.SAMBA_MODULE('ldb_skel', + 'modules/skel.c', + init_function='ldb_skel_init', + internal_module=False, + module_init_name='ldb_init_module', + deps='ldb', + subsystem='ldb') + + bld.SAMBA_MODULE('ldb_sqlite3', + 'sqlite3/ldb_sqlite3.c', + init_function='ldb_sqlite3_init', + internal_module=False, + module_init_name='ldb_init_module', + enabled=False, + deps='ldb', + subsystem='ldb') + + bld.SAMBA_MODULE('ldb_tdb', + bld.SUBDIR('ldb_tdb', + '''ldb_tdb_init.c'''), + init_function='ldb_tdb_init', + module_init_name='ldb_init_module', + internal_module=False, + deps='ldb ldb_tdb_int ldb_key_value', + subsystem='ldb') + + bld.SAMBA_LIBRARY('ldb_tdb_int', + bld.SUBDIR('ldb_tdb', + '''ldb_tdb_wrap.c ldb_tdb.c'''), + private_library=True, + deps='ldb tdb ldb_key_value ldb_tdb_err_map') + + bld.SAMBA_LIBRARY('ldb_tdb_err_map', + bld.SUBDIR('ldb_tdb', + '''ldb_tdb_err_map.c '''), + private_library=True, + deps='ldb tdb') + + bld.SAMBA_LIBRARY('ldb_key_value', + bld.SUBDIR('ldb_key_value', + '''ldb_kv.c ldb_kv_search.c ldb_kv_index.c + ldb_kv_cache.c'''), + private_library=True, + deps='tdb ldb ldb_tdb_err_map') + + if bld.CONFIG_SET('HAVE_LMDB'): + bld.SAMBA_MODULE('ldb_mdb', + bld.SUBDIR('ldb_mdb', + '''ldb_mdb_init.c'''), + init_function='ldb_mdb_init', + module_init_name='ldb_init_module', + internal_module=False, + deps='ldb ldb_key_value ldb_mdb_int', + subsystem='ldb') + + bld.SAMBA_LIBRARY('ldb_mdb_int', + bld.SUBDIR('ldb_mdb', + '''ldb_mdb.c '''), + private_library=True, + deps='ldb lmdb ldb_key_value') + lmdb_deps = ' ldb_mdb_int' + else: + lmdb_deps = '' + + + bld.SAMBA_MODULE('ldb_ldb', + bld.SUBDIR('ldb_ldb', + '''ldb_ldb.c'''), + init_function='ldb_ldb_init', + module_init_name='ldb_init_module', + internal_module=False, + deps='ldb ldb_tdb_int ldb_key_value' + lmdb_deps, + subsystem='ldb') + + # have a separate subsystem for common/ldb.c, so it can rebuild + # for install with a different -DLDB_MODULESDIR= + bld.SAMBA_SUBSYSTEM('LIBLDB_MAIN', + 'common/ldb.c', + deps='tevent tdb', + includes='include', + cflags=['-DLDB_MODULESDIR=\"%s\"' % modules_dir]) + + LDB_TOOLS='ldbadd ldbsearch ldbdel ldbmodify ldbedit ldbrename' + for t in LDB_TOOLS.split(): + bld.SAMBA_BINARY(t, 'tools/%s.c' % t, deps='ldb-cmdline ldb', + manpages='man/%s.1' % t) + + # ldbtest doesn't get installed + bld.SAMBA_BINARY('ldbtest', 'tools/ldbtest.c', deps='ldb-cmdline ldb', + install=False) + + if bld.CONFIG_SET('HAVE_LMDB'): + lmdb_deps = ' lmdb' + else: + lmdb_deps = '' + # ldbdump doesn't get installed + bld.SAMBA_BINARY('ldbdump', + 'tools/ldbdump.c', + deps='ldb-cmdline ldb' + lmdb_deps, + install=False) + + bld.SAMBA_LIBRARY('ldb-cmdline', + source='tools/ldbutil.c tools/cmdline.c', + deps='ldb dl popt', + private_library=True) + + bld.SAMBA_BINARY('ldb_tdb_mod_op_test', + source='tests/ldb_mod_op_test.c', + cflags='-DTEST_BE=\"tdb\"', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_tdb_guid_mod_op_test', + source='tests/ldb_mod_op_test.c', + cflags='-DTEST_BE=\"tdb\" -DGUID_IDX=1', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_tdb_kv_ops_test', + source='tests/ldb_kv_ops_test.c', + cflags='-DTEST_BE=\"tdb\"', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_tdb_test', + source='tests/ldb_tdb_test.c', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_msg_test', + source='tests/ldb_msg.c', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('test_ldb_qsort', + source='tests/test_ldb_qsort.c', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('test_ldb_dn', + source='tests/test_ldb_dn.c', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_match_test', + source='tests/ldb_match_test.c', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_key_value_test', + source='tests/ldb_key_value_test.c', + deps='cmocka ldb ldb_tdb_err_map', + install=False) + + bld.SAMBA_BINARY('ldb_parse_test', + source='tests/ldb_parse_test.c', + deps='cmocka ldb ldb_tdb_err_map', + install=False) + + bld.SAMBA_BINARY('ldb_filter_attrs_test', + source='tests/ldb_filter_attrs_test.c', + deps='cmocka ldb ldb_tdb_err_map', + install=False) + + bld.SAMBA_BINARY('ldb_key_value_sub_txn_tdb_test', + bld.SUBDIR('ldb_key_value', + '''ldb_kv_search.c + ldb_kv_index.c + ldb_kv_cache.c''') + + 'tests/ldb_key_value_sub_txn_test.c', + cflags='-DTEST_BE=\"tdb\"', + deps='cmocka ldb ldb_tdb_err_map', + install=False) + + if bld.CONFIG_SET('HAVE_LMDB'): + bld.SAMBA_BINARY('ldb_mdb_mod_op_test', + source='tests/ldb_mod_op_test.c', + cflags='-DTEST_BE=\"mdb\" -DGUID_IDX=1 ' + + '-DTEST_LMDB=1', + deps='cmocka ldb lmdb', + install=False) + + bld.SAMBA_BINARY('ldb_lmdb_test', + source='tests/ldb_lmdb_test.c', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_lmdb_size_test', + source='tests/ldb_lmdb_size_test.c', + deps='cmocka ldb', + install=False) + + bld.SAMBA_BINARY('ldb_mdb_kv_ops_test', + source='tests/ldb_kv_ops_test.c', + cflags='-DTEST_BE=\"mdb\" -DTEST_LMDB=1', + deps='cmocka ldb', + install=False) + + # + # We rely on the versions of the ldb_key_value functions included + # in ldb_key_value_sub_txn_test.c taking priority over the versions + # in the ldb_key_value shared library. + # If this turns out to not be the case, the dependencies will + # need to be unrolled, and all the source files included and the + # ldb_tdb module initialization code will need to be called + # manually. + bld.SAMBA_BINARY('ldb_key_value_sub_txn_mdb_test', + bld.SUBDIR('ldb_key_value', + '''ldb_kv_search.c + ldb_kv_index.c + ldb_kv_cache.c''') + + 'tests/ldb_key_value_sub_txn_test.c', + cflags='-DTEST_BE=\"mdb\"', + deps='cmocka ldb ldb_tdb_err_map', + install=False) + else: + bld.SAMBA_BINARY('ldb_no_lmdb_test', + source='tests/ldb_no_lmdb_test.c', + deps='cmocka ldb', + install=False) + +def test(ctx): + '''run ldb testsuite''' + env = samba_utils.LOAD_ENVIRONMENT() + ctx.env = env + + test_prefix = "%s/st" % (Context.g_module.out) + shutil.rmtree(test_prefix, ignore_errors=True) + os.makedirs(test_prefix) + os.environ['TEST_DATA_PREFIX'] = test_prefix + os.environ['LDB_MODULES_PATH'] = Context.g_module.out + "/modules/ldb" + if env.HAVE_LMDB: + os.environ['HAVE_LMDB'] = '1' + else: + os.environ['HAVE_LMDB'] = '0' + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') + + cmd = 'tests/test-tdb.sh %s' % Context.g_module.out + ret = samba_utils.RUN_COMMAND(cmd) + print("testsuite returned %d" % ret) + + tmp_dir = os.path.join(test_prefix, 'tmp') + if not os.path.exists(tmp_dir): + os.mkdir(tmp_dir) + pyret = samba_utils.RUN_PYTHON_TESTS( + ['tests/python/api.py', + 'tests/python/index.py', + 'tests/python/repack.py'], + extra_env={'SELFTEST_PREFIX': test_prefix}) + print("Python testsuite returned %d" % pyret) + + cmocka_ret = 0 + test_exes = ['test_ldb_qsort', + 'test_ldb_dn', + 'ldb_msg_test', + 'ldb_tdb_mod_op_test', + 'ldb_tdb_guid_mod_op_test', + 'ldb_msg_test', + 'ldb_tdb_kv_ops_test', + 'ldb_tdb_test', + 'ldb_match_test', + 'ldb_key_value_test', + # we currently don't run ldb_key_value_sub_txn_tdb_test as it + # tests the nested/sub transaction handling + # on operations which the TDB backend does not currently + # support + # 'ldb_key_value_sub_txn_tdb_test' + 'ldb_parse_test'] + + if env.HAVE_LMDB: + test_exes += ['ldb_mdb_mod_op_test', + 'ldb_lmdb_test', + # we don't want to run ldb_lmdb_size_test (which proves we can + # fit > 4G of data into the DB), it would fill up the disk on + # many of our test instances + 'ldb_mdb_kv_ops_test', + 'ldb_key_value_sub_txn_mdb_test'] + else: + test_exes += ['ldb_no_lmdb_test'] + + for test_exe in test_exes: + cmd = os.path.join(Context.g_module.out, test_exe) + cmocka_ret = cmocka_ret or samba_utils.RUN_COMMAND(cmd) + + sys.exit(ret or pyret or cmocka_ret) + +def dist(): + '''makes a tarball for distribution''' + samba_dist.dist() + +def reconfigure(ctx): + '''reconfigure if config scripts have changed''' + import samba_utils + samba_utils.reconfigure(ctx) diff --git a/libldb.spec b/libldb.spec index eac5054..a1fd727 100644 --- a/libldb.spec +++ b/libldb.spec @@ -85,10 +85,8 @@ make %{?_smp_mflags} V=1 doxygen Doxyfile %check -%ifarch ppc64le echo disabling one assertion in tests/python/repack.py sed -e '/test_guid_indexed_v1_db/,+18{/toggle_guidindex_check_pack/d}' -i tests/python/repack.py -%endif make %{?_smp_mflags} check