tevent-0.9.34/ABI/tevent-0.9.10.sigs0000660000000000000000000001276112406075657016405 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.11.sigs0000660000000000000000000001276112406075657016406 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.12.sigs0000660000000000000000000001305312406075657016402 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.13.sigs0000660000000000000000000001317212406075657016405 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.14.sigs0000660000000000000000000001375612406075657016416 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.15.sigs0000660000000000000000000001375612406075657016417 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.16.sigs0000660000000000000000000001453512406075657016414 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.17.sigs0000660000000000000000000001453512406075657016415 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.18.sigs0000660000000000000000000001500212406075657016404 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.19.sigs0000660000000000000000000001500212406075657016405 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.20.sigs0000660000000000000000000001535312406075657016406 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.21.sigs0000660000000000000000000001547012406075657016407 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.22.sigs0000660000000000000000000001547012412743715016402 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.23.sigs0000660000000000000000000001547012474026560016403 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.24.sigs0000660000000000000000000001547012475451205016403 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.25.sigs0000660000000000000000000001547012536700232016377 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.26.sigs0000660000000000000000000001601412617125507016401 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.27.sigs0000660000000000000000000001601412661701312016373 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.28.sigs0000660000000000000000000001601412661701615016402 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.29.sigs0000660000000000000000000001601412746331032016377 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.30.sigs0000660000000000000000000001701512757257013016401 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.31.sigs0000660000000000000000000001724712775624157016420 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.32.sigs0000660000000000000000000001724713123203631016373 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.33.sigs0000660000000000000000000001724713134750322016402 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.34.sigs0000660000000000000000000001724713202267000016373 0ustar rootroot00000000000000_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) tevent-0.9.34/ABI/tevent-0.9.9.sigs0000660000000000000000000001276112406075657016335 0ustar rootroot00000000000000_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) tevent-0.9.34/Makefile0000660000000000000000000000123512406075657014525 0ustar rootroot00000000000000# simple makefile wrapper to run waf WAF=WAF_MAKE=1 PATH=buildtools/bin:../../buildtools/bin:$$PATH waf 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 tevent-0.9.34/bindings.py0000660000000000000000000000733112536700232015223 0ustar rootroot00000000000000#!/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() tevent-0.9.34/configure0000770000000000000000000000064712406075657015001 0ustar rootroot00000000000000#!/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 $WAF configure "$@" || exit 1 cd $PREVPATH tevent-0.9.34/doc/img/tevent_context_stucture.png0000660000000000000000000005260012406075657022125 0ustar rootroot00000000000000‰PNG  IHDR-^ÆÕ¸×UGIDATxÚí½w\TGÛÿOï¤I D, Ñ;Š4–[ ¶ƒ±Ý&Æ’¦b¬Ñ<‰1¶X"Ñ;v%±5‚ EEEEP ŠbC$¿Ïã|³¿}¶¹,,ì.Ÿ÷¼ØSæœ3sÍõ™kΜ£¿ !„êÈY@!„:D!„:D!„P‡!„P‡!„ C>¼páÂÎ;W­Z5oÞ¼©S§&½`Ú´iß}÷ݦM›Nœ8‘ŸŸÿüùs–!„P‡*‡¬¬¬¥K—¾ýöÛþþþ¦¦¦&R¿@z pvvîØ±ã¨Q£~úé§Û·oS–!„:T>ž›ô‚‰'<¸sçÎááávvvÆÿ€mllºtéòõ×_#N*++cùBuH™™™3fÌ 433Úƒ0hàÀË—/?}útqqqiiés)Ê^ ½ „úùçŸ?úè£ÈÈHkkk‰ uïÞý÷߇ȱ !„:$ËÑ£Gû÷ïïääÍ€ü ²ùøãÏž=ûôéS¡7åJM"N7oÞ\°`A‡¬¬¬„ µlÙ299ùþýû !„:ôÿb (èOCÔòÆo¤¤¤ÝÉÉÉßßÿÔ©Sz7w΃bcc---ûöí{çΆt„Rsu())ÉÑѱI“&×®]Óë—+¸ù~ýúY[[¿ýöÛº?ØB¨CÿKff¦XPuóæÍ°øé… ‚ƒƒ-,,¶nÝÊõŠ!DtHŒ‘{çw &€˜={¶““S‹-®_¿Î±s„¢Ó:tôèÑÚµk[ZZ9rD§f«÷îÝ 311Y¶lçû!„Ö¡Áƒ#9rdaa¡!=ö¢E‹\\\¢££srrh„¢£:$Þ ÙÚÚ¦¥¥Øè²ââ∈SSÓ-[¶ð-!„è¨Í™3ÇÙÙ9>>Þ ?üœ}º···Ïš5k ï¿ÿ>??¿äädÉ’Ûø?22ÒÞÞ¾mÛ¶iiiÏž=+o *Ø·o_LL ‡ö}¬¬¬¦OŸÎ™!DçtèñãÇõë×711ùõ×_ òÏÌÌÌÀÀ@KKËsçÎՄϤ!DÏtŒ7ÎÞÞ^LQjxOž””äèèøúë¯çååÑ!DuèìÙ³vvvéééöÿáǯ¼ò ¢½7r:BÑQ 666†7ZAŒPˆŠŠR±N+!„êס#GŽx{{[YY½tM =¢¨¨HCK—.åÛ„¢Ó:TVVöÖ[oY[[2¤  À0žyîܹÎÎΆ²³³9BBtZ‡À… ÌÍÍ·nÝZ]ÓžV"™™™uêÔÁãp¡BÑ“'OvttlÖ¬™ @x‡¿9B S‡îÝ»233›2e þ×ß§]³fM­Zµœ o !„²Çûúú"’Ø´i“žvgedd„‡‡›˜˜,_¾œÃ!DÏt¨¬¬lêÔ©ŽŽŽçϟ׻`ÂÓ©S' ‹øøøÛ·o³à !DÏt””” 0ÀÆÆ¦M›6z·jܨQ£ìììš4irùòeŽ‘#„½Ô!““Wnff†¨BÞó#’srrrvvÞ³gÔ”¥N!úªCàÏ?ÿ 211yï½÷ uÿ ,Xàêêjii¹nݺG±È !D¿u¨¬¬,55500PHÑíÛ·u¹›K"B?ýôÇ&Bˆ!è¢@Šâããoݺ¥›R4iÒ$'''ˆÐ÷ß_\\ÌÂ&„Ñ!™¨¨M›6—/_Ö©t}FŒaooÏHˆB S‡„ýùçŸfff¤mÛ¶éÈwEíÛ·‡9;;ÿüóÏ|'D!†©CBŠrrrúõëgcccmm””Tí³-¬Y³FDiMš49xð LˆG!Ô¡—PRR2iÒ$GGGccãæÍ›ïÝ»·Z¼fffÿþýmmmŒŒâãã³³³9s!„ÔÑáÇ5jdfffaa1|øðË—/WÙzEEEE_|ñ…··7 ggç•+WrT!„Ô,Rt÷îÝO?ýÔÅÅz`mmýá‡Þ¼yS«AÉÇ¿ÿþûàà`³¼õÖ[—.]2˜õú!„:Tn :çÏŸïÓ§tÈØØØÞÞ¾ÿþû÷ï¯ôžºÌÌLhž¿¿?äÇÈÈ(**j×®]?f‰BHÖ!‰>|ø7Þj$F Lš4 õìÙ³Š¤œ››»pḸ8$ BÊ+V¬@(ÆYã!„:ôÿU±ÑçŸîççgjj AÂß   ÄÄÄU«V;wNͩޮ]»¶}ûvÈXtt´äIYZZvéÒ1УG¨@„BR%HŠ”””wß}7$$ÄÌÌLDHÀÍÍ-22²gÏž ãÇŸ2eJÒ >ùä“!C†tíÚ5""ÂÑѧíòÓ©S§ùóççåå•––R!„:TŽðÊéûï¿0`€’TcddäààЮ]»áǯX±âÆÏž=£üBu¨4éþýûçÎÛ¶mÛòåËgÏžgmm5qâÄE‹mܸ155qOIIÉóP~!„:¤YÌŸ?ßÙÙyôèÑ’,!B¡U_}õtè?ÿùÏ_ýÅ‚!„êuˆBuˆBuˆ:D!„:D!„:D"„B"„B¢B¡B¡Q‡!„P‡!„P‡¨C„B¨C„B¨CÔ!B!Ô!B!Ô!ê!„ê!„êuˆBuˆBuˆ:DˆbŽ=:{öì$RµìܹóÑ£G,—êÊjê}SMw1:j«««1©Z^êvX.ZÍjê}SMw1ºVÖ¨QQQãÇŸL´Oll¬µµµ::ÄrÑ^VS‡è›jº‹ÑÁ²=ztAAAÑ>óçÏWÇí°\´šÕÔ!ú¦šîbt°¬Y t-ÃY.ZÍjê}ó÷L#¡Q‡XÒÌæËš:Db ¤ob¾ñžU™™9iÒ¤€€€«W¯ªsüÆ[·níèè¸`Á‚û÷ï+L§N:¦ÿ••¥¥›WvÐ!]+ ²š:Dߤ÷u ‚.†e­&M›6533322º|ùòKþý÷ß½½½×­[WXX8a„ðððììl…éãÿ‹/–––¦¤¤Ô®]åhgg·eË–'Ož(,eeVqëÖ­Ÿ~úéwÞñðð¸råŠô®ÒÉÜ¿讕‹YM¢oÒõ: 9g%&&º¸¸´jÕ*==]²«‚.F_Ê://Ϩ½ˆá¥<{öL>“•1°±±A âÿç/P–Ž(kñYY<)) -hɱcǤKÏîçç·k×®Ç+¼h—.]^yåKKKe7)}­ÊÒ!–‹Âr)WVS‡è›t½HˆŽŽÆé Ð-‰†UÐÅèKY¯_¿¾V­Zêä³öPX. 366Vv¤t:òiÂ뉡¡¡”¥íÛU\Gª6HmèËEa¹P‡jÕœ:°mÛ6OOÏo¾ù¦¸¸-/ü?kÖ,I·žÁëЭ[·"""LMMõ¥¬U©º¬ÅƘ˜[[ÛvíÚåææª©C/½t¥ëË…:TÓu¨FÕ#FÀúwìØñôéSäC@@@\\ÂÁ¢C]ºtÝM(n777ñ-99922ÒÞÞ¾mÛ¶iiik×®…<‹núÖ­[Ã|8tôÈ‘#!ˆ¨¿¿ll¬Ìˆòº˜íÛ·+Œ‡©899I|\BB‚ä}¬f»ÆC3gάˆ¿ëÚµ+¤.&&&;;;''§iӦ׮]»ð300°E‹ˆ¤ñ¿$e§¨(kÄgˆ;“““?~ Õ÷óó“.2õËZE:/õwÂå!Oììì¤,•¢‚ýr/DXÅœ¹,™r¡†×_Ž¿5¼lܸÑÝÝ}Ñ¢Eå·­ÚÅ(¼Ï’’$îíímee5hÐ dˆdÄf»v·–×߉~?´zõê…’‚6Š©©)J°OŸ>wîÜ‘Œ€l£Á!ýi¡ÂSîÝ»Ã@Öý­ï‡X. Ë…:d ̘1íkT*xRÖøèV›6m°·ÿþ2—«ÜqÛÑЖ×ÍvU¼lÞ¼ƀ삇}ö쮵téÒÄO;wÎÈÈv»{öì0`€¤÷Ur{ò§ˆ€ÀPF2?Å)ˆ>½¼¼>6lØVtàÀé™]ä‘NDò:AY:ò1½xU)ÞYJ÷mBcÐRaf’sž®%b¹(,ê!ðÇøøø˜››C'fÏž]Ãë€ //¯wïÞÐæ:œ:u꥽16Ÿ‚9(œ$ŒS­ˆ µPþ™Þ-ùÎ.É)"MéP†Â3eéÈ\éÿE&åÜÜ\ع:×Uxº6tˆå¢°\¨CzÏÝ»w£££ÍÌÌ>øà䆊¾šR$à™ç­9:d¨¨ÿ~Q×âºZ*êÞ3bÄ;;;Éj¬Zu1Ô!êuˆ:Dú?$''»»»ÛÛÛ8p@¼Ga éaaa6J(כּ 4°´´´¶¶ÖàÜòÞ°å lý!]+ ²š:¤[\»v-44ÔÄÄdîܹ’Á`¬Zu1Ô! (UNE’ªšÖ ÃY.ZÍjênÙP¯^½¬¬¬ºté"ýe ë€V] u¨&Ã~9]Èjên•“‹‹‹··÷éÓ§¥0gjŽE±¬©CÔ!ÖÀjãäÉ“þþþ&&&«W¯–ùÈŸu€:D¨CÔ!Ö@íR\\üÚk¯™››:T~9Öê¡Q‡XµËøñãíííÃÃÃÅW¢Ì™®CQQQª—! •…Š ÎY.U–ÕÔ¡êgûöížžž(¡””ùùIY´íbtP‡ŒI¢l‚s–K•e5u¨šÉÍÍk{O:U,Ä:PÅ.F§P67Ñ*Êf^g¹TMVS‡ª“²²² Í#=6ë@Uº]3 R-°\ª1«©CÕÉ’%KÜ^pâÄ ÊÐpµêb!Õ u¨ÚÈÈÈ666þá‡>|H[$„P‡¨CUÇãÇccc-,,  ½D!„P‡¨CUARR’££cHHHff&;Ž!Ô!êP•²oß>ooossóÍ›7«^;ŽB¨CÔ¡J¦°°°Y³f¦¦¦&Làw©„Bªj†jkk}ãÆ Ú!„P‡ª”5kÖ¸»»;::þñÇ2˹Buˆ:¤]²²²êׯobb‚'}ðàú'=ztöìÙœ§§*Ù¹s§.ýJ“ yP‡¨CåÑO÷îÝ---{ôè‘——WÞœquuå$=U‰ŽÛ!M‚æA¢•›9sæàé|}}Ïž=+½Æú95~üxÎÓ£mbccuvTš̓:D*©©©P SSÓõë×?~üX³œ=ztAA'éÑ6óçÏ×};¤IÐ<¨CÔ¡rPTTÔªU+33³‘#G2gt½Èmšsž:Ä.cÆŒ±··å•W®^½ªÙÔ 4}Ú!M‚9ObkȦM›<<Eßuˆ&¡¬|ËÊÊ]bª{TÌcÇŽI7JpK~~~»ví’Ѫ§æA¢ý/§OŸ011Y¾|yÅ׸S‘3ëׯ¯U«–ŒçÕ6ê_´ŠoOÞklÛ¶ÍÓÓó›o¾)..†‹Áÿ³fͺÿ¾ëMBµI@ÄÆÐÐÐÌÌLiÄv™£Q‡ô•Gµk×ÎÜÜ|РAùùùÚË™[·nEDD˜ššV¥ÓQÿ¢U{ò^cĈ¶¶¶;vìxúô)rƒ¸¸8éù, L‡hê„ÈØÃ@=ÍÍÍ¥Q‡ P‡>ýôS‡zõê]ºt©RÖ¸S–3]ºt±´´D=AÅvss»zõ*6&''GFFÚÛÛ·mÛ6--míÚµD¯wëÖ­Å›*xgÜ!¶¬Zµ ª)sʳgÏÐNœ2eJ``à¹sç’’’¼¼¼|||pVxQ…È™’’"ÒÄ)’ô/\¸0}útooo¤¿fÍÜÞûï¿ö²ŸŸŸ¸œHJÙÂM;v¬C‡¯½öZNN޼×hÙ²¥™™®‚‚@ËàÁ¯\¹R¹Ž¦´´tΜ9¾¾¾pm‰‰‰ÙÙÙ’V¶f»hÚ3 Qèééé±±±¸™J‹Ô!êðo¿ý†* ûÞ¾};ÚàZÍáX¥ßÌ㢸ú† à,Po¡…ðn¨ØÝºukРü¯ÐEœØ»wïãÇ—””ÈŸrýúõæÍ›Ã}#å©S§¢2ïÝ»Lj]òU†Ì‘Mš4i¢V7mÚTü¿`Á‚Û·o‹Þ3ø\~çàÁƒpCâr  Û%),Y²dË–-¸a<©¼×ÀÁÆÆÆ’-8gI¿ÆPæh¢££'Nœ¨æ—sçÎuqq1z.7xðà‚‚‚Šì’ æ32dî'$$$è\]]MLLh˜„DoCÉpÊ´iÓÄpVêuÈ øÎ;°l´õݽ{· rF¦žôë×ÏÚÚ ÷ œØµÿ~Ô[¸3áéà†~üñÇ{÷î);­K1R!¤KÝÜÜ\xp…uû¥½"’4•¥¯ìr ïM¤OÔD$!cuêÔ‘Þ‚,,,ÔÑ¡rMpÙ¨Q#ÜžÑ?XYYI.¡Ù.雑Ìgj$MB“ÖRø‰,[¶ìáÇÔ!êÞ0ª š´666­[·®Äq¨p_~ù¥š:T¿~}8,ÑØHî­U«V¶¶¶Ø…ÿÇŒ#J®ì™”¥jætT'¢â§šw¨pKãÆá­p®è‘„tÇ‘2G£l Q´Äå㡆 J+ ¢a‰¢h¶K:š9sæ;#Ö=n>àH)Œ‡h/5 iƒoݺÕÃÃÃÞÞ~×®]¾¾¾Ô!ê~ðòåËkÕª…GHMM­¬5îöìÙoõꫯ*›âW¦žˆæÿÎ;å»,Xçµxñâ… ®[·®¸¸Xõ)ºãtÔ¼C…[†W{äȸ*øYÿØØX™WÓ Š)DåsöìÙNNNEIHH¼rÐl—tãF¼Ù¥RÌ›7Oͦ MB…‰ùàééiffF¢éqgff¢n ¶hÑ"I}®Ož|½$ü¸jïµ»{÷ntt44õƒ>¨ ]BÏ7nŒgD¤¸páBéw4}5Qÿ-…ë© IP‡ D‡nÞ¼ùñÇ‹©m¡ø'!!!99¹  Ò¢lБŠ”ФóçÏOž<¹Q£FpÖP#77·qãÆ•ë+ôJgĈ_ägÏ,h‚Íž=[|&Ò¬Y³ÔÔT™•ŠhúÔ!êuˆ:TŽž%D*¾¾¾¢¶I“&ß~ûmaa¡:»úšôÛo¿õë×Ñ7ÔhÊ”)bˆmç”ÕÝÝÝÞÞþÀ¯qwõêÕ.]ºXYY!¨3fÌ;wäD—M?,,ÌF U<å3hР‚okkku®.îÜò\ˆ&aHæQ£uhÇŽ‘‘‘V @QQQ¿üòKqq±6äA¨QzzºDÂÃÃSRR*ku¸víZhh(²¹sçJ÷¡• dQ`` ñññÙ¸q£²÷^ºlú¥Ê©Þ›Ñø`êP5 ƒ1ªC(’Ñ£G;88@ @›7o~øð¡¶¡FˆE5j„`ÂÂÂâã?®ÄÙtTÛh¯^½Ä ”‘þ(R}ŠŠŠF…ƒfwëÖMõÄ\4}ºxšsž:¤Š'Nˆ0¡ÉÔ©Sóó󫲋 ×B!Ö¶‚ ¶oßA´¶ßÁ]\\¼½½OŸ>­ÁµcPk䘭­í—_~ùÒ%Ãiút44 æ|¸²fÖ‘çäÉ“þþþxäÕ«W—w9‚رø/""âСCêô%ÒôéhhÌyêb.\èææfdd4f̘¼¼¼ª) #E999qqq–––~~~; ‚âââ×^{ ¡ÌСCågéWÍÍ›7{õê…¨6lذÜÜ\5sŒ¦OGC“`ÎS‡‹«««™™ÙôéÓÅtñºÀÝ»wûôécmm­%)?~¼½½}xx¸ø¨[ý·lÙR·n]„kžžžëÖ­+×bá’ ®ˆC*—N:)›UV×¼!M‚æQ£uhÁ‚!Dßÿýƒtê‘=z4xð`[[[HQåvÐmß¾*+,ר}ºuëÖP/Žš ç‹ÐL&UˆÂu†tšÍ£Fë*€¿¿?³fÍzé@¯êí Cˆ­]»v7nܨà»+œ>`ÀhILLŒêé„%@ü/^ìåå…¼jРÁž={4ž}®ŒTº\oY:4š«C7oÞë^;¶°°PÇŸíúõë"‚?~|¿+Z²d‰Û Ä´ó/=>//¯_¿~¶¶¶¡Aƒ!ßôb BÑi‚ÿíÛ·/b‚öíÛÃÅëE‹`ïÞ½b2ì­[·j<ÛBFFFpp0å‡~Pg|Áo¿ýfffÝZ¾|¹nv]BˆþéÐܹs===;¦½¯s*½ûbòäÉŽŽŽ†Ë—/k ?޵°°0`€ôbÊþì³ÏÄbϯ½öÚ©S§ô%£!D×uèÚµk 4011A¿\cŽ«{÷>úè# zçÄL !!!™™™ªeìüùó111–––-¨Ñ_ýÅNdB©4zçwlllÔ‰ tßÿaœ‹‹ ”r½§Ù·oŸ···¹¹ùæÍ›UŒ2€Þ@ž}|| ÓP¬;wJ¯²L!¤¢:tôèÑÚµk;;;«ù–^×€NtïÞ‘J¹Fý6kÖÌÔÔt„ *Î*((4hXDµÿþ9$B*Y‡zôè'w\5³Yk5$:w:1tèP[[Ûèèè7n(;æÀfffNNNß}÷Æ @¢h#Ξ=›ÓT;;wîäEZÔ¡?þøÃÛÛÛÁÁ!--M[ú‰âââ,,,¦L™¢ÎW¨kÖ¬qwwwttÄã+kðôéÓéÓ§CØŒ¡Uˆµ7Ç+} ý‹2¾úê+±’/©^8Âvuè½÷ÞCX0|øpÝÿ`H5bùÔzõê]½zUõ‚¬¬¬úõ뛘˜ ’+œµtêÔI,¢:nÜ8m/uA_Cÿ¢Â6ÄDsãÇç4ÕBll,gœÓ®ݼy388ØÒÒòÈ‘#úøfH„5-[¶„rüúë¯*à0ñ2©Gyyyò¬[·. *åïï¿iÓ¦*h,Ó×п¨¶Ñ£GpŽƒjaþüùœ[»:´xñb´Äãââ4[uT×øüóχ ¦"¶›3g¬Ê××÷ìÙ³2ý÷îÝùöööFFF={öDTT5ÚL_Cÿ¢Ú6èY†¬C]»v“jƤ‡òòòrwwWöMkjj*ÈÔÔtýúõ2c¯=Ú¬Y3sssè,¯*çÖ£¡Ó¿Ð6X5T‡233á”mll222 ã“ÌgÏž½òÊ+&&& »æ -­Zµ2339r¤tÀ„ çË/¿¬U«–±±qddä‘#GªxÙY:ý mƒEPCuhÙ²ennníÛ·7ŒN9Á|`gg§pn…1cÆ ÖPIdÈÎÎîÞ½»µµ5‚¤Q£Fݾ}»ê%™†NÿRCl£OŸ>¯¾úêÍ›7+1M´§'Mš€zŸuêÔ1ý‡¬¬,õÓQv"«§vuèã?vppøä“Otg¹ÕŠ#FÍõêÕ Š"½}Ó¦MþöìÙ# w6…„„Àìj×®«kB#ú­ú½ö/†g-[¶¬\ÛhÞ¼¹™™™‘‘ÑåË—ñ388ÿ_¼x±´´4%%U厶é–-[¤ûH¤­BFé ‚‚‚$IQ‡ªB‡:vìhaa±nÝ:™¥&//FP®&Œ<çÎóññÃB #Ù»711™9s¦xñóàÁ„GaØ\çÎ/\¸PÃék*âk$Ç&&&º¸¸´jÕ*==]²K¯ý‹Š›¬”úRÅ•ôù *÷–ž={&]¸Â6ÄÿeeeÈ71‡$š¡ÇŽ“¶ <…ŸŸß®]»¤ ôéÔ!­ëÚþõë×766>yò¤Ž|¾º~ýúZµjI[€fÔ­[>KòY®d=‹ØØØ[·na ŽŒðhÖ¬YÕÒ×TÄ×HˆŽŽ†8%$$4mÚTº!¢¿þEÅMVV}©–JZ¹H®|ACÄÆÐÐPÖÒÆ‰í2ÏBªRÊÈÈ@Ü€ õÚµkºp£P±¨]ÅM¼C‡æææ’0|Ñ¢E®®®h A™àÎ.\èéé F„´ÿ~W-¢¯Ñ)_³mÛ6ë7ß|S\\Œ.þG Cz&Ó¡J¬/ÕRI«Ò6ÄÆ˜˜[[ÛvíÚI¿§U³:tÈÛÛû_ÿú—^Jrrrdd¤½½}Û¶máÐ×®]‹ª.ºV[·n-1b„ƒƒ¶¬ZµJõçŸûöíƒY 5˜õÁƒKJJºtébii ÀénnnV$]·‹/¼j¾xLLLD #\ÒéÓ§ÅG©Ë—/ǹ½{÷Æ.ˆÐ!CpÏ:2J¾¦â¾¶/³cÇ4,(ô¸¸8éï” L‡dê‹xm¦A%•9 5D S¦L 00¯X±BýùFÅ£ÁùâDx1ü…»üí·ßTL~Z.P]?~üàÁƒ»wïÞ¹sµ¾žÞÿìÙ³éééDŽ9ràÀ={öà1‘lÚ´ ÉÏ?ÿŒø‘Á?üðí·ß~ýõ×ÿó?ÿóÅ_@2•M¸I_£¦¯ÂÁ×ã1EAçàÐ¥;UÄCü±ü,¨(5y“kذ¡´¢àö$Š¢Ù.ùxѼômÄÅÅ©iPI•R)¶ 2nÜ8DÃ0¿Aƒ‰’ôéb8Ìœ9sP7ÑÜD)ˆoÏU\ýÌ™3-[¶DÌ -A¬¬‰Ê"2ÄÓÓÆIÒÓÐÁéÀá¢];Œ²ÃOHÜ ¼†|“M!bÙ=üÍÍͽ~ýzTT”Â~91Þá3ÒG³ú¥«9È<œ²¨ü8wðàÁÇ÷Ýwßyçöïß¿wïÞ={öÄsuêÔ wÞ¦MøqÜI“&MÐzÅ).\Í%«›››““ÄmÃpM•c¢¢Í«ŽÑ×(»C”/ HL ö÷÷•¥Ð¿¨˜^VþygÏž K(Š$Ôx— Ê&cUXOežHƒJªì”J± Ѥ8qâ*j臗>¹?üí$´`E’ŽWG=EÜ µFKEÙ]½T‡D>£º‰E–©Czó~hãÆîîî"¼€áöéÓq€d/ Pÿ{X1µRƒI!Ù·ÞzK¤&º/à1ÑúƒùB*Ð&EšpL>>>;v¼té’:o‰Äû!ܧðï¢S¾\©™`ee#ÆUàd½¼¼üüüЇt………EDD >GGG·nݺmÛ¶:t€ÔuëÖ ²‡'‚¾ýöÛ¨™Ã† 9r$Ô@x$¨ŽÑ×(»Ca¢‹-Òê¸mDðH‚Šò‚ÙK/¯Ù®ŠôÙJ×”¬•Tá)÷î݃!!¯Ä—…2?e.ªºEÌ]róæM4ò`~2IM:5##Í#4$¢úê¨_¢+åðá₆"Eécä Žº{÷né˜'OžÄÇÇ£D¨CÕ©Cÿýïa‚ÿþ÷¿Õ/‡æÃÒ¥KCBB¬­­;wî ë‘~ƒ k0`€šã¿EjPÁ€€¢¢óçÏ‹Ô6oÞŒ‘‘‘©©©¢;ƒ-zQ[Ô·-ÆËI^‡@&L˜€p±Â?ü°bÅŠÕ«WÿüóÏ6lÀ!uhªïÝ»÷àÁƒð}p©§N:wî\ff&¼*Â5´©!ÕhÅ£íÛ…s,UÎsP±}š¾éCï¡ap:{´d>Œ«,ÿë•”u¥ìÒX‡¤ë ÌRƒJªðQÝlÕMæ§ÌEUÜ92•.** ÿüòË/°I™¤BCC¥û`¥å¡Ö*®¾råJ ÁãtïÞ)Ã6|}}¥‘ïB®@¼"•v ¨×h·iÉNˆZ:täÈ”¨Â÷ŸT¿òÖ.…©‰Ø"Ù+*’´£W'ñ!C†ØØØ :TÒâââòÍ7ß u¬æÊ4º3N¾F_#ÈËËCĉBG ŠÆ„ŒµÞ| ÒõEãJ*ŠLu“ù)Q¯QÅEÅ?òI¡Á„ƨèîFãÍGÐK¯.“²Ì1òÝû*Z™2NªR}èÈt1XÖóæÁ™ŠAÃb´xýõ×e7}aøéNBewnx:¤ïìÞ½û×_EëPë7Z¶lYñé]ÊÕ«¬ÎéÔ!-êÐß/ÆÔš››Ÿ9sFGæ—«,Äs¥¥¥ MjÞ¼¹›››ø0ó»ï¾ÓµEÿèkªÀ×P‡t „Ñ“'OFƒþçÁƒ3gÎTsÀ-uÈ t¨{÷îh¥*\2®‚„……Ù(AÛSvŠÅý$óæ!B{ÁдiÓºuë&b#üS½lÓ×P‡ À6*XÍE¿««««]‹-~ùå—JYx¥Aƒpk¨éåõ6âq,_Àõ‡ªN‡Ægoo¯pɸ ¢âM¾¶xË–-:tŒÙýñÇaë...‡^¶l™¿¿¿xQñÃ?èH`D_£U_£×þE—o²‚Õ\Òïªf'°wU)'R‡´«C›7o†ËîÒ¥‹ôtúŽ,'=OL|РAðDbq6ÄIo¼ñ†Œzöì©æXpúýõ5zí_èY®CðÔÁÁÁŽŽŽðÅ:2ótśʌ]¾s玘ßpâĉþàùøø@м¼¼–/_^]+±ÒÐ™í´ ÚIÖ¡¿ÿyEôóÏ?ëÈ’¬áNPPƒƒƒ˜ÞFz×îÝ»===ñ°b]"ì½råJ=¬¬¬ F½{÷ÎÊʪ®Àˆ†Îl§m°j®}ùå—Èb5¿fÕ}æÍ›‡Ç‰‹‹“žÐEáË#«üýbRÎ%K–Ô®]Räíí½zõjõg±£¡Ó¿ð&i'¤tèòåËbY”³gÏÀèm1‡ÍÒ¥Kö³!æƒDYXXôíÛW2 éÒ¥K8QFýúõ»zõjg þEõMFEEMœ81‰Tbé VO-êèÕ«\ðçŸ.†Ò_ÒÒÒ|||jÕª% wäÁ®蘈L²½¤¤äÛo¿õôôÄ.óºuëª20¢¯¡QmƤZQ6 1©4JNNvww¬¢¦§ˆõ[ß}÷]e‹Œ V¬Xáææ†º}äÈé)=ðìP©Î;#¢255}ë­·²³³«&Cèkè_”!¿©®B*M‡?~,ÖT†7|ðàž>çÍ›7ƒƒƒØ:tHõ”h–ÄÄD<µüòzŒ¾þúkFÐfÉbÕô5ô/ÕBÑ('ZÔ!°víÚZµjéuH$Æ ÄÇÇ«3à"??_,_=~üxùox‘;vÑ Aƒnܸ¡Õla §!¤¦ëˆöíÛ[XXL™2E,&­_\»v Átå÷ß—YãUûöíóööÆ#oÚ´Iá´FOŸ>7ož»»;£   ÿþ÷¿†1´BtQ‡ÀÁƒ}}}]]]?®ƒ3R«æí·ß¶±±0`€ôbÿüs„PИóçÏ+›¦úÌ™3íÚµsE2$''‡ÍgBÑŠÁ½>ÜÎήM›6Ú\¶nÝêéééì윚šZ.E$F%ÄÇÇ«06wî\777FuêÔŸÁÒ°!¤’uܾ};**ÊÜÜ\zçòóó###MMMçÍ›'½´š\¼xÒùæ›oTÌy UNOO‡B[XX Þ{ï½ÜÜ\F„RÉ:öîÝëããcmm½mÛ¶§OŸêþãõíÛw«p5ùé§Ÿë8::>|XÅ@;¨ÎãÇgΜéêê ݪW¯ÞöíÛBH%ë¼íŒ3œœœBBBþüóOQ´`ÁÑ#§z¬¶êG:t¨­­-bÁ7n¼ô`dKëÖ­-^0räȼ¼<F„Ri:ô÷‹hzöìiee™••¥³NvýúõÞÞÞfffŸ-»   Y³fHjìØ±/ý¤òèÑ£iÓ¦Aÿ…††¦¤¤èEìH!ú¡CàîÝ»íÚµC{ ]XžGž?þø#((ÈØØø³Ï>«”Eü<U377߸q£:½mP£cÇŽµlÙ§ £Þÿý;wîh¬ÙG={6'Ú1`vîÜ©k_ËÒêh:­C ;;[ô>µiÓæêÕ«:8p@ .>|¸ê)|4è ÈÈÈPGzqJqqñäÉ“q±aÆ»wïÖ,0úꫯ\]]9ËŽ£ƒ³Ñêhº®CÒRÔ¼yó³gÏêÈ»¢;vˆ‰J+Q„ƒºtébiiÙ«W/õWÁ€>|XŒ3Ĺ~øa~~~ye[2Ïéøñã9ÑŽ«›³©Òêhz CBŠÄ`åúõëëÂ[U«VyyyAÛGŽY¹"$¸|ùrݺu!råšjªƒƒ?ùäGGGÜ[DDľ}ûÊ•WÂ#Œ=ÅYv Œùóçëæê´:Z ~èxWôïÿÛÊÊ Šš””T]ß¡Â888M˜0A{ºfÍšZµjáB//U†çϟ㔦M›"0Bv}ôÑGê+%×2`t¶piu´@½Ñ¡¿_Œ ›>}ºx ÒºuëS§NUqÝÑ£G_}õU„e666?þø£ŠN+åEѰaÃlmm›5kvýúõòž{ÿþý‰'BÆWMš49xð :óÝÑ#Ð ðÆuèåvïÞ½uëÖ555ussûôÓOoß¾]ƒ>|ø?ÿó?pëAAA»wﮂOGQZQQQfffï¿ÿ¾%‡Àhß¾}7F "‘W/M„^€7F¨CjIQvvöСCíìì  ~~~óæÍ»{÷®–Ô!ך5kÂÃÃÍÍÍáЪr¹î?þø£víÚ¸î/¿ü¢Á4ÛÈ“{÷î‰uùWÍ›7?|ø°ŠÀH=BŸ>}ªÊ/ãT•dffNš4) R¹·T§NÓÈÊÊÒì`ê­N{V§/hT¹ÉA 8 zÉLLL F(ŒœœœJTdÖòåË[´haiiiddÔ²eK„AU¼æ„dÖ¬YNNNxÀsçÎiöt8 w=³µµMJJRö©“^{…Ë V%b))˜ÊåË—+÷–‚ƒƒ‘ìÅ‹¥;¢ ]\\Zµj•žž.ÙUúDí’;¡Ñê*hu)))hCWÐú—™aYZu„ðè²UzŠðÑOŸ>E°Ò A”Úûhõ÷ï߯ xNÃ#äàÑ£G‡ æãã#’Eú«V­zðàAµ|½„gìÖ­´ðßÿþ·úøåó y2fÌA\NA¤ÂPòòò`XåjUõ/úüÕ땟ÒuO[Ró…G®Ò >>>::n1:œQvv¶êSôQ‡hu:buˆE>=<<Ž;&ÝîARh(ïÚµKº™®›h¤¥tÅô6?ÿüs§N Õ&/€·…מ?þž={à»_Z0> |²Û¶móôô³³£Lñ?âfé‰Þ C‡hu:eup¶bchhhff¦´WÄv™k–I2™’žžß*ü,„Dh’……Ä*õöÛo# ˜4i’˜^b„ PÎ;7jÔ"Sp°¤0vìØ´´4„Ÿ:2ƒ„V ã>pà€ÆS©ŠŒ*((1b„ÐìV­Z?~\’ 2C¹uëVDD‚œÕrѪôê? |²(A[[Û;v \Fa¡ñ‡vnåz4uçÌ™ãëë‹k%&&"ä’¸Ív•K‡huºfubcLL J¶]»vÒk P‡þ“‚tæÌ™E‹ <9nmmýÒ©& BPø¾}û"$ºtéê6Ñ©9„Äò€(þ&Mš”w·ÂÀ jÑŸ‰ÀM颢"†"æw€U‰aŠâhrrrdd$NoÛ¶-4{íÚµh•‹>bÄ‘0wá.¡Ø²jÕ*„­2§@ÿЪš2eJ``à¹sçÐ8ðòòòññÁa8XáE"IÇHþ¿pá%ÞÞÞHpÍš5¸Ÿ÷ßZîçç'ÒWÿHqù›ÛSSSQ'‘o .ôððuOú–DO=HÓÊÊ ­œÕ«W#W'WÅUä«tË–-Qv¸sað8ù|åÊ•ÊõsçÎuqq1zª *”ä[4Ív•K‡huºfub#šû±±±HdàÀùùùÔ¡—GHÏ|êÔ©7.[¶ 5dòäÉ“^çûý÷ßoÞ¼ùìÙ³ÅÅÅhÄéšöÈp÷îÝ-ZÀûŒ=ºâ‰'… ½ûî»Ð6F¯½öÚÉ“'¿üòK…†"<ô«òíÛ·£önذ55§^½zhö¢juëÖ ò‡(r'öîÝ!WII‰ü)ÔæÍ›‹·¬S§NÍÉÉÙ»w/Ž»ä/ª éWµ’ÿ,XpûömÑ…ªŽôQÕÅ4²"}õTø¼bûµk×êׯj‰Ç_±b*¶ÌmˆzˆÊoccƒ4:T»vmwwwœ¨N®Š«ÈWiì‚‹—lÁ¸œt¿2/ЫW¯O?ýTÍÙ'5jÛ0ú¸3É%4Û%™Ø´S§N §{¡ÕéšÕIô ݵ¦M›&š°Ô!uã$eü­?9rDŒžX¿~}¥ŒÜƒQB‰ayh9::²!K Eƪúõëßwƒ…»»öïß›F+L4á#~üñGñJá)’·¬C%ÐæææÂs©Ùá ýªVa‚ ÓWÿHÏ;a´"áÄŸ¾@þ6Äa;wFjð"YÉxV5sU>êÔ©#½XXX¨£CÑÑÑðMjÎ>Ù°aCiEAXr ÍvIîDfbSF«Ó}«“Ö„M"M´ïfQ‡j°§9sæ ,¡Fã*eôÒD»,11 ¤¾G@s ‹&•@’Z«V­váÿ1cƈ®§È¤,ýSýŽog©Ÿ¾ŠŸÊn¾qãÆ¨À/M%ÖCûöíE¯ˆÂP3‹$×Å‘â} ¼<»t'’Šxèã?–ŸƒbùxQ‹“““DQ$ý0ší’ÄC3gΔ\:..NÙô—´:²:iB>oݺÕÃÃЏk×.___êP ¢¤¤D̳׭[7é÷ÒŒ6nÜcRÖ4–±*Ñ-2™#Åê´‹/^¸páºuë$³);E/<‚²›¯[·®èâPø™3gZ¶lÙ´iSTÝÚµk+»5³ˆ—…ˆá5àsýýýËʼ7VèTL'ªÐØfÍšåíí {4hèÕ©È.…ý*¦¿¤Õé”ÕÉô¿¡ìD¶{zzš™™Q‡jhö6hÐ1b#顺ŒÄô}êx„®]»¢…“““[‡»»ð300°E‹h…áI ÊNÑ  ìæ;uêdaa‘œœüøñc”‹ŸŸŸÄAHŸÞ¦MsssÄhŸª¸5³ Ñàîî¾hÑ"mÛ†Uˆ6²|ð­Ù.õÇ)ÐêtÍêäß¡ Qpvvv ¤80A¸!DÄûöíSgS5QÑ2/ŸÑhêÕ«ŒUøAOCqŸ>}îܹ#9­`´ÖÑ,•~‰¥ð”{÷îÁ}À^Ož< Ÿ%óSæ¢Ên[ú,ܹŠ%?Oœ8¡þ‘ð§ÊžW|ŠyúôéC‡!À)ØrêÔ)éÔÂÂÂpnJJÊáÇEËT¼áS3Wå«4n ÎŽ.£ÿþ¬Ë^ ¼:D«Ó)«ƒAóvïÞ-ísž}åÊ•pð È™îÝ»£ŠÂ#"Q½h Q‡*™¢¢¢W_}q÷ˆ# µíDO‹ôÐvÕÝ2 ;däO)•Bþ§üERªÕ髤êç•l—|* Ù"ó ’cÄ?ê窲ž"‘”Âü1 ¢ÕéŽÕÉß¼4¹¹¹2šMª);vÌ××m“µk×Êvª\@ª‘òNÜb0:DôËê¨C5´wN|yZ»víÓ§OW|7=uˆ:D¨C¤|”””ôêÕËÊÊêõ×_¯ø0n]öaaa6J¨âù˜«ž XZZZ[[«ó°"£,_Àõ‡huUcuúbÔ!m‘jjj:{öì ãÖePªƒ/âr=¬²ƒ©C´:íY¾X uH‹ˆ‘—¶¶¶{öì©È0nö0Ô!‚¦i1—‰]DDÄÕ«W5ÆM@/À#Ô!¢!EEE­[·6776l˜ÆÃ¸éèxc„:D4çøñãb÷êÕ«5ÆM@/À#Ô!¢9eee¢¤½¼¼N:¥Á0nqzTTÔĉ“ˆa¡l™qO´:Z uÈ@xö왘ëIf•èrycb ([ÔCtˆ¥C ¤7nÜ 3551c†X*Q}d†!†‡Âu†ªZ-:d€lÚ´ÉÃÃÃÆÆæ÷ß/×0î2RÐÁþdB ¤à‹¢±cÇÚÛÛ7lØðÊ•+úµö9!„P‡ û÷ï¿öÚkæææC‡-((`†Bu¨ª9yò¤ŸŸŸ©©éÊ•+uí•!„P‡ Ÿ²²²¯¿þZ¬Ÿ––VfÄ"„êníéÓ§µµuÇŽsss™!„ê©jnÞ¼njj:mÚ´òã&„ê©¶nÝêáá¨è·ß~{úô)3„B"UJYYÙ¸qãìííCCC³²²8Œ›B"U̓Ú¶mknnþÎ;ïp7!„:Dªôôô€€SSÓåË—?|øB¡‘*¥¬¬lÑ¢E...îîî'Ožä0nBuˆT5Оþýû[[[·k׎ø !Ô!R äää4jÔÈÔÔ4))‰Ã¸ !Ô!R ìØ±ÃÃÃÃÊÊj×®]ÆM¡‘ª¦¬¬lâĉ 4à0nBuˆTÅÅÅ111 ùùùÌBuˆT5§OŸ 411ùñÇ9Œ›B"UMYYÙwß}çêêZ«V­'Np7!„:DªšçÏŸ0ÀÚÚºmÛ¶·nÝb†B¨C¤ªÉÍ͈ˆ0554iÒ½{÷˜!„ê©jvíÚåééiii¹}ûvã&„P‡HUSVVöÉ'Ÿ888Ô«WïÒ¥KÆM¡‘ªæÑ£GíÛ··°°8p ‡qB¨C¤8{ö¬Æ=xðàI“&%ɱcÇÈ•ü‰G={6Wçø~øáþýû46B¨CD1K–,quu5VÂèÑ£ÿúë/ù³¾úê+…gñxùã!ó_|ñ¥ˆêQÌóçÏcbbÌÍÍŒŒFŽ9éÿ²mÛ6…íý#GŽÌ˜1c’<^æxgggd¬2¹"„P‡Èÿ2þ|¸KˆPAAA™ O)S—>~Þ¼yÈ[ê!Ô!¢Š¯¾úо’yKuˆÐW ¢ƒNY÷!„:D¨CÚEu÷!„:DØf'„P‡Ûì„B"„B"„B¨C„B¨C„BuˆŠ"&>þ?ÿù$ {cbb¦NŠbofff=powïÞÅaH *(oÊŽdáB"ºÎ¥K—: pƒ¤áâ¡""Âxï½÷¦H¿Z½zõ¤I“®_¿Ž&))iòäÉ"‚„ôïßÿæÍ›8}Ó¦MÐ'ɘº‰'":IOOúô)Î’¿ÄÄD¤#ь޽{ïß¿‹8iÔ¨QW¯^'B« jOž<‘¿7Gjç2'„:Dªˆ & † xðàAxx8¢8ô°°°H>âi×®ÝG}Ý!H‡ 9?ÆÿŸ~úéöíÛ¡ï¿ÿ~Û¶mOŸ>- SpØîÝ»…®Èƒ³»H‚$DW-Z´ôÝ!P[»v-nIü2dˆè¯“¿7eGj ç2'„:Dª¨Í%=(`Û¶mC‡½}û6"¤fÍšI$áÎ;uëÖMNNÂÁhܸ±äƒÖèèh—×_ýûï¿/**’ %ÏÏÏïÕ«â$eWï×¯ßæÍ›EšàÃ?4h®.~¾ùæ›§N’ýûä“OÄ`n™{SqdEtˆsUB"UÑfG`!yÏ/úÎ;Ÿ½÷Þ{’Ÿˆ?$/‡ Q/^D˜*,,„@ iÁYHDr˜<õëׇlˆÿùå—W^yå‡~(..[$=„Hyøðá8@(®Ì½©8’:DuˆhW‡*î+ûöí»páÂû÷ï#âùì³Ï¦M›&Rƒê,Y²díÚµŸ~úiAAÁøñãW®\)Qˆ#F|üñÇø+ÆÅõèÑ’õÊÌÌ|ã7öíÛ':âptEÒ]&O‹- i>\´hQŸ>}zöìùÅ_|ðÁ"š ß°aÂ)<éÀq ܌̽©8’:Duˆèºݸq£K—.7^±b…D3UÄÆÆ6  Êi×®]ZZšä­O|||×®]Ïž=+¶¤§§CQìíí!B§OŸ–~¥tüøqÓÄmݺ5äóæÍ»wïÞ˜1c:wîŒ ‰S |ÞÞÞHò6räȸ¸8¡p2÷¦âHê!Ô!¢ë:ô÷‹¾,ȉèU“Þ(ü”ß+ù‰]ÊQ=íö–¾@&’•œ"öŠ Iï’¹7GR‡¡=Ð!¼%„:Dè+u ®?DuˆP‡ª®?Duˆ°ÍN¡¶Ù !„:D!„:D!„P‡!„P‡!„ê!Ú…ëB"¤:áúC„P‡ÛìÕ¬CüF˜êa›:DuˆÐW2o !Ô!B_ɼ%„:Dè+™·„ꡯdÞB"ô•ç2'„:D¨CÕ ç2'„:D4o³‹ïŠ’äPö¥W}馛îèJ’dô}~÷õù¼îyÏSͶÕÔãñÇzý8¯çt¶×£×yóúË$&á`r€É&ðŒLnqqñ€Ø,--ñßà‘šœ ÕˆÍÛ·oùoð¨M®´´ô-ÀŸ)))ÁäÀä­!î L09ÀäšÝÝÝŠŠŠ[©ªªÚÛÛÃä“{HVVVÒÓÓ}>ß­JMMM¥¥¥­¯¯cr€É= ûûûN§srr2޲###©©©‡‡‡˜`r€×ëu»ÝqÏÉÉ©­­Åä“»o677å Ä]C¿Ô°½½É&w#ýêèèp:/_¾,--ÕŸºýÛ…0DÕÁ)))§§§mmmv»ýÅ‹zoƒÎÎN9l~~>îÎøý~©¡«« “LîzDË”¨ÍÍ͉HeffMN OGEøTxttTdnaaAÂ999êÈÂÂB‰žŸŸÇÝ™ããc©¡  “Lîf§úã«F“3FC¡Pd–ÕjUa»ÝnÌŠU¿ÔƒÉ&w “3I‰|Øz“¬¸;£Õ0±L®´´ôçÍââ"¿8“KT“Ssr¡Pè;“ sr ×_€É=¼ÉY,–H]SŠfbrj\0Œ»'ggg‰»Nî9ÏÉar€É= ê%ƒ0“ËÎΖ”………ÓÓÓ>¨RSSõÁ0–UÑÈwWÅíŒZf€ÔÐÑÑ‘ˆ&÷œ×É©+€É&wïçùw²²²ŒF•‘‘a³Ù^¿~}vvæt:Å®ÔçâŒ% ‹nooKÀ¸OWQQ‘èÚ £ÂÐÐÔ ar˜&wßÔÕÕ•––Æ]Üãñx½ÞõL“L.±9::JKK£ìää$û®br˜ÜC²±±!B611q«R>Ÿ/==}ee%q=“Ãä“{ ÔÔÔܪHeeåÞÞ^B{ &‡É&˜&ð{L®¤¤ä€?#w&‡É@˜@,09L¯É---½ˆÜ!˜¿8à‘š`r€É`r˜&€É`r€É`r˜&€É`r€É=çççoÞ¼±Ûíuuu¿µ!‡Ã!#ñÁÁÁãùÌÏÏ[ryy+*}¾“ÝZå [,–ããcî{L0¹;£²²rxx8 eddüÖ†ÄáÜn÷cû–——ÇŠŠxÝUŸåôóòò¸é19ÀänÁÐиZ¬ÜéééÚÚÚû9Û±±±®®®Çö3øøñc¬¨ô¹»»ûNšššº«ª09€garûûû¹¹¹_¿~šûãÇŒŒŒû9Ûúúú………Çö3‘][[3‰~ùòå Ÿ>&p¯&777çr¹,‹ÚRÝ(m¯_¿NNN¶ÙljîgrrR-ó ;RQ]]­³UâÒÒRaa¡”òx<âyÆãM²L”Þ¦¤¤¬¬¬È¿¡PȤÂíímé¼/á`0øêÕ+»Ý.5˜œc$r.­­­ê©A%J»ïÞ½KMMs]^^NJJR+á$=--M—Œ:Îõõõââb©-;;[ΘµÎX}ª¤HKK‹¾ìóóóüÀäày™œøÁêêêÕÏõøÚÏ$Åív‹º‰LˆFˆ©ôááam‘H ^¯WG?~ü(²òíÛ7 û|>Ñ—›dÅâôô´¬¬¬««ëäääèèHŠÜ¤-‘¹ÆÆF9¾²²RNjzzZŒÓüˆiIµ>|¸¸¸m’°êIyyyOOT+‚XUUÕÜܬŽÿòåK}}½.×ÌÌÌlkkƒ”ÚFFFT…æuFíƒt^Èîî®”ªxõ“€çhr………J€4âEEE¢*ÚßßßÒҢµµµ¢>±ªêîîRá­­-q]‰`³Ù®Í2¡¦¦fttTGEãDn®­p``àÓ§OMMM*wvvVDÊü5’ër¹677ÃÒŒsiƦSSS:+,*¢¦Z×X­Vó:cõáýû÷r©'&&òòò¾ÿ÷³¸¸øÇs¥¤¤DLNþýb#~ð‹àQ›œ¸B~~þçÏŸÂ1??/z$ªTPPÐÚÚªÚív“/hH=z‘œÈS ÐYÁ`Ðáp\› ŸÏgœÜWÓcRaYY™(šñHµ¶,Ö9“ã#çÞÃêI>ÁívïïïÇŠŠuéçÎW?Ÿí¾|ùҼΨ}Pç•••e±XÎÏÏ}^ oß¾å+À£6¹«ŸöŠŠŠÄ–T4##CL¨¼¼¼··w{{[¶ººªÖœÅªÄétêhjjª1wbb¢¡¡áÚ¬X”––{ÒÑÑ‘™™ym["gâ:ccc*]¢jm™É9IOO÷ûýa‰âXÆW:$,²¥ÂbiúiidTŒÙãñ«êû‰yQû '’’’"ò*¦ø‹ï—(““ËûàϨ9KLàQ›œü¦VsQÁ`P¤A%ŠýÙÙÙQOúo8m¶ìLœC¿Âi’ ãã×OŸ>IC­­­×¶5;;›ŸŸ¯Ó§¦¦tc£9Æ8Q·°°pvvfìÉÉɉ¸àúúºŠŽ·µµ‰À©GÌaÑééi±F£®½|ùRô7ììÂêŒÚ9/u""¬Æ§·q›£5po$ªÉuww‡B¡¥¥¥¬¬,•X\\ÜÕÕ%Æ é¢#"CêUÐÚÚZѿ߯f’ÂxýúµÑ*¤µ¢n_üÏøM5“¬XˆeŠiIÞ¿/B)'zÔÓÓc^¡ˆÔÄÄ„®DìGŠ+ŠuŽF<T%I£íííW?7–’(×A.]KK‹X£z6*õ‹ÎvvvŠiE.//+WÍÎÎÖ«ßLêŒÚ9/u©å¬å|Em#ù1Z&ð,LN°X,¹¹¹zhwwWÌÆjµfffÊïqÑ•îõz+**Ä¢ÄE"«ÊÉÉ1®Ù’Jòòò¤©jnnÎx¤IV,fff’““Å5%põs.ª¼¼\¯Ø‹UaØkrŒœ‚ÚÝ+Ö9Ó‘’‹#Mëul¢}III.—kxxXù™žB+--•úU#£rLuuµÍf“âr æLêŒÚ9/u;;;r MMM‘‹üžÀh-.7•\1ù™¼góx–¨vJJJXºÜlòçVUUUUÝÉ–n˜À7¹»BÄâõë×ü˜w¹+>þ,ûöí›üyÐÒÒb\ùh‡‹üÔâÊÊJzzº^„zC¦¦¦ÒÒÒôWܘÜ勵¿?Ö{€ÉÅAee¥tÌøåçÇô6òóÚN§3¾ Å‘‘‘ÔÔTãÜ-÷&wÇdeeÉèõéÓ§wïÞqõ1¹;Än·Gî#’ÿÿlr^¯×ívÇ][NNνíbŒÉ>– ðÞ(--}æû•-..ò‹09Àä~ÉäD•$ª>#¢&ᢢ¢k³L°X,a{à^ýüÊ`ät`ä{ Öæ655é ¢’Æ#}©Ÿj:ìÃ×÷|o€\~Q&˜Ü/™œÑŠ.//.e’eBVV–™->§¿Æ'£ºW¤Ééhrrr¬¬;YêwÃÓù}÷Æsž“Ãä“LînLÎf³IôââBç:Žk³L8==mnnV­¨3®~NÔIT=u½¡É©"úk)‘sr¿ø!•Ÿ“{ÎëäÔÀä“LîWM®¬¬L¢jõSo¡k’u-ËËËuuuZ•<¯ªª’zöööRSS¯5¹ÜÜ\ «}ØÔê:moj\0Œû"œ=ø:9L“L0¹Û±½½­”Ho†ûõëWå4çççïß¿·Z­×f™›âÎÎŽÄØô“““zu”Ô£v³U¯ˆŒŽ«ÖŽŽÔ*=A)`仫âvF-3^ý|'WjèèèàÞÀä“H˜Ñ:ò$‚ÏçËÊÊÁòx<Æ€˜g™41==-çr¹¾}û¦Ó‡††œN§Íf«««SÓia‰ì›q8js-)ÛÞÞ®TRù¨qŸ®¢¢"ѵFUÍRÃææ&÷&˜£õ}#:XZZwqS¯×˽É&Àhý¥¥¥ŽŽÆQvrr’}W19Àä­’ ²‰‰‰[•òù|ééé+++ܘ`rÏq´~<ÛøÔÔÔܪHeeåÞÞ÷&˜£5po`r€ÉÁÓ«JJJþø3rW`r˜`rc@,09L09x¼,--½ˆÍ ¿Ï‡É`r˜`r€É&€Éq)“Àä09L09¸ü~¿Ýn!xÀT“Là144TYYyWµmmmy<®*&€Éüvö÷÷sss¿~ýzWöööra19Lào¶¶¶&''Ûl¶W¯^IÊöö¶„­VëÅÅECCCjjª6³×¯_«#»»»u ¡PèÝ»wrXFFÆòòrRRÒåååää¤Ô w80¯A«iEYY™Ôÿd®üâââ3Ù¯ìþáJJJä_¶n»ÏùkÒ˜ÀXYYÉÎÎþðი“™„UúÖÖVUU•ßïÅÅÅ’²ººêv»ÅÏÄÒDþìv»:òôô´¼¼¼§§çèè( J©ææf•5<<¬ÔP«†0"›VœŸŸ;Χ7SÀo˜@<ˆ{¹\®ÍÍÍȬ¾¾¾ÞÞÞ?~¨èññqQQ‘¯¢ýýý---*ÜÐÐ :¨ ÖÖÖ~ùòE‡ÅÛ®­Á¼iÏç3zá“1¹ÒÒR¶2ƒ0JJJ09Là:;;›šš¢f‰^ý¬§§g~~~kkëÇ­­­———’.‰aI«««U  Ùíö½½=ó®mZÓÜÜ<==ýôLŽÑ¸709€xHOO÷ûý‘éâX………Æ”ŒŒ ‡ÃQ^^ÞÛÛ»½½mô¶ •°Ø¡ ¯®®º\®kk¸¶ico­“Làÿc±XŒc ggg˜­¯¯;ÒÝÙÙQPm6›N<99Q[__WÑÁÁÁÆÆÆkk#²iíˆEEEŒÖ¿›ÍÍÍööö”””ĺ’±º½»»[QQq«ªªªªôD2÷&ð¨ñx<ýýý¡PèèèHÄKÆB•þæÍ½¾MQ\\ÜÕÕ%ž'ççç«ul‡#H¢ßïïîîniiY[[SÏ[kkk§§§%½¯¯Ï¤†0"›¾úù®CMMÍÓÕáhít:ï' âp‘Ý^YYIOO÷ù|·ªjjj*--MÿA½€É<ê™ ‘9‹Å’œœl\î–½¿¿6·!îeµZ333etQSw‚8YRR’Ëå–h}}½ž–óz½­­­'''&5„ÙôÌÌŒ~•O¿‹Éý&ijÑä"»-w‘Xiä_7add$55õa·Áä09ÀäâúÝ—€&ÙmùCÂívÇ][NNNmm-÷&€ÉÝw·777%<00wmýýýRƒÉ«9˜&˜Üã5¹•••—/_Úíö7oÞè¬ýýýššI´Z­n·{~~^iSGG‡Óé<88"¥¥¥æõ¯®®fddØl¶žž£2Ž©ôŠŠ õ„]Õœ’’rzzÚÖÖ&í¾xñ¸í„sss%]?‚WéVÝ‹¿ß/5tuuqo`r‰gr¢2UUU~÷îÊm²X,¢Y_¿~•ô´´´+ÃÛsssR*33Ó¼~QÀ­­- |ÿþ]»—R1‘<•˜““sexýbttTdnaaAg]ý|ýYÎëõ^^^ŽŒŒM®°°PÂçççq_„ããc©¡  à¡~ ÿðÿ ¾ýœ7+[\\ä·`r€ÉÅcr*¼½½-ᬬ,mrZÔ$]YF¹á+Rª­­-,±¸¸8l£ª«hï1HØjµªpSS“~*Òi&˜|Ý”SSçerR_¾|©¯¯×Åâñ]¨¨}ΫÙÝÝ•‚RÕ¼ú€Éý>ä'+Z?::GY¹KÙw“L œÂÂB㳤«Ÿë~ŠŠŠÔúñ«Ÿé¥åµµµ±6ÿÿû—þVBCCƒqÚ)ìÙb___oo¯š?»–ššã(('r£PüFw[°Ùl*000ðéÓ§¦¦&•;;;«ºjr¦Æ¡×årE>Ï29©ÎÎΩ©)ãBÅêÃû÷†&&&òòò¾ÿÎhlllˆÉOíV¥ä/“ôôtãíÉar€ÉüÍTòóó?þlTùùy#‘¤‚‚‚ÖÖVýÐÐn·Çúv†È„q¶`ÿåË—W?§úÂYêù0Eiié Ç'ÌŒ“[âaâjÚ`DԀΠƒú+eee¢hÆ#ÕÚ²XgjD55¥[Œu¦FäãDÝÂÂÂÙÙ™ÉI·µµ‰À EFã»PQû /«ñéí] W%%%üµ[&ÇØ˜<"“ëîî…BKKKúc ÅÅÅ]]]â ’.""¤±ÕÖÖŠˆøý~5‡dD”B} Udtt4;;[/êr8@@ª’‚ÒVKK‹–~ŒøæÍ›X ï¢N‰iIUïß¿­=êééÑÝVUíïï‹qêï·‰H×$IW¥¸Ò©XgjÄãñHUrÀÑÑ‘4ª¾þorRR¿ÏçëììÓŠãBE태—89k9_QÛÈE~¿2\Ä“cìL‘É©Çsssõ Ðîî®8ÕjÍÌÌ”_Ù":*ÝëõVTTˆ?‰…„Õ#e«««m6[RR’`\&†$‰.—kxxX©Œq¶ITƸ†Ìœ™™™ääd1N ¨¹(©J/’nçååI·¥ósssºTØkrŒœˆÚÝ+Ö™Ó‘’K$Mk59©ÒÒR©_õ02ß…ŠÚ9/u;;;r MMM‘‹üâC´þ-@läÁä09L09Àä“L09€øy<ýÀä“Àä09L09Àä“€;àì쬫«+55Õf³•——ßü#‹ÅÅÅgµÅÛŸÜ–gûBLà±344TYYùëõÔÖÖJUêÛÎ[[[Æýå?l l ‚É$ûûû¹¹¹_¿~½óš­Vk™\iié“ßÜ¢©©INSþeŸòÌ7êÅäî€ÃÃÃÖÖÖääd›ÍöêÕ+IÙÞÞ–°ØÒÅÅECCCjjª6³×¯_«#õ®hB(z÷î–‘‘±¼¼œ””tyy999)5èYó4±š6rvv&‚˜p&Çh ܘÀ³²²’ýáÃ1'2 «ô­­­ªª*¿ßŠ‹‹%euuÕív‹Ÿ‰¥‰üÙívuäééiyyyOOÏÑÑQ0”RÍÍÍ*kxxX©¡"V aD6†T+f´L“xÖˆ{¹\®ÍÍÍȬ¾¾¾ÞÞÞ?~¨èññqQQ‘¯¢ýýý---*ÜÐÐ :¨ ÖÖÖ~ùòE‡ÅÛ®­Á¼é0666¼^/£õsFîØööö”””°ôÝÝÝŠŠŠ[U%3ìííqo`r IgggSSSÔ¬ÒÒR£ŸõôôÌÏÏomm}øð¡   µµU½| ‰aI«««U  Ùív=LƪáÚ¦|ÿþ]Äñüü“{ΈÃÙ+äžIOO÷ù|·ªjjj*--m}}{“H“ˆlZ"*¼¼¼\ZZŠÉý"{{{êå=—ý&·¹¹)a¹Iâ®MþH &SŘ&ð‘!PdÎb±$''—»egg‡m¢°»»+îeµZ333eÔQSw‚VRR’Ëå–h}}½ž–óz½­­­'''&5„Ùt]]]ØgTEæ0¹_$77W_O§Ó©ÇÆÆ222l6›üàôOauuU%öôô(yŠZ6‘Åcµ%wcGG‡8âééi[[›Ýnñâ…qó KÓ’>33c4¹ÎÎN ÏÏÏÇ}5äï ©AþÒx¨{Cþ8yæ»\,..br€ÉÝfÚãÏ(•‰x}ÿþ]999*Ýívomm]ý|ÝDùÂA,¢Ú–H¡ªvttTdnaaÁØq8ùóàòòrddÄØÂÂB ÿÊ{0ÇÇÇRCAAÁCݶW/&˜ÜíL®¸¸8lpUé‹¥­­Í¼¬ Q‹Gm+ò= ëÍ<šššôЋ‹ ã‘bx¿ø¨W5ë‡÷po<ç99L0¹;09µ!GäaYYY’žm|qøæ&µx¬¶"MNG“““ceݼ3æWãA¶€cœº˜`r¿dr‹E¢êI¨‘ÓÓÓææfu°~'ææòµx¬¶LLN …B‘YjNNgÅ}5pN“Ãä“û%“óx<­ªªº¸¸ØÛÛ Ûñvyy¹®®N»Îm§ÁŠÇjËÄäÔkêeµºNÛ›Z' ã¾ggg»N“Ãä“»‡CMŒItrrR¯Z³Z­z/5‰îìì\ýüøHfffÔ²æ¾Y]â—ÆBÌ£ªf©!êĘ&ðD‡û•Ïèÿ&ËËËcEE¼îªÏrúyyyŒÖÑÁ_ù^´Çãñz½è1˜&O¡¡¡ÊÊÊÛfýJµæŒ=ȧSÍùøñc¬¨ôÙøÅã_ajj*7GGGiii£££q”œœdßULàŽÙßßÏÍÍýúõë­²~¥Úk©¯¯_XXxlª¶¶vmmÍ$uw×{>}Fë{`ccC„lbbâV¥|>_zzúÊÊÊÃz &‡É@077çr¹ÔÇŒ/è‰]½~ý:99Ùf³©YŸÉÉIµÀ+ò Á¨Y‘5DmΤÚX J%)))2ÔÉ¿Æ=,--J…Gí º½½-ã% _½ze·Û¥“3äðð°µµU#5¨Di÷Ý»w2Ngdd,//'%%©•p’ž––¦ËFFNçúúzqq±Ô–m°cÕ«R•iiiÑðæÛC=íÑÚ›{îÉÁÁAMMÍ­ŠTVVÞÉ2JL“€§˜ÁêêêÕÏ•øZ¤$Åív‹c‰Fˆ@èÏ4 k‡#,+V Q›3©6ŒÓÓÓ²²²®®®“““££#‘!ãB¢?Š©ì>ŸOrUºÈ\cc£/¤´>==]]]mÞO#bZRí‡...D›$¬zR^^ÞÓÓ#ÕŠ VUU577«ã¿|ùR__¯‹‡EÅ5333ÛÚÚÄ ¥¶‘‘U¡yQû W'²»»+¥ª[½úÀh ܘ$<………Æw÷®~®Ç/**™PÑþþ~ýé‡ÚÚZ‘ž¨õ³LjˆlμÚ0jjjŒ«ŽDãDnTxkkKüF7ªfeT```àÓ§OMMM*wvvVíÔdÒOäº\®È÷ŒsiƦSSS:+,*¢¶O”þˆ¬:cõáýû÷CCCyyyß¿o¬*))ùàÏÈ]Éarˆ%äççþüÙ¨óóó"F"I­­­ú¡¡ÝnúÐ',+V Q›3©6 ŸÏgœÜWÓ#¢tn0t8*\VV&Šf¨óÊÊʲX,ñmÓÎ.é`&‡É@bpzzZTT¤?|•‘‘!T^^ÞÛÛ«¶W¬®®ªÕf‘„eŪ!js&Õ†QZZj¬­££CÓUûúÿÄÄDCCƒDÎÄuÆÆÆTºDÕÚ²kû©HOO÷ûýa‰âXê›a ‹l©°Xš~Z‘õx<ƪú~b^gÔ>ȉ¤¤¤ˆ¼Š) Þœ¥¥¥·±‘;“ÃäàQ#¿ªÔ,T0]P‰â=ÆcvvvÔ3¾ÁÁÁÆÆÆ¨õ„eŪ!js&Õ†a\«þéÓ§úúúÖÖV¶ÄMüF½.:;;›ŸŸ¯Ó§¦¦ôÄ^¬~‘cŒu gggÆžœœœˆ ®¯¯«èøøx[[›ÜÐÐPdtzzZ¬Ñ¨k/_¾µ ;»°:£öAÎKˆ«ñé-`rðŒL®»»; ÉßYYY*±¸¸¸««K\AÒEDDƒÔK µµµ""~¿_Í! ËŠUCÔæLªœÓ’âïß¿ÿ=êééÑÝV‹íö÷÷E õ÷ÛD¤Œß€û‘âJ§bõÓˆÇ㑪䀣£#iTí¶îp8€$J·åŒZZZÄÕ³Q©ßçóuvvŠiEª=:ÅÕFGG³³³õê7“:£öAÎK œœµœ¯¨mä"?Àäà‰›œ`±Xrssõ Ðîî®8ÕjÍÌÌ|ûö­ˆŽJ÷z½âOb!aõ„eŪ!js&Õ†133“œœ, («ŸsQåååz4š——'JÓsssºTØkrŒ´¨v÷ŠÕO#bZ"RÒgiZ¯cíKJJr¹\ÃÃÃÊÏôZii©Ô¯z•cª««m6›—S6.˜3©3jä¼ÔYìììÈ)455E.òL“Ãäööv19µ’“xÖ×××ÛíöÌÌÌøv¥ƒ{F}QOþÅänÇãÙd ž9CCC•••wRUuuµzgerr2##ƒkûøùÇüG19ù“H<ö÷÷sssï|þLd.))‰ËûøaÀoçðð°µµ599Ùf³©­{···%lµZ/..ô÷¢ÅÌ^¿~­Ž4î¥!jõîÝ;9,##cyyY4ëòòrrrRjÐ[˜× ‰Õ´‘?ŽŒŒðƒ{ü,..ŠÆÉ¿˜Àoaee%;;ûÇbN"dz/­­­ªª*¿ßŠ‹‹¯~î#âv»ÅÏÄÒDþôG¤OOOËËË{zzŽŽŽ‚Á ”jnnVYÃÃÃJ ±j#²iÅùùùçÏŸ;;;õ÷h Áäîq/—Ë¥¿«l¤¯¯¯··Wäùøø¸¨¨HS°¿¿_B¹¡¡AtP¬­­Õ›|HX}hÚ¼ó¦ÿÏ~’••%FÈÏ“xîtvv655EÍ*--5úYOOÏüüüÖÖÖ‡ Z[[Õ'”%1ì!iuuµ „B!»Ý®?:«†k›ÖH…ëë냃ƒ999üì09€çNzzºßïLÇ*,,4¦ddd8ŽòòòÞÞÞíím£·mll訄ÅUxuuÕår][õMGÂë˜\Y,ãÄØÂ‚Úlmvv¶¾¾>ìHctggG=B5~׿ääDï& 666^[C‘M‡!­TTTð³Ãäž;G}¡íèèHÄK‹ÿÍ›7z}›¢¸¸¸««K+’Ä­­­ÂÂÂìììP(¤,**RÒµˆ~YattTdnaaAg]Ýf¦Íx¤ü *ÂÔ××wqq!N)é_¾|1ÏRóa‚tòòò²ººZÂïÞ½3otggGú/bzrr"Q)èr¹ô{¦MJJRç.¢f±X$,V'5§¥¥z²r%%z~~÷OóøøXjˆ|7“Àä๛\qqqØŽì*]©Xgg§Šnll|øðÁ¤HäË Ùú“SÊ®DÔ$,6ižÖµµ5 gee]Ûnww·Ùßß/á`0hù‰z éóù^½z¥“ËÌÌÔ]•c" ;Y»Ýþ‹Ï‹UýRÏÍÊbŸýë_åߨ’käÿ÷c©öÃæÊE÷œû_ÿõ_ÿöoÿö?ÿó?0÷¿ÿû¿cý%ö›rå/ÆÈW <÷¹›œùÕùÏÿüOÉ\Œò»s@ä#ðG’+=š;77÷›rÿã?þ£´´T~Ñ$P®ü"ÜXÏ~_îÈȈËå {æx[“ÙŠåêù©ÿêëëõü\¬"‘&KnnhrF’nÕÐ$ËXƒr eÂÞÞžh™\O wuuI5553^d©sll,///Ö š\‡øÿþŽv&?åù—‘¬¡¡¡¨µ=ÎÜþç–Üý×½çÜú§z„¹---‘‹ÜÉš+ʳÊ}î&÷Ü~Þæ¹ü.xü¿ÍÍsMƧ››œè‹D·¶¶"|÷îd‰ÄÈÐküZ¬"wnr⑾¸¸ÐY‡ãÚ¬Ènè,sêêêä`ùKC,mww·µµU¢KKKÉÉÉz:gmmMl/??uuõ†&§¤Óøœ:>“»ÕœÜÀÀ€ôSþ‰ZÛïË5ùëâÑæþî¿ÄëïÒß÷WºyîãœÑx¨ùæä⟓{¨Üß73lžû8gÑê™Âc~Â+×ä™ÑÍMÎãñH´ªªJ¬hoo/555lšJ~éë÷ܹ̋ɕ••)µ’°´%áúúúk³T ʜ俀êêMšVKß^¾|)§,Qù%«,P×,ˆHâÑÑ‘É F]' ãþÅuvvÆ:9Àäž&c¼¨‰šQS Ë&''õr7«ÕÚÒÒb<¸²²RÒ¿}ûfLŒZD­Ê$ k4a¥”Z‰ÁˆË¾ÿ^ÚÚØØ0ZWÔ,ýâ…È\cc£„———oxÝ”¤Ž«¨ZhœTl"yªê☟l仫a[{™GÕ´ÔÐÑÑÉ&ðÜMnzz:)))??_oè944¤Þܬ«« ›:òûýj­X‘EÂ^€‹F6ýwSÄ‹bQYYY"jâXê›&šXYªøðð°tÏårÍÌÌÜüº‰«éIPé¶Ô¯Ÿá "ˆR­ÛíV¯÷JýÒ´ùɪ¹=£†míeUW[jØÜÜÄä“xî&÷ôÁ=¾o ‹ïª'¶ñ!ªêõzù)&€ÉarÀÑÑQZZÚèèhe'''Ùw09LîYpzzj\²öxØØØ!›˜˜¸U)ŸÏ—žž¾²²ÂO09LîQ`‹ÍÝV~ŸíÞ„ƒƒƒ¨‹M¨¬¬4YYˆÉ`rÏ‹¿þõ¯×~ “~Ê€É=ÞßzæM`Œ~Ê€É=FÖ××M>å Àü”“Æxà§ ˜0Æ?eÀäžç_RRò<]äç‹É`rðdMž˜&O¥¥¥·ð<ÛŽ09Àä“»Øã0¹D…=“KTØã09Àä“Àä“L09L.1aÀäöxL.QaÀä“L“L09Àä0¹Ä„=“KTØã0¹D…=“L09L09Àäà“[\\ü 6KKKüçx¤&§>œ ‹·oßòŸàQ›\iié[€?SRR‚É$€É1Z÷&˜`r‰ÉîînEEÅ­ŠTUUíííar€É=$+++ééé>ŸïV¥¦¦¦ÒÒÒÖ××19Àä†ýý}§Ó999GÙ‘‘‘ÔÔÔÃÃCL0¹ÀëõºÝçääÔÖÖbr€ÉÝ7›››r⮡¿¿_jØÞÞÆä QMÎï÷ëoÒ666£¯_¿–êëëUôßÿýß;::œNçÁÁÁË—/KKK¯~>⬩©±ÛíV«ÕívÏÏÏ+ÍêììLMMýþý»Çã‘Üææfm`±²ccc6›­¢¢B*WE"Û•J¤Kª¹_9ñ®®.LÕä„ñ$‘§““‰^^^º\.ýB¨D“’’DªRRR”ÒÍÍ͉effJnnn®Åb‘ܯ_¿JVZZš$ê#gff¤xuuµ„ß½{gž%H¢DWWWÅó$““c,bl·°°PRÎÏÏã>ëããc©¡  “€69¡»»[zÕßß/á`0hù‰zòèóù^½zõ·Sú‰ñE19¥V*WJI  ©#UúÚÚš„³²²Ì³„âââ°­«bµk·Ûun|¨žH=˜$¶Éíí퉄¹\. wuu‰âÔÔÔHT4nvvÖhT‘J466–——é^Fg²Z­×fI ªŸE¶µ'·þ š~<&×ÔÔôdzgqq‘ß €ÉÝ‚ºº:õSœlww·µµU¢KKKÉÉÉ———±üimmMü/??uu5–É©¨Ãá¸6KlR¢[[[ךœš“üE“{„sr¥¥¥yöÈ¥à7`r·@-tÓ¯loo+Ǫ¯¯71*Ñ8I9:: ËUaeZ;;;®ªªº6Ëãñ¨èÅÅÅÞÞ^jjj¬vÕ:¹`0÷ùž=ÎurÏ|N“L.N”H«¨Zµ¦wPP¯DíS"(|ûöM»×èè¨[cc£„———Z5krrRÏÊX­Ö–––XíF¾»*ngÔ2ó¨¤†ŽŽŽÇfrÏ|œº˜`r·fllLÌL¿:==-:uqqa40ã ‚™Ífs»Ý[[[bK.—kiiI<<<,¹’833ó×%v–044¤^¤­««SSnQÛUS†Æ}ºŠŠŠ¤7Œª†¤†ÍÍML“x &w—'û„;yYáêçÂ>õ 8><×ë}„ƒÉar€É=}“;::JKK£ìää$û®br˜\NOO•®ß<+666DÈ&&&nUÊçó¥§§¯¬¬È‡Éñ£É&˜&€É`r˜&˜&€É`r˜ÜcÃápÈppÀ¥Àä0¹_åøø¸¾¾Þn·gff~ýúõw7'çv»¹Ï09€gmrCCC•••¿^Ouuu(šœœÌÈÈøÝÝëêêâ>Ã䞯ÉíïïçææÞíšÈ\RRÒïîy}}ýÂÂ÷&ð¤LnnnÎårY,µ§QÚ^¿~œœl³Ùº»»%errÒjµê?MÊj¶··¥¸”º¸¸hhhHMM<æãÇ###±$ïÝ»wR*##cyyY„ïòòò&í*å°”””••ùWjÓYKKK………Ò1ÇóãÇÝU9^ÂÁ`ðÕ«Wv»]j0¹ €É<°É‰š¬®®J`~~^[‘¤¸ÝnQ71§ÃÃCq•><<,Šc^6Œ­­­ªª*¿ßŠ‹‹uúùùùçÏŸ;;;gff¢<==-//ïéé9::µ’Jš››oØ®”-++ëêê:99‘âÒ®×ë5ºcvvö·oß$ìóùt¯DæåøÊÊJ©zzºººÚü‚&ð&WXX¨œFs||\TT$B£¢ýýý---*\[[+6cR6’¾¾¾ÞÞ^5ïõ§þIVV–r²HVVVtTšþòåË Û­©©ÕQѸ>h³Óg'Øl6øôéSSS“Êmkk3¿ €É<¤É‰ äççþüY§ôôôÌÏÏ‹ñˆý´¶¶ªgš¡PÈn·ïíí™”¤´´Ô(d©m}}}pp0'''2W:öSO]Û®Ï端¯7Š©¸Ú÷ïßUTD-èÜ`0èp8T¸¬¬LÍx¤ZZë‚<ÿx®”””ˆÉÉ¿@l–––ø ðdMîêç³È¢¢" ÍÈȹ)//ïííÝÞÞÖ‡­®®ªed&eÃã),,4o=êëâm:*áÎÎζ+îhìvGGGff¦Ž†­Õ›˜˜hhhP]µX,cccºçN§S-­‹uAÕ¼@,Þ¾}ËoX€§irò[^M/ƒÁôôt•(Bc33fr@ÀãñX­ÖœœœÙÙYíd"‹§§§mmmRðÅ‹Æ]¢ö³³³SjžŸŸûšøý~©¡«« “Àäûh&UJ³ÄÛ¾ÿ.½E›ÛíÞÚÚ’€JZÖ„Q1¯×{yy922b,¸¾¾.×××wqqQ^^.éê{Îb‡ê°ÑÑQ‘¹……cbõ³°°P¢çççq_ããc©¡  €{“H0“+..ÛBJ¥[,–¶¶6ó²&455éG–blÆ‚¢wVß>‡“pQQÑU´#$,ÎgÞOñÅ_|n«Ú Ûbä~î ¹Jl>»¸¸Èï Àä“‹ÓäD•¢šPVV–¤ggg‹Ï©MØnerÉÉÉaNÕ½¤f£®EšœŽÆêç¬À3öá>ïÒÒR6Ÿ•KÁï Àä“‹Óä,‹DÕƒT#§§§ÍÍÍêàöööÛj“ª6 E´Ùl¾¸¸ÐY‡ãZ“‹ÕOå…º¡¸¯ sr÷&˜`r¿jrG¢UUU¢V{{{©©©Æƒ———ëêê´åÜÜäÔëRüêï+í´o•••IXmȦ¼Ö××_kr±ú©ÖɃÁ¸/ÈÙÙëäð?&˜`r·Àáp¨É-µ:mrrR?ç²Z­---Ú¢ÔÞ»¢M™™™QËš0>>®ôèèèH-†”~}ýúUeŸŸ¿ÿ^ÝØØ¸úû›‚"£±úùQËÌ£W?_¤•:::¸709Àäûh===”””ŸŸ¯·r:6›­®®NOnIÏåHq8—ËõíÛ·XeMjÅüÔvXR{{»26Áçóeee‰y<ý‘°·"_nˆÚÏíím9À¸O—X¦èÚ £ªZ©ass“{“L€Ñú¾±+--»¸Ø¤×ëåÞÀä“`´~ŽŽŽÒÒÒFGGã(;99ɾ«˜`rŒÖÉÆÆ†ÙÄÄÄ­Jù|¾ôôô••î L09€ç5ZÛbó ý988¨©©¹U‘ÊÊÊ›,øãÞÀä“L€{“Lm *))aG&Cî L“L` ˆ&‡É&—¥¥¥·±ÑßÒÃä09L“Àä“L09L“Àä“L09¸‡Cþƒƒ.&€Éüggg]]]©©©6›­¼¼|ÿw·(çv»¹ò˜&Ïš¡¡¡ÊÊÊ_¬¤¶¶Vê¹¼¼”ðÖÖV~~þïîöØØ˜¸#?>L“ƒçËþþ~nnîׯ_ï¶Z«Õú»{^__¿°°ÀO“ÀäàI177çr¹,‹ÚÍÓ(m¯_¿NNN¶ÙlÝÝÝ’299)Ê¥÷ý4)«ÙÞÞ–âRêâ⢡¡!555ò˜³³3±Ã¨} …BïÞ½“RËËËIIIjïÚvƒƒƒrXJJÊÊÊŠü+µé¬¥¥¥ÂÂBé˜Çãùñã‡îª/á`0øêÕ+»Ý.5˜\Àä“x`DMVWW%0??¯­HRÜn·¨›˜Óáá¡8JÅ1/ÆÖÖVUU•ßïÅÅÅ‘H>|ˆL?==-//ïéé9::µ’Jš››oØ®”-++ëêê:99‘âÒ®×ëÕ¹?~ÌÎÎþö후}>Ÿî•È\cc£_YY)õOOOWWW›_Àä“xH •ÓhŽ‹ŠŠDhT´¿¿¿¥¥E…kkkÅfLÊFÒ×××ÛÛ«æ½"ÙØØ0:–‘†††•••¦¿|ùrÃvkjjFGGuTšÐ²(f)§ÏN°Ùl*000ðéÓ§¦¦&•;;;ÛÖÖf~A–ÅÅÅ?ž+%%%brò¥%~Å`rðÄAÉÏÏÿüù³Néé陟Ÿãû)((hmmUÏ4C¡ÝnßÛÛ3)Iii©QÈŒ|ÿþ]tíüü<2K:öSO]Û®Ï端¯7Š©¸š´¥¢"j@@çƒA‡Ã¡Âeee¢hÆ#ÕÒºXä‘ÌKÄâíÛ·üŠÀäàészzZTT$¤¢"7ååå½½½ÛÛÛú°ÕÕUµŒÌ¤lb<………Q³ÖÖÖÚÚÚb)‘x󮮠qꮳ³ó†íŠ;»ÝÑÑ‘™™©£akõ&&&Ä&UW-ËØØ˜î¹ÓéTKëb]Gbrr¾oþŒš³Ää09xê7è_þ¢\* ¦§§«Dã1;;;ê±æàà`cc£yÙ0fggÓcÆ)7ó1F?ñNNNÄ¢Ö××oØ®±ì§OŸ¤­­­:%l‰›Ûí§T]5~ ejjJ÷<Öy$&Çh ܘ<_“ëîî…BKKKYYY*±¸¸¸««ëììLÒÇÇÇÅoÔ*·ÚÚÚééi¿ßß×׫loÞ¼1®«S Hµ*¼¼¼\ZZYÐáp©\š“VZZZÄ·ÔóÖkÛ½Ó’Þ¿/ö)744ÔÓÓ£ÏNui_Ä´¿¿_¥·µµMLLèJDã¤xoo¯Éa´L“x`“,Knn®žôÚÝÝY±Z­™™™2ˆÁ¨t¯×[QQ!btrr«lÙÙÙaû7ÔÕÕ…-噋,(”””är¹†‡‡•Wéi¹kÛ™™INNÉ“ÀÕÏ7'¤¬^Þ'g———'g'ç877gìªñ59FÎWíîë‚0ZG²¹¹ÙÞÞž’’ò”š“@îü[©ªª2®(åÞÀä`´v:æù»[Äá~ws+++ééé±V‚Æbjj*---Ö_8˜&ðGëP(tŸ&÷»›Ûßß7\!pFFFRSS¹709€„­ïÓä~ws^¯×ívÇ]<''§¶¶–{“ÀäÍÍM©y`` îúûû¥†ùr &€É&¿Z­¬¬¼|ùÒn·¿yóFgíïï×ÔÔH¢Õju»ÝóóóJ˜:::œNçÁÁ‰ú.sKKK¹¹¹RÏÌÌL˜ÉÇ#õçääÌÎÎj'“&RRRNOOÛÚÚ¤à‹/ŒûŒeddØl¶ŠŠ ýŽNgg§Ô¬:~¿_jèêêâÞÀäÉäDb...ªªª$üîÝ;•%úe±XD•¾~ý*éiiiW†·æææ¤”ñ3ÎQÙÙÙóz½———###F“[__‡ëë듦ËËË%]}ùO¿‡1::*2·°° aQ=UJéàêêê÷ïßé………ºÉ 9>>– ¸709€D29ÞÞÞ–°þ쟘œ5õ)c‘¾ÐÔÔ¤Yб›½“°úJŽ8œ„‹ŠŠ®¢½!aq>...û2ŽJ_üÅ綪ݰQßç½!׊Ígù]˜`rñ˜\˜3)¹ËËË3v«µnÉÉÉaõGu¯ËËKcÓ‘½ÒQ9&jëw²/ìôïùÞ(--eóY¹ü®L0¹xLNMJ9][[s¹\ùùù«««q›œÅb‘ƒÕ–¸aem6›„/..t–nÚÄäT…[[[a )/Ô Å}5˜“{(09Àä“û%“[__—pKK‹ŠŠÆITí¥·Éåææê­AÔÊ6í[eeej½ÝÕß¼êÍsMLÎãñH¸ªªJŠìíí¥¦¦ªtµN. Æ})ÎÎÎX'÷àÿA09Àä“»bBÒ«™™õÆCzzº^§f¹¶··Õ·oßÔk77¹ññq¥Gb„j1œ ôKU+Yçççïß¿·Z­Wó@@dtrrR?‰“"Ú;#ß]·3j™yôêç‹´RCGG÷&˜@bŒÖ{{{6›M¼M¬ÈøÃè訤»Ýî­­-ñ—˵´´¤-J¿q-CCC‡Cm‡åt:ÛÛÛ•± >ŸOê!óx<ú;#ao3D¾Ü J=Ò·ºº:= §^×0îÓUTT$ݾaTU+5lnnro`r€É0Zß7"v7ù¾],Ä&½^/÷&˜£õptt”––6::GÙÉÉIö]Åä“`´~H666DÈ&&&nUÊçó¥§§¯¬¬po`r€É<¯ÑÚ›éÏÁÁAMMÍ­ŠTVVîííqo`r€É0Z÷&˜<Ѫ¤¤„™ ¹+09L09H€ ˜&˜<^–––ÞÄFQ“Àä09Àä“L09Àä09L“L‡Ã!pppÀ¥Àä“€_Åï÷Ûív›ïg[zq8·ÛÍeÇä“xÖ UVVÞIU[[[ç~º=66ÖÕÕÅ“Làù²¿¿Ÿ››ûõë×;©mpp°··÷~z^__¿°°ÀO“LàI177çr¹,‹ÚÊ(m¯_¿NNN¶ÙlÝÝÝ’299iµZõæQ&e5ÛÛÛR\J]\\444¤¦¦sËÊÊ–——Mú …Þ½{'¥222äȤ¤¤ËËË›´«MQKIIYYY‘¥6µ´´TXX(óxŸO÷Jd®±±Qޝ¬¬”ú§§§«««Í/`r€É<$………Êi4ÇÇÇEEE"4*ÚßßßÒҢµµµb3&e#éëëëííUó^FD¡ŒRICCÃÊÊŠŽJÓ_¾|¹a»555£££:*÷áÃm–¢qúì›Í¦Ÿ>}jjjR¹³³³mmmæ09Àä”üüüÏŸ?딞žžùùy1±Ÿ‚‚‚ÖÖVõL3 Ùíö½½=“²‘”––…LÓÜÜ<==«”t ì ¦ž»¶]qÄúúz£˜Š«}ÿþ]EEԀΠƒ‡C…ËÊÊDÑŒGª¥u±.Èý³¸¸øÇs¥¤¤DLNþýb³´´Äï4Lž§§§EEE"@*š‘‘!rS^^ÞÛÛ»½½­[]]UËÈLʆ!ÆSXX5+==]+V—ÄÛ666tTÂ7lWÜÑØíŽŽŽÌÌL [«711ÑÐРºj±XÆÆÆtÏN§ZZë‚<Ô¼@,Þ¾}Ë/4LžÓ/µ¿üEM/ƒAQ+•(Bc>– ¸709€69Q%‰ªïЍIXoéa’e‚Åbikk K,..ŽœŒ|AÂâŽ*ÜÔÔ¤€ŠJüõ¥~ªé°MD¸709€39£]^^]Ê$Ë„¬¬,92;;[|NíÕ&HÁ¨îir:šœœ+ëN–úÝðt09L0¹Çkr6›M¢:×áp\›eÂééiss³j¥½½]%Z,‰ª§®749UD-%rNî?¤Âœ&ð&WVV&QµšzˆY__mÖµ,//×ÕÕiUòxjܧ«¨¨Htí†QU³Ô°¹¹É½É0Zß7¢ƒ¥¥¥q1õz½Ü˜£õptt”––6::GÙÉÉIö]Åä­’ ²‰‰‰[•òù|ééé+++ܘÀs­m±¹çžÔÔÔܪHeeåÞÞ÷&Àh ܘ<ÝѺ¤¤ä€?#w&‡É@˜@,09L/KKKobsÃïóar€É&˜&˜@¢p~~þæÍ»Ý^WW—p¿¼¼ôûý79²  àÇü¸19€'Eeeåððp(ÊÈÈH¬žƒÁÑÑÑ<22òñãG~ܘÀÓazzúÿµwíýqÇ¿df&»I]$‘I™˜™9vÑÝt‘n2“LÆÑE’ŒÌLºØMÒÕt“$éf’d2’t‘D’™IÌd232I2ßßû÷=|Ìô[¿‹ïæù¸˜Ï¿ó9çô¹èå윳™™™N<òJ¥ %€¶8þùùÙï÷³â$9º„„›ÁÁÁ‡‡‡Ž;r pš¦e2™¶¶aÑIrtƒ©©)õ›Q¯¯¯Fãåå¥Ûí6™L‡£á®²&]ßÊf³f³YÆ~~þþ~£ýåå% Ùl6é ‡Ãj¼ƒ®ëF»ßï7,—˽v»ÝëõªÁÑh4 ¶þ, ëN’ K¤R©ééiUÝÙÙ‘Àt}}-åd2©iZ+]Md2ŸÏwvv–N§MnooÇÇÇ÷÷÷¿¾¾$º©huss#ó' ‰}¹¤,Ÿg{{ÛpttdµZr¡Pèé鹿¿oëdew²‹N’ K„Ãá­­-•º$?•J%Õk6›ìjncc#‰¨ x•JE™š'/,,HAZ†††6—cSw¶U«Uu.‹Éñ´{²ÇÇÇ* ‚$@Çs:ê&¹ùùùt:­ºÊårooï]Íy½Þ››U][[K¥R’ ‰„ËåÒuýëëKÚWVVdßf¯ÉÉI£¼´´”Íf²¦iRm÷de/’#Yt’Ý Z­öõõ©ªºÍ°··~ìjBRšÛí®o”(á,‰¨X&¾}'ÜÕÕ•±ë“““ååeÕn±X$äµ{¾£££±XŒu'ÉÐ ’Éäììl}<ªï¿»»û±« [õó‹†ÛÔžžž...Œvãâœáüüüýý] oooV«5—Ë9N£EÍS,Û:Ù‡‡“ÉT(Xw’Ý  ¨ª¦iûûû¿ÿ<[:77Ç[éjbqqÑØª~žÕÕUÉdµZmwwWò™q Ãá9¥±T*mnnªoN%ÞIhnx¸¡!YºÝn—ËÕ¼¬ëz4eÑIrt‰±±±UÍçó&“IÖééiýÈ&]MØívI~ óÈ 2„³X,¦.³=>>J˜“Ðf³ÙêßKòïñ_¿âàï?ß“ÖW=ú÷Ûr.—óz½­¿C$9þjÅb1 uèÁûý~ …­×u½R©°è$9ºD<¯æ ³ììì´þs«2¸\.³â$9:ÞÈÈH­V;<<\__ïܳÈçó-¾O$N×?K’ÌçóÙl¶ÿ+Æ™ÿjäHr É€$’I›ï ÁŠñ°¥IEND®B`‚tevent-0.9.34/doc/mainpage.dox0000660000000000000000000000326112406075657016130 0ustar rootroot00000000000000/** * @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 . * */ tevent-0.9.34/doc/tevent_context.dox0000660000000000000000000000600312775624157017421 0ustar rootroot00000000000000/** @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. */ tevent-0.9.34/doc/tevent_data.dox0000660000000000000000000000707312461161556016645 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/doc/tevent_events.dox0000660000000000000000000002565012406075657017246 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/doc/tevent_queue.dox0000660000000000000000000002277612775624157017100 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/doc/tevent_request.dox0000660000000000000000000002107312406075657017425 0ustar rootroot00000000000000/** @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 func- tions 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. */ tevent-0.9.34/doc/tevent_thread.dox0000660000000000000000000002336512775624157017216 0ustar rootroot00000000000000/** @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. */ tevent-0.9.34/doc/tevent_tutorial.dox0000660000000000000000000000052012617125507017564 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/doc/tutorials.dox0000660000000000000000000000400112406075657016366 0ustar rootroot00000000000000/** * @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 */ tevent-0.9.34/doxy.config0000660000000000000000000023645712406075657015257 0ustar rootroot00000000000000# 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 tevent-0.9.34/echo_server.c0000660000000000000000000003416312746330636015541 0ustar rootroot00000000000000/** ** 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; } 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; } tevent-0.9.34/pytevent.c0000660000000000000000000005420412536700232015077 0ustar rootroot00000000000000/* 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 PyStr_Check PyUnicode_Check #define PyStr_FromString PyUnicode_FromString #define PyStr_AsUTF8 PyUnicode_AsUTF8 #define PyInt_FromLong PyLong_FromLong #else #define PyStr_Check PyString_Check #define PyStr_FromString PyString_FromString #define PyStr_AsUTF8 PyString_AsString #endif 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 (!PyStr_Check(name)) { PyErr_SetNone(PyExc_TypeError); Py_DECREF(name); return NULL; } if (!tevent_register_backend(PyStr_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) { 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) { tevent_queue_stop(self->queue); Py_RETURN_NONE; } static PyObject *py_tevent_queue_start(TeventQueue_Object *self) { 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) { 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) { 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) { 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; if (!PyArg_ParseTuple(args, "lO", &next_event, &callback)) return NULL; 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) { /* FIXME */ Py_RETURN_NONE; } static PyObject *py_tevent_req_received(PyObject *self) { /* FIXME */ Py_RETURN_NONE; } static PyObject *py_tevent_req_is_error(PyObject *self) { /* FIXME */ Py_RETURN_NONE; } static PyObject *py_tevent_req_poll(PyObject *self) { /* FIXME */ Py_RETURN_NONE; } static PyObject *py_tevent_req_is_in_progress(PyObject *self) { /* 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) { /* FIXME */ Py_RETURN_NONE; } static PyObject *py_tevent_req_notify_callback(PyObject *self) { /* 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) { 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) { 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) { 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 = (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 *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 = PyStr_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 tevent-0.9.34/testsuite.c0000660000000000000000000007362513147534071015267 0ustar rootroot00000000000000/* 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" #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 #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))); } } 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; 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; socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock); 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; } #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. Excercise 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_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; } tevent-0.9.34/tevent.c0000660000000000000000000005341413167070744014541 0ustar rootroot00000000000000/* 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 static void tevent_abort(struct tevent_context *ev, const char *reason); 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; #ifdef HAVE_PTHREAD int ret; ret = pthread_mutex_lock(&tevent_contexts_mutex); if (ret != 0) { abort(); } DLIST_REMOVE(tevent_contexts, ev); ret = pthread_mutex_unlock(&tevent_contexts_mutex); if (ret != 0) { abort(); } while (ev->threaded_contexts != NULL) { struct tevent_threaded_context *tctx = ev->threaded_contexts; ret = pthread_mutex_lock(&tctx->event_ctx_mutex); if (ret != 0) { abort(); } /* * Indicate to the thread that the tevent_context is * gone. The counterpart of this is in * _tevent_threaded_schedule_immediate, there we read * this under the threaded_context's mutex. */ tctx->event_ctx = NULL; ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); if (ret != 0) { abort(); } DLIST_REMOVE(ev->threaded_contexts, tctx); } ret = pthread_mutex_destroy(&ev->scheduled_mutex); if (ret != 0) { abort(); } #endif tevent_common_wakeup_fini(ev); for (fd = ev->fd_events; fd; fd = fn) { fn = fd->next; 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->event_ctx = NULL; DLIST_REMOVE(ev->timer_events, te); } for (ie = ev->immediate_events; ie; ie = in) { in = ie->next; 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->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; } /* 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; } static void tevent_abort(struct tevent_context *ev, const char *reason) { 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) { 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 } tevent-0.9.34/tevent.h0000660000000000000000000017247113120574744014551 0ustar rootroot00000000000000/* 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 */ 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 */ 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. * * @{ */ /** * 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] req The tevent async request which executed this callback. */ typedef void (*tevent_req_fn)(struct tevent_req *req); /** * @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. * * @param[in] req The structure to get the 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 is the request is cancelable, * othererwise 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. * * @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 the change 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 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 timval 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 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 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 Wether 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); /* @} */ /** * @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__ */ tevent-0.9.34/tevent.pc.in0000660000000000000000000000040712406075657015323 0ustar rootroot00000000000000prefix=@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/ tevent-0.9.34/tevent.py0000660000000000000000000000175013055076237014742 0ustar rootroot00000000000000# # 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, ) tevent-0.9.34/tevent_debug.c0000660000000000000000000000644112406075657015710 0ustar rootroot00000000000000/* 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) { 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->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) { 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); } } tevent-0.9.34/tevent_epoll.c0000660000000000000000000006165712757257013015744 0ustar rootroot00000000000000/* 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->event_ctx = NULL; DLIST_REMOVE(epoll_ev->ev->fd_events, add_fde); 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->event_ctx = NULL; if (mpx_fde != NULL) { DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); 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->event_ctx = NULL; if (mpx_fde != NULL) { DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); 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->event_ctx = NULL; if (mpx_fde != NULL) { DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); 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) { fde->handler(epoll_ev->ev, fde, flags, fde->private_data); break; } } 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); } tevent-0.9.34/tevent_fd.c0000660000000000000000000000477112406075657015217 0ustar rootroot00000000000000/* 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" #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" int tevent_common_fd_destructor(struct tevent_fd *fde) { 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; } 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->event_ctx = ev; fde->fd = fd; fde->flags = flags; fde->handler = handler; fde->close_fn = NULL; fde->private_data = private_data; fde->handler_name = handler_name; fde->location = location; fde->additional_flags = 0; fde->additional_data = NULL; 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; } tevent-0.9.34/tevent_immediate.c0000660000000000000000000000664112661701312016545 0ustar rootroot00000000000000/* 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" #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" static void tevent_common_immediate_cancel(struct tevent_immediate *im) { if (!im->event_ctx) { return; } 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->event_ctx = NULL; im->handler = NULL; im->private_data = NULL; im->handler_name = NULL; im->schedule_location = NULL; im->cancel_fn = NULL; im->additional_data = NULL; talloc_set_destructor(im, NULL); } /* destroy an immediate event */ static int tevent_common_immediate_destructor(struct tevent_immediate *im) { tevent_common_immediate_cancel(im); 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) { tevent_common_immediate_cancel(im); if (!handler) { return; } im->event_ctx = ev; im->handler = handler; im->private_data = private_data; im->handler_name = handler_name; im->schedule_location = location; im->cancel_fn = NULL; im->additional_data = NULL; 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); } /* 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; tevent_immediate_handler_t handler; void *private_data; if (!im) { return 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 */ handler = im->handler; private_data = im->private_data; DLIST_REMOVE(im->event_ctx->immediate_events, im); im->event_ctx = NULL; im->handler = NULL; im->private_data = NULL; im->handler_name = NULL; im->schedule_location = NULL; im->cancel_fn = NULL; im->additional_data = NULL; talloc_set_destructor(im, NULL); handler(ev, im, private_data); return true; } tevent-0.9.34/tevent_internal.h0000660000000000000000000002617413167070744016445 0ustar rootroot00000000000000/* 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; } internal; }; struct tevent_fd { struct tevent_fd *prev, *next; struct tevent_context *event_ctx; 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 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; 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; 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; int wakeup_fd; }; struct tevent_debug_ops { void (*debug)(void *context, enum tevent_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); void *context; }; void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); 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; /* * 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); 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 *); 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); 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); bool tevent_standard_init(void); bool tevent_poll_init(void); void 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); tevent-0.9.34/tevent_liboop.c0000660000000000000000000001576012406075657016112 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/tevent_poll.c0000660000000000000000000004070012757257013015561 0ustar rootroot00000000000000/* 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; /* * A DLIST for fresh fde's added by poll_event_add_fd but not * picked up yet by poll_event_loop_once */ struct tevent_fd *fresh; /* * A DLIST for disabled fde's. */ struct tevent_fd *disabled; /* * one or more events were deleted or disabled */ bool deleted; /* * These two arrays are maintained together. */ struct pollfd *fds; struct tevent_fd **fdes; unsigned num_fds; /* * Signal fd to wake the poll() thread */ int signal_fd; }; static int poll_event_context_destructor(struct poll_event_context *poll_ev) { struct tevent_fd *fd, *fn; for (fd = poll_ev->fresh; fd; fd = fn) { fn = fd->next; fd->event_ctx = NULL; DLIST_REMOVE(poll_ev->fresh, fd); } for (fd = poll_ev->disabled; fd; fd = fn) { fn = fd->next; fd->event_ctx = NULL; DLIST_REMOVE(poll_ev->disabled, fd); } if (poll_ev->signal_fd == -1) { /* * Non-threaded, no signal pipe */ return 0; } close(poll_ev->signal_fd); poll_ev->signal_fd = -1; if (poll_ev->num_fds == 0) { return 0; } if (poll_ev->fds[0].fd != -1) { close(poll_ev->fds[0].fd); poll_ev->fds[0].fd = -1; } return 0; } /* 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; poll_ev->signal_fd = -1; ev->additional_data = poll_ev; talloc_set_destructor(poll_ev, poll_event_context_destructor); return 0; } static bool set_nonblock(int fd) { int val; val = fcntl(fd, F_GETFL, 0); if (val == -1) { return false; } val |= O_NONBLOCK; return (fcntl(fd, F_SETFL, val) != -1); } static int poll_event_context_init_mt(struct tevent_context *ev) { struct poll_event_context *poll_ev; struct pollfd *pfd; int fds[2]; 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); poll_ev->fds = talloc_zero(poll_ev, struct pollfd); if (poll_ev->fds == NULL) { return -1; } ret = pipe(fds); if (ret == -1) { return -1; } if (!set_nonblock(fds[0]) || !set_nonblock(fds[1])) { close(fds[0]); close(fds[1]); return -1; } poll_ev->signal_fd = fds[1]; pfd = &poll_ev->fds[0]; pfd->fd = fds[0]; pfd->events = (POLLIN|POLLHUP); poll_ev->num_fds = 1; talloc_set_destructor(poll_ev, poll_event_context_destructor); return 0; } static void poll_event_wake_pollthread(struct poll_event_context *poll_ev) { char c; ssize_t ret; if (poll_ev->signal_fd == -1) { return; } c = 0; do { ret = write(poll_ev->signal_fd, &c, sizeof(c)); } while ((ret == -1) && (errno == EINTR)); } static void poll_event_drain_signal_fd(struct poll_event_context *poll_ev) { char buf[16]; ssize_t ret; int fd; if (poll_ev->signal_fd == -1) { return; } if (poll_ev->num_fds < 1) { return; } fd = poll_ev->fds[0].fd; do { ret = read(fd, buf, sizeof(buf)); } while (ret == sizeof(buf)); } /* 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) { struct tevent_fd **listp = (struct tevent_fd **)fde->additional_data; DLIST_REMOVE((*listp), fde); 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_ void 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); struct tevent_fd **listp; if (fde->flags != 0) { listp = &poll_ev->fresh; } else { listp = &poll_ev->disabled; } fde->additional_flags = UINT64_MAX; fde->additional_data = listp; DLIST_ADD((*listp), fde); talloc_set_destructor(fde, poll_event_fd_destructor); } /* 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; if (fd < 0) { return NULL; } fde = talloc(mem_ctx ? mem_ctx : ev, struct tevent_fd); if (fde == NULL) { return NULL; } fde->event_ctx = ev; fde->fd = fd; fde->flags = flags; fde->handler = handler; fde->close_fn = NULL; fde->private_data = private_data; fde->handler_name = handler_name; fde->location = location; fde->additional_flags = UINT64_MAX; fde->additional_data = NULL; tevent_poll_event_add_fd_internal(ev, fde); 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; } poll_ev = talloc_get_type_abort( ev->additional_data, struct poll_event_context); fde->flags = flags; if (idx == UINT64_MAX) { struct tevent_fd **listp = (struct tevent_fd **)fde->additional_data; /* * We move it between the fresh and disabled lists. */ DLIST_REMOVE((*listp), fde); 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; DLIST_REMOVE(ev->fd_events, fde); tevent_poll_event_add_fd_internal(ev, fde); 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_setup_fresh(struct tevent_context *ev, struct poll_event_context *poll_ev) { struct tevent_fd *fde, *next; unsigned num_fresh, num_fds; if (poll_ev->deleted) { unsigned first_fd = (poll_ev->signal_fd != -1) ? 1 : 0; unsigned i; for (i=first_fd; i < poll_ev->num_fds;) { fde = poll_ev->fdes[i]; if (fde != NULL) { i++; continue; } /* * This fde was talloc_free()'ed. Delete it * from the arrays */ poll_ev->num_fds -= 1; if (poll_ev->num_fds == i) { break; } poll_ev->fds[i] = poll_ev->fds[poll_ev->num_fds]; poll_ev->fdes[i] = poll_ev->fdes[poll_ev->num_fds]; if (poll_ev->fdes[i] != NULL) { poll_ev->fdes[i]->additional_flags = i; } } poll_ev->deleted = false; } if (poll_ev->fresh == NULL) { return true; } num_fresh = 0; for (fde = poll_ev->fresh; fde; fde = fde->next) { num_fresh += 1; } num_fds = poll_ev->num_fds + num_fresh; /* * We check the length of fdes here. It is the last one * enlarged, so if the realloc for poll_fd->fdes fails, * poll_fd->fds will have at least the size of poll_fd->fdes */ if (num_fds >= talloc_array_length(poll_ev->fdes)) { struct pollfd *tmp_fds; struct tevent_fd **tmp_fdes; unsigned array_length; array_length = (num_fds + 15) & ~15; /* round up to 16 */ tmp_fds = talloc_realloc( poll_ev, poll_ev->fds, struct pollfd, array_length); if (tmp_fds == NULL) { return false; } poll_ev->fds = tmp_fds; 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; } for (fde = poll_ev->fresh; fde; fde = next) { struct pollfd *pfd; pfd = &poll_ev->fds[poll_ev->num_fds]; 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); } fde->additional_flags = poll_ev->num_fds; poll_ev->fdes[poll_ev->num_fds] = fde; next = fde->next; DLIST_REMOVE(poll_ev->fresh, fde); DLIST_ADD(ev->fd_events, fde); poll_ev->num_fds += 1; } 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; 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; } poll_event_drain_signal_fd(poll_ev); if (!poll_event_setup_fresh(ev, poll_ev)) { 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->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); fde->handler(ev, fde, flags, fde->private_data); return 0; } } 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->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 int poll_event_loop_wait(struct tevent_context *ev, const char *location) { struct poll_event_context *poll_ev = talloc_get_type_abort( ev->additional_data, struct poll_event_context); /* * loop as long as we have events pending */ while (tevent_common_have_events(ev) || poll_ev->fresh || poll_ev->disabled) { 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, "poll_event_loop_wait() out of events\n"); return 0; } 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 = poll_event_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 = poll_event_loop_wait, }; _PRIVATE_ bool tevent_poll_mt_init(void) { return tevent_register_backend("poll_mt", &poll_event_mt_ops); } tevent-0.9.34/tevent_port.c0000660000000000000000000004766312757257013015616 0ustar rootroot00000000000000/* 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) { fde->handler(ev, fde, flags, fde->private_data); break; } } 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; } tevent-0.9.34/tevent_queue.c0000660000000000000000000001621512757257013015743 0ustar rootroot00000000000000/* 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_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; } tevent-0.9.34/tevent_req.c0000660000000000000000000002042613134750322015374 0ustar rootroot00000000000000/* 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; 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, .internal.create_location = location, .internal.state = TEVENT_REQ_IN_PROGRESS, .internal.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); *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) { /* * 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); _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; } tevent-0.9.34/tevent_signal.c0000660000000000000000000003106512757257013016074 0ustar rootroot00000000000000/* 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" #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) { struct tevent_common_signal_list *sl = talloc_get_type_abort(se->additional_data, struct tevent_common_signal_list); if (se->event_ctx) { struct tevent_context *ev = se->event_ctx; DLIST_REMOVE(ev->signal_events, se); } talloc_free(sl); 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]); sig_state->oldact[se->signum] = NULL; } #ifdef SA_SIGINFO if (se->sa_flags & SA_SIGINFO) { if (sig_state->sig_info[se->signum]) { talloc_free(sig_state->sig_info[se->signum]); sig_state->sig_info[se->signum] = NULL; } } #endif } 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(mem_ctx?mem_ctx:ev, struct tevent_signal); if (se == NULL) return NULL; se->event_ctx = ev; se->signum = signum; se->sa_flags = sa_flags; se->handler = handler; se->private_data = private_data; se->handler_name = handler_name; se->location = location; se->additional_data = NULL; sl = talloc(se, struct tevent_common_signal_list); if (!sl) { talloc_free(se); return NULL; } sl->se = se; se->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(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; } struct tevent_se_exists { struct tevent_se_exists **myself; }; static int tevent_se_exists_destructor(struct tevent_se_exists *s) { *s->myself = NULL; 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); #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; struct tevent_se_exists *exists; next = sl->next; /* * We have to be careful to not touch "se" * after it was deleted in its handler. Thus * we allocate a child whose destructor will * tell by nulling out itself that its parent * is gone. */ exists = talloc(se, struct tevent_se_exists); if (exists == NULL) { continue; } exists->myself = &exists; talloc_set_destructor( exists, tevent_se_exists_destructor); #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; se->handler(ev, se, i, 1, (void*)&sig_state->sig_info[i][ofs], se->private_data); if (!exists) { break; } } #ifdef SA_RESETHAND if (exists && (se->sa_flags & SA_RESETHAND)) { talloc_free(se); } #endif talloc_free(exists); continue; } #endif se->handler(ev, se, i, count, NULL, se->private_data); #ifdef SA_RESETHAND if (exists && (se->sa_flags & SA_RESETHAND)) { talloc_free(se); } #endif talloc_free(exists); } #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) { struct tevent_common_signal_list *sl = talloc_get_type_abort(se->additional_data, struct tevent_common_signal_list); tevent_common_signal_list_destructor(sl); if (sig_state->sig_handlers[se->signum] == NULL) { if (sig_state->oldact[se->signum]) { sigaction(se->signum, sig_state->oldact[se->signum], NULL); talloc_free(sig_state->oldact[se->signum]); sig_state->oldact[se->signum] = NULL; } } return; } tevent-0.9.34/tevent_standard.c0000660000000000000000000001421612746330636016417 0ustar rootroot00000000000000/* 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; struct tevent_fd *fde_next; 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) { /* * We must remove this fde off the ev->fd_events list. */ fde_next = fde->next; /* Remove from the ev->fd_events list. */ DLIST_REMOVE(ev->fd_events, fde); /* Re-add this event as a poll backend event. */ tevent_poll_event_add_fd_internal(ev, fde); } 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); } tevent-0.9.34/tevent_threads.c0000660000000000000000000002770713202266211016243 0ustar rootroot00000000000000/* 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" #if defined(HAVE_PTHREAD) #include 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; 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) { int ret; if (tctx->event_ctx != NULL) { DLIST_REMOVE(tctx->event_ctx->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_threaded_context *tctx; int ret; ret = tevent_common_wakeup_init(ev); if (ret != 0) { errno = ret; return NULL; } tctx = talloc(mem_ctx, struct tevent_threaded_context); if (tctx == NULL) { return NULL; } tctx->event_ctx = ev; tctx->wakeup_fd = ev->wakeup_fd; ret = pthread_mutex_init(&tctx->event_ctx_mutex, NULL); if (ret != 0) { TALLOC_FREE(tctx); return NULL; } DLIST_ADD(ev->threaded_contexts, tctx); talloc_set_destructor(tctx, tevent_threaded_context_destructor); return tctx; #else errno = ENOSYS; return NULL; #endif } void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, struct tevent_immediate *im, tevent_immediate_handler_t handler, void *private_data, const char *handler_name, const char *location) { #ifdef HAVE_PTHREAD struct tevent_context *ev; int ret, wakeup_fd; ret = pthread_mutex_lock(&tctx->event_ctx_mutex); if (ret != 0) { abort(); } ev = tctx->event_ctx; if (ev == NULL) { /* * Our event context is already gone. */ ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); if (ret != 0) { abort(); } return; } if ((im->event_ctx != NULL) || (handler == NULL)) { abort(); } im->event_ctx = ev; im->handler = handler; im->private_data = private_data; im->handler_name = handler_name; im->schedule_location = location; im->cancel_fn = NULL; im->additional_data = NULL; ret = pthread_mutex_lock(&ev->scheduled_mutex); if (ret != 0) { abort(); } DLIST_ADD_END(ev->scheduled_immediates, im); ret = pthread_mutex_unlock(&ev->scheduled_mutex); if (ret != 0) { abort(); } wakeup_fd = tctx->wakeup_fd; 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; DLIST_REMOVE(ev->scheduled_immediates, im); DLIST_ADD_END(ev->immediate_events, im); } ret = pthread_mutex_unlock(&ev->scheduled_mutex); if (ret != 0) { abort(); } #else /* * tevent_threaded_context_create() returned NULL with ENOSYS... */ abort(); #endif } tevent-0.9.34/tevent_timed.c0000660000000000000000000002270212775624157015726 0ustar rootroot00000000000000/* 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" #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->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); return 0; } static int tevent_common_timed_deny_destructor(struct tevent_timer *te) { return -1; } static void tevent_common_insert_timer(struct tevent_context *ev, struct tevent_timer *te, bool optimize_zero) { struct tevent_timer *prev_te = NULL; /* 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->event_ctx = ev; te->next_event = next_event; te->handler = handler; te->private_data = private_data; te->handler_name = handler_name; te->location = location; te->additional_data = NULL; if (ev->timer_events == NULL) { ev->last_zero_timer = NULL; } tevent_common_insert_timer(ev, te, optimize_zero); talloc_set_destructor(te, tevent_common_timed_destructor); 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); } /* 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; 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 ... */ /* deny the handler to free the event */ talloc_set_destructor(te, tevent_common_timed_deny_destructor); /* 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 (ev->last_zero_timer == te) { ev->last_zero_timer = DLIST_PREV(te); } DLIST_REMOVE(ev->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->handler(ev, te, current_time, te->private_data); /* The destructor isn't necessary anymore, we've already removed the * event from the list. */ talloc_set_destructor(te, NULL); tevent_debug(te->event_ctx, TEVENT_DEBUG_TRACE, "Ending timer event %p \"%s\"\n", te, te->handler_name); talloc_free(te); return tevent_timeval_zero(); } tevent-0.9.34/tevent_util.c0000660000000000000000000000454612406075657015603 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/tevent_util.h0000660000000000000000000001135712661701312015571 0ustar rootroot00000000000000/* 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 ((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 tevent-0.9.34/tevent_wakeup.c0000660000000000000000000000341612406075657016115 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/wscript0000660000000000000000000001211313202266223014462 0ustar rootroot00000000000000#!/usr/bin/env python APPNAME = 'tevent' VERSION = '0.9.34' blddir = 'bin' import sys, os # find the buildtools directory srcdir = '.' while not os.path.exists(srcdir+'/buildtools') and len(srcdir.split('/')) < 5: srcdir = srcdir + '/..' sys.path.insert(0, srcdir + '/buildtools/wafsamba') import wafsamba, samba_dist, samba_utils, Options, Logs samba_dist.DIST_DIRS('lib/tevent:. lib/replace:lib/replace lib/talloc:lib/talloc buildtools:buildtools third_party/waf:third_party/waf') def set_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) if not conf.env.disable_python: # also disable if we don't have the python libs installed conf.find_program('python', var='PYTHON') conf.check_tool('python') conf.check_python_version((2,4,2)) conf.SAMBA_CHECK_PYTHON_HEADERS(mandatory=False) if not conf.env.HAVE_PYTHON_H: Logs.warn('Disabling pytevent as python devel libs not found') conf.env.disable_python = True 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_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: for env in bld.gen_python_environments(['PKGCONFIGDIR']): 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''' import samba_utils samba_utils.reconfigure(ctx) tevent-0.9.34/lib/replace/.checker_innocent0000660000000000000000000000024612406075657020551 0ustar rootroot00000000000000>>>MISTAKE21_create_files_6a9e68ada99a97cb >>>MISTAKE21_os2_delete_9b2bfa7f38711d09 >>>MISTAKE21_os2_delete_2fcc29aaa99a97cb >>>SECURITY2_os2_delete_9b2bfa7f1c9396ca tevent-0.9.34/lib/replace/Makefile0000660000000000000000000000150312406075657016704 0ustar rootroot00000000000000# simple makefile wrapper to run waf WAF=WAF_MAKE=1 PATH=buildtools/bin:../../buildtools/bin:$$PATH waf 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: tevent-0.9.34/lib/replace/README0000660000000000000000000000304012406075657016122 0ustar rootroot00000000000000This 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 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) tevent-0.9.34/lib/replace/closefrom.c0000660000000000000000000000515712746330636017410 0ustar rootroot00000000000000/* * 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 tevent-0.9.34/lib/replace/cwrap.c0000660000000000000000000000226212406075657016527 0ustar rootroot00000000000000/* * 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; } tevent-0.9.34/lib/replace/dlfcn.c0000660000000000000000000000354312406075657016504 0ustar rootroot00000000000000/* 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 tevent-0.9.34/lib/replace/getaddrinfo.c0000660000000000000000000002454412406075657017710 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/lib/replace/getaddrinfo.h0000660000000000000000000000614112406075657017706 0ustar rootroot00000000000000/* 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 */ tevent-0.9.34/lib/replace/getifaddrs.c0000660000000000000000000002045513055076237017527 0ustar rootroot00000000000000/* 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 #if 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 tevent-0.9.34/lib/replace/hdr_replace.h0000660000000000000000000000012412406075657017663 0ustar rootroot00000000000000/* this is a replacement header for a missing system header */ #include "replace.h" tevent-0.9.34/lib/replace/inet_aton.c0000660000000000000000000000223212406075657017370 0ustar rootroot00000000000000/* * 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; } tevent-0.9.34/lib/replace/inet_ntoa.c0000660000000000000000000000247512406075657017401 0ustar rootroot00000000000000/* * 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; } tevent-0.9.34/lib/replace/inet_ntop.c0000660000000000000000000001163212406075657017413 0ustar rootroot00000000000000/* * 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 */ tevent-0.9.34/lib/replace/inet_pton.c0000660000000000000000000001201012406075657017402 0ustar rootroot00000000000000/* * 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 tevent-0.9.34/lib/replace/poll.c0000660000000000000000000000640512406075657016364 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/lib/replace/replace-test.h0000660000000000000000000000033712406075657020011 0ustar rootroot00000000000000#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__ */ tevent-0.9.34/lib/replace/replace-testsuite.h0000660000000000000000000000036312406075657021062 0ustar rootroot00000000000000#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__ */ tevent-0.9.34/lib/replace/replace.c0000660000000000000000000004634013202266211017012 0ustar rootroot00000000000000/* 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 tevent-0.9.34/lib/replace/replace.h0000660000000000000000000004750713202266211017025 0ustar rootroot00000000000000/* 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 #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 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_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 !HAVE_DECL_ENVIRON #ifdef __APPLE__ #include #define environ (*_NSGetEnviron()) #else extern char **environ; #endif #endif #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 ; #endif #if !defined(HAVE_UINTPTR_T) typedef unsigned long long uintptr_t ; #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((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) /** * zero a structure given a pointer to the structure - no zero check */ #define ZERO_STRUCTPN(x) memset((char *)(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((char *)(x), 0, sizeof(x)) /** * 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))) #if MMAP_BLACKLIST #undef HAVE_MMAP #endif #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 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 */ tevent-0.9.34/lib/replace/snprintf.c0000660000000000000000000010710613055076237017255 0ustar rootroot00000000000000/* * 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 */ tevent-0.9.34/lib/replace/socket.c0000660000000000000000000000230712406075657016703 0ustar rootroot00000000000000/* * 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; } tevent-0.9.34/lib/replace/socketpair.c0000660000000000000000000000250112406075657017553 0ustar rootroot00000000000000/* * 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); } tevent-0.9.34/lib/replace/strptime.c0000660000000000000000000005675512406075657017302 0ustar rootroot00000000000000/* 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); } tevent-0.9.34/lib/replace/system/README0000660000000000000000000000036212406075657017452 0ustar rootroot00000000000000This 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. tevent-0.9.34/lib/replace/system/aio.h0000660000000000000000000000201412406075657017507 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/capability.h0000660000000000000000000000316012406075657021063 0ustar rootroot00000000000000#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 #include #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 tevent-0.9.34/lib/replace/system/dir.h0000660000000000000000000000351713055076237017522 0ustar rootroot00000000000000#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 . */ #if 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 #if 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 tevent-0.9.34/lib/replace/system/filesys.h0000660000000000000000000001466012412743715020421 0ustar rootroot00000000000000#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 /* * Veritas File System. Often in addition to native. * Quotas different. */ #if defined(HAVE_SYS_FS_VX_QUOTA_H) #define VXFS_QUOTA #endif #if HAVE_SYS_ATTRIBUTES_H #include #elif HAVE_ATTR_ATTRIBUTES_H #include #endif /* mutually exclusive (SuSE 8.2) */ #if HAVE_ATTR_XATTR_H #include #elif 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_GETXATTR) || 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" */ #endif #if !defined(HAVE_FGETXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) 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" */ #endif #if !defined(HAVE_LISTXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) 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" */ #endif #if !defined(HAVE_FLISTXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) 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" */ #endif #if !defined(HAVE_REMOVEXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) int rep_removexattr (const char *path, const char *name); #define removexattr(path, name) rep_removexattr(path, name) /* define is in "replace.h" */ #endif #if !defined(HAVE_FREMOVEXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) int rep_fremovexattr (int filedes, const char *name); #define fremovexattr(filedes, name) rep_fremovexattr(filedes, name) /* define is in "replace.h" */ #endif #if !defined(HAVE_SETXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) 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" */ #endif #if !defined(HAVE_FSETXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) 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 #endif tevent-0.9.34/lib/replace/system/glob.h0000660000000000000000000000207712406075657017673 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/gssapi.h0000660000000000000000000000265312406075657020236 0ustar rootroot00000000000000#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 HAVE_GSSAPI_GSSAPI_H #include #elif HAVE_GSSAPI_GSSAPI_GENERIC_H #include #elif HAVE_GSSAPI_H #include #endif #if HAVE_GSSAPI_GSSAPI_KRB5_H #include #endif #if HAVE_GSSAPI_GSSAPI_SPNEGO_H #include #elif HAVE_GSSAPI_SPNEGO_H #include #endif #endif #endif tevent-0.9.34/lib/replace/system/iconv.h0000660000000000000000000000304612406075657020063 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/kerberos.h0000660000000000000000000000213112406075657020553 0ustar rootroot00000000000000#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 #if HAVE_KRB5_H #include #endif #if HAVE_COM_ERR_H #include #endif #endif #endif tevent-0.9.34/lib/replace/system/locale.h0000660000000000000000000000216412406075657020204 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/network.h0000660000000000000000000001722113055076237020432 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/passwd.h0000660000000000000000000000404212412743715020235 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/readline.h0000660000000000000000000000321312406075657020524 0ustar rootroot00000000000000#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 # 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 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 tevent-0.9.34/lib/replace/system/select.h0000660000000000000000000000462212474026560020217 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/shmem.h0000660000000000000000000000262512406075657020060 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/syslog.h0000660000000000000000000000343512406075657020267 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/terminal.h0000660000000000000000000000262512406075657020562 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/threads.h0000660000000000000000000000277712536700353020401 0ustar rootroot00000000000000#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 #endif tevent-0.9.34/lib/replace/system/time.h0000660000000000000000000000523713120574744017702 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/wait.h0000660000000000000000000000257212702766507017714 0ustar rootroot00000000000000#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 tevent-0.9.34/lib/replace/system/wscript_configure0000660000000000000000000000230312406075657022246 0ustar rootroot00000000000000#!/usr/bin/env python conf.CHECK_HEADERS('sys/capability.h') conf.CHECK_FUNCS('getpwnam_r getpwuid_r getpwent_r') # 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') conf.CHECK_FUNCS('getgrouplist') conf.CHECK_HEADERS('ctype.h locale.h langinfo.h') conf.CHECK_HEADERS('fnmatch.h locale.h langinfo.h') conf.CHECK_HEADERS('sys/ipc.h sys/mman.h sys/shm.h') conf.CHECK_HEADERS('termios.h termio.h sys/termio.h') tevent-0.9.34/lib/replace/test/getifaddrs.c0000660000000000000000000000504512406075657020510 0ustar rootroot00000000000000/* * 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; } tevent-0.9.34/lib/replace/test/incoherent_mmap.c0000660000000000000000000000345612406075657021550 0ustar rootroot00000000000000/* 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); } } tevent-0.9.34/lib/replace/test/main.c0000660000000000000000000000205012406075657017311 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/lib/replace/test/os2_delete.c0000660000000000000000000000514213120574744020412 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/lib/replace/test/shared_mmap.c0000660000000000000000000000231513055076237020645 0ustar rootroot00000000000000/* 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); } tevent-0.9.34/lib/replace/test/shared_mremap.c0000660000000000000000000000141713055076237021176 0ustar rootroot00000000000000/* 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); } tevent-0.9.34/lib/replace/test/snprintf.c0000660000000000000000000000135513055076237020233 0ustar rootroot00000000000000void 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"); } tevent-0.9.34/lib/replace/test/strptime.c0000660000000000000000000000660612406075657020247 0ustar rootroot00000000000000 #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 tevent-0.9.34/lib/replace/test/testsuite.c0000660000000000000000000007213512746330636020427 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/lib/replace/timegm.c0000660000000000000000000000476412406075657016706 0ustar rootroot00000000000000/* * 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; } tevent-0.9.34/lib/replace/win32_replace.h0000660000000000000000000001046412406075657020060 0ustar rootroot00000000000000#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 */ tevent-0.9.34/lib/replace/wscript0000660000000000000000000010410613202266211016644 0ustar rootroot00000000000000#!/usr/bin/env python APPNAME = 'libreplace' VERSION = '1.2.1' blddir = 'bin' import sys, os # find the buildtools directory srcdir = '.' while not os.path.exists(srcdir+'/buildtools') and len(srcdir.split('/')) < 5: srcdir = srcdir + '/..' sys.path.insert(0, srcdir + '/buildtools/wafsamba') import wafsamba, samba_dist import Options, Utils samba_dist.DIST_DIRS('lib/replace buildtools:buildtools third_party/waf:third_party/waf') def set_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 sys/fs/vx/quota.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 rpc/rpc.h rpc/nettype.h alloca.h float.h') conf.CHECK_HEADERS('rpcsvc/nis.h rpcsvc/ypclnt.h 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_CODE('', headers='rpc/rpc.h rpcsvc/yp_prot.h', define='HAVE_RPCSVC_YP_PROT_H') conf.CHECK_HEADERS('valgrind.h valgrind/valgrind.h valgrind/memcheck.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') conf.CHECK_HEADERS('libgen.h') if conf.CHECK_CFLAGS('-Wno-format-truncation'): conf.define('HAVE_WNO_FORMAT_TRUNCATION', '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') conf.CHECK_FUNCS_IN('''inet_ntoa inet_aton inet_ntop inet_pton connect gethostbyname getaddrinfo getnameinfo freeaddrinfo gai_strerror socketpair''', 'socket nsl', checklibc=True, headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h') # 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') # 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') 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.SET_TARGET_TYPE('attr', 'EMPTY') xattr_headers='sys/attributes.h attr/xattr.h sys/xattr.h' conf.CHECK_FUNCS_IN(''' fgetxattr flistea flistxattr fremovexattr fsetxattr getxattr listxattr removexattr setxattr ''', 'attr', checklibc=True, headers=xattr_headers) # We need to check for linux xattrs first, as we do not wish to link to -lattr # (the XFS compat API) on Linux systems with the native xattr API if not conf.CONFIG_SET('HAVE_GETXATTR'): conf.CHECK_FUNCS_IN(''' attr_get attr_getf attr_list attr_listf attropen attr_remove attr_removef attr_set attr_setf extattr_delete_fd extattr_delete_file extattr_get_fd extattr_get_file extattr_list_fd extattr_list_file extattr_set_fd extattr_set_file fgetea fremoveea fsetea getea listea removeea setea ''', 'attr', checklibc=True, headers=xattr_headers) if (conf.CONFIG_SET('HAVE_ATTR_LISTF') or conf.CONFIG_SET('HAVE_EXTATTR_LIST_FD') or conf.CONFIG_SET('HAVE_FLISTEA') or conf.CONFIG_SET('HAVE_FLISTXATTR')): conf.DEFINE('HAVE_XATTR_SUPPORT', 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") 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') if conf.CHECK_FUNCS_IN('fdatasync', 'rt', checklibc=True): # some systems are missing the declaration conf.CHECK_DECLS('fdatasync') if conf.CHECK_FUNCS_IN('clock_gettime', 'rt', checklibc=True): 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': 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' if PTHREAD_LDFLAGS == 'error': if conf.CHECK_FUNCS('pthread_attr_init'): PTHREAD_CFLAGS='-D_REENTRANT' PTHREAD_LDFLAGS='-lpthread' # 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) 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_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 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 "test/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 "test/snprintf.c"', define="HAVE_C99_VSNPRINTF", execute=True, addmain=False, msg="Checking for C99 vsnprintf") conf.CHECK_CODE('#include "test/shared_mmap.c"', addmain=False, add_headers=False, execute=True, define='HAVE_SHARED_MMAP', msg="Checking for HAVE_SHARED_MMAP") conf.CHECK_CODE('#include "test/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 "test/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_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 "test/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'], '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, functions in REPLACEMENT_FUNCTIONS.iteritems(): for function in functions: 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' 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 nsl socket rt attr' + extra_libs) replace_test_cflags="-Wno-format-zero-length" if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): replace_test_cflags += " -Wno-format-truncation" bld.SAMBA_SUBSYSTEM('replace-test', source='''test/testsuite.c test/strptime.c test/os2_delete.c test/getifaddrs.c''', deps='replace', cflags=replace_test_cflags) if bld.env.standalone_replace: bld.SAMBA_BINARY('replace_testsuite', source='test/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 dist(): '''makes a tarball for distribution''' samba_dist.dist() tevent-0.9.34/lib/replace/xattr.c0000660000000000000000000005122213055076237016551 0ustar rootroot00000000000000/* 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_GETXATTR) #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_GETEA) return getea(path, name, value, size); #elif defined(HAVE_EXTATTR_GET_FILE) 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_ATTR_GET) 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_FGETXATTR) #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_FGETEA) return fgetea(filedes, name, value, size); #elif defined(HAVE_EXTATTR_GET_FD) 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_ATTR_GETF) 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_EXTATTR_LIST_FILE) #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) { #if defined(HAVE_EXTATTR_LIST_FILE) case 0: list_size = extattr_list_file(arg.path, extattr[t].space, list, size); break; #endif #if defined(HAVE_EXTATTR_LIST_LINK) case 1: list_size = extattr_list_link(arg.path, extattr[t].space, list, size); break; #endif #if defined(HAVE_EXTATTR_LIST_FD) case 2: list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size); break; #endif 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_ATTR_LIST) && (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_LISTXATTR) #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_LISTEA) return listea(path, list, size); #elif defined(HAVE_EXTATTR_LIST_FILE) extattr_arg arg; arg.path = path; return bsd_attr_list(0, arg, list, size); #elif defined(HAVE_ATTR_LIST) && 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_FLISTXATTR) #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_FLISTEA) return flistea(filedes, list, size); #elif defined(HAVE_EXTATTR_LIST_FD) extattr_arg arg; arg.filedes = filedes; return bsd_attr_list(2, arg, list, size); #elif defined(HAVE_ATTR_LISTF) 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_REMOVEXATTR) #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_REMOVEEA) return removeea(path, name); #elif defined(HAVE_EXTATTR_DELETE_FILE) 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_ATTR_REMOVE) 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_FREMOVEXATTR) #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_FREMOVEEA) return fremoveea(filedes, name); #elif defined(HAVE_EXTATTR_DELETE_FD) 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_ATTR_REMOVEF) 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_SETXATTR) #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_SETEA) return setea(path, name, value, size, flags); #elif defined(HAVE_EXTATTR_SET_FILE) 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_ATTR_SET) 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_FSETXATTR) #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_FSETEA) return fsetea(filedes, name, value, size, flags); #elif defined(HAVE_EXTATTR_SET_FD) 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_ATTR_SETF) 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*/ tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.0.6.sigs0000660000000000000000000000050012406075657021630 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.0.7.sigs0000660000000000000000000000050012406075657021631 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.0.8.sigs0000660000000000000000000000050012406075657021632 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.0.sigs0000660000000000000000000000050012406075657021623 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.1.sigs0000660000000000000000000000050012406075657021624 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.10.sigs0000660000000000000000000000150413134750174021702 0ustar rootroot00000000000000_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.2.sigs0000660000000000000000000000050012477561557021634 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.3.sigs0000660000000000000000000000050012553526140021615 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.4.sigs0000660000000000000000000000050012617125140021612 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.5.sigs0000660000000000000000000000050012617125371021621 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.6.sigs0000660000000000000000000000120712667552643021642 0ustar rootroot00000000000000_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.7.sigs0000660000000000000000000000120712713047143021625 0ustar rootroot00000000000000_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.8.sigs0000660000000000000000000000120712746330775021642 0ustar rootroot00000000000000_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util-2.1.9.sigs0000660000000000000000000000150413055076237021635 0ustar rootroot00000000000000_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util.py3-2.1.10.sigs0000660000000000000000000000142113134750174022412 0ustar rootroot00000000000000_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util.py3-2.1.5.sigs0000660000000000000000000000041512617125371022340 0ustar rootroot00000000000000pytalloc_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 *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util.py3-2.1.6.sigs0000660000000000000000000000112412667552643022352 0ustar rootroot00000000000000_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *) _pytalloc_get_ptr: void *(PyObject *) _pytalloc_get_type: void *(PyObject *, const char *) pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *) pytalloc_BaseObject_check: int (PyObject *) pytalloc_BaseObject_size: size_t (void) pytalloc_Check: int (PyObject *) pytalloc_GetBaseObjectType: PyTypeObject *(void) pytalloc_GetObjectType: PyTypeObject *(void) pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) pytalloc_steal: PyObject *(PyTypeObject *, void *) pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util.py3-2.1.7.sigs0000660000000000000000000000112412713047143022335 0ustar rootroot00000000000000_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *) _pytalloc_get_ptr: void *(PyObject *) _pytalloc_get_type: void *(PyObject *, const char *) pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *) pytalloc_BaseObject_check: int (PyObject *) pytalloc_BaseObject_size: size_t (void) pytalloc_Check: int (PyObject *) pytalloc_GetBaseObjectType: PyTypeObject *(void) pytalloc_GetObjectType: PyTypeObject *(void) pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) pytalloc_steal: PyObject *(PyTypeObject *, void *) pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util.py3-2.1.8.sigs0000660000000000000000000000112412746330775022352 0ustar rootroot00000000000000_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *) _pytalloc_get_ptr: void *(PyObject *) _pytalloc_get_type: void *(PyObject *, const char *) pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *) pytalloc_BaseObject_check: int (PyObject *) pytalloc_BaseObject_size: size_t (void) pytalloc_Check: int (PyObject *) pytalloc_GetBaseObjectType: PyTypeObject *(void) pytalloc_GetObjectType: PyTypeObject *(void) pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) pytalloc_steal: PyObject *(PyTypeObject *, void *) pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) tevent-0.9.34/lib/talloc/ABI/pytalloc-util.py3-2.1.9.sigs0000660000000000000000000000142113055076237022345 0ustar rootroot00000000000000_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 *) tevent-0.9.34/lib/talloc/ABI/talloc-2.0.2.sigs0000660000000000000000000000644312406075657020314 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.0.3.sigs0000660000000000000000000000644312406075657020315 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.0.4.sigs0000660000000000000000000000644312406075657020316 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.0.5.sigs0000660000000000000000000000644312406075657020317 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.0.6.sigs0000660000000000000000000000644312406075657020320 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.0.7.sigs0000660000000000000000000000644312406075657020321 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.0.8.sigs0000660000000000000000000000652312406075657020321 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.0.sigs0000660000000000000000000000665312406075657020316 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.1.sigs0000660000000000000000000000665312406075657020317 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.10.sigs0000660000000000000000000000671513134750174020367 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.2.sigs0000660000000000000000000000665312477561557020327 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.3.sigs0000660000000000000000000000665312553526140020310 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.4.sigs0000660000000000000000000000671512617125140020304 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.5.sigs0000660000000000000000000000671512617125371020313 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.6.sigs0000660000000000000000000000671512667552643020327 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.7.sigs0000660000000000000000000000671512713047143020312 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.8.sigs0000660000000000000000000000671512746330775020327 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/ABI/talloc-2.1.9.sigs0000660000000000000000000000671513055076237020322 0ustar rootroot00000000000000_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) tevent-0.9.34/lib/talloc/Makefile0000660000000000000000000000153712406075657016556 0ustar rootroot00000000000000# simple makefile wrapper to run waf WAF=WAF_MAKE=1 PATH=buildtools/bin:../../buildtools/bin:$$PATH waf 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: tevent-0.9.34/lib/talloc/NEWS0000660000000000000000000000034012406075657015604 0ustar rootroot000000000000001.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. tevent-0.9.34/lib/talloc/compat/talloc_compat1.c0000660000000000000000000000312512406075657021442 0ustar rootroot00000000000000/* 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); } tevent-0.9.34/lib/talloc/compat/talloc_compat1.mk0000660000000000000000000000122612406075657021627 0ustar rootroot00000000000000talloccompatdir := $(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) tevent-0.9.34/lib/talloc/configure0000770000000000000000000000065012406075657017017 0ustar rootroot00000000000000#!/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 $WAF configure "$@" || exit 1 cd $PREVPATH tevent-0.9.34/lib/talloc/doc/context.png0000660000000000000000000001115312406075657020050 0ustar rootroot00000000000000‰PNG  IHDRx(]È~ pHYsaa¨?§itEXtSoftwareGPL Ghostscript 8.63ô*8YôIDATxœíÜ1sÛFúÇñÕýÂM&{ææ\e6¥K¤¹—àK€»káw ÌuÀ½¢MG´êˆÖs Ѧ㦋Èu'3¸â‰÷ð'!Š’øõýT°»X`Áí‹a húË©;àü=;uŽªišÙlvê^àðþö·¿ýòË/»Ëüýïÿ÷¿ÿ}œþ`ÃÅ“ztº¸¸8u åÆ+ù«¯¾úí·ßŽÓlxZw4âIeëS°Ï÷GÛ¶¿ÿþû:ƒIÌÑàI¨ëúÓ§O§îÅÓEÐàI¨ëú?þðÞŸº#OAƒó×4DLUU§îËõ'ƒŸÔ!?7ël6kšÆc­]¯×ÖÚãuÆ‚g`Ïa}ùòåÇÒ#lâÑ €:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚€:‚æAhšæíÛ·òç»wﲆªªf³Ù¡vá½wþIñÞë°'ö>vÊŽ­Gt+—ñØÅ0 whñ‘’SpÌC®ë:I’= _\üo8ÆËJ»‹#txÇ®ÍÃúòåË?*u`¼wSQ–e–e·­µ»';¶Þç&ërG£«mÛSwç ïûSwá^E}ßWUuê^àÑkÛö±_HÏNݳÕ÷}Y–}ßçynŒqÎ¥ijŒišF 4M“$IE{6DZÔʲÌZ+›êºnÛV6c†²,sÖZï½s.«ëÚZÛ4tÏ{_–eUUrë[UU]×MÓ Ã6Íçsçœô$ÔXžçUU¥i𦩔<Þû¶måtí9pƘ²,¥¤Ü’„çèɛ܅÷¾®ëp!Åq,…ó<—1mÛ6\MÓ4MÇqß÷Þû}ºqÎM>æ×umŒ‘öe_ÛÕ7®+ñîÝ;9¢(Ìð”ÈñyÛkV«Õ0 ëõÚ9w]áñr–e‹ÅB–‹E–ea9I’PÌZ+-oȲ¬( Y^­VÖÚ°‹årê^×ç^Íçóñ·‹E±^¯·»¡gÏa}ñâÅ}öDZœÆ®ëv ÜøÏ,ËÆ§+MSÇënÿ]E.ƒÕjÇñv³ëõz÷i —âF÷Æ»[,iš†2óù<ìwÇu%‡eY×u®ÜÑóó‚fµZu]×uÝr¹Üý‘–…íËÅ#Ÿdç\¸2¤åíHõ0Þãb×åÚ>½šÜÔu]Çã}Çq‚f½^ï3pÃè“¶±~¹\FQ4\?pûïÂ9WÅò3ÙºÑìv­ [‹EH·°)Š¢ðm6u]·ûºêºnyÃ00GslÖÚ<ÏåþvŸò“7À²Ò{ž¡Œ1“7óRòÆbQU•µö±Ï&ìp«›| +w Üž»ðÞGQ&ïfoKž€ö<Šו<úµm+Ï\Úxççø‡v¾â8Þ¸§æ~w4“¶¿y¶w±cù¶›º®»î NÏžÃzÿG§}n¼uã̇[†ënŸ]È…äœ?” ;š6å6m½^︮$ø–Ë¥µ–G§# ç:Ív‚loÚXN’d´mûáÇpž·¯+y yyÙ÷½l­ªê§Ÿ~Š¢ˆ_ãÑ;ù/ƒq#&ƒ¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨#h¨;|Дeyò<(‡š¾ïOÞ€åÀAÓ¶mUU§mÀCó,,•e霳ÖzïsqcêºîûÞ9ç½·Ö&IbŒ©ªªª*)E‘lJÓÔ{/åó<7ÆÄq,eò<—–۶ͲÌZ›çyÓ4ÞûÅbÇñl6óÞ'I’¦éd ·a†aȲ¬( Y^­VÖÚa‹Eš¦ÃgY–-‹ð§µv¹\†å°>´)Š¢È²,´DZ,w]g­]­VÒr×u×µp@ãCÆÙØsX_¼xq„Î`’†a½^cÆuùü;çB” ð\.sÿ«9Úë–¥‘¢(–Ÿ·J¢m¤Ìv DМ%‚æá{fŒñÞc¬µá6'Š¢°~l{ͼ÷Q…' áóe!{ɲ¬išñ®œŸ¿cœsfê]¬ß½f‡¦i¤Êuñ$“AQÉŒÌu-xìþ š,ËÆ¿^‘OxQu]‡•u]Eqc‹r{Ò÷½,E1΋ðF©ïûº®“$‘ãm´à±»Ï2yž[kå¡É9'7/×½uòÞ—e™eYš¦UUɲ¼$’­QIaiDÖcdyž×u-s@Ƙï¾ûÎ{Ÿ¦iš¦Î¹ív´æÿ?¾á ì9¬/_¾üøñãQz„MOêSGМ%‚æáãß:PwþA3›Í˜TNëÙÍEÔÌf³#ì¥iš¦i¾üòË¿þõ¯²Fî´mÿøÇ?~üñÇS÷â ÿÄŠL-'Iòí·ßžºG8¼o¾ùæçŸÞ]fŸ9š¯¾úê·ß~;\¿ð§SÞÑGÇòF,ü)¯ºpNrwܶíï¿ÿ~ÿv°íüƒ†XÁžêºþôéÓ©{qžÎ2ØS]×üñÇþ nDÐÆ#ÿo‰ýxDÐÆŒþÙªªø?îüçh€}È\¿V u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u uÍòÞ¿}ûöâââÔþDÐ<eYÞª¼sn±X(uT]×_ýuß÷'Ù;Aóœê ¦iNÒBÇY–Ykï¹÷»!hº¶m«ª:u/p0§ km–e÷Üõ=;ÕŽ¾²,ó<ŸÏç²¼\.s}ß—eE‘1¦mÛð‘ç¹µVÖ7MS…1¦ªªº®›¦†Á{_–eUUÃ0Hûyž;笵¡¶m›¦ Äq윫ëºïû<Ï1qÇq†aµZÉš,Ë‹…,/—Ki-˲,Ë®ÛÅø$‡å¢(B•Õj%U’$ %»®[.—Û-\Ww±XŒ«¯×ë݃MXkÃaýäñJõ°^þÜ®¾X,Ò4 eæóyèöö‰†A¦–Bá®ëvôÃ>ÃúâÅ‹û”éº.˲ù|¾\.ÃÁÃP…¬Y,Òÿõz-Q KE)lŒÉ>·,Õ³,ëºn½^Ë÷GEëõz½^;çâ8žÏç“-lX­V¡WY–-—ËÐ%)¦©¬_.—I’„³'ý ݸñtí ÙÅ3>Ýòé]Žcdåz½Å6†2hœsáRv¤¢\Lãß°4“uÇŸÒÉZÛ‡vc''wÿêQ?Ãè|nœXQEÈÊqîãA“$IèUÈå "MÓ0 ÛQÖo´|]šËMt×u’D¡ü÷7~c…Ö–Ë¥µV®ÞÉ/°C!hvÙÑñ'mÇÊ}‚f| 0& ÖZç\ˆ›íOõvÝí•÷šÉãÝ¿úd—dÍd³]×ÉE¿^¯7¢öFÚA#™ÂQº×uÝöE‘,_wŠ6ÖïHóaŠ¢ˆ¢hÇ5éÆo,I–®ëÆßO“_`‡Âdð-ÈŒÆÆôÇäÊ}šÚ®RU•ÜÐv]—¦éö[m™œ¬+óG·êÃ>4·?´qõq—dYÚœd­M’¤ªª¶meVèá“^Ù„I«í’“+ol9>Ïâc²,ÛqÆ®#_Wu]Ïf³o¿ýv»KÒæ»wïâ8N’$ô$Š¢ÉnÜAs ι,ËÆï€Ê²tÎÉÇ#¬Ü×puŽ×E1~w Õ›¦ ŸÌñ›HYèû^&ën¬¼íå>iòx÷¯¾Ñ¥º®oüؤiú0_±I·7¢|{eß÷ûçBøÚ0×§yÓ4Y–5M#Óê“-l»ñËS–eÛ¶2ã#¯&¿Àæ€wGÂþNòZd{ÊMÞŒ,—Ëù|nA¥Øä=ç|>— ¶ù|._ Rk±X„;U¹ÅM’¤(ŠÅb!‡u™FOÁlו•¡ò~'MÓÉ)=Ù¦6ß26M︌¬œ¬.H2Á)¥EQì>±· ÛÖºçMš¦áœÈ‘7ÍÑŒ«‡?­µ2(á¹rãT„µZ­Âì²s.Ìn·°!I’ñ¸‡)ùЇÕje­¿â¶Þ'Üvšl·‹á 7Hßl6“,ÐsqñäÎêÉKîÛÖÚgX_¾|ùñãÇû”Éó\š¼÷išÊ fxý/¯ö“$ñÞ‡·õq{ïåÇ ÙUUyïe&.I’¾ïC—Ò4•òÐÔ4MÛ¶rö꺖(cÌußÑCëQ8ì\ú¤'xVïiµZÉwi¸I¼­#ÜÑà>˜£90™bÈóüaÎ5>^$›ýß™Ìbño¿ýÖ¤ !!!>ÌÎÎîíímhhèìì‹Å&-1æÇtppàr¹1° XEá*¼P>lòOz½þÑ£G‰déÒ¥sæÌ¡gΜéää¤V«9!D§Ó9;;ÓŒŒŽŽúúúêt:‹¥×ëéÝ·žžžŽŽŽE‹y{{›œÇ¸Fóâæm „ôöövuu…††:;;[l õkלþóŸ#IJ–e7=€ì€m=;d@v`]àCÅ/µZ-“ɦ_¿ÆÆÆÌÑÙÙ/%%%OÈ`0š››gÏž½páBkh°R©ljjZ»v­««ë“s®^½ñ¶>z2Å7}ÅÅÅ"‘(%%%44Ôz688XRR"“Éöïßïëë‹HÈL7ÍAy²v¤9(@vÀŽ4åÈØ‘æ <Ùqi®¤¤ä?ÿù­kʰ#ÍAy²v¤9(@vМiÊ4jŸÊ4åÙAsP4åÙAsP4åÙAsP€ì4åÈšP€ì 9åÈšP€ì 9åÈšƒò€ì 9(Èšƒò°OÙAsP€ì 9åÈšP€ì 9åÈšP€ì 9åÈšP€ì 9å;“Ý¥K—êëëwìØŽpš¾¾¾?þØÑÑQ p8\`YvåååõõõóæÍ³‰¨T*ggç'dP(}ô"m?ŒÅÄĬ[·îŽÉG©T¾ôÒKo½õÂ4ù8XLÝ¿ÿ´Y>|a¶7~ùË_9rÄ &‘HÊÊÊ )K€ì²È ;¦ƒÁðÃ?ˆÅb&E©Tööö*•ÊÖÖV:E¥Rµ´´ç‘ËåÌKN'‰èã¡¡!©Tª×ë…B¡L&còkµZ¡PØÞÞn0pÍ!;&›3gΔ””<|ø022rëÖ­ ¥¥¥\.7///222**ŠRVVvôèQ±X¼ÿþ;v¨Tª²²² œ;wŽÒÔÔ´bÅŠŒŒ BÈñãǽ½½OŸ>½{÷n@PTTDéììܹs§H$úâ‹/’““qÙ­‡qæ“Ëåccc^^^ôäÖÓÓãïïOObmmm...l6›™ýþýïs¹\wwwzòòððxôèQHH!D*•²Ùl—û÷ï¹¹¹ÑÇÆÆ~üñÇ%K–¸¸¸×;wîÜ,^¼ØÑÑQ«ÕÒ¥˜<æ5`BOOÏÁƒ%‰ƒƒCooïçŸ~óæMBH}}}ccc]]ÝÝ»w[ZZ îÝ»Çb±6nÜšŸŸŸ}þüyú$áááo¼ñÆ7!™™™¥¥¥b±¸¼¼œÅbݼysýúõ111ÕÕÕ^^^111111õõõ¸ò6vg÷¸ÉÍ|£(êØ±c'NœèééÙ´iSmmí… L&Ï÷ßßÛÛ;??÷îÝ loo×jµ™™™EEEGŽ U(L½ !!aß¾}K–,©­­MLLÌÌÌ\¾|¹T*µX#‚ ÌQ(cccôbS¡P0#urrŠŽŽöððذaCMMMPP‹Å"„°Ùl>Ÿÿõ×_Óy˜ó˜GFFÒù#""¸\îƒx<ÞÙ³gò³³½½½qåmìÎî7¿ùÅÉíüùó&“صk×.]ºtëÖ-BˆX,~çwîܹséÒ%fò$„dee•••yzz¾ÿþûE­ZµêܹsŒ‹‹[¿~=EQ!!!ÿøÇ?¶lÙB×ëààpéÒ%Š¢üüü*++«ªª(Šò÷÷ÿûßÿž’’b±FĘ”•••’’ÂãñäryAAóÖŒ3˜e=ƒÒxzzΚ5‹>fvßôzýãªÐh4kÖ¬™7o^{{{MMMeeeaaa__ßÌ™3qýmikqrãñxï¾ûnccclllRR!ä›o¾ÉÍÍuqq¡—®&“'s†eË–BX,VTT”D"qrr (((P©Tl6{``À<çªU«˜ãŸþô§ô,m±FÌñññÙ¶m[jjªq¢Á``DUPP ‹éíšÖÖÖÄÄDBˆ«««P(¤7m.^¼h<Ɔ††èƒ«W¯&''Ï›7¯¸¸8--mÏž={öì –ËåÉÎâän2‰I¥Rÿììl“²Ìäi¡:®±±1--­¾¾ÞËËë»ï¾³øËøÝÌñãjÀ„ŠŠŠöööÏ>ûŒÅb¹¹¹ ‚ÑÑѦ¦&ww÷•+WÆÇÇoÚ´)==Ïççæævwws¹Ü×_’œœÜÛÛ»páBWQQqåÊ•˜˜Bˆ@ hhh˜?~HHH^^!¤­­íøÃ–-[š››ß|óMÚ›À–dgqr3ŸÄÖ®]›™™Ù××GïV 6›m‰íÚµëúõëk׮ݾ};‡Ã öññ1ž< !þóŸE"QyyùâÅ‹ƒ‚‚!ׯ_OII9yòä¶mÛbcc}}}¯\¹²yóæÛ·o777+Š7vttÐÇ«W¯&„ÔÔÔðx<óßxã ĘpöìYOOÏíÛ·3ûqÙÙÙŒ¡þÿ‚ŸŸŸŸŸŸIñY³fÑûwŽŽŽ&ùçÏŸo²þÆ5·:(3>ÿüó––óôááá®®.ƒÁ Ñh´Z­J¥Òét<¸uë–T*5ÎÙÓÓóÏþS©TR¥R©´Z­V«¥_R¥P(t:Z­Öh4Ei4ú¥L&“H$LN§T*µZ­F£Q«ÕÆÇE©Õj­VK›Ôh¡C‡(`OŒŽŽæææš$þío‹ŽŽÖétôࡲ=cE¡¡¡OUd`` ??1šžbÏÎâäfqóñññññaž0˜Lžôçã˜M7úl‡Ù×cŠ<ágM6kÀœøøx‹•““ãåå¥V«½ªx–[ÅÀÀÀÆÆÆ—_~Wxú,c°uø|>ŸÏ^gKMM5y° ¬ìå ;€ì²ëÂòН¾úêþýûÓ£‡jµa¶7Z[[+++­°a£££ˆÎTaá_)J¥ÒŽŽŽiÓCOOÏ€€DÚ~0 ßÿýÍ›7¿ýöÛ}ûöó5·nÝŠ‹‹{A­ª¯¯‰D K—.ÅwȬEvØ.z½¾¼¼üÎ;‰‰‰ã,EQTjjjQQó3'/‚Ó§O+Š}ûöáן ;&Us4gÏžår¹7nœ„vByS 9BˆH$:qâć~8™m¦•§T*322 <È€«¹I[ÀByS¦¹É_ÀByS ¹©ZÀByãÒÜÝ»wžQsS¾€…ò ;^ìÝœU-`‡D"9uê”ÙhîY±ª,”ÙhîùkÎj°PdìTsÏkoΜO>ù$00Ð:°OP^YYÙðððÞ½{¡<Èànn\ Ø>úÈøŸdÛ–òJKKGFF <È@sÓg åAvš³£,”Ùé ¹ŠŠŠÖÖÖ×^{íEkÎÖ°Pdl[s¿úÕ¯x<Þ$Ô8=°Pd 9;ZÀBy€æìhû?•÷ûßÿÿ9²ö¢¹i¿€…ò ;Íý—3gÎ,Z´hÆ vxý¡<ÈØ…æìm åAvÀ5g· Ø'+ott4==Ý>•Ùç¬9¡P¸uëÖ©Õ°PdìBs„Gøàëoç‡~¨V«'PP«Õ>|Øúûhœ|8N^^žmµY(þë_ÿ²(;6" ° ;dÓìÙÿò,ü6Áàà Á`ðôôd±X· ÑÖÖ¦ÓéÜÝÝýýý™D™LÖÕÕÅf³9ÎÒ¥Kqgþ7E544ìÚµËx$M3úûû_}õÕÅ‹ûøø¬[·®¿¿q·!T*UzzzHHHkk«ñ¸½~ýúoû[¥R‰e,}}}÷ïß?räˆÁ`˜®}¬««KJJ’H$"‘h``àèÑ£ˆ» ñÊ+¯ðx¼ÐÐP>Ÿ/“ÉèĹsçîØ±cÍš5+W®„ìlƒÁðÃ?ˆÅb&E©Tööö*•JffS©T---Æy!r¹œIÑét"‘ˆ>’J¥z½^(2c…ÁÇÇ'==}æÌ™Ößljuâë뛚šÊb±|}}zzz0Ìl(|„‡SZZÊáp’’’ôz=“ÈápÆßlÈκ8sæLIIÉÇ###·nÝšPZZÊåróòò"##£¢¢!eeeG‹Åû÷ïß±c‡J¥¢,XpîÜ9BHSSÓŠ+222!Ç÷öö>}úôîÝ»A@@@QQ‘-öñY:¸~ýz毢¥¥åÕW_ÅH³¡ðÑÌž=»ªªª©©iâФÀqèÐ!“”îîîÙ³gkµZŠ¢N:Åãñèô]»v………Éd²ºººæææƒÁ@Q”^¯_¾|ùÿøG:ÛæÍ› éã‚‚‚¸¸8úø'?ùIFF]äÆl6»­­Í¤êÎÎÎÇ †‚‚‚þþþ tphhèèѣϱÏÒAš{÷îmÞ¼™®ýɱ˜è6?mŠÑg _VVVoo/EQ—/_f±XEÉd²˜‡ø/ù‹ÅîàÎΊP(cccô¼B¡ ¥Óœœ¢££=<<6lØPSSD?Od³Ù|>ÿ믿f²1§29ŽŒŒ¤‹DDDp¹ÜØbŸ±ƒCCCüôÓO¬åC±±±ÅÅÅO›b£Cô¹ŒÏØØØ÷Þ{/55õîÝ»OÛx|ôÄŠ ÊÊÊJIIáñxr¹Üø¿Î˜1ƒÙøJ¥Lº§§§ñ·V™‡ ̾†9fÍš56ÚÇ wP£Ñ¼õÖ[§Nš?¾õDü½÷Þ3ù¸ÏxRlwˆ>—ñyøðáï¿ÿžÏç×ÖÖBv6ŒÏ¶mÛRSSMöƒ™QUPP ‹½¼¼!­­­‰‰‰ô[®®®B¡¢Õj/^¼hü ü¡¡!úàêÕ«ÉÉÉóæÍ3©—|z½þ©v|'¹î ^¯ÏÈÈHKKsssëêêR«Õ¾¾¾...Sî°°° ¤Øè}–ñ©Ñh4 }Ìb±JKK×­[—””ôTÛ¯uQQQÑÞÞþÙgŸ±X,777@0::ÚÔÔäîî¾råÊøøøM›6¥§§óùüÜÜÜîîn.—ûúë¯Óe’““{{{.\Èãñ***®\¹C óçÏ 1ÿj÷—_~yþüyBÈ;3˜˜ø¢ïû&ÜÇ wðÀÅÅÅÆ‹ÁÛ·o¯^½ãÍ&ÂWUUuõêU¹\ž™™¹hÑ"BÈÌ™3«ªª~ö³Ÿ=Ý6áAõìþöõõ¥¥¥ýõ¯½uëVuuõÎ;_yå•J¥ÕjµZ­R©drvuu555Éd2“3 wuu F£ÕjU*EQ«V­ª¬¬‹ÅôKs”J¥Z­ÖëõjµZ­V¿ÐÏØÇ‰uP¡P¨T*NG÷Q.—ët:kx@aoCtÂãS§Ó©Õj“'KR©´££cü(pggEœ={ÖÓÓsûöíÌfGvv6³•k¼­îççgqgÖ¬Yôþˆ£££I‘'ìU9;;›l»Xm'ÖAãëŒ3&¡›¢Ï1|ôø4ß`™3gΜ9sÆßx<µ"–-[vçÎzûL£Ñœ9s&''çÙOKÏ¢Ó¸VÕA Q« î쬈øøx‹•““ãåå¥V«APPгOÅ!!!/¿üòô룵uCÔjÃÙY|>ŸÏç?Ǧ¦¦š<8›f}´ÂbˆZgø°ŒØ²€éöì¦ N÷¸´±*Æÿãˆæ¨T*›è#æZD£ÑØDøŒ쬎•+W–””X;ÝÜÜ&PÐÙÙÙÕÕÕ&ú¸bÅ Hs‚‚‚l"|&¼öÚkÓñO²vöì@vÙd@vÙd€ì²È ;€ì`rù´î¯¬×ûIEND®B`‚tevent-0.9.34/lib/talloc/doc/mainpage.dox0000660000000000000000000001073312520121120020124 0ustar rootroot00000000000000/** * @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. * */ tevent-0.9.34/lib/talloc/doc/stealing.png0000660000000000000000000001552212406075657020176 0ustar rootroot00000000000000‰PNG  IHDR±ž3?£±sRGB®Îé pHYs  šœtIMEÜ 1r·¯ÃtEXtCommentCreated with GIMPW¿IDATxÚíyXSWþÆoB$ˆa‘¨ 2¸Œ”·¢c nTÁAáí¨ƒ:—VpTÔ‚âÂT;µ£ŽâÒªàŠJÇÇE¨e!@ âŽÂ6lYÉýý‘yòC B–›ð~þð1'÷ž“œóý¾Ü÷Üsnh$I‚ :º ‰Mh"@š½€AÙOÖÐÐPZZúúõkùËþýû{xx¸¸¸0  MMM¥¥¥/_¾”/kc2™Çïׯ:Ç¡Qm}"‡ÃùñÇ[ZZlmm===]\\h4AÍÍÍ\.·¬¬L"‘x{{/\¸ÐÂÂãôů¿þzúô醆‹5zôh‚ Z[[KKKKKKE"ј1cBCCˆî‚&ªÃ­[·®^½úÛßþ688¸ë0zòäIZZš™™Ytt´µµ5Fè’G¥¦¦Ž5*$$ÄÖÖ¶‹#‹ŠŠRSSe2YTT›ÍF×AU¥¾¾~ûöí>>>áááò«BU¨¬¬LLLœ6mÚÂ… 1@´´´ìرÃÕÕuÅŠtºªsñuuu»ví3f̲eËЇÐÄî),,üÇ?þ±mÛ¶Áƒ«qú™3g¸\n\\œÜ¹ %ÊËË÷ìÙ³yófggg5N¿zõêƒLMMÑ™ÐÄNyøðá•+WvïÞÝEËÏÏONN>pàfµ–ÈÏÏÿ׿þ•””Äd2Õ®¤¬¬,))éÀæææèRh¢8ÎÑ£G÷ï߯º_äääo¿ý–:=>lØ0mÔ\[[›œœŒØÕ/_¾LLLüþûï{¿æáÅ‹‰‰‰‡VÝzS–°°0õ.™©ᤞhjjŠŒŒ”H$šªðÎ;GŽ!)Cll¬ÁÕ >D$ýùÏšª077wïÞ½FÐ3ÆázûcµsçÎÍ›7kp±áŒ3x<Þ¯¿þŠë AöíÛ·nÝ:333MUèíímjjúŸÿü}KMô£‰yyyÆ srrÒlµ_}õÕßÿþw *Ðåååt:}Ô¨Qš­6** ³ÐÄ÷8vìXDD„Æ«5337nÜãÇ1®@#:thõêÕ¯ÖÄÄdæÌ™ÿþ÷¿ÑÃÐD‚ ˆŠŠŠ#FhiEÂÒ¥K/]º„q½§±±qÀ€ZÚ…tëÖ-t24‘ âìÙ³aaaZªÜÔÔÔÄÄD(R­£[[[/\¸°nÝ:Äœ¡páÂím Óé¶¶¶µµµFÓ]FázÐÄÊÊJ–ÉdUUU=ªêÔ©YYYTëh’$Åbñ 5†BqqñèÑ£µ¨~~~Æt©h4N×}Çõè^óÒ¥K<Ø£&&MšôË/¿P­£-,,&Ož ¡1¤ÜèÉB5ÕËË«  ÀhºËh"\ךøîÝ»®o7Ëd²ÒÒR>Ÿ¯¸ ·±±!B$•””(V˜WWW·´´(­ÁÚÚº¡¡Ê^SSSPP ‹%ÍÍÍùùù@Q"*++AQQäI÷‚®w›t¨ªÇ*ƒÁhkk3ÊÞ3è×õ³«ªªºØ×üàÁƒ+W®˜››gddDEEÙÙÙåææ¾|ù233sÖ¬Y_ýuLLÌÚµkóòòöîÝûÍ7ßtö¸°ÞoŒÑÇŽûé§ŸŠŠŠ¤Ré;wØlvLLŒMNN—Ë-((077?þü_|úèÑ£/^Ó¬“¡Àãñºx’Mºÿþ¼¼¼¨¨(Ub•ÊÚw#\ÇkÄ333¯]»¦ô-‡3kÖ,™LF’dEEÅåË—I’ øî»ïçš™™=~ü8""¢ë}TØéñágxñâ…<ä3/&LˆŽŽ …÷îÝ#IR&“ýæ7¿ÉÈȼdÉ’>ú¨¾¾þöíÛØÇ¢{ŠŠŠNž<©^ ª«=”ÆẾNd2™Ý>þ¼§§§ü/§££c```‡|}}׬Y3sæÌÒÒÒ®÷PíA¹íùøã ‚èׯ߂ =zÄd2“’’„B!NWx1&“9kÖ,‹õÉ'ŸàªM÷0™ÌöF¯Gªz¬R9Pûl„ëz>ÑÆÆ¦®®®³©Æêêê®Og³ÙC† 9zô¨!ÆJ‡hkk7n\VVV@@À矾eËWWW™L¦8•Ò#½ TCÕ¾áºÖD—W¯^)}kúôééééïÞ½{ïóÑéŠùéóçÏ[YY¥¥¥%&&>|ø°³&„B¡w§j‘H$ŸZ&B"‘deeýå/IOO÷ôôd³Ù|>ŸËå*¢J&“µ cº¸S×m ª«F†qD¸®½3ƒÁH$Jß ËÌÌôññY¶lYsssHHÈ”)Süýýããã Î;wéÒ%¶}ûöE‹ýðÃJ¯ºóòòÆOÁ¾njjrssóööþä“O,--9booïççàè蘑‘1{öì§OŸfgg0ÀËËkÁ‚P(*\õ¨¨)))/^üñǻղ²2777cê1#‰pÝOaÆÅÅ566vönEEÅÇ+++%555B¡°ý12™L$‰Åb¥5ÄÇÇ×ÖÖRpZ H¥Òºººêêêöåõõõ555$I …B‰D"•Jåÿ‘H$J§çqE7ìÛ·¯¢¢¢7Úu¬~÷ÝwåååÆtÅ8"\ûX-ZtîܹÎÞuttœ:ujûõ:¶¶¶nL£ÑLMM•>U›$I§X)F)ÌÌÌLLL¬­­ Ô¾œÅbÉêˆÉd2 ù 5'úaaa?üðCoµëX-++1b„1õ˜qD¸4q̘1Ú[¾ûömä3è=NNNïÞ½ÓҲ꼼¼>úLAôó¬0???m<(‰$ÉË—/Ï›7ã 4åiΞ=«šOœ8±xñbô04ñÌŸ??==]ãO¯9}útpp°Qî zaÊ”)¹¹¹ß*zýúu___ü¤4ñ=Ö¯_¿mÛ6 Vøüùó‚‚‚3f`PÙ¸qã–-[4XaUUUFF~”œ²0ôÕ°««ë”)SŽ?¾|ùòÞ×ÖØØ¸wïÞýû÷S§gkjjÒÒÒ´Qsss3Wg888,Z´èÀk×®í}mB¡pÇŽ‰‰‰FÐ3Æázþ}ç”””þýû‡††öR7mÚ´cÇ;;;êDLii©–†ÖÚÚÚÈîWRŸ‹/ÖÖÖ®\¹²7•‚˜˜˜72Äú¤Gžššb®÷UN§NJHHJ¥ê^\\ü§?ý‰Ïçc=Ð*W®\Ù´i“H$Rïô/^,_¾üíÛ·}³÷ hQ-Cïm–,Y’——¹~ýzÕO”J¥ÉÉÉUUU‡ÂÖ` mæÏŸïîîþÅ_¬^½ÚËË«G—'Ož,..>xð`×ÏdT@ÏÞ¹½­8xð`}}ýªU«\\\º>¸­­íÂ… ™™™Ÿþùĉ1Š@gH$’Ç¿~ý:""¢Û?á2™,##ã§Ÿ~Z¸pa¿û·iÓ&C™E¥Š&*fSRRÊÊʆ âëë;zôh‹¥ÐÁ—/_æææÊªtÁ‚òG {Z[[O:ÅápØl¶¯¯ïرc[§H’|õêU^^^vv¶T*;w.6@5@eeevvvIIIcc£ü‰Ç4ÍÅÅeܸq&LÀÂ.@ø|~vvvqqq}}½|a,I’ÎÎÎcÇŽõññùp«4š¨¶oß‹¿@u£ÐD€&4 ‰Mh"@šÐD€&4 ‰Mh"@šÐD€&4 ‰M#†.º§¸¸øÆ#GŽœ?>zà:2™¬ªªJõãMMM¯_¿ž——‡®ÐD`„,]ºôàÁƒªïêêêââ‚~ÐD` H$‡S^^.“Éä%­­­666ФRiaaaSSSû³š››óóó:PýÌ'ÖÔÔäçç«x°@ ¸wÒGµ´´œ4iÆU{¼yófÆ Ë–-+..ÎÍÍ={öìµk×rss_¾|™™™ùÍ7ߤ¥¥1Œ1cƬ\¹2!!ÁÏÏO"‘ÄÄÄØØØäääp¹Ü‚‚ssóÞøô·oß655 8ÐÉɉF£aPôBIIIEE…Š‹Åâ[·n©xððáÃGŽÙ·®srr8ŽŠûûû«(ˆA=zÁªUÎ;Çf³çÎûå—_®ZµŠ ˆÏ>ûlìØ±Ë—/¿|ùriié•+W6lØ0kÖ¬Õ«WÇÄÄÈU,00pË–-W¯^555½ÿ~o>@qqñ‹/jjjÊËËËÊÊ0"ú¢G¹6gÎlkkKIIés׉Aüîw¿ûøã5^ííÛ·¬ZeêÔ©qqqYYYaaaÞ½wï^ccc|||ÿþýX,AL&ÓÙÙ9))I(Òét>Ÿß›‹Äºº:Å˪ª*ggg333Œ‹î155õóóÓxµR©ôáÇ}Q2yòäòòòëׯ§¥¥íß¿¿ªªÊÒÒRñn]]ݰaönÝÚþ”¬¬¬U«Vݹs‡Ífçææ*f!Õ@"‘$Ù¾äÝ»w#FŒÀ¸ÃöÎÀp9räÈàÁƒW¬XqãÆ ‡––‚ ètºü?“&MÊÊÊR¬Ë‘Ë_zzº§§'›Íæóù\.W.j2™L qd2™í%˜ ùÜ"Æà:è‡ÒÒÒèèè9sæ<}ú4**ŠÍfáïï_XXxäÈ‘ÌÌÌI“&…††š˜˜¸¹¹-_¾ÜÏÏ/(((888 ÀÑÑ1##ƒÉdfgg³X¬™3göt eðàÁÏž=S¼$I’ÃáxyyÁAh"Ðûöí{þüyMMMdd¤µµµ¼0:::<<ÜÒÒ’Édž8q¢²²òíÛ·cÇŽ•딿¿EEE[[›­­íâÅ‹MLLÄbqHHI’j\*:::VVVÊ/KåˆÅâ§OŸŽ?žÉdb€€Qyçúúúµk×^¼xCYäW“'OV¢[[[…$988L˜0¡ý…‹Å²µµ•›_ƒannÎ`0úõ맆ŠÑh4ww÷Kp„Ba^^L4²Ø¨4Q$ÅÄÄÌž=ÛÊÊ ºÀÊÊÊÕÕµC¡X,ÎÏϯ©©Aÿ ‹Ä;ŸýôÓ±cÇîÛ·/00ðÃÂ˃ÓÚÚŠNÐc+Má­[·vVïÜ ×¯_wuu•ß[¤ÓéAAA7oÞTZˆ@Jé0¨Â]”C»÷>í·µÚÙÙYYY)-Dð4hШQ£ÐTKá.Êá•Ð~³×´iÓ’’’x<ž|›DQQÑ¢E‹>,Dð©ÇÀétÞÙI’dcc£X,îPÞ¯_?77·Aƒaˆõ›ÅJS¸‹rhbGnÞ¼ùèÑ#ssóÌÌÌiÓ¦ùûûGFFÅÇÇWTT¸¸¸üñ$Bi!Pƒ¡C‡ôç/++ûPÍÍÍ›g€~³¸³î¬šØ‘iÓ¦åçç+6{Ñh´ýû÷WTT¼yó&00PþÈ)‚ ”‚¾Ç«¬¬ìPhmmíéé©ú£6V³¸³î¬šØ¥{¼œœœœœœT)}©TZ^^Þ¡ÐÆÆfôèÑ=`|˜Åe+•³1 Œ7oÞH$’ö%VVVDM}×8¿çt OOO"€&‚¾ˆH$‰DíK\\\ðˆ0M}SSÓö—„t:]¾¤M¡·{,‡¾víZû’¶¶¶=ËDéñ\.ƒjÄÐh´!C†¼~ýZþrĈ¸Ñ¬/ZZZbccUÉÊe±L&Óó…?I¢££ëêê>,ß¶m›@ ø°üoû[^^ úõõõoß¾ýïÿ‹® Ú¸DEE)}+66ViyDD„P(¤Ô· ŠwNKKóõõíÑÕ5kÖ8p„ꃰX,'''ìì¤Û·o‹‹ëÑ)7nŒÇ|bGx<ÞÝ»w{ºÅ‡Á`lÚ´iÏž=ˆEôÎ… |||zº«ÒÝÝÝÎÎîÁƒÐÄ÷HHHøúë¯Õ8ÑÃÃÃÜÜüñãLjHôŸÏ¿uëVxx¸ç®Y³æÄ‰šøÿ®yÚ´ivvvê¾~ýúï¿ÿ=²sçNõ.k‚ Óé7nܹs'4Q}×Ü8h Î5SÖAëYãââÔþó €Þ©®®VÛ5SÓAëSSSSýüüÔvÍpÐè]»võþ²†RZošÈãñîÝ»§©ÇIÂA`ˆ®™‚Zoš¨×  €¡»fª9hýh¢]34íš©æ õ ‰šuÍpкk¦”ƒÖƒ&jÜ5ÃA`è®™:Zך¨%×  €A»fê8hj¢ö\34†îš)â uª‰ZuÍpкk¦‚ƒÖ&¦¦¦Î;W«®ƒvÍTpÐ:ÒD¹k ÔÙƒƒÀ]³Þ´Ž4Qg®CwÍúuкÐD»f8h Ú5ë×Ak]uïšá 0t׬G­uMÔ‹k†ƒÀÐ]³¾´v5Q®ƒvÍúrÐZÔDýºf8h Ý5ëÅAkQõîšá 0t׬{­-M¤ˆk†ƒÀ ]³î´V4‘ÇãÝ¿Ÿ ®µ]óĉ©àš;8èAƒiÕAkEãââvìØAÁaöðð°°°€ƒ@×FÁÏ­U­yM¤ knϺuëà 0,׬K­aM¤¦kþÐAïÞ½q€¹ætff¦hâÖ­[©éš;8hKKK8h”ºæ›7oRÓ5wpÐÇŽkii¡´&¦¦¦PÖ5ÃA Škާþç¤Óéýë_©«‰ÔwÍpкkÖƒ¦‘$©xQVVvéÒ%õ*zöì›Í0`€üåŠ+lmm»=+''çþýûÝÖõõõ555$I …B‰D"•JI’"‘¨­­M$‰D¢§?~¼¤¤„T]»v544tÛbkk«P(”J¥ò[ZZäCAll,©JTúy<ÞÏ?ÿÜÚÚªz=èÕ#¼ë,ÖxNé>‹»NáÎêé~š“Åb)f1…Šçjã1‚¶Ø¿Å»¦¦¦oTéw´··×ø¬z¡of±z)Œg@4 ‰MUy½ýéÓ§Õþ9SµµµŸ~ú©*G>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 */ tevent-0.9.34/lib/talloc/doc/tutorial_context.dox0000660000000000000000000001577712406075657022021 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/lib/talloc/doc/tutorial_debugging.dox0000660000000000000000000000765012406075657022257 0ustar rootroot00000000000000/** @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() */ tevent-0.9.34/lib/talloc/doc/tutorial_destructors.dox0000660000000000000000000000464112406075657022702 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/lib/talloc/doc/tutorial_dts.dox0000660000000000000000000000632112406075657021110 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/lib/talloc/doc/tutorial_introduction.dox0000660000000000000000000000267612520121120023016 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/lib/talloc/doc/tutorial_pools.dox0000660000000000000000000000711412406075657021453 0ustar rootroot00000000000000/** @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. */ tevent-0.9.34/lib/talloc/doc/tutorial_stealing.dox0000660000000000000000000000362412406075657022127 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/lib/talloc/doc/tutorial_threads.dox0000660000000000000000000001123012520121120021711 0ustar rootroot00000000000000/** @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 */ tevent-0.9.34/lib/talloc/doxy.config0000660000000000000000000022571612406075657017277 0ustar rootroot00000000000000# 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 tevent-0.9.34/lib/talloc/man/talloc.3.xml0000660000000000000000000010702112536700232020011 0ustar rootroot00000000000000 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 informations 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/. tevent-0.9.34/lib/talloc/pytalloc-util.pc.in0000660000000000000000000000053113100601766020626 0ustar rootroot00000000000000prefix=@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/ tevent-0.9.34/lib/talloc/pytalloc.c0000660000000000000000000002100013055076237017070 0ustar rootroot00000000000000/* 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; #if PY_MAJOR_VERSION >= 3 #define PyStr_FromFormat PyUnicode_FromFormat #else #define PyStr_FromFormat PyString_FromFormat #endif /* 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) { 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 PyStr_FromFormat("<%s talloc object at 0x%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 PyStr_FromFormat("<%s talloc based object at %p>", type->tp_name, talloc_obj->ptr); } /** * Simple dealloc for talloc-wrapping PyObjects */ static void pytalloc_base_dealloc(PyObject* self) { pytalloc_BaseObject *obj = (pytalloc_BaseObject *)self; assert(talloc_unlink(NULL, obj->talloc_ctx) != -1); obj->talloc_ctx = NULL; self->ob_type->tp_free(self); } /** * Default (but only slightly more useful than the default) implementation of cmp. */ #if PY_MAJOR_VERSION >= 3 static PyObject *pytalloc_base_default_richcmp(PyObject *obj1, PyObject *obj2, int op) { void *ptr1; void *ptr2; if (Py_TYPE(obj1) == Py_TYPE(obj2)) { /* When types match, compare pointers */ ptr1 = pytalloc_get_ptr(obj1); ptr2 = pytalloc_get_ptr(obj2); } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) { /* Otherwise, compare types */ ptr1 = Py_TYPE(obj1); ptr2 = Py_TYPE(obj2); } else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (op) { case Py_EQ: return PyBool_FromLong(ptr1 == ptr2); case Py_NE: return PyBool_FromLong(ptr1 != ptr2); case Py_LT: return PyBool_FromLong(ptr1 < ptr2); case Py_GT: return PyBool_FromLong(ptr1 > ptr2); case Py_LE: return PyBool_FromLong(ptr1 <= ptr2); case Py_GE: return PyBool_FromLong(ptr1 >= ptr2); } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } #else static int pytalloc_base_default_cmp(PyObject *_obj1, PyObject *_obj2) { pytalloc_BaseObject *obj1 = (pytalloc_BaseObject *)_obj1, *obj2 = (pytalloc_BaseObject *)_obj2; if (obj1->ob_type != obj2->ob_type) return ((char *)obj1->ob_type - (char *)obj2->ob_type); return ((char *)pytalloc_get_ptr(obj1) - (char *)pytalloc_get_ptr(obj2)); } #endif static PyTypeObject TallocBaseObject_Type = { .tp_name = "talloc.BaseObject", .tp_doc = "Python wrapper for a talloc-maintained object.", .tp_basicsize = sizeof(pytalloc_BaseObject), .tp_dealloc = (destructor)pytalloc_base_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_repr = pytalloc_base_default_repr, #if PY_MAJOR_VERSION >= 3 .tp_richcompare = pytalloc_base_default_richcmp, #else .tp_compare = pytalloc_base_default_cmp, #endif }; 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); PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type); Py_INCREF(&TallocBaseObject_Type); PyModule_AddObject(m, "BaseObject", (PyObject *)&TallocBaseObject_Type); Py_INCREF(&TallocGenericObject_Type); PyModule_AddObject(m, "GenericObject", (PyObject *)&TallocGenericObject_Type); return m; } #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 tevent-0.9.34/lib/talloc/pytalloc.h0000660000000000000000000000654513055076237017116 0ustar rootroot00000000000000/* 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 new reference. */ PyTypeObject *pytalloc_GetObjectType(void); /* Return the PyTypeObject for pytalloc_BaseObject. Returns a new reference. */ PyTypeObject *pytalloc_GetBaseObjectType(void); /* Check whether a specific object is a talloc Object. */ int pytalloc_Check(PyObject *); int pytalloc_BaseObject_check(PyObject *); 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)) #if PY_MAJOR_VERSION < 3 /* * Don't use this anymore! Use pytalloc_GenericObject_steal() * or pytalloc_GenericObject_reference(). */ #ifndef _DEPRECATED_ #ifdef HAVE___ATTRIBUTE__ #define _DEPRECATED_ __attribute__ ((deprecated)) #else #define _DEPRECATED_ #endif #endif PyObject *pytalloc_CObject_FromTallocPtr(void *) _DEPRECATED_; #endif /* * 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_ */ tevent-0.9.34/lib/talloc/pytalloc_guide.txt0000660000000000000000000002536513055076237020664 0ustar rootroot00000000000000Using 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. tevent-0.9.34/lib/talloc/pytalloc_private.h0000660000000000000000000000175612667552643020657 0ustar rootroot00000000000000/* 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; tevent-0.9.34/lib/talloc/pytalloc_util.c0000660000000000000000000002111713055076237020136 0ustar rootroot00000000000000/* 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" _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) { PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType(); PyTypeObject *ObjectType = pytalloc_GetObjectType(); if (mem_ctx == NULL) { return PyErr_NoMemory(); } if (PyType_IsSubtype(py_type, BaseObjectType)) { pytalloc_BaseObject *ret = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } /* * This allows us to keep multiple references to this object - * we only reference this context, which is per ptr, not the * talloc_ctx, which is per pytalloc_Object */ if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } ret->talloc_ptr_ctx = mem_ctx; talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->ptr = ptr; return (PyObject *)ret; } else if (PyType_IsSubtype(py_type, ObjectType)) { pytalloc_Object *ret = (pytalloc_Object *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->ptr = ptr; return (PyObject *)ret; } else { PyErr_SetString(PyExc_RuntimeError, "pytalloc_steal_ex() called for object type " "not based on talloc"); return NULL; } } /** * Import an existing talloc pointer into a Python object. */ _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr) { return pytalloc_steal_ex(py_type, ptr, ptr); } /** * Import an existing talloc pointer into a Python object, leaving the * original parent, and creating a reference to the object in the python * object. * * 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) { PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType(); PyTypeObject *ObjectType = pytalloc_GetObjectType(); if (mem_ctx == NULL) { return PyErr_NoMemory(); } if (PyType_IsSubtype(py_type, BaseObjectType)) { pytalloc_BaseObject *ret = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->talloc_ptr_ctx = mem_ctx; ret->ptr = ptr; return (PyObject *)ret; } else if (PyType_IsSubtype(py_type, ObjectType)) { pytalloc_Object *ret = (pytalloc_Object *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->ptr = ptr; return (PyObject *)ret; } else { PyErr_SetString(PyExc_RuntimeError, "pytalloc_reference_ex() called for object type " "not based on talloc"); return NULL; } } #if PY_MAJOR_VERSION < 3 static void py_cobject_talloc_free(void *ptr) { talloc_free(ptr); } _PUBLIC_ PyObject *pytalloc_CObject_FromTallocPtr(void *ptr) { if (ptr == NULL) { Py_RETURN_NONE; } return PyCObject_FromVoidPtr(ptr, py_cobject_talloc_free); } #endif /* * 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) { PyErr_Format(PyExc_TypeError, "pytalloc: unable to get talloc.BaseObject type"); return -1; } type->tp_base = talloc_type; type->tp_basicsize = pytalloc_BaseObject_size(); return PyType_Ready(type); } tevent-0.9.34/lib/talloc/talloc.c0000660000000000000000000021101513055076237016526 0ustar rootroot00000000000000/* 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 static unsigned int talloc_magic = ( ~TALLOC_FLAG_MASK & ( TALLOC_MAGIC_BASE + (TALLOC_BUILD_VERSION_MAJOR << 24) + (TALLOC_BUILD_VERSION_MINOR << 16) + (TALLOC_BUILD_VERSION_RELEASE << 8))); /* 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 void *autofree_context; /* 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; }; /* 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 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_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_magic(unsigned magic) { talloc_abort("Bad talloc magic value - wrong talloc version used/mixed"); } 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_MASK)) == talloc_magic) { talloc_abort_magic(tc->flags & (~TALLOC_FLAG_MASK)); return NULL; } if (tc->flags & 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; } else { 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; }; #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) { return (struct talloc_pool_hdr *)((char *)c - TP_HDR_SIZE); } static inline struct talloc_chunk *talloc_chunk_from_pool(struct talloc_pool_hdr *h) { return (struct talloc_chunk *)((char *)h + TP_HDR_SIZE); } 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; 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; } result = (struct talloc_chunk *)((char *)pool_hdr->end + prefix_len); #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) { char *ptr; /* * 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; } tc = (struct talloc_chunk *)(ptr + prefix_len); 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); tc->flags |= TALLOC_FLAG_FREE; /* 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 */ tc->name = 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); tc->flags |= TALLOC_FLAG_FREE; /* 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 */ tc->name = 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 */ tc->flags |= TALLOC_FLAG_FREE; #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); tc->flags &= ~TALLOC_FLAG_FREE; 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); tc->flags &= ~TALLOC_FLAG_FREE; 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)) { tc->flags &= ~TALLOC_FLAG_FREE; return NULL; } tc = (struct talloc_chunk *)new_ptr; tc->flags &= ~TALLOC_FLAG_FREE; 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); } /* report on any memory hanging off the null context */ static void talloc_report_null(void) { if (talloc_total_size(null_context) != 0) { talloc_report(null_context, stderr); } } /* report on any memory hanging off the null context */ static void talloc_report_null_full(void) { if (talloc_total_size(null_context) != 0) { talloc_report_full(null_context, stderr); } } /* 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(); atexit(talloc_report_null); } /* enable full leak reporting on exit */ _PUBLIC_ void talloc_enable_leak_report_full(void) { talloc_enable_null_tracking(); atexit(talloc_report_null_full); } /* 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 = _talloc_named_const(t, size, name); if (likely(newp)) { 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 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); len = vsnprintf(buf, sizeof(buf), fmt, ap2); va_end(ap2); if (unlikely(len < 0)) { 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; } static void talloc_autofree(void) { talloc_free(autofree_context); } /* 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); atexit(talloc_autofree); } 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; } tevent-0.9.34/lib/talloc/talloc.h0000660000000000000000000017422313100601766016534 0ustar rootroot00000000000000#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 1 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 #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 informations 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 informations 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); /** * @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, 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 funciton again on the sam context. * Memory limits can also be nested, meaning a hild 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. * * @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); /* @} ******************************************************************/ #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 tevent-0.9.34/lib/talloc/talloc.pc.in0000660000000000000000000000043712406075657017323 0ustar rootroot00000000000000prefix=@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/ tevent-0.9.34/lib/talloc/talloc_guide.txt0000660000000000000000000007272212536700232020302 0ustar rootroot00000000000000Using 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 informations 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 informations 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. tevent-0.9.34/lib/talloc/talloc_testsuite.h0000660000000000000000000000025612406075657020653 0ustar rootroot00000000000000#ifndef __LIB_TALLOC_TALLOC_TESTSUITE_H__ #define __LIB_TALLOC_TALLOC_TESTSUITE_H__ struct torture_context; bool torture_local_talloc(struct torture_context *tctx); #endif tevent-0.9.34/lib/talloc/test_magic_differs.sh0000770000000000000000000000055112667552643021274 0ustar rootroot00000000000000#!/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" tevent-0.9.34/lib/talloc/test_magic_differs_helper.c0000660000000000000000000000052112617125140022415 0ustar rootroot00000000000000#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; } tevent-0.9.34/lib/talloc/test_pytalloc.c0000660000000000000000000001465612667552643020162 0ustar rootroot00000000000000/* 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) { 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 *type = (PyObject *)pytalloc_GetObjectType(); Py_INCREF(type); return type; } static PyObject *testpytalloc_base_new(PyTypeObject *mod) { char *obj = talloc_strdup(NULL, "This is a test string for a BaseObject");; return pytalloc_steal(pytalloc_GetBaseObjectType(), obj); } static PyObject *testpytalloc_base_get_object_type(PyObject *mod) { PyObject *type = (PyObject *)pytalloc_GetBaseObjectType(); Py_INCREF(type); return type; } static PyObject *testpytalloc_reference(PyObject *mod, PyObject *args) { 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 tevent-0.9.34/lib/talloc/test_pytalloc.py0000660000000000000000000001400112667552643020350 0ustar rootroot00000000000000#!/usr/bin/env python # Simple tests for the talloc python bindings. # Copyright (C) 2015 Petr Viktorin import unittest import subprocess import sys import re 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() tevent-0.9.34/lib/talloc/testsuite.c0000660000000000000000000014412013055076237017303 0ustar rootroot00000000000000/* 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) { \ } 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_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(); talloc_disable_null_tracking(); return ret; } tevent-0.9.34/lib/talloc/testsuite_main.c0000660000000000000000000000207112406075657020311 0ustar rootroot00000000000000/* 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; } tevent-0.9.34/lib/talloc/web/index.html0000660000000000000000000000313012406075657017657 0ustar rootroot00000000000000 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
tevent-0.9.34/lib/talloc/wscript0000660000000000000000000001722313147534071016524 0ustar rootroot00000000000000#!/usr/bin/env python APPNAME = 'talloc' VERSION = '2.1.10' blddir = 'bin' import Logs import os, sys # find the buildtools directory srcdir = '.' while not os.path.exists(srcdir+'/buildtools') and len(srcdir.split('/')) < 5: srcdir = srcdir + '/..' sys.path.insert(0, srcdir + '/buildtools/wafsamba') import sys sys.path.insert(0, srcdir+"/buildtools/wafsamba") import wafsamba, samba_dist, Options # 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 set_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() # We need to set everything non-python up before here, because # SAMBA_CHECK_PYTHON makes a copy of conf and we need it set up correctly if not conf.env.disable_python: # also disable if we don't have the python libs installed conf.SAMBA_CHECK_PYTHON(mandatory=False, version=(2,4,2)) conf.SAMBA_CHECK_PYTHON_HEADERS(mandatory=False) if not conf.env.HAVE_PYTHON_H: Logs.warn('Disabling pytalloc-util as python devel libs not found') conf.env.disable_python = True 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 if not conf.CHECK_BUNDLED_SYSTEM_PKG('pytalloc-util', minversion=VERSION, implied_deps='talloc replace'): using_system_pytalloc_util = False # We need to get a pytalloc-util for all the python versions # we are building for if conf.env['EXTRA_PYTHON']: name = 'pytalloc-util' + conf.all_envs['extrapython']['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'): for env in bld.gen_python_environments(['PKGCONFIGDIR']): 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='pytalloc', enabled=bld.PYTHON_BUILD_IS_ENABLED(), realname='_test_pytalloc.so', install=False) def test(ctx): '''run talloc testsuite''' import Utils, samba_utils samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') cmd = os.path.join(Utils.g_module.blddir, 'talloc_testsuite') ret = samba_utils.RUN_COMMAND(cmd) print("testsuite returned %d" % ret) magic_helper_cmd = os.path.join(Utils.g_module.blddir, 'talloc_test_magic_differs_helper') magic_cmd = os.path.join(srcdir, 'lib', 'talloc', 'test_magic_differs.sh') if not os.path.exists(magic_cmd): magic_cmd = os.path.join(srcdir, '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) 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) 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) tevent-0.9.34/buildtools/README0000660000000000000000000000056212406075657016127 0ustar rootroot00000000000000See 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. tevent-0.9.34/buildtools/bin/waf0000770000000000000000000000434712520121120016474 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: ISO-8859-1 # Thomas Nagy, 2005-2010 """ 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 if sys.hexversion<0x203000f: raise ImportError("Waf requires Python >= 2.3") if 'PSYCOWAF' in os.environ: try:import psyco;psyco.full() except:pass VERSION="1.5.19" REVISION="x" INSTALL="x" C1='x' C2='x' cwd = os.getcwd() join = os.path.join 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 test(dir): try: os.stat(join(dir, 'wafadmin')); return os.path.abspath(dir) except OSError: pass def find_lib(): return os.path.abspath(os.path.join(os.path.dirname(__file__), '../../third_party/waf')) wafdir = find_lib() w = join(wafdir, 'wafadmin') t = join(w, 'Tools') f = join(w, '3rdparty') sys.path = [w, t, f] + sys.path if __name__ == '__main__': import Scripting Scripting.prepare(t, cwd, VERSION, wafdir) tevent-0.9.34/buildtools/compare_config_h4.sh0000770000000000000000000000050212406075657021145 0ustar rootroot00000000000000#!/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 tevent-0.9.34/buildtools/compare_generated.sh0000770000000000000000000000251212406075657021246 0ustar rootroot00000000000000#!/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 tevent-0.9.34/buildtools/compare_install.sh0000770000000000000000000000021212406075657020751 0ustar rootroot00000000000000#!/bin/sh prefix1="$1" prefix2="$2" (cd $prefix1 && find . ) | sort > p1.txt (cd $prefix2 && find . ) | sort > p2.txt diff -u p[12].txt tevent-0.9.34/buildtools/examples/run_on_target.py0000770000000000000000000001162012536700232022270 0ustar rootroot00000000000000#!/usr/bin/env python # # 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) tevent-0.9.34/buildtools/scripts/Makefile.waf0000660000000000000000000000176712406075657021162 0ustar rootroot00000000000000# 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 tevent-0.9.34/buildtools/scripts/abi_gen.sh0000770000000000000000000000075312406075657020662 0ustar rootroot00000000000000#!/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 -batch -x $GDBSCRIPT "$SHAREDLIB" < /dev/null rm -f $GDBSCRIPT tevent-0.9.34/buildtools/scripts/autogen-waf.sh0000770000000000000000000000135212406075657021507 0ustar rootroot00000000000000#!/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 tevent-0.9.34/buildtools/scripts/configure.waf0000770000000000000000000000037112406075657021416 0ustar rootroot00000000000000#!/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 tevent-0.9.34/buildtools/testwaf.sh0000770000000000000000000000260012406075657017255 0ustar rootroot00000000000000#!/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 tevent-0.9.34/buildtools/wafsamba/README0000660000000000000000000000037712406075657017714 0ustar rootroot00000000000000This 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 tevent-0.9.34/buildtools/wafsamba/__init__.py0000660000000000000000000000000012406075657021124 0ustar rootroot00000000000000tevent-0.9.34/buildtools/wafsamba/configure_file.py0000660000000000000000000000230112617125371022344 0ustar rootroot00000000000000# handle substitution of variables in .in files import re, os import Build, sys, 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 tevent-0.9.34/buildtools/wafsamba/generic_cc.py0000660000000000000000000000342712406075657021466 0ustar rootroot00000000000000 # compiler definition for a generic C compiler # based on suncc.py from waf import os, optparse import Utils, Options, Configure import ccroot, ar from Configure import conftest from compiler_cc import c_compiler c_compiler['default'] = ['gcc', 'generic_cc'] c_compiler['hpux'] = ['gcc', 'generic_cc'] @conftest 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') cc = conf.cmd_to_list(cc) v['CC'] = cc v['CC_NAME'] = 'generic' @conftest def generic_cc_common_flags(conf): v = conf.env v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o', ''] v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker 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['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['CCDEFINES_ST'] = '-D%s' # v['SONAME_ST'] = '-Wl,-h -Wl,%s' # v['SHLIB_MARKER'] = '-Bdynamic' # v['STATICLIB_MARKER'] = '-Bstatic' # program v['program_PATTERN'] = '%s' # shared library # v['shlib_CCFLAGS'] = ['-Kpic', '-DPIC'] # v['shlib_LINKFLAGS'] = ['-G'] v['shlib_PATTERN'] = 'lib%s.so' # static lib # v['staticlib_LINKFLAGS'] = ['-Bstatic'] # v['staticlib_PATTERN'] = 'lib%s.a' detect = ''' find_generic_cc find_cpp find_ar generic_cc_common_flags cc_load_tools cc_add_flags link_add_flags ''' tevent-0.9.34/buildtools/wafsamba/hpuxcc.py0000660000000000000000000000313012406075657020666 0ustar rootroot00000000000000# compiler definition for HPUX # based on suncc.py from waf import os, optparse, sys import Utils, Options, Configure import ccroot, ar from Configure import conftest import gcc @conftest def gcc_modifier_hpux(conf): v=conf.env v['CCFLAGS_DEBUG']=['-g'] v['CCFLAGS_RELEASE']=['-O2'] v['CC_SRC_F']='' v['CC_TGT_F']=['-c','-o',''] v['CPPPATH_ST']='-I%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' v['LIBPATH_ST']='-L%s' v['STATICLIB_ST']='-l%s' v['STATICLIBPATH_ST']='-L%s' v['RPATH_ST']='-Wl,-rpath,%s' v['CCDEFINES_ST']='-D%s' v['SONAME_ST']='-Wl,-h,%s' v['SHLIB_MARKER']=[] # v['STATICLIB_MARKER']='-Wl,-Bstatic' v['FULLSTATIC_MARKER']='-static' v['program_PATTERN']='%s' v['shlib_CCFLAGS']=['-fPIC','-DPIC'] v['shlib_LINKFLAGS']=['-shared'] v['shlib_PATTERN']='lib%s.sl' # v['staticlib_LINKFLAGS']=['-Wl,-Bstatic'] v['staticlib_PATTERN']='lib%s.a' gcc.gcc_modifier_hpux = gcc_modifier_hpux from TaskGen import feature, after @feature('cprogram', 'cshlib') @after('apply_link', 'apply_lib_vars', 'apply_obj_vars') def hpux_addfullpath(self): if sys.platform == 'hp-ux11': link = getattr(self, 'link_task', None) if link: lst = link.env.LINKFLAGS buf = [] for x in lst: if x.startswith('-L'): p2 = x[2:] if not os.path.isabs(p2): x = x[:2] + self.bld.srcnode.abspath(link.env) + "/../" + x[2:].lstrip('.') buf.append(x) link.env.LINKFLAGS = buf tevent-0.9.34/buildtools/wafsamba/irixcc.py0000660000000000000000000000372112406075657020663 0ustar rootroot00000000000000 # compiler definition for irix/MIPSpro cc compiler # based on suncc.py from waf import os, optparse import Utils, Options, Configure import ccroot, ar from Configure import conftest from compiler_cc import c_compiler c_compiler['irix'] = ['gcc', 'irixcc'] @conftest 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') cc = conf.cmd_to_list(cc) try: if Utils.cmd_output(cc + ['-c99'] + ['-version']) != '': conf.fatal('irixcc %r was not found' % cc) except ValueError: conf.fatal('irixcc -v could not be executed') conf.env.append_unique('CCFLAGS', '-c99') v['CC'] = cc v['CC_NAME'] = 'irix' @conftest def irixcc_common_flags(conf): v = conf.env v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o', ''] v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker 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['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['CCDEFINES_ST'] = '-D%s' # v['SONAME_ST'] = '-Wl,-h -Wl,%s' # v['SHLIB_MARKER'] = '-Bdynamic' # v['STATICLIB_MARKER'] = '-Bstatic' # program v['program_PATTERN'] = '%s' # shared library # v['shlib_CCFLAGS'] = ['-Kpic', '-DPIC'] # v['shlib_LINKFLAGS'] = ['-G'] v['shlib_PATTERN'] = 'lib%s.so' # static lib # v['staticlib_LINKFLAGS'] = ['-Bstatic'] # v['staticlib_PATTERN'] = 'lib%s.a' detect = ''' find_irixcc find_cpp find_ar irixcc_common_flags cc_load_tools cc_add_flags link_add_flags ''' tevent-0.9.34/buildtools/wafsamba/nothreads.py0000660000000000000000000001445612617125371021371 0ustar rootroot00000000000000# encoding: utf-8 # Thomas Nagy, 2005-2008 (ita) # this replaces the core of Runner.py in waf with a varient that works # on systems with completely broken threading (such as Python 2.5.x on # AIX). For simplicity we enable this when JOBS=1, which is triggered # by the compatibility makefile used for the waf build. That also ensures # this code is tested, as it means it is used in the build farm, and by # anyone using 'make' to build Samba with waf "Execute the tasks" import sys, random, threading try: from Queue import Queue except ImportError: from queue import Queue import Utils, Options from Constants import EXCEPTION, CRASHED, MAXJOBS, ASK_LATER, SKIPPED, SKIP_ME, SUCCESS GAP = 15 run_old = threading.Thread.run def run(*args, **kwargs): try: run_old(*args, **kwargs) except (KeyboardInterrupt, SystemExit): raise except: sys.excepthook(*sys.exc_info()) threading.Thread.run = run class TaskConsumer(object): consumers = 1 def process(tsk): m = tsk.master if m.stop: m.out.put(tsk) return try: tsk.generator.bld.printout(tsk.display()) if tsk.__class__.stat: ret = tsk.__class__.stat(tsk) # actual call to task's run() function else: ret = tsk.call_run() except Exception, e: tsk.err_msg = Utils.ex_stack() tsk.hasrun = EXCEPTION # TODO cleanup m.error_handler(tsk) m.out.put(tsk) return if ret: tsk.err_code = ret tsk.hasrun = CRASHED else: try: tsk.post_run() except Utils.WafError: pass except Exception: tsk.err_msg = Utils.ex_stack() tsk.hasrun = EXCEPTION else: tsk.hasrun = SUCCESS if tsk.hasrun != SUCCESS: m.error_handler(tsk) m.out.put(tsk) class Parallel(object): """ keep the consumer threads busy, and avoid consuming cpu cycles when no more tasks can be added (end of the build, etc) """ def __init__(self, bld, j=2): # number of consumers self.numjobs = j self.manager = bld.task_manager self.manager.current_group = 0 self.total = self.manager.total() # tasks waiting to be processed - IMPORTANT self.outstanding = [] self.maxjobs = MAXJOBS # tasks that are awaiting for another task to complete self.frozen = [] # tasks returned by the consumers self.out = Queue(0) self.count = 0 # tasks not in the producer area self.processed = 1 # progress indicator self.stop = False # error condition to stop the build self.error = False # error flag def get_next(self): "override this method to schedule the tasks in a particular order" if not self.outstanding: return None return self.outstanding.pop(0) def postpone(self, tsk): "override this method to schedule the tasks in a particular order" # TODO consider using a deque instead if random.randint(0, 1): self.frozen.insert(0, tsk) else: self.frozen.append(tsk) def refill_task_list(self): "called to set the next group of tasks" while self.count > self.numjobs + GAP or self.count >= self.maxjobs: self.get_out() while not self.outstanding: if self.count: self.get_out() if self.frozen: self.outstanding += self.frozen self.frozen = [] elif not self.count: (jobs, tmp) = self.manager.get_next_set() if jobs is not None: self.maxjobs = jobs if tmp: self.outstanding += tmp break def get_out(self): "the tasks that are put to execute are all collected using get_out" ret = self.out.get() self.manager.add_finished(ret) if not self.stop and getattr(ret, 'more_tasks', None): self.outstanding += ret.more_tasks self.total += len(ret.more_tasks) self.count -= 1 def error_handler(self, tsk): "by default, errors make the build stop (not thread safe so be careful)" if not Options.options.keep: self.stop = True self.error = True def start(self): "execute the tasks" while not self.stop: self.refill_task_list() # consider the next task tsk = self.get_next() 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 self.manager.add_finished(tsk) continue try: st = tsk.runnable_status() except Exception, e: self.processed += 1 if self.stop and not Options.options.keep: tsk.hasrun = SKIPPED self.manager.add_finished(tsk) continue self.error_handler(tsk) self.manager.add_finished(tsk) tsk.hasrun = EXCEPTION tsk.err_msg = Utils.ex_stack() continue if st == ASK_LATER: self.postpone(tsk) elif st == SKIP_ME: self.processed += 1 tsk.hasrun = SKIPPED self.manager.add_finished(tsk) else: # run me: put the task in ready queue tsk.position = (self.processed, self.total) self.count += 1 self.processed += 1 tsk.master = self process(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() #print loop assert (self.count == 0 or self.stop) # enable nothreads import Runner Runner.process = process Runner.Parallel = Parallel tevent-0.9.34/buildtools/wafsamba/pkgconfig.py0000660000000000000000000000454313100601766021340 0ustar rootroot00000000000000# handle substitution of variables in pc files import os, re, sys 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']) 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 tevent-0.9.34/buildtools/wafsamba/samba3.py0000660000000000000000000001002313055076237020535 0ustar rootroot00000000000000# a waf tool to add autoconf-like macros to the configure section # and for SAMBA_ macros for building libraries, binaries etc import Options, Build, os from samba_utils import os_path_relpath, TO_LIST, samba_add_onoff_option from samba_autoconf import library_flags Options.Handler.SAMBA3_ADD_OPTION = samba_add_onoff_option 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.curdir) # 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 tevent-0.9.34/buildtools/wafsamba/samba_abi.py0000660000000000000000000002121212632255624021266 0ustar rootroot00000000000000# functions for handling ABI checking of libraries import Options, Utils, os, Logs, samba_utils, sys, Task, fnmatch, re, Build from TaskGen import feature, before, after # 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: 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 = 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 Utils.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 Utils.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_type_from_func('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: Task.always_run(t) @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 = filter(lambda x: x[0] == '!', abi_match) global_abi = 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") if abi_match != ["*"]: f.write("\tlocal:\n") for x in local_abi: f.write("\t\t%s;\n" % x[1:]) 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 tevent-0.9.34/buildtools/wafsamba/samba_autoconf.py0000660000000000000000000007047412775624157022400 0ustar rootroot00000000000000# a waf tool to add autoconf-like macros to the configure section import os, sys import Build, Options, preproc, Logs from Configure import conf from TaskGen import feature 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('CCDEFINES', 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.check_message_1(msg) conf.saved_check_message_1 = conf.check_message_1 conf.check_message_1 = null_check_message_1 conf.saved_check_message_2 = conf.check_message_2 conf.check_message_2 = 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.check_message_1 = conf.saved_check_message_1 conf.check_message_2 = conf.saved_check_message_2 p = conf.check_message_2 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; }' % hdrs, type='nolink', execute=0, ccflags=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 conf.COMPOUND_START('Checking for %s' % f) 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)): 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): '''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 defs = conf.get_config_header() if addmain: fragment='%s\n%s\n int main(void) { %s; return 0; }\n' % (defs, hdrs, code) else: fragment='%s\n%s\n%s\n' % (defs, hdrs, code) if msg is None: msg="Checking for %s" % define cflags = TO_LIST(cflags) if local_include: cflags.append('-I%s' % conf.curdir) 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: exec_args = conf.SAMBA_CROSS_ARGS(msg=msg) else: exec_args = [] conf.COMPOUND_START(msg) ret = conf.check(fragment=fragment, execute=execute, define_name = define, mandatory = mandatory, ccflags=cflags, ldflags=ldflags, includes=includes, uselib=uselib, type=type, msg=msg, quote=quote, exec_args=exec_args, define_ret=define_ret) if not ret and CONFIG_SET(conf, define): # sometimes conf.check() returns false, but it # sets the define. Maybe a waf bug? ret = True if ret: if not define_ret: conf.DEFINE(define, 1) conf.COMPOUND_END(True) else: conf.COMPOUND_END(conf.env[define]) return True if always: conf.DEFINE(define, 0) conf.COMPOUND_END(False) return False @conf def CHECK_STRUCTURE_MEMBER(conf, structname, member, always=False, define=None, headers=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, 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 ''' return conf.check(fragment=fragment, execute=0, type='nolink', ccflags=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, 'CCFLAGS_%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) 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, ccflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False) else: res = conf.check(lib=lib, uselib_store=lib, ccflags=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.curdir) == os.path.realpath(Options.launch_dir) Options.Handler.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 if conf.check(fragment=''' #include int main(void) { char t[100000]; while (fgets(t, sizeof(t), stdin)); return 0; } ''', execute=0, ccflags='-fstack-protector', ldflags='-fstack-protector', mandatory=False, msg='Checking if toolchain accepts -fstack-protector'): conf.ADD_CFLAGS('-fstack-protector') conf.ADD_LDFLAGS('-fstack-protector') 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) 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('-Wformat=2 -Wno-format-y2k', testflags=True) conf.ADD_CFLAGS('-Werror=format-security -Wformat-security', testflags=True) # This check is because for ldb_search(), a NULL format string # is not an error, but some compilers complain about that. if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], ''' 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: conf.ADD_CFLAGS('-fno-omit-frame-pointer -O1 -fsanitize=address', testflags=True) conf.ADD_LDFLAGS('-fsanitize=address', testflags=True) conf.env['ADDRESS_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('config.h', top=True) else: conf.write_config_header(path) 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): '''add some CFLAGS to the command line optionally set testflags to ensure all the flags work ''' if testflags: ok_flags=[] for f in flags.split(): if CHECK_CFLAGS(conf, f): 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): '''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) @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')) if len(conf.env.CC) == 1: # make for nicer logs if just a single command conf.env.CC = conf.env.CC[0] @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.blddir, '.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): # we don't want any libraries or modules to rely on runtime # resolution of symbols if not sys.platform.startswith("openbsd"): conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True) if not sys.platform.startswith("openbsd") and conf.env.undefined_ignore_ldflags == []: if conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup']): conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup'] @conf def CHECK_CFG(self, *k, **kw): return self.check_cfg(*k, **kw) tevent-0.9.34/buildtools/wafsamba/samba_autoproto.py0000660000000000000000000000150312617125371022566 0ustar rootroot00000000000000# waf build tool for building automatic prototypes from C source import os 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.curdir, 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 ='cc', 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 tevent-0.9.34/buildtools/wafsamba/samba_bundled.py0000660000000000000000000002234213126252766022160 0ustar rootroot00000000000000# functions to support bundled libraries import sys import Build, Options, Logs from Configure import conf from samba_utils import TO_LIST 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: return Options.options['BUILTIN_LIBRARIES_DEFAULT'] = builtins Options.Handler.BUILTIN_DEFAULT = BUILTIN_DEFAULT def PRIVATE_EXTENSION_DEFAULT(opt, extension, noextension=''): '''set a default private library extension''' if 'PRIVATE_EXTENSION_DEFAULT' in Options.options: return Options.options['PRIVATE_EXTENSION_DEFAULT'] = extension Options.options['PRIVATE_EXTENSION_EXCEPTION'] = noextension Options.Handler.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.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 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 tevent-0.9.34/buildtools/wafsamba/samba_conftests.py0000660000000000000000000004003213100601766022535 0ustar rootroot00000000000000# a set of config tests that use the samba_autoconf functions # to test for commonly needed configuration options import os, shutil, re import Build, Configure, Utils, Options, Logs from Configure import conf from samba_utils import TO_LIST, ADD_LD_LIBRARY_PATH 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''' match = kw.get('match', []) if match: del kw['match'] opt = self.parser.add_option(*k, **kw) opt.match = match return opt Options.Handler.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.copy() # 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.Handler.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.check_message_1(kw['msg']) ret = None try: ret = self.run_c_code(*k, **kw) except Configure.ConfigurationError, e: self.check_message_2(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.check_message_2(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('return !(sizeof(off_t) >= 8)', 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('return !(sizeof(off_t) >= 8)', define, execute=True, msg='Checking for large file support without additional flags'): return True if conf.CHECK_CODE('return !(sizeof(off_t) >= 8)', 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('return !(sizeof(off_t) >= 8)', 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.blddir, '.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.pproc.Popen([lastprog] + args, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.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.check_message_1(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.pproc.Popen(['perl', 'Makefile.PL'], stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE) (out, err) = proc.communicate() os.chdir(back) ret = (proc.returncode == 0) if not ret: conf.check_message_2('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.check_message_2('not found', color='YELLOW') return ext = m.group(1) conf.check_message_2(ext) return ext conf.check_message_2('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 = 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; }''' % (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.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 = 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 Utils.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 tevent-0.9.34/buildtools/wafsamba/samba_cross.py0000660000000000000000000001315212617125371021666 0ustar rootroot00000000000000# functions for handling cross-compilation import os, sys, re, shlex import Utils, Logs, Options from Configure import conf 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 Utils.WafError("Bad answer format '%s' in %s" % (line, ca_file)) f.close() return ANSWER_UNKNOWN class cross_Popen(Utils.pproc.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.pproc.PIPE, stderr=Utils.pproc.PIPE) ce_out, ce_err = p.communicate() ans = (p.returncode, 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 exec_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.pproc.Popen Utils.pproc.Popen = cross_Popen ret = [] if conf.env.CROSS_EXECUTE: ret.extend(['--cross-execute', conf.env.CROSS_EXECUTE]) if conf.env.CROSS_ANSWERS: if msg is None: raise Utils.WafError("Cannot have NULL msg in cross-answers") ret.extend(['--cross-answers', os.path.join(Options.launch_dir, conf.env.CROSS_ANSWERS), msg]) if ret == []: raise Utils.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 Utils.WafError("Cross answers file %s is incomplete" % conf.env.CROSS_ANSWERS) return True tevent-0.9.34/buildtools/wafsamba/samba_deps.py0000660000000000000000000012143013100601766021462 0ustar rootroot00000000000000# Samba automatic dependency handling and project rules import os, sys, re, time import Build, Environment, Options, Logs, Utils from Logs import debug from Configure import conf 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() (ccflags, 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 ccflags 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.ccflags = 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.ccflags = 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: 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 Utils.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.ccflags = 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: 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', 'ccflags', '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 = Environment.Environment() 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.bdir, "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.bdir, "sambadeps") denv = Environment.Environment() 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 global tstart tstart = time.clock() bld.new_rules = True Logs.info("Checking project rules ...") debug('deps: project rules checking started') expand_subsystem_deps(bld) debug("deps: expand_subsystem_deps: %f" % (time.clock() - tstart)) replace_grouping_libraries(bld, tgt_list) debug("deps: replace_grouping_libraries: %f" % (time.clock() - tstart)) build_direct_deps(bld, tgt_list) debug("deps: build_direct_deps: %f" % (time.clock() - tstart)) break_dependency_loops(bld, tgt_list) debug("deps: break_dependency_loops: %f" % (time.clock() - tstart)) if Options.options.SHOWDEPS: show_dependencies(bld, Options.options.SHOWDEPS, set()) calculate_final_deps(bld, tgt_list, loops) debug("deps: calculate_final_deps: %f" % (time.clock() - tstart)) 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: %f" % (f, time.clock() - tstart)) 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: %f" % (time.clock() - tstart)) if not bld.check_group_ordering(tgt_list): Logs.error("Bad group ordering - aborting") sys.exit(1) debug("deps: check_group_ordering: %f" % (time.clock() - tstart)) show_final_deps(bld, tgt_list) debug("deps: show_final_deps: %f" % (time.clock() - tstart)) 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: %f" % (time.clock() - tstart)) 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 tevent-0.9.34/buildtools/wafsamba/samba_dist.py0000660000000000000000000001722613147534071021506 0ustar rootroot00000000000000# customised version of 'waf dist' for Samba tools # uses git ls-files to get file lists import os, sys, tarfile import Utils, Scripting, Logs, Options from Configure import conf from samba_utils import os_path_relpath dist_dirs = None dist_files = None dist_blacklist = "" 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) 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 Utils.cmd_output(ls_files_cmd, cwd=cwd, env=env).split() 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 = Utils.g_module.APPNAME version = Utils.g_module.VERSION if not version: version = Utils.g_module.VERSION srcdir = os.path.normpath(os.path.join(os.path.dirname(Utils.g_module.root_path), Utils.g_module.srcdir)) 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, 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) 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 tevent-0.9.34/buildtools/wafsamba/samba_git.py0000660000000000000000000000340712536700232021315 0ustar rootroot00000000000000import os import subprocess def find_git(env=None): """Find the git binary.""" if env is not None and 'GIT' in env: return env['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)) tevent-0.9.34/buildtools/wafsamba/samba_headers.py0000660000000000000000000001467412617125371022162 0ustar rootroot00000000000000# specialist handling of header files for Samba import os, re, sys, fnmatch import Build, Logs, Utils 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 Utils.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) relpath1 = os_path_relpath(bld.srcnode.abspath(), bld.curdir) relpath2 = os_path_relpath(bld.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(bld.curdir, targetdir)): raise Utils.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 tevent-0.9.34/buildtools/wafsamba/samba_install.py0000660000000000000000000002052212632255624022204 0ustar rootroot00000000000000########################### # this handles the magic we need to do for installing # with all the configure options that affect rpath and shared # library use import os import Utils from 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), os.path.join(self.path.abspath(bld.env), 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: if self.env['IS_EXTRA_PYTHON']: bld.all_envs['default'] = bld.all_envs['extrapython'] 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: # 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), os.path.join(self.path.abspath(bld.env), 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 Utils.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) tevent-0.9.34/buildtools/wafsamba/samba_optimisation.py0000660000000000000000000001774512632255624023272 0ustar rootroot00000000000000# This file contains waf optimisations for Samba # most of these optimisations are possible because of the restricted build environment # that Samba has. For example, Samba doesn't attempt to cope with Win32 paths during the # build, and Samba doesn't need build varients # overall this makes some build tasks quite a bit faster import os import Build, Utils, Node from TaskGen import feature, after, before import preproc @feature('c', 'cc', 'cxx') @after('apply_type_vars', 'apply_lib_vars', 'apply_core') def apply_incpaths(self): lst = [] try: kak = self.bld.kak except AttributeError: kak = self.bld.kak = {} # TODO move the uselib processing out of here for lib in self.to_list(self.uselib): for path in self.env['CPPPATH_' + lib]: if not path in lst: lst.append(path) if preproc.go_absolute: for path in preproc.standard_includes: if not path in lst: lst.append(path) for path in self.to_list(self.includes): if not path in lst: if preproc.go_absolute or path[0] != '/': # os.path.isabs(path): lst.append(path) else: self.env.prepend_value('CPPPATH', path) for path in lst: node = None if path[0] == '/': # os.path.isabs(path): if preproc.go_absolute: node = self.bld.root.find_dir(path) elif path[0] == '#': node = self.bld.srcnode if len(path) > 1: try: node = kak[path] except KeyError: kak[path] = node = node.find_dir(path[1:]) else: try: node = kak[(self.path.id, path)] except KeyError: kak[(self.path.id, path)] = node = self.path.find_dir(path) if node: self.env.append_value('INC_PATHS', node) @feature('c', 'cc') @after('apply_incpaths') def apply_obj_vars_cc(self): """after apply_incpaths for INC_PATHS""" env = self.env app = env.append_unique cpppath_st = env['CPPPATH_ST'] lss = env['_CCINCFLAGS'] try: cac = self.bld.cac except AttributeError: cac = self.bld.cac = {} # local flags come first # set the user-defined includes paths for i in env['INC_PATHS']: try: lss.extend(cac[i.id]) except KeyError: cac[i.id] = [cpppath_st % i.bldpath(env), cpppath_st % i.srcpath(env)] lss.extend(cac[i.id]) env['_CCINCFLAGS'] = lss # set the library include paths for i in env['CPPPATH']: app('_CCINCFLAGS', cpppath_st % i) import Node, Environment def vari(self): return "default" Environment.Environment.variant = vari def variant(self, env): if not env: return 0 elif self.id & 3 == Node.FILE: return 0 else: return "default" Node.Node.variant = variant import TaskGen, Task def create_task(self, name, src=None, tgt=None): task = Task.TaskBase.classes[name](self.env, generator=self) if src: task.set_inputs(src) if tgt: task.set_outputs(tgt) return task TaskGen.task_gen.create_task = create_task def hash_constraints(self): a = self.attr sum = hash((str(a('before', '')), str(a('after', '')), str(a('ext_in', '')), str(a('ext_out', '')), self.__class__.maxjobs)) return sum Task.TaskBase.hash_constraints = hash_constraints def hash_env_vars(self, env, vars_lst): idx = str(id(env)) + str(vars_lst) try: return self.cache_sig_vars[idx] except KeyError: pass m = Utils.md5() m.update(''.join([str(env[a]) for a in vars_lst])) ret = self.cache_sig_vars[idx] = m.digest() return ret Build.BuildContext.hash_env_vars = hash_env_vars def store_fast(self, filename): file = open(filename, 'wb') data = self.get_merged_dict() try: Build.cPickle.dump(data, file, -1) finally: file.close() Environment.Environment.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) Environment.Environment.load_fast = load_fast def is_this_a_static_lib(self, name): try: cache = self.cache_is_this_a_static_lib except AttributeError: cache = self.cache_is_this_a_static_lib = {} try: return cache[name] except KeyError: ret = cache[name] = 'cstaticlib' in self.bld.get_tgen_by_name(name).features return ret TaskGen.task_gen.is_this_a_static_lib = is_this_a_static_lib def shared_ancestors(self): try: cache = self.cache_is_this_a_static_lib except AttributeError: cache = self.cache_is_this_a_static_lib = {} try: return cache[id(self)] except KeyError: ret = [] if 'cshlib' in self.features: # or 'cprogram' in self.features: if getattr(self, 'uselib_local', None): lst = self.to_list(self.uselib_local) ret = [x for x in lst if not self.is_this_a_static_lib(x)] cache[id(self)] = ret return ret TaskGen.task_gen.shared_ancestors = shared_ancestors @feature('c', 'cc', 'cxx') @after('apply_link', 'init_cc', 'init_cxx', 'apply_core') def apply_lib_vars(self): """after apply_link because of 'link_task' after default_cc because of the attribute 'uselib'""" # after 'apply_core' in case if 'cc' if there is no link env = self.env app = env.append_value seen_libpaths = set([]) # OPTIMIZATION 1: skip uselib variables already added (700ms) seen_uselib = set([]) # 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(self.uselib) names = self.to_list(self.uselib_local) seen = set([]) tmp = Utils.deque(names) # consume a copy of the list of names while tmp: lib_name = tmp.popleft() # visit dependencies only once if lib_name in seen: continue y = self.get_tgen_by_name(lib_name) if not y: raise Utils.WafError('object %r was not found in uselib_local (required by %r)' % (lib_name, self.name)) y.post() seen.add(lib_name) # OPTIMIZATION 2: pre-compute ancestors shared libraries (100ms) tmp.extend(y.shared_ancestors()) # link task and flags if getattr(y, 'link_task', None): link_name = y.target[y.target.rfind('/') + 1:] if 'cstaticlib' in y.features: app('STATICLIB', link_name) elif 'cshlib' in y.features or 'cprogram' in y.features: # WARNING some linkers can link against programs app('LIB', link_name) # the order self.link_task.set_run_after(y.link_task) # for the recompilation dep_nodes = getattr(self.link_task, 'dep_nodes', []) self.link_task.dep_nodes = dep_nodes + y.link_task.outputs # OPTIMIZATION 3: reduce the amount of function calls # add the link path too par = y.link_task.outputs[0].parent if id(par) not in seen_libpaths: seen_libpaths.add(id(par)) tmp_path = par.bldpath(self.env) 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 for v in self.to_list(y.uselib): if v not in seen_uselib: seen_uselib.add(v) if not env['STATICLIB_' + v]: if not v in self.uselib: self.uselib.insert(0, v) # 2. the case of the libs defined outside for x in self.uselib: for v in self.p_flag_vars: val = self.env[v + '_' + x] if val: self.env.append_value(v, val) tevent-0.9.34/buildtools/wafsamba/samba_patterns.py0000660000000000000000000002255113154214633022375 0ustar rootroot00000000000000# a waf tool to add extension based build patterns for Samba 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['defines'] keys_option_with = [] keys_option_utmp = [] keys_option_have = [] keys_header_sys = [] keys_header_other = [] keys_misc = [] 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) 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 tevent-0.9.34/buildtools/wafsamba/samba_perl.py0000660000000000000000000000364013015513033021465 0ustar rootroot00000000000000import Utils from Configure import conf 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.check_tool('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): return Utils.to_list(Utils.cmd_output([conf.env.PERL, '-MConfig', '-e', cmd])) 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 tevent-0.9.34/buildtools/wafsamba/samba_pidl.py0000660000000000000000000001251712617125371021471 0ustar rootroot00000000000000# waf build tool for building IDL files with pidl import os import Build from 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 .. && %s %s ${PERL} "${PIDL}" --quiet ${OPTIONS} --outputdir ${OUTPUTDIR} -- "${SRC[0].abspath(env)}"' % (cpp, cc), ext_out = '.c', before = 'cc', update_outputs = True, shell = True, source = source, target = out_files, name = name, samba_type = 'PIDL') # prime the list of nodes we are dependent on with the cached pidl sources t.allnodes = pidl_src_nodes t.env.PIDL = os.path.join(bld.srcnode.abspath(), 'pidl/pidl') t.env.OPTIONS = TO_LIST(options) t.env.OUTPUTDIR = bld.bldnode.name + '/' + bld.path.find_dir(output_dir).bldpath(t.env) 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.relpath_gen(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') 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 += " " + node.relpath_gen(self.path) 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} --output ${TGT} | sed "s|default/||" > ${TGT}', ext_out = '.c', before = 'cc', 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 tevent-0.9.34/buildtools/wafsamba/samba_python.py0000660000000000000000000001541413100601766022054 0ustar rootroot00000000000000# waf build tool for building IDL files with pidl import os import Build, Logs, Utils, Configure from Configure import conf @conf def SAMBA_CHECK_PYTHON(conf, mandatory=True, version=(2,4,2)): # enable tool to build python extensions if conf.env.HAVE_PYTHON_H: conf.check_python_version(version) return interpreters = [] if conf.env['EXTRA_PYTHON']: conf.all_envs['extrapython'] = conf.env.copy() conf.setenv('extrapython') conf.env['PYTHON'] = conf.env['EXTRA_PYTHON'] conf.env['IS_EXTRA_PYTHON'] = 'yes' conf.find_program('python', var='PYTHON', mandatory=True) conf.check_tool('python') try: conf.check_python_version((3, 3, 0)) except Exception: Logs.warn('extra-python needs to be Python 3.3 or later') raise interpreters.append(conf.env['PYTHON']) conf.setenv('default') conf.find_program('python', var='PYTHON', mandatory=mandatory) conf.check_tool('python') path_python = conf.find_program('python') 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, mandatory=True): if conf.env.disable_python: if mandatory: raise Utils.WafError("Cannot check for python headers when " "--disable-python specified") 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 del(conf.env.defines['PYTHONDIR']) del(conf.env.defines['PYTHONARCHDIR']) return if conf.env["python_headers_checked"] == []: if conf.env['EXTRA_PYTHON']: conf.setenv('extrapython') _check_python_headers(conf, mandatory=True) conf.setenv('default') _check_python_headers(conf, mandatory) conf.env["python_headers_checked"] = "yes" if conf.env['EXTRA_PYTHON']: extraversion = conf.all_envs['extrapython']['PYTHON_VERSION'] if extraversion == conf.env['PYTHON_VERSION']: raise Utils.WafError("extrapython %s is same as main python %s" % ( extraversion, conf.env['PYTHON_VERSION'])) else: conf.msg("python headers", "using cache") # we don't want PYTHONDIR in config.h, as otherwise changing # --prefix causes a complete rebuild del(conf.env.defines['PYTHONDIR']) del(conf.env.defines['PYTHONARCHDIR']) def _check_python_headers(conf, mandatory): try: Configure.ConfigurationError conf.check_python_headers(mandatory=mandatory) except Configure.ConfigurationError: if mandatory: raise 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) 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='', 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 if bld.env['IS_EXTRA_PYTHON']: name = 'extra-' + name # 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_modules/%s' % realname else: link_name = None bld.SAMBA_LIBRARY(name, source=source, deps=deps, public_deps=public_deps, includes=includes, cflags=cflags, 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, extrapython=False): if bld.env['PYTHON_SO_ABI_FLAG']: return name + bld.env['PYTHON_SO_ABI_FLAG'] else: return name Build.BuildContext.pyembed_libname = pyembed_libname def gen_python_environments(bld, extra_env_vars=()): """Generate all Python environments To be used in a for loop. Normally, the loop body will be executed once. When --extra-python is used, the body will additionaly be executed with the extra-python environment active. """ yield if bld.env['EXTRA_PYTHON']: copied = ('GLOBAL_DEPENDENCIES', 'TARGET_TYPE') + tuple(extra_env_vars) for name in copied: bld.all_envs['extrapython'][name] = bld.all_envs['default'][name] default_env = bld.all_envs['default'] bld.all_envs['default'] = bld.all_envs['extrapython'] yield bld.all_envs['default'] = default_env Build.BuildContext.gen_python_environments = gen_python_environments tevent-0.9.34/buildtools/wafsamba/samba_third_party.py0000660000000000000000000000220613100601766023057 0ustar rootroot00000000000000# functions to support third party libraries import os import Utils, Build from Configure import conf @conf def CHECK_FOR_THIRD_PARTY(conf): return os.path.exists(os.path.join(Utils.g_module.srcdir, '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.1') Build.BuildContext.CHECK_CMOCKA = CHECK_CMOCKA tevent-0.9.34/buildtools/wafsamba/samba_utils.py0000660000000000000000000005365413055076237021713 0ustar rootroot00000000000000# 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, fnmatch, shlex from optparse import SUPPRESS_HELP import Build, Options, Utils, Task, Logs, Configure from TaskGen import feature, before, after from Configure import conf, ConfigurationContext from Logs import debug # TODO: make this a --option LIB_PATH="shared" # sigh, python octal constants are a mess MODE_644 = int('644', 8) MODE_755 = int('755', 8) @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.curdir, 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.curdir)) 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 Utils.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''' Utils.g_module.__dict__[name] = function opt.name = function Options.Handler.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" % (vname, string)) v = env[vname] 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 ENFORCE_GROUP_ORDERING(bld): '''enforce group ordering for the project. This makes the group ordering apply only when you specify a target with --target''' if Options.options.compile_targets: @feature('*') @before('exec_rule', 'apply_core', 'collect') def force_previous_groups(self): if getattr(self.bld, 'enforced_group_ordering', False): return self.bld.enforced_group_ordering = 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] my_id = id(self) bld = self.bld stop = None for g in bld.task_manager.groups: for t in g.tasks_gen: if id(t) == my_id: stop = id(g) debug('group: Forcing up to group %s for target %s', group_name(g), self.name or self.target) break if stop is not None: break if stop is None: return for i in xrange(len(bld.task_manager.groups)): g = bld.task_manager.groups[i] bld.task_manager.current_group = i if id(g) == stop: break debug('group: Forcing group %s', group_name(g)) for t in g.tasks_gen: if not getattr(t, 'forced_groups', False): debug('group: Posting %s', t.name or t.target) t.forced_groups = True t.post() Build.BuildContext.ENFORCE_GROUP_ORDERING = ENFORCE_GROUP_ORDERING 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 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 import Environment env = Environment.Environment() 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(Utils.g_module.blddir, 'python') result = 0 for interp in env.python_interpreters: 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('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('abcd') except: import Constants Constants.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''' import Environment env = Environment.Environment() try: env.load('.lock-wscript') env.load(env.blddir + '/c4che/default.cache.py') except: pass return env def IS_NEWER(bld, file1, file2): '''return True if file1 is newer than file2''' t1 = os.stat(os.path.join(bld.curdir, file1)).st_mtime t2 = os.stat(os.path.join(bld.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: visited_dirs = ctx.visited_dirs = set() d = os.path.join(ctx.curdir, directory) if os.path.exists(d): abspath = os.path.abspath(d) else: abspath = os.path.abspath(os.path.join(Utils.g_module.srcdir, 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.curdir) if ctxclass == 'Handler': return ctx.sub_options(relpath) if ctxclass == 'ConfigurationContext': return ctx.sub_config(relpath) if ctxclass == 'BuildContext': return ctx.add_subdirs(relpath) Logs.error('Unknown RECURSE context class', ctxclass) raise Options.Handler.RECURSE = RECURSE Build.BuildContext.RECURSE = RECURSE def CHECK_MAKEFLAGS(bld): '''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: return jobs_set = False # 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.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.options, opt[0:loc], opt[loc+1:]) elif opt[0] != '-': for v in opt: if v == 'j': jobs_set = True elif v == 'k': Options.options.keep = True elif opt == '-j': jobs_set = True elif opt == '-k': Options.options.keep = True if not jobs_set: # default to one job Options.options.jobs = 1 Build.BuildContext.CHECK_MAKEFLAGS = CHECK_MAKEFLAGS 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.Handler.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''' import Configure, samba_wildcard, Scripting if not os.path.exists(".lock-wscript"): raise Utils.WafError('configure has not been run') 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.shlib_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.shlib_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 Constants 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.curdir, WSCRIPT_FILE+'_'+stage+'_'+rule) txt = load_file(file_path) if txt: dc = {'ctx': self} if getattr(self.__class__, 'pre_recurse', None): dc = self.pre_recurse(txt, file_path, self.curdir) exec(compile(txt, file_path, 'exec'), dc) if getattr(self.__class__, 'post_recurse', None): dc = self.post_recurse(txt, file_path, self.curdir) 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.Handler.samba_add_onoff_option = samba_add_onoff_option tevent-0.9.34/buildtools/wafsamba/samba_version.py0000660000000000000000000002160212617125137022221 0ustar rootroot00000000000000import os import Utils 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 = 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.iteritems(): 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] if isinstance(value, basestring): 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) Utils.g_module.VERSION = version.STRING return version tevent-0.9.34/buildtools/wafsamba/samba_wildcard.py0000660000000000000000000001067712632255624022341 0ustar rootroot00000000000000# based on playground/evil in the waf svn tree import os, datetime, fnmatch import Scripting, Utils, Options, Logs, Environment from Constants import SRCDIR, BLDDIR 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 Utils.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 Utils.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(Utils.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 = Environment.Environment(Options.lockfile) except IOError: raise Utils.WafError("Project not configured (run 'waf configure' first)") bld.load_dirs(proj[SRCDIR], proj[BLDDIR]) bld.load_envs() if info: Logs.info("Waf: Entering directory `%s'" % bld.bldnode.abspath()) bld.add_subdirs([os.path.split(Utils.g_module.root_path)[0]]) bld.pre_build() if flush: bld.flush() return bld tevent-0.9.34/buildtools/wafsamba/stale_files.py0000660000000000000000000000764012406075657021700 0ustar rootroot00000000000000# 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. """ import Logs, Build, os, samba_utils, Options, 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 Utils.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 tevent-0.9.34/buildtools/wafsamba/symbols.py0000660000000000000000000005310212617125371021061 0ustar rootroot00000000000000# 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 import Utils, Build, Options, Logs from 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(':'): filename = line[:-1] ret[filename] = { "PUBLIC": set(), "UNDEFINED" : set() } continue cols = line.split(" ") if cols == ['']: 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 "BDGTRVWSi": # its a public symbol ret[filename]["PUBLIC"].add(symbol) elif symbol_type in "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(" ") if len(cols) < 3 or cols[1] != "=>": continue if cols[0].startswith("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('Shared library: \[(.*)\]') re_rpath = re.compile('Library rpath: \[(.*)\]') 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: rpath.extend(m.group(1).split(":")) 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 Utils.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 Utils.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 Utils.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 Utils.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 tevent-0.9.34/buildtools/wafsamba/test_duplicate_symbol.sh0000770000000000000000000000043412477561557023771 0ustar rootroot00000000000000#!/bin/sh # Run the waf duplicate symbol check, wrapped in subunit. . testprogs/blackbox/subunit.sh subunit_start_test duplicate_symbols if ./buildtools/bin/waf build --dup-symbol-check; then subunit_pass_test duplicate_symbols else echo | subunit_fail_test duplicate_symbols fi tevent-0.9.34/buildtools/wafsamba/tests/__init__.py0000660000000000000000000000224012406075657022276 0ustar rootroot00000000000000# 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 tevent-0.9.34/buildtools/wafsamba/tests/test_abi.py0000660000000000000000000001013712406075657022335 0ustar rootroot00000000000000# 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 cStringIO 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*; }; """) 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*; }; """) 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_*; }; """) 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*; }; """) tevent-0.9.34/buildtools/wafsamba/tests/test_bundled.py0000660000000000000000000000176412406075657023225 0ustar rootroot00000000000000# 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")) tevent-0.9.34/buildtools/wafsamba/tests/test_utils.py0000660000000000000000000000473412406075657022750 0ustar rootroot00000000000000# 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) tevent-0.9.34/buildtools/wafsamba/tru64cc.py0000660000000000000000000000363312406075657020676 0ustar rootroot00000000000000 # compiler definition for tru64/OSF1 cc compiler # based on suncc.py from waf import os, optparse import Utils, Options, Configure import ccroot, ar from Configure import conftest from compiler_cc import c_compiler c_compiler['osf1V'] = ['gcc', 'tru64cc'] @conftest def find_tru64cc(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('tru64cc was not found') cc = conf.cmd_to_list(cc) try: if not Utils.cmd_output(cc + ['-V']): conf.fatal('tru64cc %r was not found' % cc) except ValueError: conf.fatal('tru64cc -V could not be executed') v['CC'] = cc v['CC_NAME'] = 'tru64' @conftest def tru64cc_common_flags(conf): v = conf.env v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o', ''] v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker 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['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['CCDEFINES_ST'] = '-D%s' # v['SONAME_ST'] = '-Wl,-h -Wl,%s' # v['SHLIB_MARKER'] = '-Bdynamic' # v['STATICLIB_MARKER'] = '-Bstatic' # program v['program_PATTERN'] = '%s' # shared library # v['shlib_CCFLAGS'] = ['-Kpic', '-DPIC'] v['shlib_LINKFLAGS'] = ['-shared'] v['shlib_PATTERN'] = 'lib%s.so' # static lib # v['staticlib_LINKFLAGS'] = ['-Bstatic'] # v['staticlib_PATTERN'] = 'lib%s.a' detect = ''' find_tru64cc find_cpp find_ar tru64cc_common_flags cc_load_tools cc_add_flags link_add_flags ''' tevent-0.9.34/buildtools/wafsamba/wafsamba.py0000660000000000000000000010715613167070744021167 0ustar rootroot00000000000000# a waf tool to add autoconf-like macros to the configure section # and for SAMBA_ macros for building libraries, binaries etc import Build, os, sys, Options, Task, Utils, cc, TaskGen, fnmatch, re, shutil, Logs, Constants from Configure import conf from 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_optimisation import * from samba_utils import * 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 tru64cc import irixcc import hpuxcc import generic_cc import samba_dist import samba_wildcard import stale_files import symbols import pkgconfig import configure_file # some systems have broken threading in python if os.environ.get('WAF_NOTHREADS') == '1': import nothreads LIB_PATH="shared" os.environ['PYTHONUNBUFFERED'] = '1' if Constants.HEXVERSION < 0x105019: 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.blddir mkdir_p(os.path.join(conf.blddir, LIB_PATH)) mkdir_p(os.path.join(conf.blddir, LIB_PATH, "private")) mkdir_p(os.path.join(conf.blddir, "modules")) mkdir_p(os.path.join(conf.blddir, '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.blddir, 'default')) for (source, target) in [('shared', 'shared'), ('modules', 'modules'), ('python', 'python_modules')]: link_target = os.path.join(conf.blddir, 'default/' + target) if not os.path.lexists(link_target): os.symlink('../' + source, link_target) # get perl to put the blib files in the build directory blib_bld = os.path.join(conf.blddir, 'default/pidl/blib') blib_src = os.path.join(conf.srcdir, '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='', 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 pyembed and bld.env['IS_EXTRA_PYTHON']: public_headers = None if private_library and public_headers: raise Utils.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, 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 Utils.WafError("public library '%s' must have a vnum" % libname) if pc_files is None: raise Utils.WafError("public library '%s' must have pkg-config file" % libname) if public_headers is None and not bld.env['IS_EXTRA_PYTHON']: raise Utils.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 exact Python version. # Replace the Python ABI tag (e.g. ".cpython-35m") by a generic ".py3" abi_flag = bld.env['PYTHON_SO_ABI_FLAG'] replacement = '.py%s' % bld.env['PYTHON_VERSION'].split('.')[0] 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" % (Utils.g_module.APPNAME, Utils.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.shlib_PATTERN) fullpath = bld.path.find_or_declare(fullname) vscriptpath = bld.path.find_or_declare(vscript) if not fullpath: raise Utils.WafError("unable to find fullpath for %s" % fullname) if not vscriptpath: raise Utils.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.shlib_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: t.link_name = link_name if pc_files is not None and not private_library: if pyembed and bld.env['IS_EXTRA_PYTHON']: 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='', 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, 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='', 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, 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, 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='cc', 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 @conf def ENABLE_TIMESTAMP_DEPENDENCIES(conf): """use timestamps instead of file contents for deps this currently doesn't work""" def h_file(filename): import stat st = os.stat(filename) if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file') m = Utils.md5() m.update(str(st.st_mtime)) m.update(str(st.st_size)) m.update(filename) return m.digest() Utils.h_file = h_file 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.curdir, 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.exists(link_dst): os.unlink(link_dst) Logs.info("symlink: %s -> %s/%s" % (s, installdir, iname)) os.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] == "/": replacement_shebang = "#!%s\n" % task.env["PYTHON"] else: replacement_shebang = "#!/usr/bin/env %s\n" % task.env["PYTHON"] 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["PYTHON_SPECIFIED"] is 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, 0755) 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, 0755) 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''' 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.get_install_path(path, env) if bld.is_install > 0: if not os.path.isdir(destpath): try: os.makedirs(destpath) os.chmod(destpath, chmod) except OSError, e: if not os.path.isdir(destpath): raise Utils.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.srcnode.abspath() + '/bin/default/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 ############################################################# # give a nicer display when building different types of files def progress_display(self, msg, fname): col1 = Logs.colors(self.color) col2 = Logs.colors.NORMAL total = self.position[1] n = len(str(total)) fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg) return fs % (self.position[0], self.position[1], col1, fname, col2) def link_display(self): if Options.options.progress_bar != 0: return Task.Task.old_display(self) fname = self.outputs[0].bldpath(self.env) return progress_display(self, 'Linking', fname) Task.TaskBase.classes['cc_link'].display = link_display def samba_display(self): if Options.options.progress_bar != 0: return Task.Task.old_display(self) targets = LOCAL_CACHE(self, 'TARGET_TYPE') if self.name in targets: target_type = targets[self.name] type_map = { 'GENERATOR' : 'Generating', 'PROTOTYPE' : 'Generating' } if target_type in type_map: return progress_display(self, type_map[target_type], self.name) if len(self.inputs) == 0: return Task.Task.old_display(self) fname = self.inputs[0].bldpath(self.env) if fname[0:3] == '../': fname = fname[3:] ext_loc = fname.rfind('.') if ext_loc == -1: return Task.Task.old_display(self) ext = fname[ext_loc:] ext_map = { '.idl' : 'Compiling IDL', '.et' : 'Compiling ERRTABLE', '.asn1': 'Compiling ASN1', '.c' : 'Compiling' } if ext in ext_map: return progress_display(self, ext_map[ext], fname) return Task.Task.old_display(self) Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display Task.TaskBase.classes['Task'].display = samba_display @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 tevent-0.9.34/buildtools/wafsamba/wscript0000660000000000000000000006422213100601766020435 0ustar rootroot00000000000000#!/usr/bin/env python # this is a base set of waf rules that everything else pulls in first import os, sys import wafsamba, Configure, Logs, Options, Utils 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 = True def set_options(opt): opt.tool_options('compiler_cc') opt.tool_options('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 = Options.options['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 = Options.options['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 = Options.options['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]" % Utils.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) 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('--timestamp-dependencies', help=("use file timestamps instead of content for build dependencies (BROKEN)"), action="store_true", dest='timestamp_dependencies', default=False) 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('--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) opt.add_option('--extra-python', type=str, help=("build selected libraries for the specified " "additional version of Python " "(example: --extra-python=/usr/bin/python3)"), metavar="PYTHON", dest='EXTRA_PYTHON', default=None) @Utils.run_once def configure(conf): conf.env.hlist = [] conf.env.srcdir = conf.srcdir conf.define('SRCDIR', conf.env['srcdir']) if Options.options.timestamp_dependencies: conf.ENABLE_TIMESTAMP_DEPENDENCIES() conf.SETUP_CONFIGURE_CACHE(Options.options.enable_configure_cache) # load our local waf extensions conf.check_tool('gnu_dirs') conf.check_tool('wafsamba') conf.check_tool('print_commands') conf.CHECK_CC_ENV() conf.check_tool('compiler_cc') 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.srcdir, 'buildtools/wafsamba/gccdeps.pyc') if os.path.exists(p): os.remove(p) from TaskGen import feature, after @feature('testd') @after('apply_core') def check_d(self): tsk = self.compiled_tasks[0] tsk.outputs.append(tsk.outputs[0].change_ext('.d')) import Task cc = Task.TaskBase.classes['cc'] oldmeth = cc.run cc.run = Task.compile_fun_noshell('cc', '${CC} ${CCFLAGS} ${CPPFLAGS} ${_CCINCFLAGS} ${_CCDEFFLAGS} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT[0].abspath(env)}')[0] try: try: conf.check(features='c testd', fragment='int main() {return 0;}\n', ccflags=['-MD'], mandatory=True, msg='Check for -MD') except: pass else: conf.check_tool('gccdeps', tooldir=conf.srcdir + "/buildtools/wafsamba") finally: cc.run = oldmeth # 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.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 conf.env.EXTRA_PYTHON = Options.options.EXTRA_PYTHON if (conf.env.disable_python and conf.env.EXTRA_PYTHON): Logs.error('ERROR: cannot specify both --disable-python and --extra-python.') sys.exit(1) 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.GIT_LOCAL_CHANGES = Options.options.GIT_LOCAL_CHANGES conf.CHECK_COMMAND(['uname', '-a'], msg='Checking build system', define='BUILD_SYSTEM', on_target=False) 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 not conf.CHECK_LDFLAGS(['-Wl,-rpath,.']) and 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, Utils.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.WERROR_CFLAGS): conf.env.VISIBILITY_CFLAGS = '-fvisibility=hidden' conf.CHECK_CODE('''int main(void) { return 0; } __attribute__((visibility("default"))) void vis_foo2(void) {}''', cflags=conf.env.VISIBILITY_CFLAGS, 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, 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, msg='Checking for library destructor support') conf.CHECK_CODE(''' void test_attribute(void) __attribute__ (()); void test_attribute(void) { return; } int main(void) { return 0; } ''', 'HAVE___ATTRIBUTE__', addmain=False, msg='Checking for __attribute__') if sys.platform.startswith('aix'): conf.DEFINE('_ALL_SOURCE', 1, add_to_cflags=True) # Might not be needed if ALL_SOURCE is defined # 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) # 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 Utils.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.shlib_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; }""", 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; }""", 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 relpath = os_path_relpath(bld.curdir, bld.srcnode.abspath()) if relpath.find('../') != -1: Logs.error('bld.curdir %s is not a child of %s' % (bld.curdir, bld.srcnode.abspath())) raise Utils.WafError('''The top source directory has moved. Please run distclean and reconfigure''') bld.CHECK_MAKEFLAGS() bld.SETUP_BUILD_GROUPS() bld.ENFORCE_GROUP_ORDERING() bld.CHECK_PROJECT_RULES() tevent-0.9.34/third_party/waf/wafadmin/3rdparty/ParallelDebug.py0000660000000000000000000002053012520121120024553 0ustar rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007-2010 (ita) """ debugging helpers for parallel compilation, outputs a svg file in the build directory """ import os, time, sys, threading try: from Queue import Queue except: from queue import Queue import Runner, Options, Utils, Task, Logs from Constants import * #import random #random.seed(100) def set_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=1000, 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') # 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.TaskBase.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 loop(self): while 1: tsk=Runner.TaskConsumer.ready.get() tsk.master.set_running(1, id(threading.currentThread()), tsk) Runner.process_task(tsk) tsk.master.set_running(-1, id(threading.currentThread()), tsk) Runner.TaskConsumer.loop = loop old_start = Runner.Parallel.start def do_start(self): print Options.options try: Options.options.dband except AttributeError: raise ValueError('use def options(opt): opt.load("parallel_debug")!') self.taskinfo = Queue() old_start(self) process_colors(self) Runner.Parallel.start = do_start def set_running(self, by, i, tsk): self.taskinfo.put( (i, id(tsk), time.time(), tsk.__class__.__name__, self.processed, self.count, by) ) Runner.Parallel.set_running = set_running def name2class(name): return name.replace(' ', '_').replace('.', '_') def process_colors(producer): # first, cast the parameters 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" % (x[0], x[1], x[2] - ini, x[3], x[4], x[5], thread_count)) f = open('pdebug.dat', 'w') #Utils.write('\n'.join(acc)) f.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]) ) 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) out = [] out.append(""" \n """ % (0, 0, gwidth + 4, gheight + 4, 0, 0, gwidth + 4, gheight + 4)) # main title if Options.options.dtitle: out.append("""%s """ % (gwidth/2, gheight - 5, Options.options.dtitle)) # the rectangles groups = {} for (x, y, w, h, clsname) in acc: try: groups[clsname].append((x, y, w, h)) except: groups[clsname] = [(x, y, w, h)] for cls in groups: out.append("\n" % name2class(cls)) for (x, y, w, h) in groups[cls]: out.append(""" \n""" % (2 + x*ratio, 2 + y, w*ratio, h, map_to_color(cls))) out.append("\n") # output the caption cnt = THREAD_AMOUNT for (text, color) in info: # caption box b = BAND/2 out.append("""\n""" % (name2class(text), 2 + BAND, 5 + (cnt + 0.5) * BAND, b, b, color)) # caption text out.append("""%s\n""" % (2 + 2 * BAND, 5 + (cnt + 0.5) * BAND + 10, text)) cnt += 1 out.append(""" """) out.append("\n") #node = producer.bld.path.make_node('pdebug.svg') f = open('pdebug.svg', 'w') f.write("".join(out)) tevent-0.9.34/third_party/waf/wafadmin/3rdparty/batched_cc.py0000660000000000000000000001105512520121120024111 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) """ Batched builds - compile faster 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. To set this up, the method ccroot::create_task is replaced by a new version, to enable batched builds it is only necessary to import this module in the configuration (no other change required) """ MAX_BATCH = 50 MAXPARALLEL = False EXT_C = ['.c', '.cc', '.cpp', '.cxx'] import os, threading import TaskGen, Task, ccroot, Build, Logs from TaskGen import extension, feature, before from Constants import * cc_str = '${CC} ${CCFLAGS} ${CPPFLAGS} ${_CCINCFLAGS} ${_CCDEFFLAGS} -c ${SRCLST}' cc_fun = Task.compile_fun_noshell('batched_cc', cc_str)[0] cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${_CXXINCFLAGS} ${_CXXDEFFLAGS} -c ${SRCLST}' cxx_fun = Task.compile_fun_noshell('batched_cxx', cxx_str)[0] count = 70000 class batch_task(Task.Task): color = 'RED' after = 'cc cxx' before = 'cc_link cxx_link static_link' def __str__(self): return '(batch compilation for %d slaves)\n' % 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 ASK_LATER for t in self.slaves: #if t.executed: if t.hasrun != SKIPPED: return RUN_ME return SKIP_ME def run(self): outputs = [] self.outputs = [] srclst = [] slaves = [] for t in self.slaves: if t.hasrun != SKIPPED: slaves.append(t) srclst.append(t.inputs[0].abspath(self.env)) self.env.SRCLST = srclst self.cwd = slaves[0].inputs[0].parent.abspath(self.env) env = self.env app = env.append_unique cpppath_st = env['CPPPATH_ST'] env._CCINCFLAGS = env.CXXINCFLAGS = [] # local flags come first # set the user-defined includes paths for i in env['INC_PATHS']: app('_CCINCFLAGS', cpppath_st % i.abspath()) app('_CXXINCFLAGS', cpppath_st % i.abspath()) app('_CCINCFLAGS', cpppath_st % i.abspath(env)) app('_CXXINCFLAGS', cpppath_st % i.abspath(env)) # set the library include paths for i in env['CPPPATH']: app('_CCINCFLAGS', cpppath_st % i) app('_CXXINCFLAGS', cpppath_st % i) if self.slaves[0].__class__.__name__ == 'cc': ret = cc_fun(self) else: ret = cxx_fun(self) if ret: return ret for t in slaves: t.old_post_run() from TaskGen import extension, feature, after import cc, cxx def wrap(fun): def foo(self, node): # we cannot control the extension, this sucks self.obj_ext = '.o' task = fun(self, node) if not getattr(self, 'masters', None): self.masters = {} self.allmasters = [] if not node.parent.id in self.masters: m = self.masters[node.parent.id] = self.master = self.create_task('batch') self.allmasters.append(m) else: m = self.masters[node.parent.id] if len(m.slaves) > MAX_BATCH: m = self.masters[node.parent.id] = self.master = self.create_task('batch') self.allmasters.append(m) m.add_slave(task) return task return foo c_hook = wrap(cc.c_hook) extension(cc.EXT_CC)(c_hook) cxx_hook = wrap(cxx.cxx_hook) extension(cxx.EXT_CXX)(cxx_hook) @feature('cprogram', 'cshlib', 'cstaticlib') @after('apply_link') def link_after_masters(self): if getattr(self, 'allmasters', None): for m in self.allmasters: self.link_task.set_run_after(m) for c in ['cc', 'cxx']: t = Task.TaskBase.classes[c] def run(self): pass def post_run(self): #self.executed=1 pass def can_retrieve_cache(self): if self.old_can_retrieve_cache(): for m in self.generator.allmasters: try: m.slaves.remove(self) except ValueError: pass #this task wasn't included in that master return 1 else: return None setattr(t, 'oldrun', t.__dict__['run']) setattr(t, 'run', run) setattr(t, 'old_post_run', t.post_run) setattr(t, 'post_run', post_run) setattr(t, 'old_can_retrieve_cache', t.can_retrieve_cache) setattr(t, 'can_retrieve_cache', can_retrieve_cache) tevent-0.9.34/third_party/waf/wafadmin/3rdparty/boost.py0000660000000000000000000002524112520121120023202 0ustar rootroot00000000000000#!/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 # #def set_options(opt): # opt.tool_options('boost') # # ... # #def configure(conf): # # ... (e.g. conf.check_tool('g++')) # conf.check_tool('boost') # conf.check_boost(lib='signals filesystem', static='onlystatic', score_version=(-1000, 1000), tag_minscore=1000) # #def build(bld): # bld(source='main.c', target='bar', uselib="BOOST BOOST_SYSTEM") # #ISSUES: # * find_includes should be called only once! # * support mandatory ######## boost update ########### ## ITA: * the method get_boost_version_number does work ## * the rest of the code has not really been tried # * make certain a demo is provided (in demos/adv for example) # TODO: bad and underdocumented code -> boost.py will be removed in waf 1.6 to be rewritten later import os.path, glob, types, re, sys import Configure, config_c, Options, Utils, Logs from Logs import warn, debug from Configure import conf boost_code = ''' #include #include int main() { std::cout << BOOST_VERSION << std::endl; } ''' boost_libpath = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] boost_cpppath = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include'] STATIC_NOSTATIC = 'nostatic' STATIC_BOTH = 'both' STATIC_ONLYSTATIC = 'onlystatic' is_versiontag = re.compile('^\d+_\d+_?\d*$') is_threadingtag = re.compile('^mt$') is_abitag = re.compile('^[sgydpn]+$') is_toolsettag = re.compile('^(acc|borland|como|cw|dmc|darwin|gcc|hp_cxx|intel|kylix|vc|mgw|qcc|sun|vacpp)\d*$') is_pythontag=re.compile('^py[0-9]{2}$') def set_options(opt): opt.add_option('--boost-includes', type='string', default='', dest='boostincludes', help='path to the boost directory where the includes are e.g. /usr/local/include/boost-1_35') opt.add_option('--boost-libs', type='string', default='', dest='boostlibs', help='path to the directory where the boost libs are e.g. /usr/local/lib') def string_to_version(s): version = s.split('.') if len(version) < 3: return 0 return int(version[0])*100000 + int(version[1])*100 + int(version[2]) def version_string(version): major = version / 100000 minor = version / 100 % 1000 minor_minor = version % 100 if minor_minor == 0: return "%d_%d" % (major, minor) else: return "%d_%d_%d" % (major, minor, minor_minor) def libfiles(lib, pattern, lib_paths): result = [] for lib_path in lib_paths: libname = pattern % ('boost_%s[!_]*' % lib) result += glob.glob(os.path.join(lib_path, libname)) return result @conf def get_boost_version_number(self, dir): """silently retrieve the boost version number""" try: return self.run_c_code(compiler='cxx', code=boost_code, includes=dir, execute=1, env=self.env.copy(), type='cprogram', compile_mode='cxx', compile_filename='test.cpp') except Configure.ConfigurationError, e: return -1 def set_default(kw, var, val): if not var in kw: kw[var] = val def tags_score(tags, kw): """ checks library tags see http://www.boost.org/doc/libs/1_35_0/more/getting_started/unix-variants.html 6.1 """ score = 0 needed_tags = { 'threading': kw['tag_threading'], 'abi': kw['tag_abi'], 'toolset': kw['tag_toolset'], 'version': kw['tag_version'], 'python': kw['tag_python'] } if kw['tag_toolset'] is None: v = kw['env'] toolset = v['CXX_NAME'] if v['CXX_VERSION']: version_no = v['CXX_VERSION'].split('.') toolset += version_no[0] if len(version_no) > 1: toolset += version_no[1] needed_tags['toolset'] = toolset found_tags = {} for tag in tags: if is_versiontag.match(tag): found_tags['version'] = tag if is_threadingtag.match(tag): found_tags['threading'] = tag if is_abitag.match(tag): found_tags['abi'] = tag if is_toolsettag.match(tag): found_tags['toolset'] = tag if is_pythontag.match(tag): found_tags['python'] = tag for tagname in needed_tags.iterkeys(): if needed_tags[tagname] is not None and tagname in found_tags: if re.compile(needed_tags[tagname]).match(found_tags[tagname]): score += kw['score_' + tagname][0] else: score += kw['score_' + tagname][1] return score @conf def validate_boost(self, kw): ver = kw.get('version', '') for x in 'min_version max_version version'.split(): set_default(kw, x, ver) set_default(kw, 'lib', '') kw['lib'] = Utils.to_list(kw['lib']) set_default(kw, 'env', self.env) set_default(kw, 'libpath', boost_libpath) set_default(kw, 'cpppath', boost_cpppath) for x in 'tag_threading tag_version tag_toolset'.split(): set_default(kw, x, None) set_default(kw, 'tag_abi', '^[^d]*$') set_default(kw, 'python', str(sys.version_info[0]) + str(sys.version_info[1]) ) set_default(kw, 'tag_python', '^py' + kw['python'] + '$') set_default(kw, 'score_threading', (10, -10)) set_default(kw, 'score_abi', (10, -10)) set_default(kw, 'score_python', (10,-10)) set_default(kw, 'score_toolset', (1, -1)) set_default(kw, 'score_version', (100, -100)) set_default(kw, 'score_min', 0) set_default(kw, 'static', STATIC_NOSTATIC) set_default(kw, 'found_includes', False) set_default(kw, 'min_score', 0) set_default(kw, 'errmsg', 'not found') set_default(kw, 'okmsg', 'ok') @conf def find_boost_includes(self, kw): """ check every path in kw['cpppath'] for subdir that either starts with boost- or is named boost. Then the version is checked and selected accordingly to min_version/max_version. The highest possible version number is selected! If no versiontag is set the versiontag is set accordingly to the selected library and CPPPATH_BOOST is set. """ boostPath = getattr(Options.options, 'boostincludes', '') if boostPath: boostPath = [os.path.normpath(os.path.expandvars(os.path.expanduser(boostPath)))] else: boostPath = Utils.to_list(kw['cpppath']) min_version = string_to_version(kw.get('min_version', '')) max_version = string_to_version(kw.get('max_version', '')) or (sys.maxint - 1) version = 0 for include_path in boostPath: boost_paths = [p for p in glob.glob(os.path.join(include_path, 'boost*')) if os.path.isdir(p)] debug('BOOST Paths: %r' % boost_paths) for path in boost_paths: pathname = os.path.split(path)[-1] ret = -1 if pathname == 'boost': path = include_path ret = self.get_boost_version_number(path) elif pathname.startswith('boost-'): ret = self.get_boost_version_number(path) ret = int(ret) if ret != -1 and ret >= min_version and ret <= max_version and ret > version: boost_path = path version = ret if not version: self.fatal('boost headers not found! (required version min: %s max: %s)' % (kw['min_version'], kw['max_version'])) return False found_version = version_string(version) versiontag = '^' + found_version + '$' if kw['tag_version'] is None: kw['tag_version'] = versiontag elif kw['tag_version'] != versiontag: warn('boost header version %r and tag_version %r do not match!' % (versiontag, kw['tag_version'])) env = self.env env['CPPPATH_BOOST'] = boost_path env['BOOST_VERSION'] = found_version self.found_includes = 1 ret = 'Version %s (%s)' % (found_version, boost_path) return ret @conf def find_boost_library(self, lib, kw): def find_library_from_list(lib, files): lib_pattern = re.compile('.*boost_(.*?)\..*') result = (None, None) resultscore = kw['min_score'] - 1 for file in files: m = lib_pattern.search(file, 1) if m: libname = m.group(1) libtags = libname.split('-')[1:] currentscore = tags_score(libtags, kw) if currentscore > resultscore: result = (libname, file) resultscore = currentscore return result lib_paths = getattr(Options.options, 'boostlibs', '') if lib_paths: lib_paths = [os.path.normpath(os.path.expandvars(os.path.expanduser(lib_paths)))] else: lib_paths = Utils.to_list(kw['libpath']) v = kw.get('env', self.env) (libname, file) = (None, None) if kw['static'] in [STATIC_NOSTATIC, STATIC_BOTH]: st_env_prefix = 'LIB' files = libfiles(lib, v['shlib_PATTERN'], lib_paths) (libname, file) = find_library_from_list(lib, files) if libname is None and kw['static'] in [STATIC_ONLYSTATIC, STATIC_BOTH]: st_env_prefix = 'STATICLIB' staticLibPattern = v['staticlib_PATTERN'] if self.env['CC_NAME'] == 'msvc': staticLibPattern = 'lib' + staticLibPattern files = libfiles(lib, staticLibPattern, lib_paths) (libname, file) = find_library_from_list(lib, files) if libname is not None: v['LIBPATH_BOOST_' + lib.upper()] = [os.path.split(file)[0]] if self.env['CC_NAME'] == 'msvc' and os.path.splitext(file)[1] == '.lib': v[st_env_prefix + '_BOOST_' + lib.upper()] = ['libboost_'+libname] else: v[st_env_prefix + '_BOOST_' + lib.upper()] = ['boost_'+libname] return self.fatal('lib boost_' + lib + ' not found!') @conf def check_boost(self, *k, **kw): """ This should be the main entry point - min_version - max_version - version - include_path - lib_path - lib - toolsettag - None or a regexp - threadingtag - None or a regexp - abitag - None or a regexp - versiontag - WARNING: you should rather use version or min_version/max_version - static - look for static libs (values: 'nostatic' or STATIC_NOSTATIC - ignore static libs (default) 'both' or STATIC_BOTH - find static libs, too 'onlystatic' or STATIC_ONLYSTATIC - find only static libs - score_version - score_abi - scores_threading - score_toolset * the scores are tuples (match_score, nomatch_score) match_score is the added to the score if the tag is matched nomatch_score is added when a tag is found and does not match - min_score """ if not self.env['CXX']: self.fatal('load a c++ compiler tool first, for example conf.check_tool("g++")') self.validate_boost(kw) ret = None try: if not kw.get('found_includes', None): self.check_message_1(kw.get('msg_includes', 'boost headers')) ret = self.find_boost_includes(kw) except Configure.ConfigurationError, e: if 'errmsg' in kw: self.check_message_2(kw['errmsg'], 'YELLOW') if 'mandatory' in kw: if Logs.verbose > 1: raise else: self.fatal('the configuration failed (see %r)' % self.log.name) else: if 'okmsg' in kw: self.check_message_2(kw.get('okmsg_includes', ret)) for lib in kw['lib']: self.check_message_1('library boost_'+lib) try: self.find_boost_library(lib, kw) except Configure.ConfigurationError, e: ret = False if 'errmsg' in kw: self.check_message_2(kw['errmsg'], 'YELLOW') if 'mandatory' in kw: if Logs.verbose > 1: raise else: self.fatal('the configuration failed (see %r)' % self.log.name) else: if 'okmsg' in kw: self.check_message_2(kw['okmsg']) return ret tevent-0.9.34/third_party/waf/wafadmin/3rdparty/build_file_tracker.py0000660000000000000000000000235212520121120025663 0ustar rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2015 """ Force tasks to use file timestamps to force partial rebuilds when touch-ing build files touch out/libfoo.a ... rebuild what depends on libfoo.a to use:: def options(opt): opt.tool_options('build_file_tracker') """ import os import Task, Utils def signature(self): try: return self.cache_sig[0] except AttributeError: pass self.m = Utils.md5() # explicit deps exp_sig = self.sig_explicit_deps() # env vars var_sig = self.sig_vars() # implicit deps imp_sig = Task.SIG_NIL if self.scan: try: imp_sig = self.sig_implicit_deps() except ValueError: return self.signature() # timestamp dependency on build files only (source files are hashed) buf = [] for k in self.inputs + getattr(self, 'dep_nodes', []) + self.generator.bld.node_deps.get(self.unique_id(), []): if k.id & 3 == 3: t = os.stat(k.abspath(self.env)).st_mtime buf.append(t) self.m.update(str(buf)) # we now have the signature (first element) and the details (for debugging) ret = self.m.digest() self.cache_sig = (ret, exp_sig, imp_sig, var_sig) return ret Task.Task.signature_bak = Task.Task.signature # unused, kept just in case Task.Task.signature = signature # overridden tevent-0.9.34/third_party/waf/wafadmin/3rdparty/fluid.py0000660000000000000000000000154212520121120023155 0ustar rootroot00000000000000#!/usr/bin/python # encoding: utf-8 # Grygoriy Fuchedzhy 2009 """ Compile fluid files (fltk graphic library). Use the 'fluid' feature in conjuction with the 'cxx' feature. """ import Task from TaskGen import extension Task.simple_task_type('fluid', '${FLUID} -c -o ${TGT[0].abspath(env)} -h ${TGT[1].abspath(env)} ${SRC}', 'BLUE', shell=False, ext_out='.cxx') @extension('.fl') def 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.allnodes.append(cpp) def detect(conf): fluid = conf.find_program('fluid', var='FLUID', mandatory=True) conf.check_cfg(path='fltk-config', package='', args='--cxxflags --ldflags', uselib_store='FLTK', mandatory=True) tevent-0.9.34/third_party/waf/wafadmin/3rdparty/gccdeps.py0000660000000000000000000000542712661701312023505 0ustar rootroot00000000000000#!/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 """ import os, re, threading import Task, Logs, Utils, preproc from TaskGen import before, after, feature lock = threading.Lock() preprocessor_flag = '-MD' @feature('cc', 'c') @before('apply_core') def add_mmd_cc(self): if self.env.get_flat('CCFLAGS').find(preprocessor_flag) < 0: self.env.append_value('CCFLAGS', preprocessor_flag) @feature('cxx') @before('apply_core') def add_mmd_cxx(self): if self.env.get_flat('CXXFLAGS').find(preprocessor_flag) < 0: self.env.append_value('CXXFLAGS', preprocessor_flag) def scan(self): "the scanner does not do anything initially" nodes = self.generator.bld.node_deps.get(self.unique_id(), []) names = [] return (nodes, names) re_o = re.compile("\.o$") re_src = re.compile("^(\.\.)[\\/](.*)$") def post_run(self): # The following code is executed by threads, it is not safe, so a lock is needed... if getattr(self, 'cached', None): return Task.Task.post_run(self) name = self.outputs[0].abspath(self.env) name = re_o.sub('.d', name) txt = Utils.readf(name) #os.unlink(name) txt = txt.replace('\\\n', '') lst = txt.strip().split(':') val = ":".join(lst[1:]) val = val.split() nodes = [] bld = self.generator.bld f = re.compile("^("+self.env.variant()+"|\.\.)[\\/](.*)$") for x in val: if os.path.isabs(x): if not preproc.go_absolute: continue lock.acquire() try: node = bld.root.find_resource(x) finally: lock.release() else: g = re.search(re_src, x) if g: x = g.group(2) lock.acquire() try: node = bld.bldnode.parent.find_resource(x) finally: lock.release() else: g = re.search(f, x) if g: x = g.group(2) lock.acquire() try: node = bld.srcnode.find_resource(x) finally: lock.release() 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 if not node: raise ValueError('could not find %r for %r' % (x, self)) else: nodes.append(node) Logs.debug('deps: real scanner for %s returned %s' % (str(self), str(nodes))) bld.node_deps[self.unique_id()] = nodes bld.raw_deps[self.unique_id()] = [] try: del self.cache_sig except: pass Task.Task.post_run(self) import Constants, Utils def sig_implicit_deps(self): try: return Task.Task.sig_implicit_deps(self) except Utils.WafError: return Constants.SIG_NIL for name in 'cc cxx'.split(): try: cls = Task.TaskBase.classes[name] except KeyError: pass else: cls.post_run = post_run cls.scan = scan cls.sig_implicit_deps = sig_implicit_deps tevent-0.9.34/third_party/waf/wafadmin/3rdparty/go.py0000660000000000000000000000662012520121120022461 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # go.py - Waf tool for the Go programming language # By: Tom Wambold import platform, os import Task import Utils from TaskGen import feature, extension, after Task.simple_task_type('gocompile', '${GOC} ${GOCFLAGS} -o ${TGT} ${SRC}', shell=False) Task.simple_task_type('gopack', '${GOP} grc ${TGT} ${SRC}', shell=False) Task.simple_task_type('golink', '${GOL} ${GOLFLAGS} -o ${TGT} ${SRC}', shell=False) def detect(conf): def set_def(var, val): if not conf.env[var]: conf.env[var] = val goarch = os.getenv("GOARCH") if goarch == '386': set_def('GO_PLATFORM', 'i386') elif goarch == 'amd64': set_def('GO_PLATFORM', 'x86_64') elif goarch == 'arm': set_def('GO_PLATFORM', 'arm') else: set_def('GO_PLATFORM', platform.machine()) if conf.env.GO_PLATFORM == 'x86_64': set_def('GO_COMPILER', '6g') set_def('GO_LINKER', '6l') set_def('GO_EXTENSION', '.6') elif conf.env.GO_PLATFORM in ['i386', 'i486', 'i586', 'i686']: set_def('GO_COMPILER', '8g') set_def('GO_LINKER', '8l') set_def('GO_EXTENSION', '.8') elif conf.env.GO_PLATFORM == 'arm': set_def('GO_COMPILER', '5g') set_def('GO_LINKER', '5l') set_def('GO_EXTENSION', '.5') if not (conf.env.GO_COMPILER or conf.env.GO_LINKER or conf.env.GO_EXTENSION): raise conf.fatal('Unsupported platform ' + platform.machine()) set_def('GO_PACK', 'gopack') set_def('GO_PACK_EXTENSION', '.a') conf.find_program(conf.env.GO_COMPILER, var='GOC', mandatory=True) conf.find_program(conf.env.GO_LINKER, var='GOL', mandatory=True) conf.find_program(conf.env.GO_PACK, var='GOP', mandatory=True) conf.find_program('cgo', var='CGO', mandatory=True) @extension('.go') def compile_go(self, node): try: self.go_nodes.append(node) except AttributeError: self.go_nodes = [node] @feature('go') @after('apply_core') def apply_compile_go(self): try: nodes = self.go_nodes except AttributeError: self.go_compile_task = None else: self.go_compile_task = self.create_task('gocompile', nodes, [self.path.find_or_declare(self.target + self.env.GO_EXTENSION)]) @feature('gopackage', 'goprogram') @after('apply_compile_go') def apply_goinc(self): if not getattr(self, 'go_compile_task', None): return names = self.to_list(getattr(self, 'uselib_local', [])) for name in names: obj = self.name_to_obj(name) if not obj: raise Utils.WafError('object %r was not found in uselib_local ' '(required by %r)' % (lib_name, self.name)) obj.post() self.go_compile_task.set_run_after(obj.go_package_task) self.go_compile_task.dep_nodes.extend(obj.go_package_task.outputs) self.env.append_unique('GOCFLAGS', '-I' + obj.path.abspath(obj.env)) self.env.append_unique('GOLFLAGS', '-L' + obj.path.abspath(obj.env)) @feature('gopackage') @after('apply_goinc') def apply_gopackage(self): self.go_package_task = self.create_task('gopack', self.go_compile_task.outputs[0], self.path.find_or_declare(self.target + self.env.GO_PACK_EXTENSION)) self.go_package_task.set_run_after(self.go_compile_task) self.go_package_task.dep_nodes.extend(self.go_compile_task.outputs) @feature('goprogram') @after('apply_goinc') def apply_golink(self): self.go_link_task = self.create_task('golink', self.go_compile_task.outputs[0], self.path.find_or_declare(self.target)) self.go_link_task.set_run_after(self.go_compile_task) self.go_link_task.dep_nodes.extend(self.go_compile_task.outputs) tevent-0.9.34/third_party/waf/wafadmin/3rdparty/lru_cache.py0000660000000000000000000000456312520121120024005 0ustar rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy 2011 import os, shutil, re import Options, Build, Logs """ Apply a least recently used policy to the Waf cache. For performance reasons, it is called after the build is complete. We assume that the the folders are written atomically Do export WAFCACHE=/tmp/foo-xyz where xyz represents the cache size in megabytes If missing, the default cache size will be set to 10GB """ re_num = re.compile('[a-zA-Z_]+(\d+)') CACHESIZE = 10*1024*1024*1024 # in bytes CLEANRATIO = 0.8 DIRSIZE = 4096 def compile(self): if Options.cache_global and not Options.options.nocache: try: os.makedirs(Options.cache_global) except: pass try: self.raw_compile() finally: if Options.cache_global and not Options.options.nocache: self.sweep() def sweep(self): global CACHESIZE CACHEDIR = Options.cache_global # get the cache max size from the WAFCACHE filename re_num = re.compile('[a-zA-Z_]+(\d+)') val = re_num.sub('\\1', os.path.basename(Options.cache_global)) try: CACHESIZE = int(val) except: pass # map folder names to timestamps flist = {} for x in os.listdir(CACHEDIR): j = os.path.join(CACHEDIR, x) if os.path.isdir(j) and len(x) == 32: # dir names are md5 hexdigests flist[x] = [os.stat(j).st_mtime, 0] for (x, v) in flist.items(): cnt = DIRSIZE # each entry takes 4kB d = os.path.join(CACHEDIR, x) for k in os.listdir(d): cnt += os.stat(os.path.join(d, k)).st_size flist[x][1] = cnt total = sum([x[1] for x in flist.values()]) Logs.debug('lru: Cache size is %r' % total) if total >= CACHESIZE: Logs.debug('lru: Trimming the cache since %r > %r' % (total, CACHESIZE)) # make a list to sort the folders by timestamp lst = [(p, v[0], v[1]) for (p, v) in flist.items()] lst.sort(key=lambda x: x[1]) # sort by timestamp lst.reverse() while total >= CACHESIZE * CLEANRATIO: (k, t, s) = lst.pop() p = os.path.join(CACHEDIR, k) v = p + '.del' try: os.rename(p, v) except: # someone already did it pass else: try: shutil.rmtree(v) except: # this should not happen, but who knows? Logs.warn('If you ever see this message, report it (%r)' % v) total -= s del flist[k] Logs.debug('lru: Total at the end %r' % total) Build.BuildContext.raw_compile = Build.BuildContext.compile Build.BuildContext.compile = compile Build.BuildContext.sweep = sweep tevent-0.9.34/third_party/waf/wafadmin/3rdparty/paranoid.py0000660000000000000000000000156513126252766023704 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # ita 2010 import Logs, Utils, Build, Task def say(txt): Logs.warn("^o^: %s" % txt) try: ret = Utils.cmd_output('which cowsay 2> /dev/null').strip() except Exception, e: pass else: def say(txt): f = Utils.cmd_output([ret, txt]) Utils.pprint('PINK', f) say('you make the errors, we detect them') def check_task_classes(self): for x in Task.TaskBase.classes: if isinstance(x, Task.Task): if not getattr(x, 'ext_in', None) or getattr(x, 'before', None): say('class %s has no precedence constraints (ext_in/before)') if not getattr(x, 'ext_out', None) or getattr(x, 'after', None): say('class %s has no precedence constraints (ext_out/after)') comp = Build.BuildContext.compile def compile(self): if not getattr(self, 'magic', None): check_task_classes(self) return comp(self) Build.BuildContext.compile = compile tevent-0.9.34/third_party/waf/wafadmin/3rdparty/prefork.py0000770000000000000000000001340712520121120023527 0ustar rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2015 (ita) # # prefer the waf 1.8 version """ The full samba build can be faster by ~10%, but there are a few limitations: * only one build process should be run at a time as the servers would use the same ports * only one build command is going to be called ("waf build configure build" would not work) def build(bld): mod = Utils.load_tool('prefork') mod.build(bld) ... (build declarations after) """ import os, re, socket, threading, sys, subprocess, time, atexit, traceback try: import SocketServer except ImportError: import socketserver as SocketServer try: from queue import Queue except ImportError: from Queue import Queue try: import cPickle except ImportError: import pickle as cPickle DEFAULT_PORT = 51200 HEADER_SIZE = 128 REQ = 'REQ' RES = 'RES' BYE = 'BYE' def make_header(params): header = ','.join(params) if sys.hexversion > 0x3000000: header = header.encode('iso8859-1') header = header.ljust(HEADER_SIZE) assert(len(header) == HEADER_SIZE) return header re_valid_query = re.compile('^[a-zA-Z0-9_, ]+$') class req(SocketServer.StreamRequestHandler): def handle(self): while 1: try: self.process_command() except Exception as e: print(e) break def process_command(self): query = self.rfile.read(HEADER_SIZE) if not query: return #print(len(query)) assert(len(query) == HEADER_SIZE) if sys.hexversion > 0x3000000: query = query.decode('iso8859-1') #print "%r" % query if not re_valid_query.match(query): raise ValueError('Invalid query %r' % query) query = query.strip().split(',') if query[0] == REQ: self.run_command(query[1:]) elif query[0] == BYE: raise ValueError('Exit') else: raise ValueError('Invalid query %r' % query) def run_command(self, query): size = int(query[0]) data = self.rfile.read(size) assert(len(data) == size) kw = cPickle.loads(data) # run command ret = out = err = exc = None cmd = kw['cmd'] del kw['cmd'] #print(cmd) try: if kw['stdout'] or kw['stderr']: p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() ret = p.returncode else: ret = subprocess.Popen(cmd, **kw).wait() except Exception as e: ret = -1 exc = str(e) + traceback.format_exc() # write the results if out or err or exc: data = (out, err, exc) data = cPickle.dumps(data, -1) else: data = '' params = [RES, str(ret), str(len(data))] self.wfile.write(make_header(params)) if data: self.wfile.write(data) def create_server(conn, cls): #SocketServer.ThreadingTCPServer.allow_reuse_address = True #server = SocketServer.ThreadingTCPServer(conn, req) SocketServer.TCPServer.allow_reuse_address = True server = SocketServer.TCPServer(conn, req) #server.timeout = 6000 # seconds server.serve_forever(poll_interval=0.001) if __name__ == '__main__': if len(sys.argv) > 1: port = int(sys.argv[1]) else: port = DEFAULT_PORT #conn = (socket.gethostname(), port) conn = ("127.0.0.1", port) #print("listening - %r %r\n" % conn) create_server(conn, req) else: import Runner, Utils def init_task_pool(self): # lazy creation, and set a common pool for all task consumers pool = self.pool = [] for i in range(self.numjobs): consumer = Runner.get_pool() pool.append(consumer) consumer.idx = i self.ready = Queue(0) def setq(consumer): consumer.ready = self.ready try: threading.current_thread().idx = consumer.idx except Exception as e: print(e) for x in pool: x.ready.put(setq) return pool Runner.Parallel.init_task_pool = init_task_pool PORT = 51200 def make_server(idx): port = PORT + idx cmd = [sys.executable, os.path.abspath(__file__), str(port)] proc = subprocess.Popen(cmd) proc.port = port return proc def make_conn(srv): #port = PORT + idx port = srv.port conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) conn.connect(('127.0.0.1', port)) return conn SERVERS = [] CONNS = [] def close_all(): while CONNS: conn = CONNS.pop() try: conn.close() except: pass while SERVERS: srv = SERVERS.pop() try: srv.kill() except: pass atexit.register(close_all) def put_data(conn, data): conn.send(data) def read_data(conn, siz): ret = conn.recv(siz) if not ret: print("closed connection?") assert(len(ret) == siz) return ret def exec_command(cmd, **kw): if 'log' in kw: log = kw['log'] kw['stdout'] = kw['stderr'] = subprocess.PIPE del(kw['log']) else: kw['stdout'] = kw['stderr'] = None kw['shell'] = isinstance(cmd, str) idx = threading.current_thread().idx kw['cmd'] = cmd data = cPickle.dumps(kw, -1) params = [REQ, str(len(data))] header = make_header(params) conn = CONNS[idx] put_data(conn, header) put_data(conn, data) data = read_data(conn, HEADER_SIZE) if sys.hexversion > 0x3000000: data = data.decode('iso8859-1') lst = data.split(',') ret = int(lst[1]) dlen = int(lst[2]) out = err = None if dlen: data = read_data(conn, dlen) (out, err, exc) = cPickle.loads(data) if exc: raise Utils.WafError('Execution failure: %s' % exc) if out: log.write(out) if err: log.write(err) return ret def __init__(self): threading.Thread.__init__(self) # identifier of the current thread self.idx = len(SERVERS) # create a server and wait for the connection srv = make_server(self.idx) SERVERS.append(srv) conn = None for x in range(30): try: conn = make_conn(srv) break except socket.error: time.sleep(0.01) if not conn: raise ValueError('Could not start the server!') CONNS.append(conn) self.setDaemon(1) self.start() Runner.TaskConsumer.__init__ = __init__ def build(bld): # dangerous, there is no other command hopefully Utils.exec_command = exec_command tevent-0.9.34/third_party/waf/wafadmin/3rdparty/print_commands.py0000660000000000000000000000112012632255624025104 0ustar rootroot00000000000000#! /usr/bin/env python """ In this case, print the commands being executed as strings (the commands are usually lists, so this can be misleading) """ import Build, Utils, Logs def exec_command(self, cmd, **kw): txt = cmd if isinstance(cmd, list): txt = ' '.join(cmd) Logs.debug('runner: %s' % txt) if self.log: self.log.write('%s\n' % cmd) kw['log'] = self.log try: if not kw.get('cwd', None): kw['cwd'] = self.cwd except AttributeError: self.cwd = kw['cwd'] = self.bldnode.abspath() return Utils.exec_command(cmd, **kw) Build.BuildContext.exec_command = exec_command tevent-0.9.34/third_party/waf/wafadmin/3rdparty/swig.py0000660000000000000000000001166712520121120023034 0ustar rootroot00000000000000#! /usr/bin/env python # encoding: UTF-8 # Petar Forai # Thomas Nagy 2008 import re import Task, Utils, Logs from TaskGen import extension from Configure import conf import preproc """ Welcome in the hell of adding tasks dynamically swig interface files may be created at runtime, the module name may be unknown in advance rev 5859 is much more simple """ SWIG_EXTS = ['.swig', '.i'] swig_str = '${SWIG} ${SWIGFLAGS} ${_CCINCFLAGS} ${_CXXINCFLAGS} ${_CCDEFFLAGS} ${_CXXDEFFLAGS} ${SRC}' cls = Task.simple_task_type('swig', swig_str, color='BLUE', ext_in='.i .h', ext_out='.o .c .cxx', shell=False) def runnable_status(self): for t in self.run_after: if not t.hasrun: return 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(self.env) 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 Task.Task.runnable_status(self) setattr(cls, 'runnable_status', runnable_status) re_module = re.compile('%module(?:\s*\(.*\))?\s+(.+)', re.M) re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) re_2 = re.compile('%include "(.*)"', re.M) re_3 = re.compile('#include "(.*)"', re.M) def scan(self): "scan for swig dependencies, climb the .i files" env = self.env lst_src = [] seen = [] to_see = [self.inputs[0]] while to_see: node = to_see.pop(0) if node.id in seen: continue seen.append(node.id) lst_src.append(node) # read the file code = node.read(env) code = preproc.re_nl.sub('', code) code = preproc.re_cpp.sub(preproc.repl, code) # find .i files and project headers names = re_2.findall(code) + re_3.findall(code) for n in names: for d in self.generator.env.INC_PATHS + [node.parent]: u = d.find_resource(n) if u: to_see.append(u) break else: Logs.warn('could not find %r' % n) # list of nodes this one depends on, and module name if present if Logs.verbose: Logs.debug('deps: deps for %s: %s' % (str(self), str(lst_src))) return (lst_src, []) cls.scan = scan # provide additional language processing swig_langs = {} def swig(fun): swig_langs[fun.__name__.replace('swig_', '')] = fun 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) try: if '-c++' in flags: fun = self.generator.cxx_hook else: fun = self.generator.c_hook except AttributeError: raise Utils.WafError('No c%s compiler was found to process swig files' % ('-c++' in flags and '++' or '')) task = fun(out_node) task.set_run_after(self) ge = self.generator.bld.generator ge.outstanding.insert(0, task) ge.total += 1 try: ltask = self.generator.link_task except AttributeError: pass else: ltask.inputs.append(task.outputs[0]) self.outputs.append(out_node) if not '-o' in self.env['SWIGFLAGS']: self.env.append_value('SWIGFLAGS', '-o') self.env.append_value('SWIGFLAGS', self.outputs[0].abspath(self.env)) @swig def swig_python(tsk): tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.py')) @swig def swig_ocaml(tsk): tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.ml')) tsk.set_outputs(tsk.inputs[0].parent.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', [])) self.env.append_value('SWIGFLAGS', flags) if not '-outdir' in flags: flags.append('-outdir') flags.append(node.parent.abspath(self.env)) @conf def check_swig_version(conf, minver=None): """Check for a minimum swig version like conf.check_swig_version('1.3.28') or conf.check_swig_version((1,3,28)) """ reg_swig = re.compile(r'SWIG Version\s(.*)', re.M) swig_out = Utils.cmd_output('%s -version' % conf.env['SWIG']) swigver = [int(s) for s in reg_swig.findall(swig_out)[0].split('.')] if isinstance(minver, basestring): minver = [int(s) for s in minver.split(".")] if isinstance(minver, tuple): minver = [int(s) for s in minver] result = (minver is None) or (minver[:3] <= swigver[:3]) swigver_full = '.'.join(map(str, swigver)) if result: conf.env['SWIG_VERSION'] = swigver_full minver_str = '.'.join(map(str, minver)) if minver is None: conf.check_message_custom('swig version', '', swigver_full) else: conf.check_message('swig version', '>= %s' % (minver_str,), result, option=swigver_full) return result def detect(conf): swig = conf.find_program('swig', var='SWIG', mandatory=True) tevent-0.9.34/third_party/waf/wafadmin/3rdparty/valadoc.py0000660000000000000000000000716512520121120023472 0ustar rootroot00000000000000#! /usr/bin/env python # encoding: UTF-8 # Nicolas Joseph 2009 from fnmatch import fnmatchcase import os, os.path, re, stat import Task, Utils, Node, Constants from TaskGen import feature, extension, after from Logs import debug, warn, error VALADOC_STR = '${VALADOC}' class valadoc_task(Task.Task): vars = ['VALADOC', 'VALADOCFLAGS'] color = 'BLUE' after = 'cxx_link cc_link' quiet = True output_dir = '' doclet = '' package_name = '' package_version = '' files = [] protected = True private = False inherit = False deps = False enable_non_null_experimental = False force = False def runnable_status(self): return True def run(self): if self.env['VALADOC']: 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, '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, 'enable_non_null_experimental', None): cmd.append ('--enable-non-null-experimental') if getattr(self, 'force', None): cmd.append ('--force') cmd.append (' '.join ([x.relpath_gen (self.generator.bld.bldnode) for x in self.files])) return self.generator.bld.exec_command(' '.join(cmd)) else: error ('You must install valadoc for generate the API documentation') return -1 @feature('valadoc') def process_valadoc(self): task = getattr(self, 'task', None) if not task: task = self.create_task('valadoc') self.task = task if getattr(self, 'output_dir', None): task.output_dir = self.output_dir else: Utils.WafError('no output directory') if getattr(self, 'doclet', None): task.doclet = self.doclet else: Utils.WafError('no doclet directory') if getattr(self, 'package_name', None): task.package_name = self.package_name else: Utils.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): task.vapi_dirs = Utils.to_list(self.vapi_dirs) if getattr(self, 'files', None): task.files = self.files else: Utils.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, '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 detect(conf): conf.find_program('valadoc', var='VALADOC', mandatory=False) tevent-0.9.34/third_party/waf/wafadmin/Build.py0000660000000000000000000006752312617125140021371 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) """ Dependency tree holder The class Build holds all the info related to a build: * file system representation (tree of Node instances) * various cached objects (task signatures, file scan results, ..) There is only one Build object at a time (bld singleton) """ import os, sys, errno, re, glob, gc, datetime, shutil try: import cPickle except: import pickle as cPickle import Runner, TaskGen, Node, Scripting, Utils, Environment, Task, Logs, Options from Logs import debug, error, info from Constants import * SAVED_ATTRS = 'root srcnode bldnode node_sigs node_deps raw_deps task_sigs id_nodes'.split() "Build class members to save" bld = None "singleton - safe to use when Waf is not used as a library" class BuildError(Utils.WafError): def __init__(self, b=None, t=[]): self.bld = b self.tasks = t self.ret = 1 Utils.WafError.__init__(self, self.format_error()) def format_error(self): lst = ['Build failed:'] for tsk in self.tasks: txt = tsk.format_error() if txt: lst.append(txt) sep = ' ' if len(lst) > 2: sep = '\n' return sep.join(lst) def group_method(fun): """ sets a build context method to execute after the current group has finished executing this is useful for installing build files: * calling install_files/install_as will fail if called too early * people do not want to define install method in their task classes TODO: try it """ def f(*k, **kw): if not k[0].is_install: return False postpone = True if 'postpone' in kw: postpone = kw['postpone'] del kw['postpone'] # TODO waf 1.6 in theory there should be no reference to the TaskManager internals here if postpone: m = k[0].task_manager if not m.groups: m.add_group() m.groups[m.current_group].post_funs.append((fun, k, kw)) if not 'cwd' in kw: kw['cwd'] = k[0].path else: fun(*k, **kw) return f class BuildContext(Utils.Context): "holds the dependency tree" def __init__(self): # not a singleton, but provided for compatibility global bld bld = self self.task_manager = Task.TaskManager() # instead of hashing the nodes, we assign them a unique id when they are created self.id_nodes = 0 self.idx = {} # map names to environments, the 'default' must be defined self.all_envs = {} # ======================================= # # code for reading the scripts # project build directory - do not reset() from load_dirs() self.bdir = '' # the current directory from which the code is run # the folder changes everytime a wscript is read self.path = None # Manual dependencies. self.deps_man = Utils.DefaultDict(list) # ======================================= # # cache variables # local cache for absolute paths - cache_node_abspath[variant][node] self.cache_node_abspath = {} # list of folders that are already scanned # so that we do not need to stat them one more time self.cache_scanned_folders = {} # list of targets to uninstall for removing the empty folders after uninstalling self.uninstall = [] # ======================================= # # tasks and objects # build dir variants (release, debug, ..) for v in 'cache_node_abspath task_sigs node_deps raw_deps node_sigs'.split(): var = {} setattr(self, v, var) self.cache_dir_contents = {} self.all_task_gen = [] self.task_gen_cache_names = {} self.cache_sig_vars = {} self.log = None self.root = None self.srcnode = None self.bldnode = None # bind the build context to the nodes in use # this means better encapsulation and no build context singleton class node_class(Node.Node): pass self.node_class = node_class self.node_class.__module__ = "Node" self.node_class.__name__ = "Nodu" self.node_class.bld = self self.is_install = None def __copy__(self): "nodes are not supposed to be copied" raise Utils.WafError('build contexts are not supposed to be cloned') def load(self): "load the cache from the disk" try: env = Environment.Environment(os.path.join(self.cachedir, 'build.config.py')) except (IOError, OSError): pass else: if env['version'] < HEXVERSION: raise Utils.WafError('Version mismatch! reconfigure the project') for t in env['tools']: self.setup(**t) try: gc.disable() f = data = None Node.Nodu = self.node_class try: f = open(os.path.join(self.bdir, DBFILE), 'rb') except (IOError, EOFError): # handle missing file/empty file pass try: if f: data = cPickle.load(f) except AttributeError: # handle file of an old Waf version # that has an attribute which no longer exist # (e.g. AttributeError: 'module' object has no attribute 'BuildDTO') if Logs.verbose > 1: raise if data: for x in SAVED_ATTRS: setattr(self, x, data[x]) else: debug('build: Build cache loading failed') finally: if f: f.close() gc.enable() def save(self): "store the cache on disk, see self.load" gc.disable() self.root.__class__.bld = None # some people are very nervous with ctrl+c so we have to make a temporary file Node.Nodu = self.node_class db = os.path.join(self.bdir, DBFILE) file = open(db + '.tmp', 'wb') data = {} for x in SAVED_ATTRS: data[x] = getattr(self, x) cPickle.dump(data, file, -1) file.close() # do not use shutil.move try: os.unlink(db) except OSError: pass os.rename(db + '.tmp', db) self.root.__class__.bld = self gc.enable() # ======================================= # def clean(self): debug('build: clean called') # does not clean files created during the configuration precious = set([]) for env in self.all_envs.values(): for x in env[CFG_FILES]: node = self.srcnode.find_resource(x) if node: precious.add(node.id) def clean_rec(node): for x in list(node.childs.keys()): nd = node.childs[x] tp = nd.id & 3 if tp == Node.DIR: clean_rec(nd) elif tp == Node.BUILD: if nd.id in precious: continue for env in self.all_envs.values(): try: os.remove(nd.abspath(env)) except OSError: pass node.childs.__delitem__(x) clean_rec(self.srcnode) for v in 'node_sigs node_deps task_sigs raw_deps cache_node_abspath'.split(): setattr(self, v, {}) def compile(self): """The cache file is not written if nothing was build at all (build is up to date)""" debug('build: compile called') """ import cProfile, pstats cProfile.run("import Build\nBuild.bld.flush()", 'profi.txt') p = pstats.Stats('profi.txt') p.sort_stats('cumulative').print_stats(80) """ self.flush() #""" self.generator = Runner.Parallel(self, Options.options.jobs) def dw(on=True): if Options.options.progress_bar: if on: sys.stderr.write(Logs.colors.cursor_on) else: sys.stderr.write(Logs.colors.cursor_off) debug('build: executor starting') back = os.getcwd() os.chdir(self.bldnode.abspath()) try: try: dw(on=False) self.generator.start() except KeyboardInterrupt: dw() # if self.generator.processed != 1: TODO self.save() raise except Exception: dw() # do not store anything, for something bad happened raise else: dw() #if self.generator.processed != 1: TODO self.save() if self.generator.error: raise BuildError(self, self.task_manager.tasks_done) finally: os.chdir(back) def install(self): "this function is called for both install and uninstall" debug('build: install called') self.flush() # remove empty folders after uninstalling if self.is_install < 0: lst = [] for x in self.uninstall: dir = os.path.dirname(x) if not dir in lst: lst.append(dir) lst.sort() lst.reverse() nlst = [] for y in lst: x = y while len(x) > 4: if not x in nlst: nlst.append(x) x = os.path.dirname(x) nlst.sort() nlst.reverse() for x in nlst: try: os.rmdir(x) except OSError: pass def new_task_gen(self, *k, **kw): if self.task_gen_cache_names: self.task_gen_cache_names = {} kw['bld'] = self if len(k) == 0: ret = TaskGen.task_gen(*k, **kw) else: cls_name = k[0] try: cls = TaskGen.task_gen.classes[cls_name] except KeyError: raise Utils.WscriptError('%s is not a valid task generator -> %s' % (cls_name, [x for x in TaskGen.task_gen.classes])) ret = cls(*k, **kw) return ret def __call__(self, *k, **kw): if self.task_gen_cache_names: self.task_gen_cache_names = {} kw['bld'] = self return TaskGen.task_gen(*k, **kw) def load_envs(self): try: lst = Utils.listdir(self.cachedir) except OSError, e: if e.errno == errno.ENOENT: raise Utils.WafError('The project was not configured: run "waf configure" first!') else: raise if not lst: raise Utils.WafError('The cache directory is empty: reconfigure the project') for file in lst: if file.endswith(CACHE_SUFFIX): env = Environment.Environment(os.path.join(self.cachedir, file)) name = file[:-len(CACHE_SUFFIX)] self.all_envs[name] = env self.init_variants() for env in self.all_envs.values(): for f in env[CFG_FILES]: newnode = self.path.find_or_declare(f) try: hash = Utils.h_file(newnode.abspath(env)) except (IOError, AttributeError): error("cannot find "+f) hash = SIG_NIL self.node_sigs[env.variant()][newnode.id] = hash # TODO: hmmm, these nodes are removed from the tree when calling rescan() self.bldnode = self.root.find_dir(self.bldnode.abspath()) self.path = self.srcnode = self.root.find_dir(self.srcnode.abspath()) self.cwd = self.bldnode.abspath() def setup(self, tool, tooldir=None, funs=None): "setup tools for build process" if isinstance(tool, list): for i in tool: self.setup(i, tooldir) return if not tooldir: tooldir = Options.tooldir module = Utils.load_tool(tool, tooldir) if hasattr(module, "setup"): module.setup(self) def init_variants(self): debug('build: init variants') lstvariants = [] for env in self.all_envs.values(): if not env.variant() in lstvariants: lstvariants.append(env.variant()) self.lst_variants = lstvariants debug('build: list of variants is %r', lstvariants) for name in lstvariants+[0]: for v in 'node_sigs cache_node_abspath'.split(): var = getattr(self, v) if not name in var: var[name] = {} # ======================================= # # node and folder handling # this should be the main entry point def load_dirs(self, srcdir, blddir, load_cache=1): "this functions should be the start of everything" assert(os.path.isabs(srcdir)) assert(os.path.isabs(blddir)) self.cachedir = os.path.join(blddir, CACHE_DIR) if srcdir == blddir: raise Utils.WafError("build dir must be different from srcdir: %s <-> %s " % (srcdir, blddir)) self.bdir = blddir # try to load the cache file, if it does not exist, nothing happens self.load() if not self.root: Node.Nodu = self.node_class self.root = Node.Nodu('', None, Node.DIR) if not self.srcnode: self.srcnode = self.root.ensure_dir_node_from_path(srcdir) debug('build: srcnode is %s and srcdir %s', self.srcnode.name, srcdir) self.path = self.srcnode # create this build dir if necessary try: os.makedirs(blddir) except OSError: pass if not self.bldnode: self.bldnode = self.root.ensure_dir_node_from_path(blddir) self.init_variants() def rescan(self, src_dir_node): """ look the contents of a (folder)node and update its list of childs The intent is to perform the following steps * remove the nodes for the files that have disappeared * remove the signatures for the build files that have disappeared * cache the results of os.listdir * create the build folder equivalent (mkdir) for each variant src/bar -> build/default/src/bar, build/release/src/bar when a folder in the source directory is removed, we do not check recursively to remove the unused nodes. To do that, call 'waf clean' and build again. """ # do not rescan over and over again # TODO use a single variable in waf 1.6 if self.cache_scanned_folders.get(src_dir_node.id, None): return self.cache_scanned_folders[src_dir_node.id] = True # TODO remove in waf 1.6 if hasattr(self, 'repository'): self.repository(src_dir_node) if not src_dir_node.name and sys.platform == 'win32': # the root has no name, contains drive letters, and cannot be listed return # first, take the case of the source directory parent_path = src_dir_node.abspath() try: lst = set(Utils.listdir(parent_path)) except OSError: lst = set([]) # TODO move this at the bottom self.cache_dir_contents[src_dir_node.id] = lst # hash the existing source files, remove the others cache = self.node_sigs[0] for x in src_dir_node.childs.values(): if x.id & 3 != Node.FILE: continue if x.name in lst: try: cache[x.id] = Utils.h_file(x.abspath()) except IOError: raise Utils.WafError('The file %s is not readable or has become a dir' % x.abspath()) else: try: del cache[x.id] except KeyError: pass del src_dir_node.childs[x.name] # first obtain the differences between srcnode and src_dir_node h1 = self.srcnode.height() h2 = src_dir_node.height() lst = [] child = src_dir_node while h2 > h1: lst.append(child.name) child = child.parent h2 -= 1 lst.reverse() # list the files in the build dirs try: for variant in self.lst_variants: sub_path = os.path.join(self.bldnode.abspath(), variant , *lst) self.listdir_bld(src_dir_node, sub_path, variant) except OSError: # listdir failed, remove the build node signatures for all variants for node in src_dir_node.childs.values(): if node.id & 3 != Node.BUILD: continue for dct in self.node_sigs.values(): if node.id in dct: dct.__delitem__(node.id) # the policy is to avoid removing nodes representing directories src_dir_node.childs.__delitem__(node.name) for variant in self.lst_variants: sub_path = os.path.join(self.bldnode.abspath(), variant , *lst) try: os.makedirs(sub_path) except OSError: pass # ======================================= # def listdir_src(self, parent_node): """do not use, kept for compatibility""" pass def remove_node(self, node): """do not use, kept for compatibility""" pass def listdir_bld(self, parent_node, path, variant): """in this method we do not add timestamps but we remove them when the files no longer exist (file removed in the build dir)""" i_existing_nodes = [x for x in parent_node.childs.values() if x.id & 3 == Node.BUILD] lst = set(Utils.listdir(path)) node_names = set([x.name for x in i_existing_nodes]) remove_names = node_names - lst # remove the stamps of the build nodes that no longer exist on the filesystem ids_to_remove = [x.id for x in i_existing_nodes if x.name in remove_names] cache = self.node_sigs[variant] for nid in ids_to_remove: if nid in cache: cache.__delitem__(nid) def get_env(self): return self.env_of_name('default') def set_env(self, name, val): self.all_envs[name] = val env = property(get_env, set_env) def add_manual_dependency(self, path, value): 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) self.deps_man[node.id].append(value) def launch_node(self): """return the launch directory as a node""" # p_ln is kind of private, but public in case if try: return self.p_ln except AttributeError: self.p_ln = self.root.find_dir(Options.launch_dir) return self.p_ln def glob(self, pattern, relative=True): "files matching the pattern, seen from the current folder" path = self.path.abspath() files = [self.root.find_resource(x) for x in glob.glob(path+os.sep+pattern)] if relative: files = [x.path_to_parent(self.path) for x in files if x] else: files = [x.abspath() for x in files if x] return files ## the following methods are candidates for the stable apis ## def add_group(self, *k): self.task_manager.add_group(*k) def set_group(self, *k, **kw): self.task_manager.set_group(*k, **kw) def hash_env_vars(self, env, vars_lst): """hash environment variables ['CXX', ..] -> [env['CXX'], ..] -> md5()""" # ccroot objects use the same environment for building the .o at once # the same environment and the same variables are used idx = str(id(env)) + str(vars_lst) try: return self.cache_sig_vars[idx] except KeyError: pass lst = [str(env[a]) for a in vars_lst] ret = Utils.h_list(lst) debug('envhash: %r %r', ret, lst) # next time self.cache_sig_vars[idx] = ret return ret def name_to_obj(self, name, env): """retrieve a task generator from its name or its target name remember that names must be unique""" cache = self.task_gen_cache_names if not cache: # create the index lazily for x in self.all_task_gen: vt = x.env.variant() + '_' if x.name: cache[vt + x.name] = x else: if isinstance(x.target, str): target = x.target else: target = ' '.join(x.target) v = vt + target if not cache.get(v, None): cache[v] = x return cache.get(env.variant() + '_' + name, None) def get_tgen_by_name(self, name): """waf 1.8 api""" return self.name_to_obj(name, self.env) def flush(self, all=1): """tell the task generators to create the tasks""" self.ini = datetime.datetime.now() # force the initialization of the mapping name->object in flush # name_to_obj can be used in userland scripts, in that case beware of incomplete mapping self.task_gen_cache_names = {} self.name_to_obj('', self.env) debug('build: delayed operation TaskGen.flush() called') if Options.options.compile_targets: debug('task_gen: posting objects %r listed in compile_targets', Options.options.compile_targets) mana = self.task_manager to_post = [] min_grp = 0 # ensure the target names exist, fail before any post() target_objects = Utils.DefaultDict(list) for target_name in Options.options.compile_targets.split(','): # trim target_name (handle cases when the user added spaces to targets) target_name = target_name.strip() for env in self.all_envs.values(): tg = self.name_to_obj(target_name, env) if tg: target_objects[target_name].append(tg) m = mana.group_idx(tg) if m > min_grp: min_grp = m to_post = [tg] elif m == min_grp: to_post.append(tg) if not target_name in target_objects and all: raise Utils.WafError("target '%s' does not exist" % target_name) debug('group: Forcing up to group %s for target %s', mana.group_name(min_grp), Options.options.compile_targets) # post all the task generators in previous groups for i in xrange(len(mana.groups)): mana.current_group = i if i == min_grp: break g = mana.groups[i] debug('group: Forcing group %s', mana.group_name(g)) for t in g.tasks_gen: debug('group: Posting %s', t.name or t.target) t.post() # then post the task generators listed in compile_targets in the last group for t in to_post: t.post() else: debug('task_gen: posting objects (normal)') ln = self.launch_node() # if the build is started from the build directory, do as if it was started from the top-level # for the pretty-printing (Node.py), the two lines below cannot be moved to Build::launch_node if ln.is_child_of(self.bldnode) or not ln.is_child_of(self.srcnode): ln = self.srcnode # if the project file is located under the source directory, build all targets by default # else 'waf configure build' does nothing proj_node = self.root.find_dir(os.path.split(Utils.g_module.root_path)[0]) if proj_node.id != self.srcnode.id: ln = self.srcnode for i in xrange(len(self.task_manager.groups)): g = self.task_manager.groups[i] self.task_manager.current_group = i if Logs.verbose: groups = [x for x in self.task_manager.groups_names if id(self.task_manager.groups_names[x]) == id(g)] name = groups and groups[0] or 'unnamed' Logs.debug('group: group', name) for tg in g.tasks_gen: if not tg.path.is_child_of(ln): continue if Logs.verbose: Logs.debug('group: %s' % tg) tg.post() def env_of_name(self, name): try: return self.all_envs[name] except KeyError: error('no such environment: '+name) return None def progress_line(self, state, total, col1, col2): n = len(str(total)) Utils.rot_idx += 1 ind = Utils.rot_chr[Utils.rot_idx % 4] ini = self.ini pc = (100.*state)/total eta = Utils.get_elapsed_time(ini) fs = "[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s][" % (n, n, ind) left = fs % (state, total, col1, pc, col2) right = '][%s%s%s]' % (col1, eta, col2) cols = Utils.get_term_cols() - len(left) - len(right) + 2*len(col1) + 2*len(col2) if cols < 7: cols = 7 ratio = int((cols*state)/total) - 1 bar = ('='*ratio+'>').ljust(cols) msg = Utils.indicator % (left, bar, right) return msg # do_install is not used anywhere def do_install(self, src, tgt, chmod=O644): """returns true if the file was effectively installed or uninstalled, false otherwise""" if self.is_install > 0: 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 >= st2.st_mtime and st1.st_size == st2.st_size: return False srclbl = src.replace(self.srcnode.abspath(None)+os.sep, '') info("* installing %s as %s" % (srclbl, tgt)) # following is for shared libs and stale inodes (-_-) try: os.remove(tgt) except OSError: pass try: shutil.copy2(src, tgt) os.chmod(tgt, chmod) except IOError: try: os.stat(src) except (OSError, IOError): error('File %r does not exist' % src) raise Utils.WafError('Could not install the file %r' % tgt) return True elif self.is_install < 0: info("* uninstalling %s" % tgt) self.uninstall.append(tgt) try: os.remove(tgt) except OSError, 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)) return True red = re.compile(r"^([A-Za-z]:)?[/\\\\]*") def get_install_path(self, path, env=None): "installation path prefixed by the destdir, the variables like in '${PREFIX}/bin' are substituted" if not env: env = self.env destdir = env.get_destdir() path = path.replace('/', os.sep) destpath = Utils.subst_vars(path, env) if destdir: destpath = os.path.join(destdir, self.red.sub('', destpath)) return destpath def install_dir(self, path, env=None): """ create empty folders for the installation (very rarely used) """ if env: assert isinstance(env, Environment.Environment), "invalid parameter" else: env = self.env if not path: return [] destpath = self.get_install_path(path, env) if self.is_install > 0: info('* creating %s' % destpath) Utils.check_dir(destpath) elif self.is_install < 0: info('* removing %s' % destpath) self.uninstall.append(destpath + '/xxx') # yes, ugly def install_files(self, path, files, env=None, chmod=O644, relative_trick=False, cwd=None): """To install files only after they have been built, put the calls in a method named post_build on the top-level wscript The files must be a list and contain paths as strings or as Nodes The relative_trick flag can be set to install folders, use bld.path.ant_glob() with it """ if env: assert isinstance(env, Environment.Environment), "invalid parameter" else: env = self.env if not path: return [] if not cwd: cwd = self.path if isinstance(files, str) and '*' in files: gl = cwd.abspath() + os.sep + files lst = glob.glob(gl) else: lst = Utils.to_list(files) if not getattr(lst, '__iter__', False): lst = [lst] destpath = self.get_install_path(path, env) Utils.check_dir(destpath) installed_files = [] for filename in lst: if isinstance(filename, str) and os.path.isabs(filename): alst = Utils.split_path(filename) destfile = os.path.join(destpath, alst[-1]) else: if isinstance(filename, Node.Node): nd = filename else: nd = cwd.find_resource(filename) if not nd: raise Utils.WafError("Unable to install the file %r (not found in %s)" % (filename, cwd)) if relative_trick: destfile = os.path.join(destpath, filename) Utils.check_dir(os.path.dirname(destfile)) else: destfile = os.path.join(destpath, nd.name) filename = nd.abspath(env) if self.do_install(filename, destfile, chmod): installed_files.append(destfile) return installed_files def install_as(self, path, srcfile, env=None, chmod=O644, cwd=None): """ srcfile may be a string or a Node representing the file to install returns True if the file was effectively installed, False otherwise """ if env: assert isinstance(env, Environment.Environment), "invalid parameter" else: env = self.env if not path: raise Utils.WafError("where do you want to install %r? (%r?)" % (srcfile, path)) if not cwd: cwd = self.path destpath = self.get_install_path(path, env) dir, name = os.path.split(destpath) Utils.check_dir(dir) # the source path if isinstance(srcfile, Node.Node): src = srcfile.abspath(env) else: src = srcfile if not os.path.isabs(srcfile): node = cwd.find_resource(srcfile) if not node: raise Utils.WafError("Unable to install the file %r (not found in %s)" % (srcfile, cwd)) src = node.abspath(env) return self.do_install(src, destpath, chmod) def symlink_as(self, path, src, env=None, cwd=None): """example: bld.symlink_as('${PREFIX}/lib/libfoo.so', 'libfoo.so.1.2.3') """ if sys.platform == 'win32': # well, this *cannot* work return if not path: raise Utils.WafError("where do you want to install %r? (%r?)" % (src, path)) tgt = self.get_install_path(path, env) dir, name = os.path.split(tgt) Utils.check_dir(dir) if self.is_install > 0: link = False if not os.path.islink(tgt): link = True elif os.readlink(tgt) != src: link = True if link: try: os.remove(tgt) except OSError: pass info('* symlink %s (-> %s)' % (tgt, src)) os.symlink(src, tgt) return 0 else: # UNINSTALL try: info('* removing %s' % (tgt)) os.remove(tgt) return 0 except OSError: return 1 def exec_command(self, cmd, **kw): # 'runner' zone is printed out for waf -v, see wafadmin/Options.py debug('runner: system command -> %s', cmd) if self.log: self.log.write('%s\n' % cmd) kw['log'] = self.log try: if not kw.get('cwd', None): kw['cwd'] = self.cwd except AttributeError: self.cwd = kw['cwd'] = self.bldnode.abspath() return Utils.exec_command(cmd, **kw) def printout(self, s): f = self.log or sys.stderr f.write(s) f.flush() def add_subdirs(self, dirs): self.recurse(dirs, 'build') def pre_recurse(self, name_or_mod, path, nexdir): if not hasattr(self, 'oldpath'): self.oldpath = [] self.oldpath.append(self.path) self.path = self.root.find_dir(nexdir) return {'bld': self, 'ctx': self} def post_recurse(self, name_or_mod, path, nexdir): self.path = self.oldpath.pop() ###### user-defined behaviour def pre_build(self): if hasattr(self, 'pre_funs'): for m in self.pre_funs: m(self) def post_build(self): if hasattr(self, 'post_funs'): for m in self.post_funs: m(self) def add_pre_fun(self, meth): try: self.pre_funs.append(meth) except AttributeError: self.pre_funs = [meth] def add_post_fun(self, meth): try: self.post_funs.append(meth) except AttributeError: self.post_funs = [meth] def use_the_magic(self): Task.algotype = Task.MAXPARALLEL Task.file_deps = Task.extract_deps self.magic = True install_as = group_method(install_as) install_files = group_method(install_files) symlink_as = group_method(symlink_as) tevent-0.9.34/third_party/waf/wafadmin/Configure.py0000660000000000000000000002762012520121120022230 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2008 (ita) """ Configuration system A configuration instance is created when "waf configure" is called, it is used to: * create data dictionaries (Environment instances) * store the list of modules to import The old model (copied from Scons) was to store logic (mapping file extensions to functions) along with the data. In Waf a way was found to separate that logic by adding an indirection layer (storing the names in the Environment instances) In the new model, the logic is more object-oriented, and the user scripts provide the logic. The data files (Environments) must contain configuration data only (flags, ..). Note: the c/c++ related code is in the module config_c """ import os, shlex, sys, time try: import cPickle except ImportError: import pickle as cPickle import Environment, Utils, Options, Logs from Logs import warn from Constants import * try: from urllib import request except: from urllib import urlopen else: urlopen = request.urlopen 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 ConfigurationError(Utils.WscriptError): pass autoconfig = False "reconfigure the project automatically" def find_file(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 occurrence filename or '' if filename could not be found """ for directory in Utils.to_list(path_list): if os.path.exists(os.path.join(directory, filename)): return directory return '' def find_program_impl(env, filename, path_list=[], var=None, environ=None): """find a program in folders path_lst, and sets env[var] @param env: environment @param filename: name of the program to search for @param path_list: list of directories to search for filename @param var: environment value to be checked for in env or os.environ @return: either the value that is referenced with [var] in env or os.environ or the first occurrence filename or '' if filename could not be found """ if not environ: environ = os.environ try: path_list = path_list.split() except AttributeError: pass if var: if env[var]: return env[var] if var in environ: env[var] = environ[var] if not path_list: path_list = environ.get('PATH', '').split(os.pathsep) ext = (Options.platform == 'win32') and '.exe,.com,.bat,.cmd' or '' for y in [filename+x for x in ext.split(',')]: for directory in path_list: x = os.path.join(directory, y) if os.path.isfile(x): if var: env[var] = x return x return '' class ConfigurationContext(Utils.Context): tests = {} error_handlers = [] def __init__(self, env=None, blddir='', srcdir=''): self.env = None self.envname = '' self.environ = dict(os.environ) self.line_just = 40 self.blddir = blddir self.srcdir = srcdir self.all_envs = {} # curdir: necessary for recursion self.cwd = self.curdir = os.getcwd() self.tools = [] # tools loaded in the configuration, and that will be loaded when building self.setenv(DEFAULT) self.lastprog = '' self.hash = 0 self.files = [] self.tool_cache = [] if self.blddir: self.post_init() def post_init(self): self.cachedir = os.path.join(self.blddir, CACHE_DIR) path = os.path.join(self.blddir, WAF_CONFIG_LOG) try: os.unlink(path) except (OSError, IOError): pass try: self.log = open(path, 'w') except (OSError, IOError): self.fatal('could not open %r for writing' % path) app = Utils.g_module.APPNAME if app: ver = getattr(Utils.g_module, 'VERSION', '') if ver: app = "%s (%s)" % (app, ver) now = time.ctime() pyver = sys.hexversion systype = sys.platform args = " ".join(sys.argv) wafver = WAFVERSION abi = ABI self.log.write(conf_template % vars()) def __del__(self): """cleanup function: close config.log""" # may be ran by the gc, not always after initialization if hasattr(self, 'log') and self.log: self.log.close() def fatal(self, msg): raise ConfigurationError(msg) def check_tool(self, input, tooldir=None, funs=None): "load a waf tool" tools = Utils.to_list(input) if tooldir: tooldir = Utils.to_list(tooldir) for tool in tools: tool = tool.replace('++', 'xx') if tool == 'java': tool = 'javaw' if tool.lower() == 'unittest': tool = 'unittestw' # avoid loading the same tool more than once with the same functions # used by composite projects mag = (tool, id(self.env), funs) if mag in self.tool_cache: continue self.tool_cache.append(mag) module = None try: module = Utils.load_tool(tool, tooldir) except Exception, e: ex = e if Options.options.download: _3rdparty = os.path.normpath(Options.tooldir[0] + os.sep + '..' + os.sep + '3rdparty') # try to download the tool from the repository then # the default is set to false for x in Utils.to_list(Options.remote_repo): for sub in ['branches/waf-%s/wafadmin/3rdparty' % WAFVERSION, 'trunk/wafadmin/3rdparty']: url = '/'.join((x, sub, tool + '.py')) try: web = urlopen(url) if web.getcode() != 200: continue except Exception, e: # on python3 urlopen throws an exception continue else: loc = None try: loc = open(_3rdparty + os.sep + tool + '.py', 'wb') loc.write(web.read()) web.close() finally: if loc: loc.close() Logs.warn('downloaded %s from %s' % (tool, url)) try: module = Utils.load_tool(tool, tooldir) except: Logs.warn('module %s from %s is unusable' % (tool, url)) try: os.unlink(_3rdparty + os.sep + tool + '.py') except: pass continue else: break if not module: Logs.error('Could not load the tool %r or download a suitable replacement from the repository (sys.path %r)\n%s' % (tool, sys.path, e)) raise ex else: Logs.error('Could not load the tool %r in %r (try the --download option?):\n%s' % (tool, sys.path, e)) raise ex if funs is not None: self.eval_rules(funs) else: func = getattr(module, 'detect', None) if func: if type(func) is type(find_file): func(self) else: self.eval_rules(func) self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs}) def sub_config(self, k): "executes the configure function of a wscript module" self.recurse(k, name='configure') def pre_recurse(self, name_or_mod, path, nexdir): return {'conf': self, 'ctx': self} def post_recurse(self, name_or_mod, path, nexdir): if not autoconfig: return self.hash = hash((self.hash, getattr(name_or_mod, 'waf_hash_val', name_or_mod))) self.files.append(path) def store(self, file=''): "save the config results into the cache file" if not os.path.isdir(self.cachedir): os.makedirs(self.cachedir) if not file: file = open(os.path.join(self.cachedir, 'build.config.py'), 'w') file.write('version = 0x%x\n' % HEXVERSION) file.write('tools = %r\n' % self.tools) file.close() 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, key + CACHE_SUFFIX)) def set_env_name(self, name, env): "add a new environment called name" self.all_envs[name] = env return env def retrieve(self, name, fromenv=None): "retrieve an environment called name" try: env = self.all_envs[name] except KeyError: env = Environment.Environment() env['PREFIX'] = os.path.abspath(os.path.expanduser(Options.options.prefix)) self.all_envs[name] = env else: if fromenv: warn("The environment %s may have been configured already" % name) return env def setenv(self, name): "enable the environment called name" self.env = self.retrieve(name) self.envname = name def add_os_flags(self, var, dest=None): # do not use 'get' to make certain the variable is not defined try: self.env.append_value(dest or var, Utils.to_list(self.environ[var])) except KeyError: pass def check_message_1(self, sr): self.line_just = max(self.line_just, len(sr)) for x in ('\n', self.line_just * '-', '\n', sr, '\n'): self.log.write(x) Utils.pprint('NORMAL', "%s :" % sr.ljust(self.line_just), sep='') def check_message_2(self, sr, color='GREEN'): self.log.write(sr) self.log.write('\n') Utils.pprint(color, sr) def check_message(self, th, msg, state, option=''): sr = 'Checking for %s %s' % (th, msg) self.check_message_1(sr) p = self.check_message_2 if state: p('ok ' + str(option)) else: p('not found', 'YELLOW') # FIXME remove in waf 1.6 # the parameter 'option' is not used (kept for compatibility) def check_message_custom(self, th, msg, custom, option='', color='PINK'): sr = 'Checking for %s %s' % (th, msg) self.check_message_1(sr) self.check_message_2(custom, color) def msg(self, msg, result, color=None): """Prints a configuration message 'Checking for xxx: ok'""" self.start_msg('Checking for ' + msg) if not isinstance(color, str): color = result and 'GREEN' or 'YELLOW' self.end_msg(result, color) def start_msg(self, msg): try: if self.in_msg: return except: self.in_msg = 0 self.in_msg += 1 self.line_just = max(self.line_just, len(msg)) for x in ('\n', self.line_just * '-', '\n', msg, '\n'): self.log.write(x) Utils.pprint('NORMAL', "%s :" % msg.ljust(self.line_just), sep='') def end_msg(self, result, color): self.in_msg -= 1 if self.in_msg: return if not color: color = 'GREEN' if result == True: msg = 'ok' elif result == False: msg = 'not found' color = 'YELLOW' else: msg = str(result) self.log.write(msg) self.log.write('\n') Utils.pprint(color, msg) def find_program(self, filename, path_list=[], var=None, mandatory=False): "wrapper that adds a configuration message" ret = None if var: if self.env[var]: ret = self.env[var] elif var in os.environ: ret = os.environ[var] if not isinstance(filename, list): filename = [filename] if not ret: for x in filename: ret = find_program_impl(self.env, x, path_list, var, environ=self.environ) if ret: break self.check_message_1('Checking for program %s' % ' or '.join(filename)) self.log.write(' find program=%r paths=%r var=%r\n -> %r\n' % (filename, path_list, var, ret)) if ret: Utils.pprint('GREEN', str(ret)) else: Utils.pprint('YELLOW', 'not found') if mandatory: self.fatal('The program %r is required' % filename) if var: self.env[var] = ret return ret def cmd_to_list(self, cmd): "commands may be written in pseudo shell like 'ccache g++'" if isinstance(cmd, str) and cmd.find(' '): try: os.stat(cmd) except OSError: return shlex.split(cmd) else: return [cmd] return cmd def __getattr__(self, name): r = self.__class__.__dict__.get(name, None) if r: return r if name and name.startswith('require_'): for k in ['check_', 'find_']: n = name.replace('require_', k) ret = self.__class__.__dict__.get(n, None) if ret: def run(*k, **kw): r = ret(self, *k, **kw) if not r: self.fatal('requirement failure') return r return run self.fatal('No such method %r' % name) def eval_rules(self, rules): self.rules = Utils.to_list(rules) for x in self.rules: f = getattr(self, x) if not f: self.fatal("No such method '%s'." % x) try: f() except Exception, e: ret = self.err_handler(x, e) if ret == BREAK: break elif ret == CONTINUE: continue else: self.fatal(e) def err_handler(self, fun, error): pass def conf(f): "decorator: attach new configuration functions" setattr(ConfigurationContext, f.__name__, f) return f def conftest(f): "decorator: attach new configuration tests (registered as strings)" ConfigurationContext.tests[f.__name__] = f return conf(f) tevent-0.9.34/third_party/waf/wafadmin/Constants.py0000660000000000000000000000243312520121120022256 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Yinon dot me gmail 2008 """ these constants are somewhat public, try not to mess them maintainer: the version number is updated from the top-level wscript file """ # do not touch these three lines, they are updated automatically HEXVERSION=0x105019 WAFVERSION="1.5.19" WAFREVISION = "9709M" ABI = 7 # permissions O644 = 420 O755 = 493 MAXJOBS = 99999999 CACHE_DIR = 'c4che' CACHE_SUFFIX = '.cache.py' DBFILE = '.wafpickle-%d' % ABI WSCRIPT_FILE = 'wscript' WSCRIPT_BUILD_FILE = 'wscript_build' WAF_CONFIG_LOG = 'config.log' WAF_CONFIG_H = 'config.h' SIG_NIL = 'iluvcuteoverload' VARIANT = '_VARIANT_' DEFAULT = 'default' SRCDIR = 'srcdir' BLDDIR = 'blddir' APPNAME = 'APPNAME' VERSION = 'VERSION' DEFINES = 'defines' UNDEFINED = () BREAK = "break" CONTINUE = "continue" # task scheduler options JOBCONTROL = "JOBCONTROL" MAXPARALLEL = "MAXPARALLEL" NORMAL = "NORMAL" # task state NOT_RUN = 0 MISSING = 1 CRASHED = 2 EXCEPTION = 3 SKIPPED = 8 SUCCESS = 9 ASK_LATER = -1 SKIP_ME = -2 RUN_ME = -3 LOG_FORMAT = "%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s" HOUR_FORMAT = "%H:%M:%S" TEST_OK = True CFG_FILES = 'cfg_files' # positive '->' install # negative '<-' uninstall INSTALL = 1337 UNINSTALL = -1337 tevent-0.9.34/third_party/waf/wafadmin/Environment.py0000660000000000000000000001166412520121120022614 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) """Environment representation There is one gotcha: getitem returns [] if the contents evals to False This means env['foo'] = {}; print env['foo'] will print [] not {} """ import os, copy, re import Logs, Options, Utils from Constants import * re_imp = re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) class Environment(object): """A safe-to-use dictionary, but do not attach functions to it please (break cPickle) An environment instance can be stored into a file and loaded easily """ __slots__ = ("table", "parent") def __init__(self, filename=None): self.table = {} #self.parent = None if filename: self.load(filename) def __contains__(self, key): if key in self.table: return True try: return self.parent.__contains__(key) except AttributeError: return False # parent may not exist def __str__(self): keys = set() cur = self while cur: keys.update(cur.table.keys()) cur = getattr(cur, 'parent', None) keys = list(keys) keys.sort() return "\n".join(["%r %r" % (x, self.__getitem__(x)) for x in keys]) def __getitem__(self, key): try: while 1: x = self.table.get(key, None) if not x is None: return x self = self.parent except AttributeError: return [] def __setitem__(self, key, value): self.table[key] = value def __delitem__(self, key): del self.table[key] def pop(self, key, *args): if len(args): return self.table.pop(key, *args) return self.table.pop(key) def set_variant(self, name): self.table[VARIANT] = name def variant(self): try: while 1: x = self.table.get(VARIANT, None) if not x is None: return x self = self.parent except AttributeError: return DEFAULT def copy(self): # TODO waf 1.6 rename this method derive, #368 newenv = Environment() newenv.parent = self return newenv def detach(self): """TODO try it modifying the original env will not change the copy""" 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 def get_flat(self, key): s = self[key] if isinstance(s, str): return s return ' '.join(s) def _get_list_value_for_modification(self, key): """Gets a value that must be a list for further modification. The list may be modified inplace and there is no need to "self.table[var] = value" afterwards. """ try: value = self.table[key] except KeyError: try: value = self.parent[key] except AttributeError: value = [] if isinstance(value, list): value = value[:] else: value = [value] else: if not isinstance(value, list): value = [value] self.table[key] = value return value def append_value(self, var, value): current_value = self._get_list_value_for_modification(var) if isinstance(value, list): current_value.extend(value) else: current_value.append(value) def prepend_value(self, var, value): current_value = self._get_list_value_for_modification(var) if isinstance(value, list): current_value = value + current_value # a new list: update the dictionary entry self.table[var] = current_value else: current_value.insert(0, value) # prepend unique would be ambiguous def append_unique(self, var, value): current_value = self._get_list_value_for_modification(var) if isinstance(value, list): for value_item in value: if value_item not in current_value: current_value.append(value_item) else: if value not in current_value: current_value.append(value) def get_merged_dict(self): """compute a merged table""" 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): "Write the variables into a file" file = open(filename, 'w') merged_table = self.get_merged_dict() keys = list(merged_table.keys()) keys.sort() for k in keys: file.write('%s = %r\n' % (k, merged_table[k])) file.close() def load(self, filename): "Retrieve the variables from a file" tbl = self.table code = Utils.readf(filename) for m in re_imp.finditer(code): g = m.group tbl[g(2)] = eval(g(3)) Logs.debug('env: %s', self.table) def get_destdir(self): "return the destdir, useful for installing" if self.__getitem__('NOINSTALL'): return '' return Options.options.destdir def update(self, d): for k, v in d.iteritems(): self[k] = v def __getattr__(self, name): if name in self.__slots__: return object.__getattr__(self, name) else: return self[name] def __setattr__(self, name, value): if name in self.__slots__: object.__setattr__(self, name, value) else: self[name] = value def __delattr__(self, name): if name in self.__slots__: object.__delattr__(self, name) else: del self[name] tevent-0.9.34/third_party/waf/wafadmin/Logs.py0000660000000000000000000000547312520121120021215 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) import ansiterm import os, re, logging, traceback, sys from Constants import * zones = '' verbose = 0 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', 'NORMAL':'\x1b[0m', 'cursor_on' :'\x1b[?25h', 'cursor_off' :'\x1b[?25l', } got_tty = False term = os.environ.get('TERM', 'dumb') if not term in ['dumb', 'emacs']: try: got_tty = sys.stderr.isatty() or (sys.platform == 'win32' and term in ['xterm', 'msys']) except AttributeError: pass import Utils if not got_tty or 'NOCOLOR' in os.environ: colors_lst['USE'] = False # test #if sys.platform == 'win32': # colors_lst['USE'] = True def get_color(cl): if not colors_lst['USE']: return '' return colors_lst.get(cl, '') class foo(object): def __getattr__(self, a): return get_color(a) def __call__(self, a): return get_color(a) colors = foo() re_log = re.compile(r'(\w+): (.*)', re.M) class log_filter(logging.Filter): def __init__(self, name=None): pass def filter(self, rec): rec.c1 = colors.PINK rec.c2 = colors.NORMAL rec.zone = rec.module if rec.levelno >= logging.INFO: if rec.levelno >= logging.ERROR: rec.c1 = colors.RED elif rec.levelno >= logging.WARNING: rec.c1 = colors.YELLOW else: rec.c1 = colors.GREEN return True zone = '' m = re_log.match(rec.msg) if m: zone = 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 formatter(logging.Formatter): def __init__(self): logging.Formatter.__init__(self, LOG_FORMAT, HOUR_FORMAT) def format(self, rec): if rec.levelno >= logging.WARNING or rec.levelno == logging.INFO: try: return '%s%s%s' % (rec.c1, rec.msg.decode('utf-8'), rec.c2) except: return rec.c1+rec.msg+rec.c2 return logging.Formatter.format(self, rec) def debug(*k, **kw): if verbose: k = list(k) k[0] = k[0].replace('\n', ' ') logging.debug(*k, **kw) def error(*k, **kw): logging.error(*k, **kw) if verbose > 1: if isinstance(k[0], Utils.WafError): st = k[0].stack else: st = traceback.extract_stack() if st: st = st[:-1] buf = [] for filename, lineno, name, line in st: buf.append(' File "%s", line %d, in %s' % (filename, lineno, name)) if line: buf.append(' %s' % line.strip()) if buf: logging.error("\n".join(buf)) warn = logging.warn info = logging.info def init_log(): log = logging.getLogger() log.handlers = [] log.filters = [] hdlr = logging.StreamHandler() hdlr.setFormatter(formatter()) log.addHandler(hdlr) log.addFilter(log_filter()) log.setLevel(logging.DEBUG) # may be initialized more than once init_log() tevent-0.9.34/third_party/waf/wafadmin/Node.py0000660000000000000000000004510712617125140021211 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) """ Node: filesystem structure, contains lists of nodes IMPORTANT: 1. Each file/folder is represented by exactly one node. 2. Most would-be class properties are stored in Build: nodes to depend on, signature, flags, .. unused class members increase the .wafpickle file size sensibly with lots of objects. 3. The build is launched from the top of the build dir (for example, in _build_/). 4. Node should not be instantiated directly. Each instance of Build.BuildContext has a Node subclass. (aka: 'Nodu', see BuildContext initializer) The BuildContext is referenced here as self.__class__.bld Its Node class is referenced here as self.__class__ The public and advertised apis are the following: ${TGT} -> dir/to/file.ext ${TGT[0].base()} -> dir/to/file ${TGT[0].dir(env)} -> dir/to ${TGT[0].file()} -> file.ext ${TGT[0].file_base()} -> file ${TGT[0].suffix()} -> .ext ${TGT[0].abspath(env)} -> /path/to/dir/to/file.ext """ import os, sys, fnmatch, re, stat import Utils, Constants UNDEFINED = 0 DIR = 1 FILE = 2 BUILD = 3 type_to_string = {UNDEFINED: "unk", DIR: "dir", FILE: "src", BUILD: "bld"} # These fnmatch expressions are used by default to prune the directory tree # while doing the recursive traversal in the find_iter method of the Node class. prune_pats = '.git .bzr .hg .svn _MTN _darcs CVS SCCS'.split() # These fnmatch expressions are used by default to exclude files and dirs # while doing the recursive traversal in the find_iter method of the Node class. exclude_pats = prune_pats + '*~ #*# .#* %*% ._* .gitignore .cvsignore vssver.scc .DS_Store'.split() # These Utils.jar_regexp expressions are used by default to exclude files and dirs and also prune the directory tree # while doing the recursive traversal in the ant_glob method of the Node class. exclude_regs = ''' **/*~ **/#*# **/.#* **/%*% **/._* **/CVS **/CVS/** **/.cvsignore **/SCCS **/SCCS/** **/vssver.scc **/.svn **/.svn/** **/.git **/.git/** **/.gitignore **/.bzr **/.bzr/** **/.hg **/.hg/** **/_MTN **/_MTN/** **/_darcs **/_darcs/** **/.DS_Store''' class Node(object): __slots__ = ("name", "parent", "id", "childs") def __init__(self, name, parent, node_type = UNDEFINED): self.name = name self.parent = parent # assumption: one build object at a time self.__class__.bld.id_nodes += 4 self.id = self.__class__.bld.id_nodes + node_type if node_type == DIR: self.childs = {} # We do not want to add another type attribute (memory) # use the id to find out: type = id & 3 # for setting: new type = type + x - type & 3 if parent and name in parent.childs: raise Utils.WafError('node %s exists in the parent files %r already' % (name, parent)) if parent: parent.childs[name] = self def __setstate__(self, data): if len(data) == 4: (self.parent, self.name, self.id, self.childs) = data else: (self.parent, self.name, self.id) = data def __getstate__(self): if getattr(self, 'childs', None) is None: return (self.parent, self.name, self.id) else: return (self.parent, self.name, self.id, self.childs) def __str__(self): if not self.parent: return '' return "%s://%s" % (type_to_string[self.id & 3], self.abspath()) def __repr__(self): return self.__str__() def __hash__(self): "expensive, make certain it is not used" raise Utils.WafError('nodes, you are doing it wrong') def __copy__(self): "nodes are not supposed to be copied" raise Utils.WafError('nodes are not supposed to be cloned') def get_type(self): return self.id & 3 def set_type(self, t): "dangerous, you are not supposed to use this" self.id = self.id + t - self.id & 3 def dirs(self): return [x for x in self.childs.values() if x.id & 3 == DIR] def files(self): return [x for x in self.childs.values() if x.id & 3 == FILE] def get_dir(self, name, default=None): node = self.childs.get(name, None) if not node or node.id & 3 != DIR: return default return node def get_file(self, name, default=None): node = self.childs.get(name, None) if not node or node.id & 3 != FILE: return default return node def get_build(self, name, default=None): node = self.childs.get(name, None) if not node or node.id & 3 != BUILD: return default return node def find_resource(self, lst): "Find an existing input file: either a build node declared previously or a source node" if isinstance(lst, str): lst = Utils.split_path(lst) if len(lst) == 1: parent = self else: parent = self.find_dir(lst[:-1]) if not parent: return None self.__class__.bld.rescan(parent) name = lst[-1] node = parent.childs.get(name, None) if node: tp = node.id & 3 if tp == FILE or tp == BUILD: return node else: return None tree = self.__class__.bld if not name in tree.cache_dir_contents[parent.id]: return None path = parent.abspath() + os.sep + name try: st = Utils.h_file(path) except IOError: return None child = self.__class__(name, parent, FILE) tree.node_sigs[0][child.id] = st return child def find_or_declare(self, lst): "Used for declaring a build node representing a file being built" if isinstance(lst, str): lst = Utils.split_path(lst) if len(lst) == 1: parent = self else: parent = self.find_dir(lst[:-1]) if not parent: return None self.__class__.bld.rescan(parent) name = lst[-1] node = parent.childs.get(name, None) if node: tp = node.id & 3 if tp != BUILD: raise Utils.WafError('find_or_declare found a source file where a build file was expected %r' % '/'.join(lst)) return node node = self.__class__(name, parent, BUILD) return node def find_dir(self, lst): "search a folder in the filesystem" if isinstance(lst, str): lst = Utils.split_path(lst) current = self for name in lst: self.__class__.bld.rescan(current) prev = current if not current.parent and name == current.name: continue elif not name: continue elif name == '.': continue elif name == '..': current = current.parent or current else: current = prev.childs.get(name, None) if current is None: dir_cont = self.__class__.bld.cache_dir_contents if prev.id in dir_cont and name in dir_cont[prev.id]: if not prev.name: if os.sep == '/': # cygwin //machine/share dirname = os.sep + name else: # windows c: dirname = name else: # regular path dirname = prev.abspath() + os.sep + name if not os.path.isdir(dirname): return None current = self.__class__(name, prev, DIR) elif (not prev.name and len(name) == 2 and name[1] == ':') or name.startswith('\\\\'): # drive letter or \\ path for windows current = self.__class__(name, prev, DIR) else: return None else: if current.id & 3 != DIR: return None return current def ensure_dir_node_from_path(self, lst): "used very rarely, force the construction of a branch of node instance for representing folders" if isinstance(lst, str): lst = Utils.split_path(lst) current = self for name in lst: if not name: continue elif name == '.': continue elif name == '..': current = current.parent or current else: prev = current current = prev.childs.get(name, None) if current is None: current = self.__class__(name, prev, DIR) return current def exclusive_build_node(self, path): """ create a hierarchy in the build dir (no source folders) for ill-behaving compilers the node is not hashed, so you must do it manually after declaring such a node, find_dir and find_resource should work as expected """ lst = Utils.split_path(path) name = lst[-1] if len(lst) > 1: parent = None try: parent = self.find_dir(lst[:-1]) except OSError: pass if not parent: parent = self.ensure_dir_node_from_path(lst[:-1]) self.__class__.bld.rescan(parent) else: try: self.__class__.bld.rescan(parent) except OSError: pass else: parent = self node = parent.childs.get(name, None) if not node: node = self.__class__(name, parent, BUILD) return node def path_to_parent(self, parent): "path relative to a direct ancestor, as string" lst = [] p = self h1 = parent.height() h2 = p.height() while h2 > h1: h2 -= 1 lst.append(p.name) p = p.parent if lst: lst.reverse() ret = os.path.join(*lst) else: ret = '' return ret def find_ancestor(self, node): "find a common ancestor for two nodes - for the shortest path in hierarchy" dist = self.height() - node.height() if dist < 0: return node.find_ancestor(self) # now the real code cand = self while dist > 0: cand = cand.parent dist -= 1 if cand == node: return cand cursor = node while cand.parent: cand = cand.parent cursor = cursor.parent if cand == cursor: return cand def relpath_gen(self, from_node): "string representing a relative path between self to another node" if self == from_node: return '.' if from_node.parent == self: return '..' # up_path is '../../../' and down_path is 'dir/subdir/subdir/file' ancestor = self.find_ancestor(from_node) lst = [] cand = self while not cand.id == ancestor.id: lst.append(cand.name) cand = cand.parent cand = from_node while not cand.id == ancestor.id: lst.append('..') cand = cand.parent lst.reverse() return os.sep.join(lst) def nice_path(self, env=None): "printed in the console, open files easily from the launch directory" tree = self.__class__.bld ln = tree.launch_node() if self.id & 3 == FILE: return self.relpath_gen(ln) else: return os.path.join(tree.bldnode.relpath_gen(ln), env.variant(), self.relpath_gen(tree.srcnode)) def is_child_of(self, node): "does this node belong to the subtree node" p = self diff = self.height() - node.height() while diff > 0: diff -= 1 p = p.parent return p.id == node.id def variant(self, env): "variant, or output directory for this node, a source has for variant 0" if not env: return 0 elif self.id & 3 == FILE: return 0 else: return env.variant() def height(self): "amount of parents" # README a cache can be added here if necessary d = self val = -1 while d: d = d.parent val += 1 return val # helpers for building things def abspath(self, env=None): """ absolute path @param env [Environment]: * obligatory for build nodes: build/variant/src/dir/bar.o * optional for dirs: get either src/dir or build/variant/src/dir * excluded for source nodes: src/dir/bar.c Instead of computing the absolute path each time again, store the already-computed absolute paths in one of (variants+1) dictionaries: bld.cache_node_abspath[0] holds absolute paths for source nodes. bld.cache_node_abspath[variant] holds the absolute path for the build nodes which reside in the variant given by env. """ ## absolute path - hot zone, so do not touch # less expensive variant = (env and (self.id & 3 != FILE) and env.variant()) or 0 ret = self.__class__.bld.cache_node_abspath[variant].get(self.id, None) if ret: return ret if not variant: # source directory if not self.parent: val = os.sep == '/' and os.sep or '' elif not self.parent.name: # root val = (os.sep == '/' and os.sep or '') + self.name else: val = self.parent.abspath() + os.sep + self.name else: # build directory val = os.sep.join((self.__class__.bld.bldnode.abspath(), variant, self.path_to_parent(self.__class__.bld.srcnode))) self.__class__.bld.cache_node_abspath[variant][self.id] = val return val def change_ext(self, ext): "node of the same path, but with a different extension - hot zone so do not touch" name = self.name k = name.rfind('.') if k >= 0: name = name[:k] + ext else: name = name + ext return self.parent.find_or_declare([name]) def src_dir(self, env): "src path without the file name" return self.parent.srcpath(env) def bld_dir(self, env): "build path without the file name" return self.parent.bldpath(env) def bld_base(self, env): "build path without the extension: src/dir/foo(.cpp)" s = os.path.splitext(self.name)[0] return os.path.join(self.bld_dir(env), s) def bldpath(self, env=None): "path seen from the build dir default/src/foo.cpp" if self.id & 3 == FILE: return self.relpath_gen(self.__class__.bld.bldnode) p = self.path_to_parent(self.__class__.bld.srcnode) if p is not '': return env.variant() + os.sep + p return env.variant() def srcpath(self, env=None): "path in the srcdir from the build dir ../src/foo.cpp" if self.id & 3 == BUILD: return self.bldpath(env) return self.relpath_gen(self.__class__.bld.bldnode) def read(self, env): "get the contents of a file, it is not used anywhere for the moment" return Utils.readf(self.abspath(env)) def dir(self, env): "scons-like" return self.parent.abspath(env) def file(self): "scons-like" return self.name def file_base(self): "scons-like" return os.path.splitext(self.name)[0] def suffix(self): "scons-like - hot zone so do not touch" k = max(0, self.name.rfind('.')) return self.name[k:] def find_iter_impl(self, src=True, bld=True, dir=True, accept_name=None, is_prune=None, maxdepth=25): """find nodes in the filesystem hierarchy, try to instanciate the nodes passively; same gotcha as ant_glob""" bld_ctx = self.__class__.bld bld_ctx.rescan(self) for name in bld_ctx.cache_dir_contents[self.id]: if accept_name(self, name): node = self.find_resource(name) if node: if src and node.id & 3 == FILE: yield node else: node = self.find_dir(name) if node and node.id != bld_ctx.bldnode.id: if dir: yield node if not is_prune(self, name): if maxdepth: for k in node.find_iter_impl(src, bld, dir, accept_name, is_prune, maxdepth=maxdepth - 1): yield k else: if not is_prune(self, name): node = self.find_resource(name) if not node: # not a file, it is a dir node = self.find_dir(name) if node and node.id != bld_ctx.bldnode.id: if maxdepth: for k in node.find_iter_impl(src, bld, dir, accept_name, is_prune, maxdepth=maxdepth - 1): yield k if bld: for node in self.childs.values(): if node.id == bld_ctx.bldnode.id: continue if node.id & 3 == BUILD: if accept_name(self, node.name): yield node raise StopIteration def find_iter(self, in_pat=['*'], ex_pat=exclude_pats, prune_pat=prune_pats, src=True, bld=True, dir=False, maxdepth=25, flat=False): """find nodes recursively, this returns everything but folders by default; same gotcha as ant_glob""" if not (src or bld or dir): raise StopIteration if self.id & 3 != DIR: raise StopIteration in_pat = Utils.to_list(in_pat) ex_pat = Utils.to_list(ex_pat) prune_pat = Utils.to_list(prune_pat) def accept_name(node, name): for pat in ex_pat: if fnmatch.fnmatchcase(name, pat): return False for pat in in_pat: if fnmatch.fnmatchcase(name, pat): return True return False def is_prune(node, name): for pat in prune_pat: if fnmatch.fnmatchcase(name, pat): return True return False ret = self.find_iter_impl(src, bld, dir, accept_name, is_prune, maxdepth=maxdepth) if flat: return " ".join([x.relpath_gen(self) for x in ret]) return ret def ant_glob(self, *k, **kw): """ known gotcha: will enumerate the files, but only if the folder exists in the source directory """ src=kw.get('src', 1) bld=kw.get('bld', 0) dir=kw.get('dir', 0) excl = kw.get('excl', exclude_regs) incl = k and k[0] or kw.get('incl', '**') def to_pat(s): lst = Utils.to_list(s) ret = [] for x in lst: x = x.replace('//', '/') if x.endswith('/'): x += '**' lst2 = x.split('/') accu = [] for k in lst2: if k == '**': accu.append(k) else: k = k.replace('.', '[.]').replace('*', '.*').replace('?', '.') k = '^%s$' % k #print "pattern", k accu.append(re.compile(k)) ret.append(accu) return ret def filtre(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 accept(name, pats): nacc = filtre(name, pats[0]) nrej = filtre(name, pats[1]) if [] in nrej: nacc = [] return [nacc, nrej] def ant_iter(nodi, maxdepth=25, pats=[]): nodi.__class__.bld.rescan(nodi) tmp = list(nodi.__class__.bld.cache_dir_contents[nodi.id]) tmp.sort() for name in tmp: npats = accept(name, pats) if npats and npats[0]: accepted = [] in npats[0] #print accepted, nodi, name node = nodi.find_resource(name) if node and accepted: if src and node.id & 3 == FILE: yield node else: node = nodi.find_dir(name) if node and node.id != nodi.__class__.bld.bldnode.id: if accepted and dir: yield node if maxdepth: for k in ant_iter(node, maxdepth=maxdepth - 1, pats=npats): yield k if bld: for node in nodi.childs.values(): if node.id == nodi.__class__.bld.bldnode.id: continue if node.id & 3 == BUILD: npats = accept(node.name, pats) if npats and npats[0] and [] in npats[0]: yield node raise StopIteration ret = [x for x in ant_iter(self, pats=[to_pat(incl), to_pat(excl)])] if kw.get('flat', True): return " ".join([x.relpath_gen(self) for x in ret]) return ret def update_build_dir(self, env=None): if not env: for env in self.bld.all_envs: self.update_build_dir(env) return path = self.abspath(env) lst = Utils.listdir(path) try: self.__class__.bld.cache_dir_contents[self.id].update(lst) except KeyError: self.__class__.bld.cache_dir_contents[self.id] = set(lst) self.__class__.bld.cache_scanned_folders[self.id] = True for k in lst: npath = path + os.sep + k st = os.stat(npath) if stat.S_ISREG(st[stat.ST_MODE]): ick = self.find_or_declare(k) if not (ick.id in self.__class__.bld.node_sigs[env.variant()]): self.__class__.bld.node_sigs[env.variant()][ick.id] = Constants.SIG_NIL elif stat.S_ISDIR(st[stat.ST_MODE]): child = self.find_dir(k) if not child: child = self.ensure_dir_node_from_path(k) child.update_build_dir(env) def read(self, flags='r', encoding='ISO8859-1'): """backported from waf 1.8""" return Utils.readf(self.abspath(), flags, encoding) def write(self, data, flags='w', encoding='ISO8859-1'): """backported from waf 1.8""" Utils.writef(self.abspath(self.bld.env), data, flags, encoding) class Nodu(Node): pass tevent-0.9.34/third_party/waf/wafadmin/Options.py0000660000000000000000000001721212520121120021736 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Scott Newton, 2005 (scottn) # Thomas Nagy, 2006 (ita) "Custom command-line options" import os, sys, imp, types, tempfile, optparse import Logs, Utils from Constants import * cmds = 'distclean configure build install clean uninstall check dist distcheck'.split() # TODO remove in waf 1.6 the following two commands = {} is_install = False options = {} arg_line = [] launch_dir = '' tooldir = '' lockfile = os.environ.get('WAFLOCK', '.lock-wscript') try: cache_global = os.path.abspath(os.environ['WAFCACHE']) except KeyError: cache_global = '' platform = Utils.unversioned_sys_platform() conf_file = 'conf-runs-%s-%d.pickle' % (platform, ABI) remote_repo = ['http://waf.googlecode.com/svn/'] """remote directory for the plugins""" # Such a command-line should work: JOBS=4 PREFIX=/opt/ DESTDIR=/tmp/ahoj/ waf configure default_prefix = os.environ.get('PREFIX') if not default_prefix: if 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/' default_jobs = os.environ.get('JOBS', -1) if default_jobs < 1: try: if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: default_jobs = os.sysconf('SC_NPROCESSORS_ONLN') else: default_jobs = int(Utils.cmd_output(['sysctl', '-n', 'hw.ncpu'])) except: if os.name == 'java': # platform.system() == 'Java' from java.lang import Runtime default_jobs = Runtime.getRuntime().availableProcessors() else: # environment var defined on win32 default_jobs = int(os.environ.get('NUMBER_OF_PROCESSORS', 1)) default_destdir = os.environ.get('DESTDIR', '') def get_usage(self): cmds_str = [] module = Utils.g_module if module: # create the help messages for commands tbl = module.__dict__ keys = list(tbl.keys()) keys.sort() if 'build' in tbl: if not module.build.__doc__: module.build.__doc__ = 'builds the project' if 'configure' in tbl: if not module.configure.__doc__: module.configure.__doc__ = 'configures the project' ban = ['set_options', 'init', 'shutdown'] optlst = [x for x in keys if not x in ban and type(tbl[x]) is type(parse_args_impl) and tbl[x].__doc__ and not x.startswith('_')] just = max([len(x) for x in optlst]) for x in optlst: cmds_str.append(' %s: %s' % (x.ljust(just), tbl[x].__doc__)) ret = '\n'.join(cmds_str) else: ret = ' '.join(cmds) return '''waf [command] [options] Main commands (example: ./waf build -j4) %s ''' % ret setattr(optparse.OptionParser, 'get_usage', get_usage) def create_parser(module=None): Logs.debug('options: create_parser is called') parser = optparse.OptionParser(conflict_handler="resolve", version = 'waf %s (%s)' % (WAFVERSION, WAFREVISION)) parser.formatter.width = Utils.get_term_cols() p = parser.add_option p('-j', '--jobs', type = 'int', default = default_jobs, help = 'amount of parallel jobs (%r)' % default_jobs, dest = 'jobs') p('-k', '--keep', action = 'store_true', default = False, help = 'keep running happily on independent task groups', dest = 'keep') p('-v', '--verbose', action = 'count', default = 0, help = 'verbosity level -v -vv or -vvv [default: 0]', dest = 'verbose') p('--nocache', action = 'store_true', default = False, help = 'ignore the WAFCACHE (if set)', dest = 'nocache') p('--zones', action = 'store', default = '', help = 'debugging zones (task_gen, deps, tasks, etc)', dest = 'zones') p('-p', '--progress', action = 'count', default = 0, help = '-p: progress bar; -pp: ide output', dest = 'progress_bar') p('--targets', action = 'store', default = '', help = 'build given task generators, e.g. "target1,target2"', dest = 'compile_targets') gr = optparse.OptionGroup(parser, 'configuration options') parser.add_option_group(gr) gr.add_option('-b', '--blddir', action = 'store', default = '', help = 'out dir for the project (configuration)', dest = 'blddir') gr.add_option('-s', '--srcdir', action = 'store', default = '', help = 'top dir for the project (configuration)', dest = 'srcdir') gr.add_option('--prefix', help = 'installation prefix (configuration) [default: %r]' % default_prefix, default = default_prefix, dest = 'prefix') gr.add_option('--download', action = 'store_true', default = False, help = 'try to download the tools if missing', dest = 'download') gr = optparse.OptionGroup(parser, 'installation options') parser.add_option_group(gr) gr.add_option('--destdir', help = 'installation root [default: %r]' % default_destdir, default = default_destdir, dest = 'destdir') gr.add_option('-f', '--force', action = 'store_true', default = False, help = 'force file installation', dest = 'force') return parser def parse_args_impl(parser, _args=None): global options, commands, arg_line (options, args) = parser.parse_args(args=_args) arg_line = args #arg_line = args[:] # copy # By default, 'waf' is equivalent to 'waf build' commands = {} for var in cmds: commands[var] = 0 if not args: commands['build'] = 1 args.append('build') # Parse the command arguments for arg in args: commands[arg] = True # the check thing depends on the build if 'check' in args: idx = args.index('check') try: bidx = args.index('build') if bidx > idx: raise ValueError('build before check') except ValueError, e: args.insert(idx, 'build') if args[0] != 'init': args.insert(0, 'init') # TODO -k => -j0 if options.keep: options.jobs = 1 if options.jobs < 1: options.jobs = 1 if 'install' in sys.argv or 'uninstall' in sys.argv: # absolute path only if set options.destdir = options.destdir and os.path.abspath(os.path.expanduser(options.destdir)) Logs.verbose = options.verbose Logs.init_log() 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 = ['*'] # TODO waf 1.6 # 1. rename the class to OptionsContext # 2. instead of a class attribute, use a module (static 'parser') # 3. parse_args_impl was made in times when we did not know about binding new methods to classes class Handler(Utils.Context): """loads wscript modules in folders for adding options This class should be named 'OptionsContext' A method named 'recurse' is bound when used by the module Scripting""" parser = None # make it possible to access the reference, like Build.bld def __init__(self, module=None): self.parser = create_parser(module) self.cwd = os.getcwd() Handler.parser = self def add_option(self, *k, **kw): self.parser.add_option(*k, **kw) def add_option_group(self, *k, **kw): return self.parser.add_option_group(*k, **kw) def get_option_group(self, opt_str): return self.parser.get_option_group(opt_str) def sub_options(self, *k, **kw): if not k: raise Utils.WscriptError('folder expected') self.recurse(k[0], name='set_options') def tool_options(self, *k, **kw): Utils.python_24_guard() if not k[0]: raise Utils.WscriptError('invalid tool_options call %r %r' % (k, kw)) tools = Utils.to_list(k[0]) # TODO waf 1.6 remove the global variable tooldir path = Utils.to_list(kw.get('tdir', kw.get('tooldir', tooldir))) for tool in tools: tool = tool.replace('++', 'xx') if tool == 'java': tool = 'javaw' if tool.lower() == 'unittest': tool = 'unittestw' module = Utils.load_tool(tool, path) try: fun = module.set_options except AttributeError: pass else: fun(kw.get('option_group', self)) def parse_args(self, args=None): parse_args_impl(self.parser, args) tevent-0.9.34/third_party/waf/wafadmin/Runner.py0000660000000000000000000001266312520121120021561 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2008 (ita) "Execute the tasks" import os, sys, random, time, threading, traceback try: from Queue import Queue except ImportError: from queue import Queue import Build, Utils, Logs, Options from Logs import debug, error from Constants import * GAP = 15 run_old = threading.Thread.run def run(*args, **kwargs): try: run_old(*args, **kwargs) except (KeyboardInterrupt, SystemExit): raise except: sys.excepthook(*sys.exc_info()) threading.Thread.run = run def process_task(tsk): m = tsk.master if m.stop: m.out.put(tsk) return try: tsk.generator.bld.printout(tsk.display()) if tsk.__class__.stat: ret = tsk.__class__.stat(tsk) # actual call to task's run() function else: ret = tsk.call_run() except Exception, e: tsk.err_msg = Utils.ex_stack() tsk.hasrun = EXCEPTION # TODO cleanup m.error_handler(tsk) m.out.put(tsk) return if ret: tsk.err_code = ret tsk.hasrun = CRASHED else: try: tsk.post_run() except Utils.WafError: pass except Exception: tsk.err_msg = Utils.ex_stack() tsk.hasrun = EXCEPTION else: tsk.hasrun = SUCCESS if tsk.hasrun != SUCCESS: m.error_handler(tsk) m.out.put(tsk) class TaskConsumer(threading.Thread): ready = Queue(0) consumers = [] def __init__(self): threading.Thread.__init__(self) self.setDaemon(1) self.start() def run(self): try: self.loop() except: pass def loop(self): while 1: tsk = TaskConsumer.ready.get() process_task(tsk) class Parallel(object): """ keep the consumer threads busy, and avoid consuming cpu cycles when no more tasks can be added (end of the build, etc) """ def __init__(self, bld, j=2): # number of consumers self.numjobs = j self.manager = bld.task_manager self.manager.current_group = 0 self.total = self.manager.total() # tasks waiting to be processed - IMPORTANT self.outstanding = [] self.maxjobs = MAXJOBS # tasks that are awaiting for another task to complete self.frozen = [] # tasks returned by the consumers self.out = Queue(0) self.count = 0 # tasks not in the producer area self.processed = 1 # progress indicator self.stop = False # error condition to stop the build self.error = False # error flag def get_next(self): "override this method to schedule the tasks in a particular order" if not self.outstanding: return None return self.outstanding.pop(0) def postpone(self, tsk): "override this method to schedule the tasks in a particular order" # TODO consider using a deque instead if random.randint(0, 1): self.frozen.insert(0, tsk) else: self.frozen.append(tsk) def refill_task_list(self): "called to set the next group of tasks" while self.count > self.numjobs + GAP or self.count >= self.maxjobs: self.get_out() while not self.outstanding: if self.count: self.get_out() if self.frozen: self.outstanding += self.frozen self.frozen = [] elif not self.count: (jobs, tmp) = self.manager.get_next_set() if jobs != None: self.maxjobs = jobs if tmp: self.outstanding += tmp break def get_out(self): "the tasks that are put to execute are all collected using get_out" ret = self.out.get() self.manager.add_finished(ret) if not self.stop and getattr(ret, 'more_tasks', None): self.outstanding += ret.more_tasks self.total += len(ret.more_tasks) self.count -= 1 def error_handler(self, tsk): "by default, errors make the build stop (not thread safe so be careful)" if not Options.options.keep: self.stop = True self.error = True def start(self): "execute the tasks" if TaskConsumer.consumers: # the worker pool is usually loaded lazily (see below) # in case it is re-used with a different value of numjobs: while len(TaskConsumer.consumers) < self.numjobs: TaskConsumer.consumers.append(TaskConsumer()) while not self.stop: self.refill_task_list() # consider the next task tsk = self.get_next() 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 self.manager.add_finished(tsk) continue try: st = tsk.runnable_status() except Exception, e: self.processed += 1 if self.stop and not Options.options.keep: tsk.hasrun = SKIPPED self.manager.add_finished(tsk) continue self.error_handler(tsk) self.manager.add_finished(tsk) tsk.hasrun = EXCEPTION tsk.err_msg = Utils.ex_stack() continue if st == ASK_LATER: self.postpone(tsk) elif st == SKIP_ME: self.processed += 1 tsk.hasrun = SKIPPED self.manager.add_finished(tsk) else: # run me: put the task in ready queue tsk.position = (self.processed, self.total) self.count += 1 tsk.master = self self.processed += 1 if self.numjobs == 1: process_task(tsk) else: TaskConsumer.ready.put(tsk) # create the consumer threads only if there is something to consume if not TaskConsumer.consumers: TaskConsumer.consumers = [TaskConsumer() for i in xrange(self.numjobs)] # 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() #print loop assert (self.count == 0 or self.stop) tevent-0.9.34/third_party/waf/wafadmin/Scripting.py0000660000000000000000000003570212520121120022251 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) "Module called for configuring, compiling and installing targets" import os, sys, shutil, traceback, datetime, inspect, errno import Utils, Configure, Build, Logs, Options, Environment, Task from Logs import error, warn, info from Constants import * g_gz = 'bz2' commands = [] def prepare_impl(t, cwd, ver, wafdir): Options.tooldir = [t] Options.launch_dir = cwd # some command-line options can be processed immediately if '--version' in sys.argv: opt_obj = Options.Handler() opt_obj.curdir = cwd opt_obj.parse_args() sys.exit(0) # now find the wscript file msg1 = 'Waf: Please run waf from a directory containing a file named "%s" or run distclean' % WSCRIPT_FILE # in theory projects can be configured in an autotool-like manner: # mkdir build && cd build && ../waf configure && ../waf build_dir_override = None candidate = None lst = os.listdir(cwd) search_for_candidate = True if WSCRIPT_FILE in lst: candidate = cwd elif 'configure' in sys.argv and not WSCRIPT_BUILD_FILE in lst: # autotool-like configuration calldir = os.path.abspath(os.path.dirname(sys.argv[0])) if WSCRIPT_FILE in os.listdir(calldir): candidate = calldir search_for_candidate = False else: error('arg[0] directory does not contain a wscript file') sys.exit(1) build_dir_override = cwd # climb up to find a script if it is not found while search_for_candidate: if len(cwd) <= 3: break # stop at / or c: dirlst = os.listdir(cwd) if WSCRIPT_FILE in dirlst: candidate = cwd if 'configure' in sys.argv and candidate: break if Options.lockfile in dirlst: env = Environment.Environment() try: env.load(os.path.join(cwd, Options.lockfile)) except: error('could not load %r' % Options.lockfile) try: os.stat(env['cwd']) except: candidate = cwd else: candidate = env['cwd'] break cwd = os.path.dirname(cwd) # climb up if not candidate: # check if the user only wanted to display the help if '-h' in sys.argv or '--help' in sys.argv: warn('No wscript file found: the help message may be incomplete') opt_obj = Options.Handler() opt_obj.curdir = cwd opt_obj.parse_args() else: error(msg1) sys.exit(0) # We have found wscript, but there is no guarantee that it is valid try: os.chdir(candidate) except OSError: raise Utils.WafError("the folder %r is unreadable" % candidate) # define the main module containing the functions init, shutdown, .. Utils.set_main_module(os.path.join(candidate, WSCRIPT_FILE)) if build_dir_override: d = getattr(Utils.g_module, BLDDIR, None) if d: # test if user has set the blddir in wscript. msg = ' Overriding build directory %s with %s' % (d, build_dir_override) warn(msg) Utils.g_module.blddir = build_dir_override # bind a few methods and classes by default def set_def(obj, name=''): n = name or obj.__name__ if not n in Utils.g_module.__dict__: setattr(Utils.g_module, n, obj) for k in [dist, distclean, distcheck, clean, install, uninstall]: set_def(k) set_def(Configure.ConfigurationContext, 'configure_context') for k in ['build', 'clean', 'install', 'uninstall']: set_def(Build.BuildContext, k + '_context') # now parse the options from the user wscript file opt_obj = Options.Handler(Utils.g_module) opt_obj.curdir = candidate try: f = Utils.g_module.set_options except AttributeError: pass else: opt_obj.sub_options(['']) opt_obj.parse_args() if not 'init' in Utils.g_module.__dict__: Utils.g_module.init = Utils.nada if not 'shutdown' in Utils.g_module.__dict__: Utils.g_module.shutdown = Utils.nada main() def prepare(t, cwd, ver, wafdir): if WAFVERSION != ver: msg = 'Version mismatch: waf %s <> wafadmin %s (wafdir %s)' % (ver, WAFVERSION, wafdir) print('\033[91mError: %s\033[0m' % msg) sys.exit(1) #""" try: prepare_impl(t, cwd, ver, wafdir) except Utils.WafError, e: error(str(e)) sys.exit(1) except KeyboardInterrupt: Utils.pprint('RED', 'Interrupted') sys.exit(68) """ import cProfile, pstats cProfile.runctx("import Scripting; Scripting.prepare_impl(t, cwd, ver, wafdir)", {}, {'t': t, 'cwd':cwd, 'ver':ver, 'wafdir':wafdir}, 'profi.txt') p = pstats.Stats('profi.txt') p.sort_stats('time').print_stats(45) #""" def main(): global commands commands = Options.arg_line[:] while commands: x = commands.pop(0) ini = datetime.datetime.now() if x == 'configure': fun = configure elif x == 'build': fun = build else: fun = getattr(Utils.g_module, x, None) if not fun: raise Utils.WscriptError('No such command %r' % x) ctx = getattr(Utils.g_module, x + '_context', Utils.Context)() if x in ['init', 'shutdown', 'dist', 'distclean', 'distcheck']: # compatibility TODO remove in waf 1.6 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': info('%r finished successfully%s' % (x, ela)) if not commands and x != 'shutdown': commands.append('shutdown') def configure(conf): src = getattr(Options.options, SRCDIR, None) if not src: src = getattr(Utils.g_module, SRCDIR, None) if not src: src = getattr(Utils.g_module, 'top', None) if not src: src = '.' incomplete_src = 1 src = os.path.abspath(src) bld = getattr(Options.options, BLDDIR, None) if not bld: bld = getattr(Utils.g_module, BLDDIR, None) if not bld: bld = getattr(Utils.g_module, 'out', None) if not bld: bld = 'build' incomplete_bld = 1 if bld == '.': raise Utils.WafError('Setting blddir="." may cause distclean problems') bld = os.path.abspath(bld) try: os.makedirs(bld) except OSError: pass # It is not possible to compile specific targets in the configuration # this may cause configuration errors if autoconfig is set targets = Options.options.compile_targets Options.options.compile_targets = None Options.is_install = False conf.srcdir = src conf.blddir = bld conf.post_init() if 'incomplete_src' in vars(): conf.check_message_1('Setting srcdir to') conf.check_message_2(src) if 'incomplete_bld' in vars(): conf.check_message_1('Setting blddir to') conf.check_message_2(bld) # calling to main wscript's configure() conf.sub_config(['']) conf.store() # 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 = Environment.Environment() env[BLDDIR] = bld env[SRCDIR] = src env['argv'] = sys.argv env['commands'] = Options.commands env['options'] = Options.options.__dict__ # conf.hash & conf.files hold wscript files paths and hash # (used only by Configure.autoconfig) env['hash'] = conf.hash env['files'] = conf.files env['environ'] = dict(conf.environ) env['cwd'] = os.path.split(Utils.g_module.root_path)[0] if Utils.g_module.root_path != src: # in case the source dir is somewhere else env.store(os.path.join(src, Options.lockfile)) env.store(Options.lockfile) Options.options.compile_targets = targets def clean(bld): '''removes the build files''' try: proj = Environment.Environment(Options.lockfile) except IOError: raise Utils.WafError('Nothing to clean (project not configured)') bld.load_dirs(proj[SRCDIR], proj[BLDDIR]) bld.load_envs() bld.is_install = 0 # False # read the scripts - and set the path to the wscript path (useful for srcdir='/foo/bar') bld.add_subdirs([os.path.split(Utils.g_module.root_path)[0]]) try: bld.clean() finally: bld.save() def check_configured(bld): if not Configure.autoconfig: return bld conf_cls = getattr(Utils.g_module, 'configure_context', Utils.Context) bld_cls = getattr(Utils.g_module, 'build_context', Utils.Context) def reconf(proj): back = (Options.commands, Options.options.__dict__, Logs.zones, Logs.verbose) Options.commands = proj['commands'] Options.options.__dict__ = proj['options'] conf = conf_cls() conf.environ = proj['environ'] configure(conf) (Options.commands, Options.options.__dict__, Logs.zones, Logs.verbose) = back try: proj = Environment.Environment(Options.lockfile) except IOError: conf = conf_cls() configure(conf) else: try: bld = bld_cls() bld.load_dirs(proj[SRCDIR], proj[BLDDIR]) bld.load_envs() except Utils.WafError: reconf(proj) return bld_cls() try: proj = Environment.Environment(Options.lockfile) except IOError: raise Utils.WafError('Auto-config: project does not configure (bug)') h = 0 try: for file in proj['files']: if file.endswith('configure'): h = hash((h, Utils.readf(file))) else: mod = Utils.load_module(file) h = hash((h, mod.waf_hash_val)) except (OSError, IOError): warn('Reconfiguring the project: a file is unavailable') reconf(proj) else: if (h != proj['hash']): warn('Reconfiguring the project: the configuration has changed') reconf(proj) return bld_cls() def install(bld): '''installs the build files''' bld = check_configured(bld) Options.commands['install'] = True Options.commands['uninstall'] = False Options.is_install = True bld.is_install = INSTALL build_impl(bld) bld.install() def uninstall(bld): '''removes the installed files''' Options.commands['install'] = False Options.commands['uninstall'] = True Options.is_install = True bld.is_install = UNINSTALL try: def runnable_status(self): return SKIP_ME setattr(Task.Task, 'runnable_status_back', Task.Task.runnable_status) setattr(Task.Task, 'runnable_status', runnable_status) build_impl(bld) bld.install() finally: setattr(Task.Task, 'runnable_status', Task.Task.runnable_status_back) def build(bld): bld = check_configured(bld) Options.commands['install'] = False Options.commands['uninstall'] = False Options.is_install = False bld.is_install = 0 # False return build_impl(bld) def build_impl(bld): # compile the project and/or install the files try: proj = Environment.Environment(Options.lockfile) except IOError: raise Utils.WafError("Project not configured (run 'waf configure' first)") bld.load_dirs(proj[SRCDIR], proj[BLDDIR]) bld.load_envs() info("Waf: Entering directory `%s'" % bld.bldnode.abspath()) bld.add_subdirs([os.path.split(Utils.g_module.root_path)[0]]) # execute something immediately before the build starts bld.pre_build() try: bld.compile() finally: if Options.options.progress_bar: print('') info("Waf: Leaving directory `%s'" % bld.bldnode.abspath()) # execute something immediately after a successful build bld.post_build() bld.install() excludes = '.bzr .bzrignore .git .gitignore .svn CVS .cvsignore .arch-ids {arch} SCCS BitKeeper .hg _MTN _darcs Makefile Makefile.in config.log .gitattributes .hgignore .hgtags'.split() dist_exts = '~ .rej .orig .pyc .pyo .bak .tar.bz2 tar.gz .zip .swp'.split() def dont_dist(name, src, build_dir): global excludes, dist_exts if (name.startswith(',,') or name.startswith('++') or name.startswith('.waf') or (src == '.' and name == Options.lockfile) or name in excludes or name == build_dir ): return True for ext in dist_exts: if name.endswith(ext): return True return False # like shutil.copytree # exclude files and to raise exceptions immediately def copytree(src, dst, build_dir): names = os.listdir(src) os.makedirs(dst) for name in names: srcname = os.path.join(src, name) dstname = os.path.join(dst, name) if dont_dist(name, src, build_dir): continue if os.path.isdir(srcname): copytree(srcname, dstname, build_dir) else: shutil.copy2(srcname, dstname) # TODO in waf 1.6, change this method if "srcdir == blddir" is allowed def distclean(ctx=None): '''removes the build directory''' global commands lst = os.listdir('.') for f in lst: if f == Options.lockfile: try: proj = Environment.Environment(f) except: Logs.warn('could not read %r' % f) continue try: shutil.rmtree(proj[BLDDIR]) except IOError: pass except OSError, e: if e.errno != errno.ENOENT: Logs.warn('project %r cannot be removed' % proj[BLDDIR]) try: os.remove(f) except OSError, e: if e.errno != errno.ENOENT: Logs.warn('file %r cannot be removed' % f) # remove the local waf cache if not commands and f.startswith('.waf'): shutil.rmtree(f, ignore_errors=True) # FIXME waf 1.6 a unique ctx parameter, and remove the optional appname and version def dist(appname='', version=''): '''makes a tarball for redistributing the sources''' # return return (distdirname, tarballname) import tarfile if not appname: appname = Utils.g_module.APPNAME if not version: version = Utils.g_module.VERSION tmp_folder = appname + '-' + version if g_gz in ['gz', 'bz2']: arch_name = tmp_folder + '.tar.' + g_gz else: arch_name = tmp_folder + '.' + 'zip' # remove the previous dir try: shutil.rmtree(tmp_folder) except (OSError, IOError): pass # remove the previous archive try: os.remove(arch_name) except (OSError, IOError): pass # copy the files into the temporary folder blddir = getattr(Utils.g_module, BLDDIR, None) if not blddir: blddir = getattr(Utils.g_module, 'out', None) copytree('.', tmp_folder, blddir) # undocumented hook for additional cleanup dist_hook = getattr(Utils.g_module, 'dist_hook', None) if dist_hook: back = os.getcwd() os.chdir(tmp_folder) try: dist_hook() finally: # go back to the root directory os.chdir(back) if g_gz in ['gz', 'bz2']: tar = tarfile.open(arch_name, 'w:' + g_gz) tar.add(tmp_folder) tar.close() else: Utils.zip_folder(tmp_folder, arch_name, tmp_folder) try: from hashlib import sha1 as sha except ImportError: from sha import sha try: digest = " (sha=%r)" % sha(Utils.readf(arch_name)).hexdigest() except: digest = '' info('New archive created: %s%s' % (arch_name, digest)) if os.path.exists(tmp_folder): shutil.rmtree(tmp_folder) return arch_name # FIXME waf 1.6 a unique ctx parameter, and remove the optional appname and version def distcheck(appname='', version='', subdir=''): '''checks if the sources compile (tarball from 'dist')''' import tempfile, tarfile if not appname: appname = Utils.g_module.APPNAME if not version: version = Utils.g_module.VERSION waf = os.path.abspath(sys.argv[0]) tarball = dist(appname, version) path = appname + '-' + version # remove any previous instance if os.path.exists(path): shutil.rmtree(path) t = tarfile.open(tarball) for x in t: t.extract(x) t.close() # build_path is the directory for the waf invocation if subdir: build_path = os.path.join(path, subdir) else: build_path = path instdir = tempfile.mkdtemp('.inst', '%s-%s' % (appname, version)) ret = Utils.pproc.Popen([waf, 'configure', 'build', 'install', 'uninstall', '--destdir=' + instdir], cwd=build_path).wait() if ret: raise Utils.WafError('distcheck failed with code %i' % ret) if os.path.exists(instdir): raise Utils.WafError('distcheck succeeded, but files were left in %s' % instdir) shutil.rmtree(path) # FIXME remove in Waf 1.6 (kept for compatibility) def add_subdir(dir, bld): bld.recurse(dir, 'build') tevent-0.9.34/third_party/waf/wafadmin/Task.py0000660000000000000000000010300712520121120021203 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2008 (ita) """ Running tasks in parallel is a simple problem, but in practice it is more complicated: * dependencies discovered during the build (dynamic task creation) * dependencies discovered after files are compiled * the amount of tasks and dependencies (graph size) can be huge This is why the dependency management is split on three different levels: 1. groups of tasks that run all after another group of tasks 2. groups of tasks that can be run in parallel 3. tasks that can run in parallel, but with possible unknown ad-hoc dependencies The point #1 represents a strict sequential order between groups of tasks, for example a compiler is produced and used to compile the rest, whereas #2 and #3 represent partial order constraints where #2 applies to the kind of task and #3 applies to the task instances. #1 is held by the task manager: ordered list of TaskGroups (see bld.add_group) #2 is held by the task groups and the task types: precedence after/before (topological sort), and the constraints extracted from file extensions #3 is held by the tasks individually (attribute run_after), and the scheduler (Runner.py) use Task::runnable_status to reorder the tasks -- To try, use something like this in your code: import Constants, Task Task.algotype = Constants.MAXPARALLEL -- There are two concepts with the tasks (individual units of change): * dependency (if 1 is recompiled, recompile 2) * order (run 2 after 1) example 1: if t1 depends on t2 and t2 depends on t3 it is not necessary to make t1 depend on t3 (dependency is transitive) example 2: if t1 depends on a node produced by t2, it is not immediately obvious that t1 must run after t2 (order is not obvious) The role of the Task Manager is to give the tasks in order (groups of task that may be run in parallel one after the other) """ import os, shutil, sys, re, random, datetime, tempfile, shlex from Utils import md5 import Build, Runner, Utils, Node, Logs, Options from Logs import debug, warn, error from Constants import * algotype = NORMAL #algotype = JOBCONTROL #algotype = MAXPARALLEL COMPILE_TEMPLATE_SHELL = ''' def f(task): env = task.env wd = getattr(task, 'cwd', None) p = env.get_flat cmd = \'\'\' %s \'\'\' % s return task.exec_command(cmd, cwd=wd) ''' COMPILE_TEMPLATE_NOSHELL = ''' def f(task): env = task.env wd = getattr(task, 'cwd', None) def to_list(xx): if isinstance(xx, str): return [xx] return xx lst = [] %s lst = [x for x in lst if x] return task.exec_command(lst, cwd=wd) ''' """ Enable different kind of dependency algorithms: 1 make groups: first compile all cpps and then compile all links (NORMAL) 2 parallelize all (each link task run after its dependencies) (MAXPARALLEL) 3 like 1 but provide additional constraints for the parallelization (MAXJOBS) In theory 1. will be faster than 2 for waf, but might be slower for builds The scheme 2 will not allow for running tasks one by one so it can cause disk thrashing on huge builds """ file_deps = Utils.nada """ Additional dependency pre-check may be added by replacing the function file_deps. e.g. extract_outputs, extract_deps below. """ class TaskManager(object): """The manager is attached to the build object, it holds a list of TaskGroup""" def __init__(self): self.groups = [] self.tasks_done = [] self.current_group = 0 self.groups_names = {} def group_name(self, g): """name for the group g (utility)""" if not isinstance(g, TaskGroup): g = self.groups[g] for x in self.groups_names: if id(self.groups_names[x]) == id(g): return x return '' def group_idx(self, tg): """group the task generator tg is in""" se = id(tg) for i in range(len(self.groups)): g = self.groups[i] for t in g.tasks_gen: if id(t) == se: return i return None def get_next_set(self): """return the next set of tasks to execute the first parameter is the maximum amount of parallelization that may occur""" ret = None while not ret and self.current_group < len(self.groups): ret = self.groups[self.current_group].get_next_set() if ret: return ret else: self.groups[self.current_group].process_install() self.current_group += 1 return (None, None) def add_group(self, name=None, set=True): #if self.groups and not self.groups[0].tasks: # error('add_group: an empty group is already present') g = TaskGroup() if name and name in self.groups_names: error('add_group: name %s already present' % name) self.groups_names[name] = g self.groups.append(g) if set: self.current_group = len(self.groups) - 1 def set_group(self, idx): if isinstance(idx, str): g = self.groups_names[idx] for x in xrange(len(self.groups)): if id(g) == id(self.groups[x]): self.current_group = x else: self.current_group = idx def add_task_gen(self, tgen): if not self.groups: self.add_group() self.groups[self.current_group].tasks_gen.append(tgen) def add_task(self, task): if not self.groups: self.add_group() self.groups[self.current_group].tasks.append(task) def total(self): total = 0 if not self.groups: return 0 for group in self.groups: total += len(group.tasks) return total def add_finished(self, tsk): self.tasks_done.append(tsk) bld = tsk.generator.bld if bld.is_install: f = None if 'install' in tsk.__dict__: f = tsk.__dict__['install'] # install=0 to prevent installation if f: f(tsk) else: tsk.install() class TaskGroup(object): "the compilation of one group does not begin until the previous group has finished (in the manager)" def __init__(self): self.tasks = [] # this list will be consumed self.tasks_gen = [] self.cstr_groups = Utils.DefaultDict(list) # tasks having equivalent constraints self.cstr_order = Utils.DefaultDict(set) # partial order between the cstr groups self.temp_tasks = [] # tasks put on hold self.ready = 0 self.post_funs = [] def reset(self): "clears the state of the object (put back the tasks into self.tasks)" for x in self.cstr_groups: self.tasks += self.cstr_groups[x] self.tasks = self.temp_tasks + self.tasks self.temp_tasks = [] self.cstr_groups = Utils.DefaultDict(list) self.cstr_order = Utils.DefaultDict(set) self.ready = 0 def process_install(self): for (f, k, kw) in self.post_funs: f(*k, **kw) def prepare(self): "prepare the scheduling" self.ready = 1 file_deps(self.tasks) self.make_cstr_groups() self.extract_constraints() def get_next_set(self): "next list of tasks to execute using max job settings, returns (maxjobs, task_list)" global algotype if algotype == NORMAL: tasks = self.tasks_in_parallel() maxj = MAXJOBS elif algotype == JOBCONTROL: (maxj, tasks) = self.tasks_by_max_jobs() elif algotype == MAXPARALLEL: tasks = self.tasks_with_inner_constraints() maxj = MAXJOBS else: raise Utils.WafError("unknown algorithm type %s" % (algotype)) if not tasks: return () return (maxj, tasks) def make_cstr_groups(self): "unite the tasks that have similar constraints" self.cstr_groups = Utils.DefaultDict(list) for x in self.tasks: h = x.hash_constraints() self.cstr_groups[h].append(x) def set_order(self, a, b): self.cstr_order[a].add(b) def compare_exts(self, t1, t2): "extension production" x = "ext_in" y = "ext_out" in_ = t1.attr(x, ()) out_ = t2.attr(y, ()) for k in in_: if k in out_: return -1 in_ = t2.attr(x, ()) out_ = t1.attr(y, ()) for k in in_: if k in out_: return 1 return 0 def compare_partial(self, t1, t2): "partial relations after/before" m = "after" n = "before" name = t2.__class__.__name__ if name in Utils.to_list(t1.attr(m, ())): return -1 elif name in Utils.to_list(t1.attr(n, ())): return 1 name = t1.__class__.__name__ if name in Utils.to_list(t2.attr(m, ())): return 1 elif name in Utils.to_list(t2.attr(n, ())): return -1 return 0 def extract_constraints(self): "extract the parallelization constraints from the tasks with different constraints" keys = self.cstr_groups.keys() max = len(keys) # hopefully the length of this list is short for i in xrange(max): t1 = self.cstr_groups[keys[i]][0] for j in xrange(i + 1, max): t2 = self.cstr_groups[keys[j]][0] # add the constraints based on the comparisons val = (self.compare_exts(t1, t2) or self.compare_partial(t1, t2) ) if val > 0: self.set_order(keys[i], keys[j]) elif val < 0: self.set_order(keys[j], keys[i]) def tasks_in_parallel(self): "(NORMAL) next list of tasks that may be executed in parallel" if not self.ready: self.prepare() keys = self.cstr_groups.keys() unconnected = [] remainder = [] for u in keys: for k in self.cstr_order.values(): if u in k: remainder.append(u) break else: unconnected.append(u) toreturn = [] for y in unconnected: toreturn.extend(self.cstr_groups[y]) # remove stuff only after for y in unconnected: try: self.cstr_order.__delitem__(y) except KeyError: pass self.cstr_groups.__delitem__(y) if not toreturn and remainder: raise Utils.WafError("circular order constraint detected %r" % remainder) return toreturn def tasks_by_max_jobs(self): "(JOBCONTROL) returns the tasks that can run in parallel with the max amount of jobs" if not self.ready: self.prepare() if not self.temp_tasks: self.temp_tasks = self.tasks_in_parallel() if not self.temp_tasks: return (None, None) maxjobs = MAXJOBS ret = [] remaining = [] for t in self.temp_tasks: m = getattr(t, "maxjobs", getattr(self.__class__, "maxjobs", MAXJOBS)) if m > maxjobs: remaining.append(t) elif m < maxjobs: remaining += ret ret = [t] maxjobs = m else: ret.append(t) self.temp_tasks = remaining return (maxjobs, ret) def tasks_with_inner_constraints(self): """(MAXPARALLEL) returns all tasks in this group, but add the constraints on each task instance as an optimization, it might be desirable to discard the tasks which do not have to run""" if not self.ready: self.prepare() if getattr(self, "done", None): return None for p in self.cstr_order: for v in self.cstr_order[p]: for m in self.cstr_groups[p]: for n in self.cstr_groups[v]: n.set_run_after(m) self.cstr_order = Utils.DefaultDict(set) self.cstr_groups = Utils.DefaultDict(list) self.done = 1 return self.tasks[:] # make a copy class store_task_type(type): "store the task types that have a name ending in _task into a map (remember the existing task types)" def __init__(cls, name, bases, dict): super(store_task_type, cls).__init__(name, bases, dict) name = cls.__name__ if name.endswith('_task'): name = name.replace('_task', '') if name != 'TaskBase': TaskBase.classes[name] = cls class TaskBase(object): """Base class for all Waf tasks The most important methods are (by usual order of call): 1 runnable_status: ask the task if it should be run, skipped, or if we have to ask later 2 __str__: string to display to the user 3 run: execute the task 4 post_run: after the task is run, update the cache about the task This class should be seen as an interface, it provides the very minimum necessary for the scheduler so it does not do much. For illustration purposes, TaskBase instances try to execute self.fun (if provided) """ __metaclass__ = store_task_type color = "GREEN" maxjobs = MAXJOBS classes = {} stat = None def __init__(self, *k, **kw): self.hasrun = NOT_RUN try: self.generator = kw['generator'] except KeyError: self.generator = self self.bld = Build.bld if kw.get('normal', 1): self.generator.bld.task_manager.add_task(self) def __repr__(self): "used for debugging" return '\n\t{task: %s %s}' % (self.__class__.__name__, str(getattr(self, "fun", ""))) def __str__(self): "string to display to the user" if hasattr(self, 'fun'): return 'executing: %s\n' % self.fun.__name__ return self.__class__.__name__ + '\n' def exec_command(self, *k, **kw): "use this for executing commands from tasks" # TODO in waf 1.6, eliminate bld.exec_command, and move the cwd processing to here if self.env['env']: kw['env'] = self.env['env'] return self.generator.bld.exec_command(*k, **kw) def runnable_status(self): "RUN_ME SKIP_ME or ASK_LATER" return RUN_ME def can_retrieve_cache(self): return False def call_run(self): if self.can_retrieve_cache(): return 0 return self.run() def run(self): "called if the task must run" if hasattr(self, 'fun'): return self.fun(self) return 0 def post_run(self): "update the dependency tree (node stats)" pass def display(self): "print either the description (using __str__) or the progress bar or the ide output" col1 = Logs.colors(self.color) col2 = Logs.colors.NORMAL if Options.options.progress_bar == 1: return self.generator.bld.progress_line(self.position[0], self.position[1], col1, col2) if Options.options.progress_bar == 2: ela = Utils.get_elapsed_time(self.generator.bld.ini) 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' % (self.position[1], self.position[0], ins, outs, ela) total = self.position[1] n = len(str(total)) fs = '[%%%dd/%%%dd] %%s%%s%%s' % (n, n) return fs % (self.position[0], self.position[1], col1, str(self), col2) def attr(self, att, default=None): "retrieve an attribute from the instance or from the class (microoptimization here)" ret = getattr(self, att, self) if ret is self: return getattr(self.__class__, att, default) return ret def hash_constraints(self): "identify a task type for all the constraints relevant for the scheduler: precedence, file production" a = self.attr sum = hash((self.__class__.__name__, str(a('before', '')), str(a('after', '')), str(a('ext_in', '')), str(a('ext_out', '')), self.__class__.maxjobs)) return sum def format_error(self): "error message to display to the user (when a build fails)" if getattr(self, "err_msg", None): return self.err_msg elif self.hasrun == CRASHED: try: return " -> task failed (err #%d): %r" % (self.err_code, self) except AttributeError: return " -> task failed: %r" % self elif self.hasrun == MISSING: return " -> missing files: %r" % self else: return '' def install(self): """ installation is performed by looking at the task attributes: * install_path: installation path like "${PREFIX}/bin" * filename: install the first node in the outputs as a file with a particular name, be certain to give os.sep * chmod: permissions """ bld = self.generator.bld d = self.attr('install') if self.attr('install_path'): lst = [a.relpath_gen(bld.srcnode) for a in self.outputs] perm = self.attr('chmod', O644) if self.attr('src'): # if src is given, install the sources too lst += [a.relpath_gen(bld.srcnode) for a in self.inputs] if self.attr('filename'): dir = self.install_path.rstrip(os.sep) + os.sep + self.attr('filename') bld.install_as(dir, lst[0], self.env, perm) else: bld.install_files(self.install_path, lst, self.env, perm) class Task(TaskBase): """The parent class is quite limited, in this version: * file system interaction: input and output nodes * persistence: do not re-execute tasks that have already run * caching: same files can be saved and retrieved from a cache directory * dependencies: implicit, like .c files depending on .h files explicit, like the input nodes or the dep_nodes environment variables, like the CXXFLAGS in self.env """ vars = [] def __init__(self, env, **kw): TaskBase.__init__(self, **kw) self.env = env # inputs and outputs are nodes # use setters when possible self.inputs = [] self.outputs = [] self.dep_nodes = [] self.run_after = [] # Additionally, you may define the following #self.dep_vars = 'PREFIX DATADIR' def __str__(self): "string to display to the user" env = self.env src_str = ' '.join([a.nice_path(env) for a in self.inputs]) tgt_str = ' '.join([a.nice_path(env) for a in self.outputs]) if self.outputs: sep = ' -> ' else: sep = '' return '%s: %s%s%s\n' % (self.__class__.__name__.replace('_task', ''), src_str, sep, tgt_str) def __repr__(self): return "".join(['\n\t{task: ', self.__class__.__name__, " ", ",".join([x.name for x in self.inputs]), " -> ", ",".join([x.name for x in self.outputs]), '}']) def unique_id(self): "get a unique id: hash the node paths, the variant, the class, the function" try: return self.uid except AttributeError: "this is not a real hot zone, but we want to avoid surprizes here" m = md5() up = m.update up(self.__class__.__name__) up(self.env.variant()) p = None for x in self.inputs + self.outputs: if p != x.parent.id: p = x.parent.id up(x.parent.abspath()) up(x.name) self.uid = m.digest() return self.uid def set_inputs(self, inp): if isinstance(inp, list): self.inputs += inp else: self.inputs.append(inp) def set_outputs(self, out): if isinstance(out, list): self.outputs += out else: self.outputs.append(out) def set_run_after(self, task): "set (scheduler) order on another task" # TODO: handle list or object assert isinstance(task, TaskBase) self.run_after.append(task) def add_file_dependency(self, filename): "TODO user-provided file dependencies" node = self.generator.bld.path.find_resource(filename) self.dep_nodes.append(node) def signature(self): # compute the result one time, and suppose the scan_signature will give the good result try: return self.cache_sig[0] except AttributeError: pass self.m = md5() # explicit deps exp_sig = self.sig_explicit_deps() # env vars var_sig = self.sig_vars() # implicit deps imp_sig = SIG_NIL if self.scan: try: imp_sig = self.sig_implicit_deps() except ValueError: return self.signature() # we now have the signature (first element) and the details (for debugging) ret = self.m.digest() self.cache_sig = (ret, exp_sig, imp_sig, var_sig) return ret def runnable_status(self): "SKIP_ME RUN_ME or ASK_LATER" #return 0 # benchmarking if self.inputs and (not self.outputs): if not getattr(self.__class__, 'quiet', None): warn("invalid task (no inputs OR outputs): override in a Task subclass or set the attribute 'quiet' %r" % self) for t in self.run_after: if not t.hasrun: return ASK_LATER env = self.env bld = self.generator.bld # first compute the signature new_sig = self.signature() # compare the signature to a signature computed previously key = self.unique_id() try: prev_sig = bld.task_sigs[key][0] except KeyError: debug("task: task %r must run as it was never run before or the task code changed", self) return RUN_ME # compare the signatures of the outputs for node in self.outputs: variant = node.variant(env) try: if bld.node_sigs[variant][node.id] != new_sig: return RUN_ME except KeyError: debug("task: task %r must run as the output nodes do not exist", self) return RUN_ME # debug if asked to if Logs.verbose: self.debug_why(bld.task_sigs[key]) if new_sig != prev_sig: return RUN_ME return SKIP_ME def post_run(self): "called after a successful task run" bld = self.generator.bld env = self.env sig = self.signature() ssig = sig.encode('hex') variant = env.variant() for node in self.outputs: # check if the node exists .. try: os.stat(node.abspath(env)) except OSError: self.hasrun = MISSING self.err_msg = '-> missing file: %r' % node.abspath(env) raise Utils.WafError # important, store the signature for the next run bld.node_sigs[variant][node.id] = sig bld.task_sigs[self.unique_id()] = self.cache_sig # file caching, if possible # try to avoid data corruption as much as possible if not Options.cache_global or Options.options.nocache or not self.outputs: return None if getattr(self, 'cached', None): return None dname = os.path.join(Options.cache_global, ssig) tmpdir = tempfile.mkdtemp(prefix=Options.cache_global + os.sep + 'waf') try: shutil.rmtree(dname) except: pass try: i = 0 for node in self.outputs: variant = node.variant(env) dest = os.path.join(tmpdir, str(i) + node.name) shutil.copy2(node.abspath(env), dest) i += 1 except (OSError, IOError): try: shutil.rmtree(tmpdir) except: pass else: try: os.rename(tmpdir, dname) except OSError: try: shutil.rmtree(tmpdir) except: pass else: try: os.chmod(dname, O755) except: pass def can_retrieve_cache(self): """ Retrieve build nodes from the cache update the file timestamps to help cleaning the least used entries from the cache additionally, set an attribute 'cached' to avoid re-creating the same cache files suppose there are files in cache/dir1/file1 and cache/dir2/file2 first, read the timestamp of dir1 then try to copy the files then look at the timestamp again, if it has changed, the data may have been corrupt (cache update by another process) should an exception occur, ignore the data """ if not Options.cache_global or Options.options.nocache or not self.outputs: return None env = self.env sig = self.signature() ssig = sig.encode('hex') # first try to access the cache folder for the task dname = os.path.join(Options.cache_global, ssig) try: t1 = os.stat(dname).st_mtime except OSError: return None i = 0 for node in self.outputs: variant = node.variant(env) orig = os.path.join(dname, str(i) + node.name) try: shutil.copy2(orig, node.abspath(env)) # mark the cache file as used recently (modified) os.utime(orig, None) except (OSError, IOError): debug('task: failed retrieving file') return None i += 1 # is it the same folder? try: t2 = os.stat(dname).st_mtime except OSError: return None if t1 != t2: return None for node in self.outputs: self.generator.bld.node_sigs[variant][node.id] = sig if Options.options.progress_bar < 1: self.generator.bld.printout('restoring from cache %r\n' % node.bldpath(env)) self.cached = True return 1 def debug_why(self, old_sigs): "explains why a task is run" new_sigs = self.cache_sig def v(x): return x.encode('hex') debug("Task %r", self) msgs = ['Task must run', '* Source file or manual dependency', '* Implicit dependency', '* Environment variable'] tmp = 'task: -> %s: %s %s' for x in xrange(len(msgs)): if (new_sigs[x] != old_sigs[x]): debug(tmp, msgs[x], v(old_sigs[x]), v(new_sigs[x])) def sig_explicit_deps(self): bld = self.generator.bld up = self.m.update # the inputs for x in self.inputs + getattr(self, 'dep_nodes', []): if not x.parent.id in bld.cache_scanned_folders: bld.rescan(x.parent) variant = x.variant(self.env) try: up(bld.node_sigs[variant][x.id]) except KeyError: raise Utils.WafError('Missing node signature for %r (required by %r)' % (x, self)) # 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.id] except KeyError: continue for v in d: if isinstance(v, Node.Node): bld.rescan(v.parent) variant = v.variant(self.env) try: v = bld.node_sigs[variant][v.id] except KeyError: raise Utils.WafError('Missing node signature for %r (required by %r)' % (v, self)) elif hasattr(v, '__call__'): v = v() # dependency is a function, call it up(v) for x in self.dep_nodes: v = bld.node_sigs[x.variant(self.env)][x.id] up(v) return self.m.digest() def sig_vars(self): bld = self.generator.bld env = self.env # dependencies on the environment vars act_sig = bld.hash_env_vars(env, self.__class__.vars) self.m.update(act_sig) # additional variable dependencies, if provided dep_vars = getattr(self, 'dep_vars', None) if dep_vars: self.m.update(bld.hash_env_vars(env, dep_vars)) return self.m.digest() #def scan(self, node): # """this method returns a tuple containing: # * a list of nodes corresponding to real files # * a list of names for files not found in path_lst # the input parameters may have more parameters that the ones used below # """ # return ((), ()) scan = None # compute the signature, recompute it if there is no match in the cache def sig_implicit_deps(self): "the signature obtained may not be the one if the files have changed, we do it in two steps" bld = self.generator.bld # get the task signatures from previous runs key = self.unique_id() prev_sigs = bld.task_sigs.get(key, ()) if prev_sigs: try: # for issue #379 if prev_sigs[2] == self.compute_sig_implicit_deps(): return prev_sigs[2] except (KeyError, OSError): pass del bld.task_sigs[key] raise ValueError('rescan') # no previous run or the signature of the dependencies has changed, rescan the dependencies (nodes, names) = self.scan() if Logs.verbose: debug('deps: scanner for %s returned %s %s', str(self), str(nodes), str(names)) # store the dependencies in the cache bld.node_deps[key] = nodes bld.raw_deps[key] = names # recompute the signature and return it try: sig = self.compute_sig_implicit_deps() except KeyError: try: nodes = [] for k in bld.node_deps.get(self.unique_id(), []): if k.id & 3 == 2: # Node.FILE: if not k.id in bld.node_sigs[0]: nodes.append(k) else: if not k.id in bld.node_sigs[self.env.variant()]: nodes.append(k) except: nodes = '?' raise Utils.WafError('Missing node signature for %r (for implicit dependencies %r)' % (nodes, self)) return sig def compute_sig_implicit_deps(self): """it is intended for .cpp and inferred .h files there is a single list (no tree traversal) this is the hot spot so ... do not touch""" upd = self.m.update bld = self.generator.bld tstamp = bld.node_sigs env = self.env for k in bld.node_deps.get(self.unique_id(), []): # unlikely but necessary if it happens if not k.parent.id in bld.cache_scanned_folders: # if the parent folder is removed, an OSError may be thrown bld.rescan(k.parent) # if the parent folder is removed, a KeyError will be thrown if k.id & 3 == 2: # Node.FILE: upd(tstamp[0][k.id]) else: upd(tstamp[env.variant()][k.id]) return self.m.digest() def funex(c): dc = {} exec(c, dc) return dc['f'] reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})", re.M) def compile_fun_shell(name, line): """Compiles a string (once) into a function, eg: simple_task_type('c++', '${CXX} -o ${TGT[0]} ${SRC} -I ${SRC[0].parent.bldpath()}') The env variables (CXX, ..) on the task must not hold dicts (order) The reserved keywords TGT and SRC represent the task input and output nodes quick test: bld(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"') """ 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 parm = [] dvars = [] app = parm.append for (var, meth) in extr: if var == 'SRC': if meth: app('task.inputs%s' % meth) else: app('" ".join([a.srcpath(env) for a in task.inputs])') elif var == 'TGT': if meth: app('task.outputs%s' % meth) else: app('" ".join([a.bldpath(env) for a in task.outputs])') else: if not var in dvars: dvars.append(var) app("p('%s')" % var) if parm: parm = "%% (%s) " % (',\n\t\t'.join(parm)) else: parm = '' c = COMPILE_TEMPLATE_SHELL % (line, parm) debug('action: %s', c) return (funex(c), dvars) def compile_fun_noshell(name, line): extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('subst'): extr.append((g('var'), g('code'))); return "<<|@|>>" return None line2 = reg_act.sub(repl, line) params = line2.split('<<|@|>>') buf = [] dvars = [] app = buf.append for x in xrange(len(extr)): params[x] = params[x].strip() if params[x]: app("lst.extend(%r)" % params[x].split()) (var, meth) = extr[x] if var == 'SRC': if meth: app('lst.append(task.inputs%s)' % meth) else: app("lst.extend([a.srcpath(env) for a in task.inputs])") elif var == 'TGT': if meth: app('lst.append(task.outputs%s)' % meth) else: app("lst.extend([a.bldpath(env) for a in task.outputs])") else: app('lst.extend(to_list(env[%r]))' % var) if not var in dvars: dvars.append(var) if params[-1]: app("lst.extend(%r)" % shlex.split(params[-1])) fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf) debug('action: %s', fun) return (funex(fun), dvars) def compile_fun(name, line, shell=None): "commands can be launched by the shell or not" if line.find('<') > 0 or line.find('>') > 0 or line.find('&&') > 0: shell = True #else: # shell = False if shell is None: if sys.platform == 'win32': shell = False else: shell = True if shell: return compile_fun_shell(name, line) else: return compile_fun_noshell(name, line) def simple_task_type(name, line, color='GREEN', vars=[], ext_in=[], ext_out=[], before=[], after=[], shell=None): """return a new Task subclass with the function run compiled from the line given""" (fun, dvars) = compile_fun(name, line, shell) fun.code = line return task_type_from_func(name, fun, vars or dvars, color, ext_in, ext_out, before, after) def task_type_from_func(name, func, vars=[], color='GREEN', ext_in=[], ext_out=[], before=[], after=[]): """return a new Task subclass with the function run compiled from the line given""" params = { 'run': func, 'vars': vars, 'color': color, 'name': name, 'ext_in': Utils.to_list(ext_in), 'ext_out': Utils.to_list(ext_out), 'before': Utils.to_list(before), 'after': Utils.to_list(after), } cls = type(Task)(name, (Task,), params) TaskBase.classes[name] = cls return cls def always_run(cls): """Set all task instances of this class to be executed whenever a build is started The task signature is calculated, but the result of the comparation between task signatures is bypassed """ old = cls.runnable_status def always(self): ret = old(self) if ret == SKIP_ME: return RUN_ME return ret cls.runnable_status = always def update_outputs(cls): """When a command is always run, it is possible that the output only change sometimes. By default the build node have as a hash the signature of the task which may not change. With this, the output nodes (produced) are hashed, and the hashes are set to the build nodes This may avoid unnecessary recompilations, but it uses more resources (hashing the output files) so it is not used by default """ old_post_run = cls.post_run def post_run(self): old_post_run(self) bld = self.generator.bld for output in self.outputs: bld.node_sigs[self.env.variant()][output.id] = Utils.h_file(output.abspath(self.env)) bld.task_sigs[output.id] = self.unique_id() cls.post_run = post_run old_runnable_status = cls.runnable_status def runnable_status(self): status = old_runnable_status(self) if status != RUN_ME: return status uid = self.unique_id() try: bld = self.outputs[0].__class__.bld new_sig = self.signature() prev_sig = bld.task_sigs[uid][0] if prev_sig == new_sig: for x in self.outputs: if not x.id in bld.node_sigs[self.env.variant()]: return RUN_ME if bld.task_sigs[x.id] != uid: # ensure the outputs are associated with *this* task return RUN_ME return SKIP_ME except KeyError: pass except IndexError: pass return RUN_ME cls.runnable_status = runnable_status def extract_outputs(tasks): """file_deps: Infer additional dependencies from task input and output nodes """ v = {} for x in tasks: try: (ins, outs) = v[x.env.variant()] except KeyError: ins = {} outs = {} v[x.env.variant()] = (ins, outs) for a in getattr(x, 'inputs', []): try: ins[a.id].append(x) except KeyError: ins[a.id] = [x] for a in getattr(x, 'outputs', []): try: outs[a.id].append(x) except KeyError: outs[a.id] = [x] for (ins, outs) in v.values(): links = set(ins.iterkeys()).intersection(outs.iterkeys()) for k in links: for a in ins[k]: for b in outs[k]: a.set_run_after(b) def extract_deps(tasks): """file_deps: Infer additional dependencies from task input and output nodes and from implicit dependencies returned by the scanners - that will only work if all tasks are created this is aimed at people who have pathological builds and who do not care enough to implement the build dependencies properly with two loops over the list of tasks, do not expect this to be really fast """ # first reuse the function above extract_outputs(tasks) # map the output nodes to the tasks producing them out_to_task = {} for x in tasks: v = x.env.variant() try: lst = x.outputs except AttributeError: pass else: for node in lst: out_to_task[(v, node.id)] = x # map the dependencies found to the tasks compiled dep_to_task = {} for x in tasks: try: x.signature() except: # this is on purpose pass v = x.env.variant() key = x.unique_id() for k in x.generator.bld.node_deps.get(x.unique_id(), []): try: dep_to_task[(v, k.id)].append(x) except KeyError: dep_to_task[(v, k.id)] = [x] # now get the intersection deps = set(dep_to_task.keys()).intersection(set(out_to_task.keys())) # and add the dependencies from task to task for idx in deps: for k in dep_to_task[idx]: k.set_run_after(out_to_task[idx]) # cleanup, remove the signatures for x in tasks: try: delattr(x, 'cache_sig') except AttributeError: pass tevent-0.9.34/third_party/waf/wafadmin/TaskGen.py0000660000000000000000000004260712617125140021662 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2008 (ita) """ The class 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 delayed. To achieve this, various methods are called from the method "apply" The class task_gen contains lots of methods, and a configuration table: * the methods to call (self.meths) can be specified dynamically (removing, adding, ..) * the order of the methods (self.prec or by default task_gen.prec) is configurable * new methods can be inserted dynamically without pasting old code Additionally, task_gen provides the method apply_core * file extensions are mapped to methods: def meth(self, name_or_node) * if a mapping is not found in self.mappings, it is searched in task_gen.mappings * when called, the functions may modify self.allnodes to re-add source to process * the mappings can map an extension or a filename (see the code below) WARNING: subclasses must reimplement the clone method """ import os, traceback, copy import Build, Task, Utils, Logs, Options from Logs import debug, error, warn from Constants import * typos = { 'sources':'source', 'targets':'target', 'include':'includes', 'define':'defines', 'importpath':'importpaths', 'install_var':'install_path', 'install_subdir':'install_path', 'inst_var':'install_path', 'inst_dir':'install_path', 'feature':'features', } class register_obj(type): """no decorators for classes, so we use a metaclass we store into task_gen.classes the classes that inherit task_gen and whose names end in '_taskgen' """ def __init__(cls, name, bases, dict): super(register_obj, cls).__init__(name, bases, dict) name = cls.__name__ suffix = '_taskgen' if name.endswith(suffix): task_gen.classes[name.replace(suffix, '')] = cls class task_gen(object): """ Most methods are of the form 'def meth(self):' without any parameters there are many of them, and they do many different things: * task creation * task results installation * environment modification * attribute addition/removal The inheritance approach is complicated * mixing several languages at once * subclassing is needed even for small changes * inserting new methods is complicated This new class uses a configuration table: * adding new methods easily * obtaining the order in which to call the methods * postponing the method calls (post() -> apply) Additionally, a 'traits' static attribute is provided: * this list contains methods * the methods can remove or add methods from self.meths Example1: the attribute 'staticlib' is set on an instance a method set in the list of traits is executed when the instance is posted, it finds that flag and adds another method for execution Example2: a method set in the list of traits finds the msvc compiler (from self.env['MSVC']==1); more methods are added to self.meths """ __metaclass__ = register_obj mappings = {} mapped = {} prec = Utils.DefaultDict(list) traits = Utils.DefaultDict(set) classes = {} def __init__(self, *kw, **kwargs): self.prec = Utils.DefaultDict(list) "map precedence of function names to call" # so we will have to play with directed acyclic graphs # detect cycles, etc self.source = '' self.target = '' # list of methods to execute - does not touch it by hand unless you know self.meths = [] # list of mappings extension -> function self.mappings = {} # list of features (see the documentation on traits) self.features = list(kw) # not always a good idea self.tasks = [] self.default_chmod = O644 self.default_install_path = None # kind of private, beware of what you put in it, also, the contents are consumed self.allnodes = [] self.bld = kwargs.get('bld', Build.bld) self.env = self.bld.env.copy() self.path = self.bld.path # emulate chdir when reading scripts self.name = '' # give a name to the target (static+shlib with the same targetname ambiguity) # provide a unique id self.idx = self.bld.idx[self.path.id] = self.bld.idx.get(self.path.id, 0) + 1 for key, val in kwargs.iteritems(): setattr(self, key, val) self.bld.task_manager.add_task_gen(self) self.bld.all_task_gen.append(self) def __str__(self): return ("" % (self.name or self.target, self.__class__.__name__, str(self.path))) def __setattr__(self, name, attr): real = typos.get(name, name) if real != name: warn('typo %s -> %s' % (name, real)) if Logs.verbose > 0: traceback.print_stack() object.__setattr__(self, real, attr) def to_list(self, value): "helper: returns a list" if isinstance(value, str): return value.split() else: return value def apply(self): "order the methods to execute using self.prec or task_gen.prec" keys = set(self.meths) # add the methods listed in the features self.features = Utils.to_list(self.features) for x in self.features + ['*']: st = task_gen.traits[x] if not st: warn('feature %r does not exist - bind at least one method to it' % x) keys.update(st) # copy the precedence table prec = {} prec_tbl = self.prec or task_gen.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) # 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) if prec: raise Utils.WafError("graph has a cycle %s" % str(prec)) out.reverse() self.meths = out # then we run the methods in order debug('task_gen: posting %s %d', self, id(self)) for x in out: try: v = getattr(self, x) except AttributeError: raise Utils.WafError("tried to retrieve %s which is not a valid method" % x) debug('task_gen: -> %s (%d)', x, id(self)) v() def post(self): "runs the code to create the tasks, do not subclass" if not self.name: if isinstance(self.target, list): self.name = ' '.join(self.target) else: self.name = self.target if getattr(self, 'posted', None): #error("OBJECT ALREADY POSTED" + str( self)) return self.apply() self.posted = True debug('task_gen: posted %s', self.name) def get_hook(self, ext): try: return self.mappings[ext] except KeyError: try: return task_gen.mappings[ext] except KeyError: return None # TODO waf 1.6: always set the environment # TODO waf 1.6: create_task(self, name, inputs, outputs) def create_task(self, name, src=None, tgt=None, env=None): env = env or self.env task = Task.TaskBase.classes[name](env.copy(), generator=self) if src: task.set_inputs(src) if tgt: task.set_outputs(tgt) self.tasks.append(task) return task def name_to_obj(self, name): return self.bld.name_to_obj(name, self.env) def get_tgen_by_name(self, name): return self.bld.get_tgen_by_name(name) def find_sources_in_dirs(self, dirnames, excludes=[], exts=[]): """ The attributes "excludes" and "exts" must be lists to avoid the confusion find_sources_in_dirs('a', 'b', 'c') <-> find_sources_in_dirs('a b c') do not use absolute paths do not use paths outside of the source tree the files or folder beginning by . are not returned # TODO: remove in Waf 1.6 """ err_msg = "'%s' attribute must be a list" if not isinstance(excludes, list): raise Utils.WscriptError(err_msg % 'excludes') if not isinstance(exts, list): raise Utils.WscriptError(err_msg % 'exts') lst = [] #make sure dirnames is a list helps with dirnames with spaces dirnames = self.to_list(dirnames) ext_lst = exts or list(self.mappings.keys()) + list(task_gen.mappings.keys()) for name in dirnames: anode = self.path.find_dir(name) if not anode or not anode.is_child_of(self.bld.srcnode): raise Utils.WscriptError("Unable to use '%s' - either because it's not a relative path" \ ", or it's not child of '%s'." % (name, self.bld.srcnode)) self.bld.rescan(anode) for name in self.bld.cache_dir_contents[anode.id]: # ignore hidden files if name.startswith('.'): continue (base, ext) = os.path.splitext(name) if ext in ext_lst and not name in lst and not name in excludes: lst.append((anode.relpath_gen(self.path) or '.') + os.path.sep + name) lst.sort() self.source = self.to_list(self.source) if not self.source: self.source = lst else: self.source += lst def clone(self, env): """when creating a clone in a task generator method, make sure to set posted=False on the clone else the other task generator will not create its tasks""" newobj = task_gen(bld=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.__class__ = self.__class__ if isinstance(env, str): newobj.env = self.bld.all_envs[env].copy() else: newobj.env = env.copy() return newobj def get_inst_path(self): return getattr(self, '_install_path', getattr(self, 'default_install_path', '')) def set_inst_path(self, val): self._install_path = val install_path = property(get_inst_path, set_inst_path) def get_chmod(self): return getattr(self, '_chmod', getattr(self, 'default_chmod', O644)) def set_chmod(self, val): self._chmod = val chmod = property(get_chmod, set_chmod) def declare_extension(var, func): try: for x in Utils.to_list(var): task_gen.mappings[x] = func except: raise Utils.WscriptError('declare_extension takes either a list or a string %r' % var) task_gen.mapped[func.__name__] = func def declare_order(*k): assert(len(k) > 1) n = len(k) - 1 for i in xrange(n): f1 = k[i] f2 = k[i+1] if not f1 in task_gen.prec[f2]: task_gen.prec[f2].append(f1) def declare_chain(name='', action='', ext_in='', ext_out='', reentrant=True, color='BLUE', install=0, before=[], after=[], decider=None, rule=None, scan=None): """ see Tools/flex.py for an example while i do not like such wrappers, some people really do """ action = action or rule if isinstance(action, str): act = Task.simple_task_type(name, action, color=color) else: act = Task.task_type_from_func(name, action, color=color) act.ext_in = tuple(Utils.to_list(ext_in)) act.ext_out = tuple(Utils.to_list(ext_out)) act.before = Utils.to_list(before) act.after = Utils.to_list(after) act.scan = scan def x_file(self, node): if decider: ext = decider(self, node) else: ext = ext_out if isinstance(ext, str): out_source = node.change_ext(ext) if reentrant: self.allnodes.append(out_source) elif isinstance(ext, list): out_source = [node.change_ext(x) for x in ext] if reentrant: for i in xrange((reentrant is True) and len(out_source) or reentrant): self.allnodes.append(out_source[i]) else: # XXX: useless: it will fail on Utils.to_list above... raise Utils.WafError("do not know how to process %s" % str(ext)) tsk = self.create_task(name, node, out_source) if node.__class__.bld.is_install: tsk.install = install declare_extension(act.ext_in, x_file) return x_file def bind_feature(name, methods): lst = Utils.to_list(methods) task_gen.traits[name].update(lst) """ All the following decorators are registration decorators, i.e add an attribute to current class (task_gen and its derivatives), with same name as func, which points to func itself. For example: @taskgen def sayHi(self): print("hi") Now taskgen.sayHi() may be called If python were really smart, it could infer itself the order of methods by looking at the attributes. A prerequisite for execution is to have the attribute set before. Intelligent compilers binding aspect-oriented programming and parallelization, what a nice topic for studies. """ def taskgen(func): """ register a method as a task generator method """ setattr(task_gen, func.__name__, func) return func def feature(*k): """ declare a task generator method that will be executed when the object attribute 'feature' contains the corresponding key(s) """ def deco(func): setattr(task_gen, func.__name__, func) for name in k: task_gen.traits[name].update([func.__name__]) return func return deco def before(*k): """ declare a task generator method which will be executed before the functions of given name(s) """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: if not func.__name__ in task_gen.prec[fun_name]: task_gen.prec[fun_name].append(func.__name__) return func return deco def after(*k): """ declare a task generator method which will be executed after the functions of given name(s) """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: if not fun_name in task_gen.prec[func.__name__]: task_gen.prec[func.__name__].append(fun_name) return func return deco def extension(var): """ declare a task generator method which will be invoked during the processing of source files for the extension given """ def deco(func): setattr(task_gen, func.__name__, func) try: for x in Utils.to_list(var): task_gen.mappings[x] = func except: raise Utils.WafError('extension takes either a list or a string %r' % var) task_gen.mapped[func.__name__] = func return func return deco # TODO make certain the decorators may be used here def apply_core(self): """Process the attribute source transform the names into file nodes try to process the files by name first, later by extension""" # get the list of folders to use by the scanners # all our objects share the same include paths anyway find_resource = self.path.find_resource for filename in self.to_list(self.source): # if self.mappings or task_gen.mappings contains a file of the same name x = self.get_hook(filename) if x: x(self, filename) else: node = find_resource(filename) if not node: raise Utils.WafError("source not found: '%s' in '%s'" % (filename, str(self.path))) self.allnodes.append(node) for node in self.allnodes: # self.mappings or task_gen.mappings map the file extension to a function x = self.get_hook(node.suffix()) if not x: raise Utils.WafError("Cannot guess how to process %s (got mappings %r in %r) -> try conf.check_tool(..)?" % \ (str(node), self.__class__.mappings.keys(), self.__class__)) x(self, node) feature('*')(apply_core) def exec_rule(self): """Process the attribute rule, when provided the method apply_core will be disabled """ if not getattr(self, 'rule', None): return # someone may have removed it already try: self.meths.remove('apply_core') except ValueError: pass # get the function and the variables func = self.rule vars2 = [] if isinstance(func, str): # use the shell by default for user-defined commands (func, vars2) = Task.compile_fun('', self.rule, shell=getattr(self, 'shell', True)) func.code = self.rule # create the task class name = getattr(self, 'name', None) or self.target or self.rule if not isinstance(name, str): name = str(self.idx) cls = Task.task_type_from_func(name, func, getattr(self, 'vars', vars2)) cls.color = getattr(self, 'color', 'BLUE') # now create one instance tsk = self.create_task(name) dep_vars = getattr(self, 'dep_vars', ['ruledeps']) if dep_vars: tsk.dep_vars = dep_vars if isinstance(self.rule, str): tsk.env.ruledeps = self.rule else: # only works if the function is in a global module such as a waf tool tsk.env.ruledeps = Utils.h_fun(self.rule) # we assume that the user knows that without inputs or outputs #if not getattr(self, 'target', None) and not getattr(self, 'source', None): # cls.quiet = True if getattr(self, 'target', None): cls.quiet = True tsk.outputs = [self.path.find_or_declare(x) for x in self.to_list(self.target)] if getattr(self, 'source', None): cls.quiet = True tsk.inputs = [] for x in self.to_list(self.source): y = self.path.find_resource(x) if not y: raise Utils.WafError('input file %r could not be found (%r)' % (x, self.path.abspath())) tsk.inputs.append(y) if self.allnodes: tsk.inputs.extend(self.allnodes) if getattr(self, 'scan', None): cls.scan = self.scan if getattr(self, 'install_path', None): tsk.install_path = self.install_path if getattr(self, 'cwd', None): tsk.cwd = self.cwd if getattr(self, 'on_results', None) or getattr(self, 'update_outputs', None): Task.update_outputs(cls) if getattr(self, 'always', None): Task.always_run(cls) for x in ['after', 'before', 'ext_in', 'ext_out']: setattr(cls, x, getattr(self, x, [])) feature('*')(exec_rule) before('apply_core')(exec_rule) def sequence_order(self): """ add a strict sequential constraint between the tasks generated by task generators it uses the fact that task generators are posted in order it will not post objects which belong to other folders there is also an awesome trick for executing the method in last position to use: bld(features='javac seq') bld(features='jar seq') to start a new sequence, set the attribute seq_start, for example: obj.seq_start = True """ 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 feature('seq')(sequence_order) tevent-0.9.34/third_party/waf/wafadmin/Tools/__init__.py0000660000000000000000000000010212520121120023130 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) tevent-0.9.34/third_party/waf/wafadmin/Tools/ar.py0000660000000000000000000000153312520121120022004 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2008 (ita) # Ralf Habacker, 2006 (rh) "ar and ranlib" import os, sys import Task, Utils from Configure import conftest ar_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' cls = Task.simple_task_type('static_link', ar_str, color='YELLOW', ext_in='.o', ext_out='.bin', shell=False) cls.maxjobs = 1 cls.install = Utils.nada # remove the output in case it already exists old = cls.run def wrap(self): try: os.remove(self.outputs[0].abspath(self.env)) except OSError: pass return old(self) setattr(cls, 'run', wrap) def detect(conf): conf.find_program('ar', var='AR') conf.find_program('ranlib', var='RANLIB') conf.env.ARFLAGS = 'rcs' @conftest def find_ar(conf): v = conf.env conf.check_tool('ar') if not v['AR']: conf.fatal('ar is required for static libraries - not found') tevent-0.9.34/third_party/waf/wafadmin/Tools/bison.py0000660000000000000000000000177712520121120022526 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 # Thomas Nagy 2009 "Bison processing" import Task from TaskGen import extension bison = '${BISON} ${BISONFLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}' cls = Task.simple_task_type('bison', bison, 'GREEN', ext_in='.yc .y .yy', ext_out='.c .cxx .h .l', shell=False) @extension(['.y', '.yc', '.yy']) def big_bison(self, node): """when it becomes complicated (unlike flex), the old recipes work better (cwd)""" 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.bld_dir(tsk.env) # and the c/cxx file must be compiled too self.allnodes.append(outs[0]) def detect(conf): bison = conf.find_program('bison', var='BISON', mandatory=True) conf.env['BISONFLAGS'] = '-d' tevent-0.9.34/third_party/waf/wafadmin/Tools/cc.py0000660000000000000000000000553512617125140022012 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) "Base for c programs/libraries" import os import TaskGen, Build, Utils, Task from Logs import debug import ccroot from TaskGen import feature, before, extension, after g_cc_flag_vars = [ 'CCDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'STATICLIB', 'LIB', 'LIBPATH', 'LINKFLAGS', 'RPATH', 'CCFLAGS', 'CPPPATH', 'CPPFLAGS', 'CCDEFINES'] EXT_CC = ['.c'] g_cc_type_vars = ['CCFLAGS', 'LINKFLAGS'] # TODO remove in waf 1.6 class cc_taskgen(ccroot.ccroot_abstract): pass @feature('c', 'cc') @before('apply_type_vars') @after('default_cc') def init_cc(self): self.p_flag_vars = set(self.p_flag_vars).union(g_cc_flag_vars) self.p_type_vars = set(self.p_type_vars).union(g_cc_type_vars) if not self.env['CC_NAME']: raise Utils.WafError("At least one compiler (gcc, ..) must be selected") @feature('c', 'cc') @after('apply_incpaths') def apply_obj_vars_cc(self): """after apply_incpaths for INC_PATHS""" env = self.env app = env.append_unique cpppath_st = env['CPPPATH_ST'] # local flags come first # set the user-defined includes paths for i in env['INC_PATHS']: app('_CCINCFLAGS', cpppath_st % i.bldpath(env)) app('_CCINCFLAGS', cpppath_st % i.srcpath(env)) # set the library include paths for i in env['CPPPATH']: app('_CCINCFLAGS', cpppath_st % i) @feature('c', 'cc') @after('apply_lib_vars') def apply_defines_cc(self): """after uselib is set for CCDEFINES""" self.defines = getattr(self, 'defines', []) lst = self.to_list(self.defines) + self.to_list(self.env['CCDEFINES']) milst = [] # now process the local defines for defi in lst: if not defi in milst: milst.append(defi) # CCDEFINES_ libs = self.to_list(self.uselib) for l in libs: val = self.env['CCDEFINES_'+l] if val: milst += val self.env['DEFLINES'] = ["%s %s" % (x[0], Utils.trimquotes('='.join(x[1:]))) for x in [y.split('=') for y in milst]] y = self.env['CCDEFINES_ST'] self.env.append_unique('_CCDEFFLAGS', [y%x for x in milst]) @extension(EXT_CC) def c_hook(self, node): # create the compilation task: cpp or cc if getattr(self, 'obj_ext', None): obj_ext = self.obj_ext else: obj_ext = '_%d.o' % self.idx task = self.create_task('cc', node, node.change_ext(obj_ext)) try: self.compiled_tasks.append(task) except AttributeError: raise Utils.WafError('Have you forgotten to set the feature "cc" on %s?' % str(self)) return task cc_str = '${CC} ${CCFLAGS} ${CPPFLAGS} ${_CCINCFLAGS} ${_CCDEFFLAGS} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT}' cls = Task.simple_task_type('cc', cc_str, 'GREEN', ext_out='.o', ext_in='.c', shell=False) cls.scan = ccroot.scan cls.vars.append('CCDEPS') link_str = '${LINK_CC} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}' cls = Task.simple_task_type('cc_link', link_str, color='YELLOW', ext_in='.o', ext_out='.bin', shell=False) cls.maxjobs = 1 cls.install = Utils.nada tevent-0.9.34/third_party/waf/wafadmin/Tools/ccroot.py0000660000000000000000000004544712617125140022724 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2008 (ita) "base for all c/c++ programs and libraries" import os, sys, re import TaskGen, Task, Utils, preproc, Logs, Build, Options from Logs import error, debug, warn from Utils import md5 from TaskGen import taskgen, after, before, feature from Constants import * from Configure import conftest try: from cStringIO import StringIO except ImportError: from io import StringIO import config_c # <- necessary for the configuration, do not touch USE_TOP_LEVEL = False def get_cc_version(conf, cc, gcc=False, icc=False): cmd = cc + ['-dM', '-E', '-'] try: p = Utils.pproc.Popen(cmd, stdin=Utils.pproc.PIPE, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE) p.stdin.write('\n') out = p.communicate()[0] except: conf.fatal('could not determine the compiler version %r' % cmd) # PY3K: do not touch out = str(out) if gcc: if out.find('__INTEL_COMPILER') >= 0: conf.fatal('The intel compiler pretends to be gcc') if out.find('__GNUC__') < 0: conf.fatal('Could not determine the compiler type') if icc and out.find('__INTEL_COMPILER') < 0: conf.fatal('Not icc/icpc') k = {} if icc or gcc: out = out.split('\n') 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' # Some documentation is available at http://predef.sourceforge.net # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns. mp1 = { '__linux__' : 'linux', '__GNU__' : 'gnu', '__FreeBSD__' : 'freebsd', '__NetBSD__' : 'netbsd', '__OpenBSD__' : 'openbsd', '__sun' : 'sunos', '__hpux' : 'hpux', '__sgi' : 'irix', '_AIX' : 'aix', '__CYGWIN__' : 'cygwin', '__MSYS__' : 'msys', '_UWIN' : 'uwin', '_WIN64' : 'win32', '_WIN32' : 'win32', '__POWERPC__' : 'powerpc', } for i in mp1: if isD(i): conf.env.DEST_OS = mp1[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__'): conf.env.DEST_BINFMT = 'pe' elif isD('__APPLE__'): conf.env.DEST_BINFMT = 'mac-o' mp2 = { '__x86_64__' : 'x86_64', '__i386__' : 'x86', '__ia64__' : 'ia', '__mips__' : 'mips', '__sparc__' : 'sparc', '__alpha__' : 'alpha', '__arm__' : 'arm', '__hppa__' : 'hppa', '__powerpc__' : 'powerpc', } for i in mp2: if isD(i): conf.env.DEST_CPU = mp2[i] break debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')])) conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) return k class DEBUG_LEVELS: """Will disappear in waf 1.6""" ULTRADEBUG = "ultradebug" DEBUG = "debug" RELEASE = "release" OPTIMIZED = "optimized" CUSTOM = "custom" ALL = [ULTRADEBUG, DEBUG, RELEASE, OPTIMIZED, CUSTOM] def scan(self): "look for .h the .cpp need" debug('ccroot: _scan_preprocessor(self, node, env, path_lst)') # TODO waf 1.6 - assume the default input has exactly one file if len(self.inputs) == 1: node = self.inputs[0] (nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS']) if Logs.verbose: debug('deps: deps for %s: %r; unresolved %r', str(node), nodes, names) return (nodes, names) all_nodes = [] all_names = [] seen = set() for node in self.inputs: (nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS']) if Logs.verbose: debug('deps: deps for %s: %r; unresolved %r', str(node), nodes, names) for x in nodes: if id(x) in seen: continue seen.add(id(x)) all_nodes.append(x) for x in names: if not x in all_names: all_names.append(x) return (all_nodes, all_names) class ccroot_abstract(TaskGen.task_gen): "Parent class for programs and libraries in languages c, c++ and moc (Qt)" def __init__(self, *k, **kw): # COMPAT remove in waf 1.6 TODO if len(k) > 1: k = list(k) if k[1][0] != 'c': k[1] = 'c' + k[1] TaskGen.task_gen.__init__(self, *k, **kw) def get_target_name(self): tp = 'program' for x in self.features: if x in ['cshlib', 'cstaticlib']: tp = x.lstrip('c') pattern = self.env[tp + '_PATTERN'] if not pattern: pattern = '%s' dir, name = os.path.split(self.target) if 'cshlib' in self.features and getattr(self, 'vnum', None): nums = self.vnum.split('.') if self.env.DEST_BINFMT == 'pe': # include the version in the dll file name, # the import lib file name stays unversionned. name = name + '-' + nums[0] elif self.env.DEST_OS == 'openbsd': pattern = '%s.%s' % (pattern, nums[0]) if len(nums) >= 2: pattern += '.%s' % nums[1] return os.path.join(dir, pattern % name) @feature('c', 'cc', 'cxx') @before('apply_core') def default_cc(self): """compiled_tasks attribute must be set before the '.c->.o' tasks can be created""" Utils.def_attrs(self, includes = '', defines= '', rpaths = '', uselib = '', uselib_local = '', add_objects = '', p_flag_vars = [], p_type_vars = [], compiled_tasks = [], link_task = None) # The only thing we need for cross-compilation is DEST_BINFMT. # At some point, we may reach a case where DEST_BINFMT is not enough, but for now it's sufficient. # Currently, cross-compilation is auto-detected only for the gnu and intel compilers. if not self.env.DEST_BINFMT: # Infer the binary format from the os name. self.env.DEST_BINFMT = Utils.unversioned_sys_platform_to_binary_format( self.env.DEST_OS or Utils.unversioned_sys_platform()) if not self.env.BINDIR: self.env.BINDIR = Utils.subst_vars('${PREFIX}/bin', self.env) if not self.env.LIBDIR: self.env.LIBDIR = Utils.subst_vars('${PREFIX}/lib${LIB_EXT}', self.env) @feature('cprogram', 'dprogram', 'cstaticlib', 'dstaticlib', 'cshlib', 'dshlib') def apply_verif(self): """no particular order, used for diagnostic""" if not (self.source or getattr(self, 'add_objects', None) or getattr(self, 'uselib_local', None) or getattr(self, 'obj_files', None)): raise Utils.WafError('no source files specified for %s' % self) if not self.target: raise Utils.WafError('no target for %s' % self) # TODO reference the d programs, shlibs in d.py, not here @feature('cprogram', 'dprogram') @after('default_cc') @before('apply_core') def vars_target_cprogram(self): self.default_install_path = self.env.BINDIR self.default_chmod = O755 @after('default_cc') @feature('cshlib', 'dshlib') @before('apply_core') def vars_target_cshlib(self): if self.env.DEST_BINFMT == 'pe': # set execute bit on libs to avoid 'permission denied' (issue 283) self.default_chmod = O755 self.default_install_path = self.env.BINDIR else: self.default_install_path = self.env.LIBDIR @feature('cprogram', 'dprogram', 'cstaticlib', 'dstaticlib', 'cshlib', 'dshlib') @after('apply_link', 'vars_target_cprogram', 'vars_target_cshlib') def default_link_install(self): """you may kill this method to inject your own installation for the first element any other install should only process its own nodes and not those from the others""" if self.install_path: self.bld.install_files(self.install_path, self.link_task.outputs[0], env=self.env, chmod=self.chmod) @feature('c', 'cc', 'cxx') @after('apply_type_vars', 'apply_lib_vars', 'apply_core') def apply_incpaths(self): """used by the scanner after processing the uselib for CPPPATH after apply_core because some processing may add include paths """ lst = [] # TODO move the uselib processing out of here for lib in self.to_list(self.uselib): for path in self.env['CPPPATH_' + lib]: if not path in lst: lst.append(path) if preproc.go_absolute: for path in preproc.standard_includes: if not path in lst: lst.append(path) for path in self.to_list(self.includes): if not path in lst: if preproc.go_absolute or not os.path.isabs(path): lst.append(path) else: self.env.prepend_value('CPPPATH', path) for path in lst: node = None if os.path.isabs(path): if preproc.go_absolute: node = self.bld.root.find_dir(path) elif path[0] == '#': node = self.bld.srcnode if len(path) > 1: node = node.find_dir(path[1:]) else: node = self.path.find_dir(path) if node: self.env.append_value('INC_PATHS', node) # TODO WAF 1.6 if USE_TOP_LEVEL: self.env.append_value('INC_PATHS', self.bld.srcnode) @feature('c', 'cc', 'cxx') @after('init_cc', 'init_cxx') @before('apply_lib_vars') def apply_type_vars(self): """before apply_lib_vars because we modify uselib after init_cc and init_cxx because web need p_type_vars """ for x in self.features: if not x in ['cprogram', 'cstaticlib', 'cshlib']: continue x = x.lstrip('c') # if the type defines uselib to add, add them st = self.env[x + '_USELIB'] if st: self.uselib = self.uselib + ' ' + st # each compiler defines variables like 'shlib_CXXFLAGS', 'shlib_LINKFLAGS', etc # so when we make a task generator of the type shlib, CXXFLAGS are modified accordingly for var in self.p_type_vars: compvar = '%s_%s' % (x, var) #print compvar value = self.env[compvar] if value: self.env.append_value(var, value) @feature('cprogram', 'cshlib', 'cstaticlib') @after('apply_core') def apply_link(self): """executes after apply_core for collecting 'compiled_tasks' use a custom linker if specified (self.link='name-of-custom-link-task')""" link = getattr(self, 'link', None) if not link: if 'cstaticlib' in self.features: link = 'static_link' elif 'cxx' in self.features: link = 'cxx_link' else: link = 'cc_link' tsk = self.create_task(link) outputs = [t.outputs[0] for t in self.compiled_tasks] tsk.set_inputs(outputs) tsk.set_outputs(self.path.find_or_declare(get_target_name(self))) self.link_task = tsk @feature('c', 'cc', 'cxx') @after('apply_link', 'init_cc', 'init_cxx', 'apply_core') def apply_lib_vars(self): """after apply_link because of 'link_task' after default_cc because of the attribute 'uselib'""" # after 'apply_core' in case if 'cc' if there is no link env = self.env # 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(self.uselib) names = self.to_list(self.uselib_local) seen = set([]) tmp = Utils.deque(names) # consume a copy of the list of names while tmp: lib_name = tmp.popleft() # visit dependencies only once if lib_name in seen: continue y = self.name_to_obj(lib_name) if not y: raise Utils.WafError('object %r was not found in uselib_local (required by %r)' % (lib_name, self.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): lst = y.to_list(y.uselib_local) if 'cshlib' in y.features or 'cprogram' in y.features: lst = [x for x in lst if not 'cstaticlib' in self.name_to_obj(x).features] tmp.extend(lst) # link task and flags if getattr(y, 'link_task', None): link_name = y.target[y.target.rfind(os.sep) + 1:] if 'cstaticlib' in y.features: env.append_value('STATICLIB', link_name) elif 'cshlib' in y.features or 'cprogram' in y.features: # WARNING 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 dep_nodes = getattr(self.link_task, 'dep_nodes', []) self.link_task.dep_nodes = dep_nodes + y.link_task.outputs # add the link path too tmp_path = y.link_task.outputs[0].parent.bldpath(self.env) 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 for v in self.to_list(y.uselib): if not env['STATICLIB_' + v]: if not v in self.uselib: self.uselib.insert(0, v) # if the library task generator provides 'export_incdirs', add to the include path # the export_incdirs must be a list of paths relative to the other library if getattr(y, 'export_incdirs', None): for x in self.to_list(y.export_incdirs): node = y.path.find_dir(x) if not node: raise Utils.WafError('object %r: invalid folder %r in export_incdirs' % (y.target, x)) self.env.append_unique('INC_PATHS', node) # 2. the case of the libs defined outside for x in self.uselib: for v in self.p_flag_vars: val = self.env[v + '_' + x] if val: self.env.append_value(v, val) @feature('cprogram', 'cstaticlib', 'cshlib') @after('init_cc', 'init_cxx', 'apply_link') def apply_objdeps(self): "add the .o files produced by some other object files in the same manner as uselib_local" if not getattr(self, 'add_objects', None): return seen = [] names = self.to_list(self.add_objects) while names: x = names[0] # visit dependencies only once if x in seen: names = names[1:] continue # object does not exist ? y = self.name_to_obj(x) if not y: raise Utils.WafError('object %r was not found in uselib_local (required by add_objects %r)' % (x, self.name)) # 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 y.compiled_tasks: self.link_task.inputs.extend(t.outputs) @feature('cprogram', 'cshlib', 'cstaticlib') @after('apply_lib_vars') def apply_obj_vars(self): """after apply_lib_vars for uselib""" v = self.env lib_st = v['LIB_ST'] staticlib_st = v['STATICLIB_ST'] libpath_st = v['LIBPATH_ST'] staticlibpath_st = v['STATICLIBPATH_ST'] rpath_st = v['RPATH_ST'] app = v.append_unique if v['FULLSTATIC']: v.append_value('LINKFLAGS', v['FULLSTATIC_MARKER']) for i in v['RPATH']: if i and rpath_st: app('LINKFLAGS', rpath_st % i) for i in v['LIBPATH']: app('LINKFLAGS', libpath_st % i) app('LINKFLAGS', staticlibpath_st % i) if v['STATICLIB']: v.append_value('LINKFLAGS', v['STATICLIB_MARKER']) k = [(staticlib_st % i) for i in v['STATICLIB']] app('LINKFLAGS', k) # fully static binaries ? if not v['FULLSTATIC']: if v['STATICLIB'] or v['LIB']: v.append_value('LINKFLAGS', v['SHLIB_MARKER']) app('LINKFLAGS', [lib_st % i for i in v['LIB']]) @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 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) c_attrs = { 'cxxflag' : 'CXXFLAGS', 'cflag' : 'CCFLAGS', 'ccflag' : 'CCFLAGS', 'linkflag' : 'LINKFLAGS', 'ldflag' : 'LINKFLAGS', 'lib' : 'LIB', 'libpath' : 'LIBPATH', 'staticlib': 'STATICLIB', 'staticlibpath': 'STATICLIBPATH', 'rpath' : 'RPATH', 'framework' : 'FRAMEWORK', 'frameworkpath' : 'FRAMEWORKPATH' } @feature('c', 'cc', 'cxx') @before('init_cxx', 'init_cc') @before('apply_lib_vars', 'apply_obj_vars', 'apply_incpaths', 'init_cc') def add_extra_flags(self): """case and plural insensitive before apply_obj_vars for processing the library attributes """ for x in self.__dict__.keys(): y = x.lower() if y[-1] == 's': y = y[:-1] if c_attrs.get(y, None): self.env.append_unique(c_attrs[y], getattr(self, x)) # ============ the code above must not know anything about import libs ========== @feature('cshlib') @after('apply_link', 'default_cc') @before('apply_lib_vars', 'apply_objdeps', 'default_link_install') def apply_implib(self): """On mswindows, handle dlls and their import libs the .dll.a is the import lib and it is required for linking so it is installed too """ if not self.env.DEST_BINFMT == 'pe': return self.meths.remove('default_link_install') bindir = self.install_path if not bindir: return # install the dll in the bin dir dll = self.link_task.outputs[0] self.bld.install_files(bindir, dll, self.env, self.chmod) # add linker flags to generate the import lib implib = self.env['implib_PATTERN'] % os.path.split(self.target)[1] implib = dll.parent.find_or_declare(implib) self.link_task.outputs.append(implib) self.bld.install_as('${LIBDIR}/%s' % implib.name, implib, self.env) self.env.append_value('LINKFLAGS', (self.env['IMPLIB_ST'] % implib.bldpath(self.env)).split()) # ============ the code above must not know anything about vnum processing on unix platforms ========= @feature('cshlib') @after('apply_link') @before('apply_lib_vars', 'default_link_install') def apply_vnum(self): """ libfoo.so is installed as libfoo.so.1.2.3 """ if not getattr(self, 'vnum', '') or not 'cshlib' in self.features or os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'): return self.meths.remove('default_link_install') link = self.link_task nums = self.vnum.split('.') node = link.outputs[0] libname = node.name if libname.endswith('.dylib'): name3 = libname.replace('.dylib', '.%s.dylib' % self.vnum) name2 = libname.replace('.dylib', '.%s.dylib' % nums[0]) else: name3 = libname + '.' + self.vnum name2 = libname + '.' + nums[0] if self.env.SONAME_ST: v = self.env.SONAME_ST % name2 self.env.append_value('LINKFLAGS', v.split()) bld = self.bld nums = self.vnum.split('.') path = self.install_path if not path: return if self.env.DEST_OS == 'openbsd': libname = self.link_task.outputs[0].name bld.install_as('%s%s%s' % (path, os.sep, libname), node, env=self.env) else: bld.install_as(path + os.sep + name3, node, env=self.env) bld.symlink_as(path + os.sep + name2, name3) bld.symlink_as(path + os.sep + libname, name3) # the following task is just to enable execution from the build dir :-/ if self.env.DEST_OS != 'openbsd': self.create_task('vnum', node, [node.parent.find_or_declare(name2), node.parent.find_or_declare(name3)]) def exec_vnum_link(self): for x in self.outputs: path = x.abspath(self.env) try: os.remove(path) except OSError: pass try: os.symlink(self.inputs[0].name, path) except OSError: return 1 cls = Task.task_type_from_func('vnum', func=exec_vnum_link, ext_in='.bin', color='CYAN') cls.quiet = 1 # ============ the --as-needed flag should added during the configuration, not at runtime ========= @conftest def add_as_needed(conf): if conf.env.DEST_BINFMT == 'elf' and 'gcc' in (conf.env.CXX_NAME, conf.env.CC_NAME): conf.env.append_unique('LINKFLAGS', '--as-needed') tevent-0.9.34/third_party/waf/wafadmin/Tools/compiler_cc.py0000660000000000000000000000407312520121120023663 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Matthias Jahn jahn dôt matthias ât freenet dôt de, 2007 (pmarat) import os, sys, imp, types, ccroot import optparse import Utils, Configure, Options from Logs import debug c_compiler = { 'win32': ['msvc', 'gcc'], 'cygwin': ['gcc'], 'darwin': ['gcc'], 'aix': ['xlc', 'gcc'], 'linux': ['gcc', 'icc', 'suncc'], 'sunos': ['gcc', 'suncc'], 'irix': ['gcc'], 'hpux': ['gcc'], 'gnu': ['gcc'], 'default': ['gcc'] } def __list_possible_compiler(platform): try: return c_compiler[platform] except KeyError: return c_compiler["default"] def detect(conf): """ for each compiler for the platform, try to configure the compiler in theory the tools should raise a configuration error if the compiler pretends to be something it is not (setting CC=icc and trying to configure gcc) """ try: test_for_compiler = Options.options.check_c_compiler except AttributeError: conf.fatal("Add set_options(opt): opt.tool_options('compiler_cc')") orig = conf.env for compiler in test_for_compiler.split(): conf.env = orig.copy() try: conf.check_tool(compiler) except Configure.ConfigurationError, e: debug('compiler_cc: %r' % e) else: if conf.env['CC']: orig.table = conf.env.get_merged_dict() conf.env = orig conf.check_message(compiler, '', True) conf.env['COMPILER_CC'] = compiler break conf.check_message(compiler, '', False) break else: conf.fatal('could not configure a c compiler!') def set_options(opt): build_platform = Utils.unversioned_sys_platform() possible_compiler_list = __list_possible_compiler(build_platform) test_for_compiler = ' '.join(possible_compiler_list) cc_compiler_opts = opt.add_option_group("C Compiler Options") cc_compiler_opts.add_option('--check-c-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following C-Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), dest="check_c_compiler") for c_compiler in test_for_compiler.split(): opt.tool_options('%s' % c_compiler, option_group=cc_compiler_opts) tevent-0.9.34/third_party/waf/wafadmin/Tools/compiler_cxx.py0000660000000000000000000000360512520121120024100 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Matthias Jahn jahn dôt matthias ât freenet dôt de 2007 (pmarat) import os, sys, imp, types, ccroot import optparse import Utils, Configure, Options from Logs import debug cxx_compiler = { 'win32': ['msvc', 'g++'], 'cygwin': ['g++'], 'darwin': ['g++'], 'aix': ['xlc++', 'g++'], 'linux': ['g++', 'icpc', 'sunc++'], 'sunos': ['g++', 'sunc++'], 'irix': ['g++'], 'hpux': ['g++'], 'gnu': ['g++'], 'default': ['g++'] } def __list_possible_compiler(platform): try: return cxx_compiler[platform] except KeyError: return cxx_compiler["default"] def detect(conf): try: test_for_compiler = Options.options.check_cxx_compiler except AttributeError: raise Configure.ConfigurationError("Add set_options(opt): opt.tool_options('compiler_cxx')") orig = conf.env for compiler in test_for_compiler.split(): try: conf.env = orig.copy() conf.check_tool(compiler) except Configure.ConfigurationError, e: debug('compiler_cxx: %r' % e) else: if conf.env['CXX']: orig.table = conf.env.get_merged_dict() conf.env = orig conf.check_message(compiler, '', True) conf.env['COMPILER_CXX'] = compiler break conf.check_message(compiler, '', False) break else: conf.fatal('could not configure a cxx compiler!') def set_options(opt): build_platform = Utils.unversioned_sys_platform() possible_compiler_list = __list_possible_compiler(build_platform) test_for_compiler = ' '.join(possible_compiler_list) cxx_compiler_opts = opt.add_option_group('C++ Compiler Options') cxx_compiler_opts.add_option('--check-cxx-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following C++ Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), dest="check_cxx_compiler") for cxx_compiler in test_for_compiler.split(): opt.tool_options('%s' % cxx_compiler, option_group=cxx_compiler_opts) tevent-0.9.34/third_party/waf/wafadmin/Tools/compiler_d.py0000660000000000000000000000151412520121120023516 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) import os, sys, imp, types import Utils, Configure, Options def detect(conf): if getattr(Options.options, 'check_dmd_first', None): test_for_compiler = ['dmd', 'gdc'] else: test_for_compiler = ['gdc', 'dmd'] for d_compiler in test_for_compiler: try: conf.check_tool(d_compiler) except: pass else: break else: conf.fatal('no suitable d compiler was found') def set_options(opt): d_compiler_opts = opt.add_option_group('D Compiler Options') d_compiler_opts.add_option('--check-dmd-first', action='store_true', help='checks for the gdc compiler before dmd (default is the other way round)', dest='check_dmd_first', default=False) for d_compiler in ['gdc', 'dmd']: opt.tool_options('%s' % d_compiler, option_group=d_compiler_opts) tevent-0.9.34/third_party/waf/wafadmin/Tools/config_c.py0000660000000000000000000004667613055076237023220 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2008 (ita) """ c/c++ configuration routines """ import os, imp, sys, shlex, shutil from Utils import md5 import Build, Utils, Configure, Task, Options, Logs, TaskGen from Constants import * from Configure import conf, conftest cfg_ver = { 'atleast-version': '>=', 'exact-version': '==', 'max-version': '<=', } SNIP1 = ''' int main() { void *p; p=(void*)(%s); return 0; } ''' SNIP2 = ''' int main() { if ((%(type_name)s *) 0) return 0; if (sizeof (%(type_name)s)) return 0; } ''' SNIP3 = ''' int main() { return 0; } ''' def parse_flags(line, uselib, env): """pkg-config still has bugs on some platforms, and there are many -config programs, parsing flags is necessary :-/""" lst = shlex.split(line) while lst: x = lst.pop(0) st = x[:2] ot = x[2:] app = env.append_value if st == '-I' or st == '/I': if not ot: ot = lst.pop(0) app('CPPPATH_' + uselib, ot) elif st == '-D': if not ot: ot = lst.pop(0) app('CXXDEFINES_' + uselib, ot) app('CCDEFINES_' + uselib, ot) elif st == '-l': if not ot: ot = lst.pop(0) app('LIB_' + uselib, ot) elif st == '-L': if not ot: ot = lst.pop(0) app('LIBPATH_' + uselib, ot) elif x == '-pthread' or x.startswith('+'): app('CCFLAGS_' + uselib, x) app('CXXFLAGS_' + uselib, x) app('LINKFLAGS_' + uselib, x) elif x == '-framework': app('FRAMEWORK_' + uselib, lst.pop(0)) elif x.startswith('-F'): app('FRAMEWORKPATH_' + uselib, x[2:]) elif x.startswith('-std'): app('CCFLAGS_' + uselib, x) app('CXXFLAGS_' + uselib, x) app('LINKFLAGS_' + uselib, x) # # NOTE on special treatment of -Wl,-R and -Wl,-rpath: # # It is important to not put a library provided RPATH # into the LINKFLAGS but in the RPATH instead, since # the provided LINKFLAGS get prepended to our own internal # RPATH later, and hence can potentially lead to linking # in too old versions of our internal libs. # elif x == '-Wl,-rpath' or x == '-Wl,-R': app('RPATH_' + uselib, lst.pop(0).lstrip('-Wl,')) elif x.startswith('-Wl,-R,'): app('RPATH_' + uselib, x[7:]) elif x.startswith('-Wl,-R'): app('RPATH_' + uselib, x[6:]) elif x.startswith('-Wl,-rpath,'): app('RPATH_' + uselib, x[11:]) elif x.startswith('-Wl'): app('LINKFLAGS_' + uselib, x) elif x.startswith('-m') or x.startswith('-f'): app('CCFLAGS_' + uselib, x) app('CXXFLAGS_' + uselib, x) @conf def ret_msg(self, f, kw): """execute a function, when provided""" if isinstance(f, str): return f return f(kw) @conf def validate_cfg(self, kw): if not 'path' in kw: if not self.env.PKGCONFIG: self.find_program('pkg-config', var='PKGCONFIG') kw['path'] = self.env.PKGCONFIG # pkg-config version if 'atleast_pkgconfig_version' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for pkg-config version >= %s' % kw['atleast_pkgconfig_version'] return # pkg-config --modversion if 'modversion' in kw: return if 'variables' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for %s variables' % kw['package'] return # checking for the version of a module, for the moment, one thing at a time for x in cfg_ver.keys(): y = x.replace('-', '_') if y in kw: if not 'package' in kw: raise ValueError('%s requires a package' % x) if not 'msg' in kw: kw['msg'] = 'Checking for %s %s %s' % (kw['package'], cfg_ver[x], kw[y]) return if not 'msg' in kw: kw['msg'] = 'Checking for %s' % (kw['package'] or kw['path']) if not 'okmsg' in kw: kw['okmsg'] = 'yes' if not 'errmsg' in kw: kw['errmsg'] = 'not found' @conf def cmd_and_log(self, cmd, kw): Logs.debug('runner: %s\n' % cmd) if self.log: self.log.write('%s\n' % cmd) try: p = Utils.pproc.Popen(cmd, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE, shell=True) (out, err) = p.communicate() except OSError, e: self.log.write('error %r' % e) self.fatal(str(e)) # placeholder, don't touch out = str(out) err = str(err) if self.log: self.log.write(out) self.log.write(err) if p.returncode: if not kw.get('errmsg', ''): if kw.get('mandatory', False): kw['errmsg'] = out.strip() else: kw['errmsg'] = 'no' self.fatal('fail') return out @conf def exec_cfg(self, kw): # pkg-config version if 'atleast_pkgconfig_version' in kw: cmd = '%s --atleast-pkgconfig-version=%s' % (kw['path'], kw['atleast_pkgconfig_version']) self.cmd_and_log(cmd, kw) if not 'okmsg' in kw: kw['okmsg'] = 'yes' return # checking for the version of a module for x in cfg_ver: y = x.replace('-', '_') if y in kw: self.cmd_and_log('%s --%s=%s %s' % (kw['path'], x, kw[y], kw['package']), kw) if not 'okmsg' in kw: kw['okmsg'] = 'yes' self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0) break # retrieving the version of a module if 'modversion' in kw: version = self.cmd_and_log('%s --modversion %s' % (kw['path'], kw['modversion']), kw).strip() self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version) return version # retrieving variables of a module if 'variables' in kw: env = kw.get('env', self.env) uselib = kw.get('uselib_store', kw['package'].upper()) vars = Utils.to_list(kw['variables']) for v in vars: val = self.cmd_and_log('%s --variable=%s %s' % (kw['path'], v, kw['package']), kw).strip() var = '%s_%s' % (uselib, v) env[var] = val if not 'okmsg' in kw: kw['okmsg'] = 'yes' return lst = [kw['path']] defi = kw.get('define_variable', None) if not defi: defi = self.env.PKG_CONFIG_DEFINES or {} for key, val in defi.iteritems(): lst.append('--define-variable=%s=%s' % (key, val)) lst.append(kw.get('args', '')) lst.append(kw['package']) # so we assume the command-line will output flags to be parsed afterwards cmd = ' '.join(lst) ret = self.cmd_and_log(cmd, kw) if not 'okmsg' in kw: kw['okmsg'] = 'yes' self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0) parse_flags(ret, kw.get('uselib_store', kw['package'].upper()), kw.get('env', self.env)) return ret @conf def check_cfg(self, *k, **kw): """ for pkg-config mostly, but also all the -config tools conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', package='', uselib_store='OPEN_MPI') conf.check_cfg(package='dbus-1', variables='system_bus_default_address session_bus_services_dir') """ self.validate_cfg(kw) if 'msg' in kw: self.check_message_1(kw['msg']) ret = None try: ret = self.exec_cfg(kw) except Configure.ConfigurationError, e: if 'errmsg' in kw: self.check_message_2(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 if 'okmsg' in kw: self.check_message_2(self.ret_msg(kw['okmsg'], kw)) return ret # the idea is the following: now that we are certain # that all the code here is only for c or c++, it is # easy to put all the logic in one function # # this should prevent code duplication (ita) # env: an optional environment (modified -> provide a copy) # compiler: cc or cxx - it tries to guess what is best # type: cprogram, cshlib, cstaticlib # code: a c code to execute # uselib_store: where to add the variables # uselib: parameters to use for building # define: define to set, like FOO in #define FOO, if not set, add /* #undef FOO */ # execute: True or False - will return the result of the execution @conf def validate_c(self, kw): """validate the parameters for the test method""" if not 'env' in kw: kw['env'] = self.env.copy() env = kw['env'] if not 'compiler' in kw: kw['compiler'] = 'cc' if env['CXX_NAME'] and Task.TaskBase.classes.get('cxx', None): 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 'type' in kw: kw['type'] = 'cprogram' assert not(kw['type'] != 'cprogram' and kw.get('execute', 0)), 'can only execute programs' #if kw['type'] != 'program' and kw.get('execute', 0): # raise ValueError, 'can only execute programs' 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 '' # set the file name if not 'compile_mode' in kw: kw['compile_mode'] = (kw['compiler'] == 'cxx') and 'cxx' or 'cc' if not 'compile_filename' in kw: kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '') #OSX if 'framework_name' in kw: try: TaskGen.task_gen.create_task_macapp except AttributeError: self.fatal('frameworks require the osx tool') fwkname = kw['framework_name'] if not 'uselib_store' in kw: kw['uselib_store'] = fwkname.upper() if not kw.get('no_header', False): if not 'header_name' in kw: kw['header_name'] = [] fwk = '%s/%s.h' % (fwkname, fwkname) if kw.get('remove_dot_h', None): fwk = fwk[:-2] kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk] kw['msg'] = 'Checking for framework %s' % fwkname kw['framework'] = fwkname #kw['frameworkpath'] = set it yourself if 'function_name' in kw: fu = kw['function_name'] if not 'msg' in kw: kw['msg'] = 'Checking for function %s' % fu kw['code'] = to_header(kw) + SNIP1 % fu if not 'uselib_store' in kw: kw['uselib_store'] = fu.upper() if not 'define_name' in kw: kw['define_name'] = self.have_define(fu) elif 'type_name' in kw: tu = kw['type_name'] if not 'msg' in kw: kw['msg'] = 'Checking for type %s' % tu if not 'header_name' in kw: kw['header_name'] = 'stdint.h' kw['code'] = to_header(kw) + SNIP2 % {'type_name' : tu} if not 'define_name' in kw: kw['define_name'] = self.have_define(tu.upper()) 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)>0, 'list of headers in header_name is empty' kw['code'] = to_header(kw) + SNIP3 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 'staticlib' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for static library %s' % kw['staticlib'] if not 'uselib_store' in kw: kw['uselib_store'] = kw['staticlib'].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 custom code' 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 not 'errmsg' in kw: kw['errmsg'] = 'not found' if not 'okmsg' in kw: kw['okmsg'] = 'yes' if not 'code' in kw: kw['code'] = SNIP3 if not kw.get('success'): kw['success'] = None assert 'msg' in kw, 'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c' @conf def post_check(self, *k, **kw): "set the variables after a test was run successfully" is_success = False if kw['execute']: if kw['success'] is not None: is_success = True else: is_success = (kw['success'] == 0) if 'define_name' in kw: if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw: if kw['execute']: key = kw['success'] if isinstance(key, str): if key: self.define(kw['define_name'], key, quote=kw.get('quote', 1)) else: self.define_cond(kw['define_name'], True) else: self.define_cond(kw['define_name'], False) else: self.define_cond(kw['define_name'], is_success) if is_success and 'uselib_store' in kw: import cc, cxx for k in set(cc.g_cc_flag_vars).union(cxx.g_cxx_flag_vars): lk = k.lower() # inconsistency: includes -> CPPPATH if k == 'CPPPATH': lk = 'includes' if k == 'CXXDEFINES': lk = 'defines' if k == 'CCDEFINES': lk = 'defines' if lk in kw: val = kw[lk] # remove trailing slash if isinstance(val, str): val = val.rstrip(os.path.sep) self.env.append_unique(k + '_' + kw['uselib_store'], val) @conf def check(self, *k, **kw): # so this will be the generic function # it will be safer to use check_cxx or check_cc self.validate_c(kw) self.check_message_1(kw['msg']) ret = None try: ret = self.run_c_code(*k, **kw) except Configure.ConfigurationError, e: self.check_message_2(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.check_message_2(self.ret_msg(kw['okmsg'], kw)) self.post_check(*k, **kw) if not kw.get('execute', False): return ret == 0 return ret @conf def run_c_code(self, *k, **kw): test_f_name = kw['compile_filename'] k = 0 while k < 10000: # make certain to use a fresh folder - necessary for win32 dir = os.path.join(self.blddir, '.conf_check_%d' % k) # if the folder already exists, remove it try: shutil.rmtree(dir) except OSError: pass try: os.stat(dir) except OSError: break k += 1 try: os.makedirs(dir) except: self.fatal('cannot create a configuration test folder %r' % dir) try: os.stat(dir) except: self.fatal('cannot use the configuration test folder %r' % dir) bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) env = kw['env'] dest = open(os.path.join(dir, test_f_name), 'w') dest.write(kw['code']) dest.close() back = os.path.abspath('.') bld = Build.BuildContext() bld.log = self.log bld.all_envs.update(self.all_envs) bld.all_envs['default'] = env bld.lst_variants = bld.all_envs.keys() bld.load_dirs(dir, bdir) os.chdir(dir) bld.rescan(bld.srcnode) if not 'features' in kw: # conf.check(features='cc cprogram pyext', ...) kw['features'] = [kw['compile_mode'], kw['type']] # "cprogram cc" o = bld(features=kw['features'], source=test_f_name, target='testprog') for k, v in kw.iteritems(): setattr(o, k, v) self.log.write("==>\n%s\n<==\n" % kw['code']) # compile the program try: bld.compile() except Utils.WafError: ret = Utils.ex_stack() else: ret = 0 # chdir before returning os.chdir(back) if ret: self.log.write('command returned %r' % ret) self.fatal(str(ret)) # if we need to run the program, try to get its result # keep the name of the program to execute if kw['execute']: lastprog = o.link_task.outputs[0].abspath(env) args = Utils.to_list(kw.get('exec_args', [])) proc = Utils.pproc.Popen([lastprog] + args, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE) (out, err) = proc.communicate() w = self.log.write w(str(out)) w('\n') w(str(err)) w('\n') w('returncode %r' % proc.returncode) w('\n') if proc.returncode: self.fatal(Utils.ex_stack()) ret = out return ret @conf def check_cxx(self, *k, **kw): kw['compiler'] = 'cxx' return self.check(*k, **kw) @conf def check_cc(self, *k, **kw): kw['compiler'] = 'cc' return self.check(*k, **kw) @conf def define(self, define, value, quote=1): """store a single define and its state into an internal list for later writing to a config header file. Value can only be a string or int; other types not supported. String values will appear properly quoted in the generated header file.""" assert define and isinstance(define, str) # ordered_dict is for writing the configuration header in order tbl = self.env[DEFINES] or Utils.ordered_dict() # the user forgot to tell if the value is quoted or not if isinstance(value, str): if quote: tbl[define] = '"%s"' % repr('"'+value)[2:-1].replace('"', '\\"') else: tbl[define] = value elif isinstance(value, int): tbl[define] = value else: raise TypeError('define %r -> %r must be a string or an int' % (define, value)) # add later to make reconfiguring faster self.env[DEFINES] = tbl self.env[define] = value # <- not certain this is necessary @conf def undefine(self, define): """store a single define and its state into an internal list for later writing to a config header file""" assert define and isinstance(define, str) tbl = self.env[DEFINES] or Utils.ordered_dict() value = UNDEFINED tbl[define] = value # add later to make reconfiguring faster self.env[DEFINES] = tbl self.env[define] = value @conf def define_cond(self, name, value): """Conditionally define a name. Formally equivalent to: if value: define(name, 1) else: undefine(name)""" if value: self.define(name, 1) else: self.undefine(name) @conf def is_defined(self, key): defines = self.env[DEFINES] if not defines: return False try: value = defines[key] except KeyError: return False else: return value != UNDEFINED @conf def get_define(self, define): "get the value of a previously stored define" try: return self.env[DEFINES][define] except KeyError: return None @conf def have_define(self, name): "prefix the define with 'HAVE_' and make sure it has valid characters." return self.__dict__.get('HAVE_PAT', 'HAVE_%s') % Utils.quote_define_name(name) @conf def write_config_header(self, configfile='', env='', guard='', top=False): "save the defines into a file" if not configfile: configfile = WAF_CONFIG_H waf_guard = guard or '_%s_WAF' % Utils.quote_define_name(configfile) # configfile -> absolute path # there is a good reason to concatenate first and to split afterwards if not env: env = self.env if top: diff = '' else: diff = Utils.diff_path(self.srcdir, self.curdir) full = os.sep.join([self.blddir, env.variant(), diff, configfile]) full = os.path.normpath(full) (dir, base) = os.path.split(full) try: os.makedirs(dir) except: pass dest = open(full, 'w') dest.write('/* Configuration header created by Waf - do not edit */\n') dest.write('#ifndef %s\n#define %s\n\n' % (waf_guard, waf_guard)) dest.write(self.get_config_header()) # config files are not removed on "waf clean" env.append_unique(CFG_FILES, os.path.join(diff, configfile)) dest.write('\n#endif /* %s */\n' % waf_guard) dest.close() @conf def get_config_header(self): """Fill-in the contents of the config header. Override when you need to write your own config header.""" config_header = [] tbl = self.env[DEFINES] or Utils.ordered_dict() for key in tbl.allkeys: value = tbl[key] if value is None: config_header.append('#define %s' % key) elif value is UNDEFINED: config_header.append('/* #undef %s */' % key) else: config_header.append('#define %s %s' % (key, value)) return "\n".join(config_header) @conftest def find_cpp(conf): v = conf.env cpp = [] if v['CPP']: cpp = v['CPP'] elif 'CPP' in conf.environ: cpp = conf.environ['CPP'] if not cpp: cpp = conf.find_program('cpp', var='CPP') #if not cpp: cpp = v['CC'] #if not cpp: cpp = v['CXX'] v['CPP'] = cpp @conftest def cc_add_flags(conf): conf.add_os_flags('CFLAGS', 'CCFLAGS') conf.add_os_flags('CPPFLAGS') @conftest def cxx_add_flags(conf): conf.add_os_flags('CXXFLAGS') conf.add_os_flags('CPPFLAGS') @conftest def link_add_flags(conf): conf.add_os_flags('LINKFLAGS') conf.add_os_flags('LDFLAGS', 'LINKFLAGS') @conftest def cc_load_tools(conf): conf.check_tool('cc') @conftest def cxx_load_tools(conf): conf.check_tool('cxx') tevent-0.9.34/third_party/waf/wafadmin/Tools/cs.py0000660000000000000000000000341212520121120022005 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) "C# support" import TaskGen, Utils, Task, Options from Logs import error from TaskGen import before, after, taskgen, feature flag_vars= ['FLAGS', 'ASSEMBLIES'] @feature('cs') def init_cs(self): Utils.def_attrs(self, flags = '', assemblies = '', resources = '', uselib = '') @feature('cs') @after('init_cs') def apply_uselib_cs(self): if not self.uselib: return global flag_vars for var in self.to_list(self.uselib): for v in self.flag_vars: val = self.env[v+'_'+var] if val: self.env.append_value(v, val) @feature('cs') @after('apply_uselib_cs') @before('apply_core') def apply_cs(self): try: self.meths.remove('apply_core') except ValueError: pass # process the flags for the assemblies for i in self.to_list(self.assemblies) + self.env['ASSEMBLIES']: self.env.append_unique('_ASSEMBLIES', '/r:'+i) # process the flags for the resources for i in self.to_list(self.resources): self.env.append_unique('_RESOURCES', '/resource:'+i) # what kind of assembly are we generating? self.env['_TYPE'] = getattr(self, 'type', 'exe') # additional flags self.env.append_unique('_FLAGS', self.to_list(self.flags)) self.env.append_unique('_FLAGS', self.env.FLAGS) # process the sources nodes = [self.path.find_resource(i) for i in self.to_list(self.source)] self.create_task('mcs', nodes, self.path.find_or_declare(self.target)) Task.simple_task_type('mcs', '${MCS} ${SRC} /target:${_TYPE} /out:${TGT} ${_FLAGS} ${_ASSEMBLIES} ${_RESOURCES}', color='YELLOW') def detect(conf): csc = getattr(Options.options, 'cscbinary', None) if csc: conf.env.MCS = csc conf.find_program(['gmcs', 'mcs'], var='MCS') def set_options(opt): opt.add_option('--with-csc-binary', type='string', dest='cscbinary') tevent-0.9.34/third_party/waf/wafadmin/Tools/cxx.py0000660000000000000000000000606712520121120022213 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) "Base for c++ programs and libraries" import TaskGen, Task, Utils from Logs import debug import ccroot # <- do not remove from TaskGen import feature, before, extension, after g_cxx_flag_vars = [ 'CXXDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'STATICLIB', 'LIB', 'LIBPATH', 'LINKFLAGS', 'RPATH', 'CXXFLAGS', 'CCFLAGS', 'CPPPATH', 'CPPFLAGS', 'CXXDEFINES'] "main cpp variables" EXT_CXX = ['.cpp', '.cc', '.cxx', '.C', '.c++'] g_cxx_type_vars=['CXXFLAGS', 'LINKFLAGS'] # TODO remove in waf 1.6 class cxx_taskgen(ccroot.ccroot_abstract): pass @feature('cxx') @before('apply_type_vars') @after('default_cc') def init_cxx(self): if not 'cc' in self.features: self.mappings['.c'] = TaskGen.task_gen.mappings['.cxx'] self.p_flag_vars = set(self.p_flag_vars).union(g_cxx_flag_vars) self.p_type_vars = set(self.p_type_vars).union(g_cxx_type_vars) if not self.env['CXX_NAME']: raise Utils.WafError("At least one compiler (g++, ..) must be selected") @feature('cxx') @after('apply_incpaths') def apply_obj_vars_cxx(self): """after apply_incpaths for INC_PATHS""" env = self.env app = env.append_unique cxxpath_st = env['CPPPATH_ST'] # local flags come first # set the user-defined includes paths for i in env['INC_PATHS']: app('_CXXINCFLAGS', cxxpath_st % i.bldpath(env)) app('_CXXINCFLAGS', cxxpath_st % i.srcpath(env)) # set the library include paths for i in env['CPPPATH']: app('_CXXINCFLAGS', cxxpath_st % i) @feature('cxx') @after('apply_lib_vars') def apply_defines_cxx(self): """after uselib is set for CXXDEFINES""" self.defines = getattr(self, 'defines', []) lst = self.to_list(self.defines) + self.to_list(self.env['CXXDEFINES']) milst = [] # now process the local defines for defi in lst: if not defi in milst: milst.append(defi) # CXXDEFINES_USELIB libs = self.to_list(self.uselib) for l in libs: val = self.env['CXXDEFINES_'+l] if val: milst += self.to_list(val) self.env['DEFLINES'] = ["%s %s" % (x[0], Utils.trimquotes('='.join(x[1:]))) for x in [y.split('=') for y in milst]] y = self.env['CXXDEFINES_ST'] self.env.append_unique('_CXXDEFFLAGS', [y%x for x in milst]) @extension(EXT_CXX) def cxx_hook(self, node): # create the compilation task: cpp or cc if getattr(self, 'obj_ext', None): obj_ext = self.obj_ext else: obj_ext = '_%d.o' % self.idx task = self.create_task('cxx', node, node.change_ext(obj_ext)) try: self.compiled_tasks.append(task) except AttributeError: raise Utils.WafError('Have you forgotten to set the feature "cxx" on %s?' % str(self)) return task cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${_CXXINCFLAGS} ${_CXXDEFFLAGS} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}' cls = Task.simple_task_type('cxx', cxx_str, color='GREEN', ext_out='.o', ext_in='.cxx', shell=False) cls.scan = ccroot.scan cls.vars.append('CXXDEPS') link_str = '${LINK_CXX} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}' cls = Task.simple_task_type('cxx_link', link_str, color='YELLOW', ext_in='.o', ext_out='.bin', shell=False) cls.maxjobs = 1 cls.install = Utils.nada tevent-0.9.34/third_party/waf/wafadmin/Tools/d.py0000660000000000000000000003423312520121120021630 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2007-2008 (ita) import os, sys, re, optparse import ccroot # <- leave this import TaskGen, Utils, Task, Configure, Logs, Build from Logs import debug, error from TaskGen import taskgen, feature, after, before, extension from Configure import conftest EXT_D = ['.d', '.di', '.D'] D_METHS = ['apply_core', 'apply_vnum', 'apply_objdeps'] # additional d methods 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; } } } """ def filter_comments(filename): 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): def __init__(self, env, incpaths): #self.code = '' #self.module = '' #self.imports = [] self.allnames = [] self.re_module = re.compile("module\s+([^;]+)") self.re_import = re.compile("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): 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): #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('\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('\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): 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): path = node.abspath(self.env) # 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 the .d source need" env = self.env gruik = d_parser(env, env['INC_PATHS']) gruik.start(self.inputs[0]) if Logs.verbose: debug('deps: nodes found for %s: %s %s' % (str(self.inputs[0]), str(gruik.nodes), str(gruik.names))) #debug("deps found for %s: %s" % (str(node), str(gruik.deps)), 'deps') return (gruik.nodes, gruik.names) def get_target_name(self): "for d programs and libs" v = self.env tp = 'program' for x in self.features: if x in ['dshlib', 'dstaticlib']: tp = x.lstrip('d') return v['D_%s_PATTERN' % tp] % self.target d_params = { 'dflags': '', 'importpaths':'', 'libs':'', 'libpaths':'', 'generate_headers':False, } @feature('d') @before('apply_type_vars') def init_d(self): for x in d_params: setattr(self, x, getattr(self, x, d_params[x])) class d_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) # COMPAT if len(k) > 1: self.features.append('d' + k[1]) # okay, we borrow a few methods from ccroot TaskGen.bind_feature('d', D_METHS) @feature('d') @before('apply_d_libs') def init_d(self): Utils.def_attrs(self, dflags='', importpaths='', libs='', libpaths='', uselib='', uselib_local='', generate_headers=False, # set to true if you want .di files as well as .o compiled_tasks=[], add_objects=[], link_task=None) @feature('d') @after('apply_d_link', 'init_d') @before('apply_vnum', 'apply_d_vars') def apply_d_libs(self): """after apply_link because of 'link_task' after default_cc because of the attribute 'uselib'""" env = self.env # 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(self.uselib) names = self.to_list(self.uselib_local) seen = set([]) tmp = Utils.deque(names) # consume a copy of the list of names while tmp: lib_name = tmp.popleft() # visit dependencies only once if lib_name in seen: continue y = self.name_to_obj(lib_name) if not y: raise Utils.WafError('object %r was not found in uselib_local (required by %r)' % (lib_name, self.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): lst = y.to_list(y.uselib_local) if 'dshlib' in y.features or 'dprogram' in y.features: lst = [x for x in lst if not 'dstaticlib' in self.name_to_obj(x).features] tmp.extend(lst) # link task and flags if getattr(y, 'link_task', None): link_name = y.target[y.target.rfind(os.sep) + 1:] if 'dstaticlib' in y.features or 'dshlib' in y.features: env.append_unique('DLINKFLAGS', env.DLIB_ST % link_name) env.append_unique('DLINKFLAGS', env.DLIBPATH_ST % y.link_task.outputs[0].parent.bldpath(env)) # the order self.link_task.set_run_after(y.link_task) # for the recompilation dep_nodes = getattr(self.link_task, 'dep_nodes', []) self.link_task.dep_nodes = dep_nodes + y.link_task.outputs # add ancestors uselib too - but only propagate those that have no staticlib for v in self.to_list(y.uselib): if not v in self.uselib: self.uselib.insert(0, v) # if the library task generator provides 'export_incdirs', add to the include path # the export_incdirs must be a list of paths relative to the other library if getattr(y, 'export_incdirs', None): for x in self.to_list(y.export_incdirs): node = y.path.find_dir(x) if not node: raise Utils.WafError('object %r: invalid folder %r in export_incdirs' % (y.target, x)) self.env.append_unique('INC_PATHS', node) @feature('dprogram', 'dshlib', 'dstaticlib') @after('apply_core') def apply_d_link(self): link = getattr(self, 'link', None) if not link: if 'dstaticlib' in self.features: link = 'static_link' else: link = 'd_link' outputs = [t.outputs[0] for t in self.compiled_tasks] self.link_task = self.create_task(link, outputs, self.path.find_or_declare(get_target_name(self))) @feature('d') @after('apply_core') def apply_d_vars(self): env = self.env dpath_st = env['DPATH_ST'] lib_st = env['DLIB_ST'] libpath_st = env['DLIBPATH_ST'] importpaths = self.to_list(self.importpaths) libpaths = [] libs = [] uselib = self.to_list(self.uselib) for i in uselib: if env['DFLAGS_' + i]: env.append_unique('DFLAGS', env['DFLAGS_' + i]) for x in self.features: if not x in ['dprogram', 'dstaticlib', 'dshlib']: continue x.lstrip('d') d_shlib_dflags = env['D_' + x + '_DFLAGS'] if d_shlib_dflags: env.append_unique('DFLAGS', d_shlib_dflags) # add import paths for i in uselib: if env['DPATH_' + i]: for entry in self.to_list(env['DPATH_' + i]): if not entry in importpaths: importpaths.append(entry) # now process the import paths for path in importpaths: if os.path.isabs(path): env.append_unique('_DIMPORTFLAGS', dpath_st % path) else: node = self.path.find_dir(path) self.env.append_unique('INC_PATHS', node) env.append_unique('_DIMPORTFLAGS', dpath_st % node.srcpath(env)) env.append_unique('_DIMPORTFLAGS', dpath_st % node.bldpath(env)) # add library paths for i in uselib: if env['LIBPATH_' + i]: for entry in self.to_list(env['LIBPATH_' + i]): if not entry in libpaths: libpaths.append(entry) libpaths = self.to_list(self.libpaths) + libpaths # now process the library paths # apply same path manipulation as used with import paths for path in libpaths: if not os.path.isabs(path): node = self.path.find_resource(path) if not node: raise Utils.WafError('could not find libpath %r from %r' % (path, self)) path = node.abspath(self.env) env.append_unique('DLINKFLAGS', libpath_st % path) # add libraries for i in uselib: if env['LIB_' + i]: for entry in self.to_list(env['LIB_' + i]): if not entry in libs: libs.append(entry) libs.extend(self.to_list(self.libs)) # process user flags for flag in self.to_list(self.dflags): env.append_unique('DFLAGS', flag) # now process the libraries for lib in libs: env.append_unique('DLINKFLAGS', lib_st % lib) # add linker flags for i in uselib: dlinkflags = env['DLINKFLAGS_' + i] if dlinkflags: for linkflag in dlinkflags: env.append_unique('DLINKFLAGS', linkflag) @feature('dshlib') @after('apply_d_vars') def add_shlib_d_flags(self): for linkflag in self.env['D_shlib_LINKFLAGS']: self.env.append_unique('DLINKFLAGS', linkflag) @extension(EXT_D) def d_hook(self, node): # create the compilation task: cpp or cc task = self.create_task(self.generate_headers and 'd_with_header' or 'd') try: obj_ext = self.obj_ext except AttributeError: obj_ext = '_%d.o' % self.idx task.inputs = [node] task.outputs = [node.change_ext(obj_ext)] self.compiled_tasks.append(task) if self.generate_headers: header_node = node.change_ext(self.env['DHEADER_ext']) task.outputs += [header_node] d_str = '${D_COMPILER} ${DFLAGS} ${_DIMPORTFLAGS} ${D_SRC_F}${SRC} ${D_TGT_F}${TGT}' d_with_header_str = '${D_COMPILER} ${DFLAGS} ${_DIMPORTFLAGS} \ ${D_HDR_F}${TGT[1].bldpath(env)} \ ${D_SRC_F}${SRC} \ ${D_TGT_F}${TGT[0].bldpath(env)}' link_str = '${D_LINKER} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F}${TGT} ${DLINKFLAGS}' def override_exec(cls): """stupid dmd wants -of stuck to the file name""" old_exec = cls.exec_command def exec_command(self, *k, **kw): if isinstance(k[0], list): lst = k[0] for i in xrange(len(lst)): if lst[i] == '-of': del lst[i] lst[i] = '-of' + lst[i] break return old_exec(self, *k, **kw) cls.exec_command = exec_command cls = Task.simple_task_type('d', d_str, 'GREEN', before='static_link d_link', shell=False) cls.scan = scan override_exec(cls) cls = Task.simple_task_type('d_with_header', d_with_header_str, 'GREEN', before='static_link d_link', shell=False) override_exec(cls) cls = Task.simple_task_type('d_link', link_str, color='YELLOW', shell=False) override_exec(cls) # for feature request #104 @taskgen def generate_header(self, filename, install_path): if not hasattr(self, 'header_lst'): self.header_lst = [] self.meths.append('process_header') self.header_lst.append([filename, install_path]) @before('apply_core') def process_header(self): env = self.env for i in getattr(self, 'header_lst', []): node = self.path.find_resource(i[0]) if not node: raise Utils.WafError('file not found on d obj '+i[0]) task = self.create_task('d_header') task.set_inputs(node) task.set_outputs(node.change_ext('.di')) d_header_str = '${D_COMPILER} ${D_HEADER} ${SRC}' Task.simple_task_type('d_header', d_header_str, color='BLUE', shell=False) @conftest def d_platform_flags(conf): v = conf.env binfmt = v.DEST_BINFMT or Utils.unversioned_sys_platform_to_binary_format( v.DEST_OS or Utils.unversioned_sys_platform()) if binfmt == 'pe': v['D_program_PATTERN'] = '%s.exe' v['D_shlib_PATTERN'] = 'lib%s.dll' v['D_staticlib_PATTERN'] = 'lib%s.a' else: v['D_program_PATTERN'] = '%s' v['D_shlib_PATTERN'] = 'lib%s.so' v['D_staticlib_PATTERN'] = 'lib%s.a' @conftest def check_dlibrary(conf): ret = conf.check_cc(features='d dprogram', fragment=DLIB, mandatory=True, compile_filename='test.d', execute=True) conf.env.DLIBRARY = ret.strip() # quick test # if __name__ == "__main__": #Logs.verbose = 2 try: arg = sys.argv[1] except IndexError: arg = "file.d" print("".join(filter_comments(arg))) # TODO paths = ['.'] #gruik = filter() #gruik.start(arg) #code = "".join(gruik.buf) #print "we have found the following code" #print code #print "now parsing" #print "-------------------------------------------" """ parser_ = d_parser() parser_.start(arg) print "module: %s" % parser_.module print "imports: ", for imp in parser_.imports: print imp + " ", print """ tevent-0.9.34/third_party/waf/wafadmin/Tools/dbus.py0000660000000000000000000000175712520121120022347 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 import Task, Utils from TaskGen import taskgen, before, after, feature @taskgen def add_dbus_file(self, filename, prefix, mode): if not hasattr(self, 'dbus_lst'): self.dbus_lst = [] self.meths.append('process_dbus') self.dbus_lst.append([filename, prefix, mode]) @before('apply_core') def process_dbus(self): for filename, prefix, mode in getattr(self, 'dbus_lst', []): node = self.path.find_resource(filename) if not node: raise Utils.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 Task.simple_task_type('dbus_binding_tool', '${DBUS_BINDING_TOOL} --prefix=${DBUS_BINDING_TOOL_PREFIX} --mode=${DBUS_BINDING_TOOL_MODE} --output=${TGT} ${SRC}', color='BLUE', before='cc') def detect(conf): dbus_binding_tool = conf.find_program('dbus-binding-tool', var='DBUS_BINDING_TOOL') tevent-0.9.34/third_party/waf/wafadmin/Tools/dmd.py0000660000000000000000000000305412520121120022146 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2008 (ita) import sys import Utils, ar from Configure import conftest @conftest def find_dmd(conf): conf.find_program(['dmd', 'ldc'], var='D_COMPILER', mandatory=True) @conftest def common_flags_ldc(conf): v = conf.env v['DFLAGS'] = ['-d-version=Posix'] v['DLINKFLAGS'] = [] v['D_shlib_DFLAGS'] = ['-relocation-model=pic'] @conftest def common_flags_dmd(conf): v = conf.env # _DFLAGS _DIMPORTFLAGS # Compiler is dmd so 'gdc' part will be ignored, just # ensure key is there, so wscript can append flags to it v['DFLAGS'] = ['-version=Posix'] v['D_SRC_F'] = '' v['D_TGT_F'] = ['-c', '-of'] v['DPATH_ST'] = '-I%s' # template for adding import paths # linker v['D_LINKER'] = v['D_COMPILER'] v['DLNK_SRC_F'] = '' v['DLNK_TGT_F'] = '-of' v['DLIB_ST'] = '-L-l%s' # template for adding libs v['DLIBPATH_ST'] = '-L-L%s' # template for adding libpaths # linker debug levels v['DFLAGS_OPTIMIZED'] = ['-O'] v['DFLAGS_DEBUG'] = ['-g', '-debug'] v['DFLAGS_ULTRADEBUG'] = ['-g', '-debug'] v['DLINKFLAGS'] = ['-quiet'] v['D_shlib_DFLAGS'] = ['-fPIC'] v['D_shlib_LINKFLAGS'] = ['-L-shared'] v['DHEADER_ext'] = '.di' v['D_HDR_F'] = ['-H', '-Hf'] def detect(conf): conf.find_dmd() conf.check_tool('ar') conf.check_tool('d') conf.common_flags_dmd() conf.d_platform_flags() if conf.env.D_COMPILER.find('ldc') > -1: conf.common_flags_ldc() tevent-0.9.34/third_party/waf/wafadmin/Tools/flex.py0000660000000000000000000000072612520121120022343 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 # Thomas Nagy, 2006-2008 "Flex processing" import TaskGen def decide_ext(self, node): if 'cxx' in self.features: return '.lex.cc' else: return '.lex.c' TaskGen.declare_chain( name = 'flex', rule = '${FLEX} -o${TGT} ${FLEXFLAGS} ${SRC}', ext_in = '.l', ext_out = '.c .cxx', decider = decide_ext ) def detect(conf): conf.find_program('flex', var='FLEX', mandatory=True) conf.env['FLEXFLAGS'] = '' tevent-0.9.34/third_party/waf/wafadmin/Tools/gas.py0000660000000000000000000000212412520121120022151 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008 (ita) "as and gas" import os, sys import Task from TaskGen import extension, taskgen, after, before EXT_ASM = ['.s', '.S', '.asm', '.ASM', '.spp', '.SPP'] as_str = '${AS} ${ASFLAGS} ${_ASINCFLAGS} ${SRC} -o ${TGT}' Task.simple_task_type('asm', as_str, 'PINK', ext_out='.o', shell=False) @extension(EXT_ASM) def asm_hook(self, node): # create the compilation task: cpp or cc try: obj_ext = self.obj_ext except AttributeError: obj_ext = '_%d.o' % self.idx task = self.create_task('asm', node, node.change_ext(obj_ext)) self.compiled_tasks.append(task) self.meths.append('asm_incflags') @after('apply_obj_vars_cc') @after('apply_obj_vars_cxx') @before('apply_link') def asm_incflags(self): self.env.append_value('_ASINCFLAGS', self.env.ASINCFLAGS) var = ('cxx' in self.features) and 'CXX' or 'CC' self.env.append_value('_ASINCFLAGS', self.env['_%sINCFLAGS' % var]) def detect(conf): conf.find_program(['gas', 'as'], var='AS') if not conf.env.AS: conf.env.AS = conf.env.CC #conf.env.ASFLAGS = ['-c'] <- may be necesary for .S files tevent-0.9.34/third_party/waf/wafadmin/Tools/gcc.py0000660000000000000000000000761312520121120022143 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2008 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 import os, sys import Configure, Options, Utils import ccroot, ar from Configure import conftest @conftest def find_gcc(conf): cc = conf.find_program(['gcc', 'cc'], var='CC', mandatory=True) cc = conf.cmd_to_list(cc) ccroot.get_cc_version(conf, cc, gcc=True) conf.env.CC_NAME = 'gcc' conf.env.CC = cc @conftest def gcc_common_flags(conf): v = conf.env # CPPFLAGS CCDEFINES _CCINCFLAGS _CCDEFFLAGS v['CCFLAGS_DEBUG'] = ['-g'] v['CCFLAGS_RELEASE'] = ['-O2'] v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = '' v['CCLNK_TGT_F'] = ['-o', ''] # shell hack for -MD v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['CCDEFINES_ST'] = '-D%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Wl,-Bdynamic' v['STATICLIB_MARKER'] = '-Wl,-Bstatic' v['FULLSTATIC_MARKER'] = '-static' # program v['program_PATTERN'] = '%s' # shared library v['shlib_CCFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro v['shlib_LINKFLAGS'] = ['-shared'] v['shlib_PATTERN'] = 'lib%s.so' # static lib v['staticlib_LINKFLAGS'] = ['-Wl,-Bstatic'] v['staticlib_PATTERN'] = 'lib%s.a' # osx stuff v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] v['CCFLAGS_MACBUNDLE'] = ['-fPIC'] v['macbundle_PATTERN'] = '%s.bundle' @conftest def gcc_modifier_win32(conf): v = conf.env v['program_PATTERN'] = '%s.exe' v['shlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' dest_arch = v['DEST_CPU'] v['shlib_CCFLAGS'] = ['-DPIC'] v.append_value('shlib_CCFLAGS', '-DDLL_EXPORT') # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea # 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') @conftest def gcc_modifier_cygwin(conf): gcc_modifier_win32(conf) v = conf.env v['shlib_PATTERN'] = 'cyg%s.dll' v.append_value('shlib_LINKFLAGS', '-Wl,--enable-auto-image-base') @conftest def gcc_modifier_darwin(conf): v = conf.env v['shlib_CCFLAGS'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['shlib_LINKFLAGS'] = ['-dynamiclib'] v['shlib_PATTERN'] = 'lib%s.dylib' v['staticlib_LINKFLAGS'] = [] v['SHLIB_MARKER'] = '' v['STATICLIB_MARKER'] = '' v['SONAME_ST'] = '' @conftest def gcc_modifier_aix(conf): v = conf.env v['program_LINKFLAGS'] = ['-Wl,-brtl'] v['shlib_LINKFLAGS'] = ['-shared','-Wl,-brtl,-bexpfull'] v['SHLIB_MARKER'] = '' @conftest def gcc_modifier_openbsd(conf): conf.env['SONAME_ST'] = [] @conftest def gcc_modifier_platform(conf): # * 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. dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() gcc_modifier_func = globals().get('gcc_modifier_' + dest_os) if gcc_modifier_func: gcc_modifier_func(conf) def detect(conf): conf.find_gcc() conf.find_cpp() conf.find_ar() conf.gcc_common_flags() conf.gcc_modifier_platform() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() tevent-0.9.34/third_party/waf/wafadmin/Tools/gdc.py0000660000000000000000000000226712520121120022144 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) import sys import Utils, ar from Configure import conftest @conftest def find_gdc(conf): conf.find_program('gdc', var='D_COMPILER', mandatory=True) @conftest def common_flags_gdc(conf): v = conf.env # _DFLAGS _DIMPORTFLAGS # for mory info about the meaning of this dict see dmd.py v['DFLAGS'] = [] v['D_SRC_F'] = '' v['D_TGT_F'] = ['-c', '-o', ''] v['DPATH_ST'] = '-I%s' # template for adding import paths # linker v['D_LINKER'] = v['D_COMPILER'] v['DLNK_SRC_F'] = '' v['DLNK_TGT_F'] = ['-o', ''] v['DLIB_ST'] = '-l%s' # template for adding libs v['DLIBPATH_ST'] = '-L%s' # template for adding libpaths # debug levels v['DLINKFLAGS'] = [] v['DFLAGS_OPTIMIZED'] = ['-O3'] v['DFLAGS_DEBUG'] = ['-O0'] v['DFLAGS_ULTRADEBUG'] = ['-O0'] v['D_shlib_DFLAGS'] = [] v['D_shlib_LINKFLAGS'] = ['-shared'] v['DHEADER_ext'] = '.di' v['D_HDR_F'] = '-fintfc -fintfc-file=' def detect(conf): conf.find_gdc() conf.check_tool('ar') conf.check_tool('d') conf.common_flags_gdc() conf.d_platform_flags() tevent-0.9.34/third_party/waf/wafadmin/Tools/glib2.py0000660000000000000000000001165712520121120022411 0ustar rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2008 (ita) "GLib2 support" import Task, Utils from TaskGen import taskgen, before, after, feature # # glib-genmarshal # @taskgen def add_marshal_file(self, filename, prefix): if not hasattr(self, 'marshal_list'): self.marshal_list = [] self.meths.append('process_marshal') self.marshal_list.append((filename, prefix)) @before('apply_core') def process_marshal(self): for f, prefix in getattr(self, 'marshal_list', []): node = self.path.find_resource(f) if not node: raise Utils.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.allnodes.append(c_node) def genmarshal_func(self): bld = self.inputs[0].__class__.bld get = self.env.get_flat cmd1 = "%s %s --prefix=%s --header > %s" % ( get('GLIB_GENMARSHAL'), self.inputs[0].srcpath(self.env), get('GLIB_GENMARSHAL_PREFIX'), self.outputs[0].abspath(self.env) ) ret = bld.exec_command(cmd1) if ret: return ret #print self.outputs[1].abspath(self.env) f = open(self.outputs[1].abspath(self.env), 'wb') c = '''#include "%s"\n''' % self.outputs[0].name f.write(c) f.close() cmd2 = "%s %s --prefix=%s --body >> %s" % ( get('GLIB_GENMARSHAL'), self.inputs[0].srcpath(self.env), get('GLIB_GENMARSHAL_PREFIX'), self.outputs[1].abspath(self.env) ) ret = Utils.exec_command(cmd2) if ret: return ret # # glib-mkenums # @taskgen def add_enums_from_template(self, source='', target='', template='', comments=''): 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 def add_enums(self, source='', target='', file_head='', file_prod='', file_tail='', enum_prod='', value_head='', value_prod='', value_tail='', comments=''): 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('apply_core') def process_enums(self): 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 Utils.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.srcpath(env) for k in source_list] # find the target if not enum['target']: raise Utils.WafError('missing target ' + str(enum)) tgt_node = self.path.find_or_declare(enum['target']) if tgt_node.name.endswith('.c'): self.allnodes.append(tgt_node) env['GLIB_MKENUMS_TARGET'] = tgt_node.abspath(env) options = [] if enum['template']: # template, if provided template_node = self.path.find_resource(enum['template']) options.append('--template %s' % (template_node.abspath(env))) 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.iteritems(): 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) Task.task_type_from_func('glib_genmarshal', func=genmarshal_func, vars=['GLIB_GENMARSHAL_PREFIX', 'GLIB_GENMARSHAL'], color='BLUE', before='cc cxx') Task.simple_task_type('glib_mkenums', '${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}', color='PINK', before='cc cxx') def detect(conf): glib_genmarshal = conf.find_program('glib-genmarshal', var='GLIB_GENMARSHAL') mk_enums_tool = conf.find_program('glib-mkenums', var='GLIB_MKENUMS') tevent-0.9.34/third_party/waf/wafadmin/Tools/gnome.py0000660000000000000000000001710012520121120022504 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2008 (ita) "Gnome support" import os, re import TaskGen, Utils, Runner, Task, Build, Options, Logs import cc from Logs import error from TaskGen import taskgen, before, after, feature n1_regexp = re.compile('(.*)', re.M) n2_regexp = re.compile('(.*)', re.M) def postinstall_schemas(prog_name): if Build.bld.is_install: dir = Build.bld.get_install_path('${PREFIX}/etc/gconf/schemas/%s.schemas' % prog_name) if not Options.options.destdir: # add the gconf schema Utils.pprint('YELLOW', 'Installing GConf schema') command = 'gconftool-2 --install-schema-file=%s 1> /dev/null' % dir ret = Utils.exec_command(command) else: Utils.pprint('YELLOW', 'GConf schema not installed. After install, run this:') Utils.pprint('YELLOW', 'gconftool-2 --install-schema-file=%s' % dir) def postinstall_icons(): dir = Build.bld.get_install_path('${DATADIR}/icons/hicolor') if Build.bld.is_install: if not Options.options.destdir: # update the pixmap cache directory Utils.pprint('YELLOW', "Updating Gtk icon cache.") command = 'gtk-update-icon-cache -q -f -t %s' % dir ret = Utils.exec_command(command) else: Utils.pprint('YELLOW', 'Icon cache not updated. After install, run this:') Utils.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % dir) def postinstall_scrollkeeper(prog_name): if Build.bld.is_install: # now the scrollkeeper update if we can write to the log file if os.access('/var/log/scrollkeeper.log', os.W_OK): dir1 = Build.bld.get_install_path('${PREFIX}/var/scrollkeeper') dir2 = Build.bld.get_install_path('${DATADIR}/omf/%s' % prog_name) command = 'scrollkeeper-update -q -p %s -o %s' % (dir1, dir2) ret = Utils.exec_command(command) def postinstall(prog_name='myapp', schemas=1, icons=1, scrollkeeper=1): if schemas: postinstall_schemas(prog_name) if icons: postinstall_icons() if scrollkeeper: postinstall_scrollkeeper(prog_name) # OBSOLETE class gnome_doc_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('gnome_doc') def init_gnome_doc(self): self.default_install_path = '${PREFIX}/share' @feature('gnome_doc') @after('init_gnome_doc') def apply_gnome_doc(self): self.env['APPNAME'] = self.doc_module lst = self.to_list(self.doc_linguas) bld = self.bld lst.append('C') for x in lst: if not x == 'C': tsk = self.create_task('xml2po') node = self.path.find_resource(x+'/'+x+'.po') src = self.path.find_resource('C/%s.xml' % self.doc_module) out = self.path.find_or_declare('%s/%s.xml' % (x, self.doc_module)) tsk.set_inputs([node, src]) tsk.set_outputs(out) else: out = self.path.find_resource('%s/%s.xml' % (x, self.doc_module)) tsk2 = self.create_task('xsltproc2po') out2 = self.path.find_or_declare('%s/%s-%s.omf' % (x, self.doc_module, x)) tsk2.set_outputs(out2) node = self.path.find_resource(self.doc_module+".omf.in") tsk2.inputs = [node, out] tsk2.run_after.append(tsk) if bld.is_install: path = self.install_path + '/gnome/help/%s/%s' % (self.doc_module, x) bld.install_files(self.install_path + '/omf', out2, env=self.env) for y in self.to_list(self.doc_figures): try: os.stat(self.path.abspath() + '/' + x + '/' + y) bld.install_as(path + '/' + y, self.path.abspath() + '/' + x + '/' + y) except: bld.install_as(path + '/' + y, self.path.abspath() + '/C/' + y) bld.install_as(path + '/%s.xml' % self.doc_module, out.abspath(self.env)) if x == 'C': xmls = self.to_list(self.doc_includes) xmls.append(self.doc_entities) for z in xmls: out = self.path.find_resource('%s/%s' % (x, z)) bld.install_as(path + '/%s' % z, out.abspath(self.env)) # OBSOLETE class xml_to_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('xml_to') def init_xml_to(self): Utils.def_attrs(self, source = 'xmlfile', xslt = 'xlsltfile', target = 'hey', default_install_path = '${PREFIX}', task_created = None) @feature('xml_to') @after('init_xml_to') def apply_xml_to(self): xmlfile = self.path.find_resource(self.source) xsltfile = self.path.find_resource(self.xslt) tsk = self.create_task('xmlto', [xmlfile, xsltfile], xmlfile.change_ext('html')) tsk.install_path = self.install_path def sgml_scan(self): node = self.inputs[0] env = self.env variant = node.variant(env) fi = open(node.abspath(env), 'r') content = fi.read() fi.close() # we should use a sgml parser :-/ name = n1_regexp.findall(content)[0] num = n2_regexp.findall(content)[0] doc_name = name+'.'+num if not self.outputs: self.outputs = [self.generator.path.find_or_declare(doc_name)] return ([], [doc_name]) class gnome_sgml2man_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('gnome_sgml2man') def apply_gnome_sgml2man(self): """ we could make it more complicated, but for now we just scan the document each time """ assert(getattr(self, 'appname', None)) def install_result(task): out = task.outputs[0] name = out.name ext = name[-1] env = task.env self.bld.install_files('${DATADIR}/man/man%s/' % ext, out, env) self.bld.rescan(self.path) for name in self.bld.cache_dir_contents[self.path.id]: base, ext = os.path.splitext(name) if ext != '.sgml': continue task = self.create_task('sgml2man') task.set_inputs(self.path.find_resource(name)) task.task_generator = self if self.bld.is_install: task.install = install_result # no outputs, the scanner does it # no caching for now, this is not a time-critical feature # in the future the scanner can be used to do more things (find dependencies, etc) task.scan() cls = Task.simple_task_type('sgml2man', '${SGML2MAN} -o ${TGT[0].bld_dir(env)} ${SRC} > /dev/null', color='BLUE') cls.scan = sgml_scan cls.quiet = 1 Task.simple_task_type('xmlto', '${XMLTO} html -m ${SRC[1].abspath(env)} ${SRC[0].abspath(env)}') Task.simple_task_type('xml2po', '${XML2PO} ${XML2POFLAGS} ${SRC} > ${TGT}', color='BLUE') # how do you expect someone to understand this?! xslt_magic = """${XSLTPROC2PO} -o ${TGT[0].abspath(env)} \ --stringparam db2omf.basename ${APPNAME} \ --stringparam db2omf.format docbook \ --stringparam db2omf.lang ${TGT[0].abspath(env)[:-4].split('-')[-1]} \ --stringparam db2omf.dtd '-//OASIS//DTD DocBook XML V4.3//EN' \ --stringparam db2omf.omf_dir ${PREFIX}/share/omf \ --stringparam db2omf.help_dir ${PREFIX}/share/gnome/help \ --stringparam db2omf.omf_in ${SRC[0].abspath(env)} \ --stringparam db2omf.scrollkeeper_cl ${SCROLLKEEPER_DATADIR}/Templates/C/scrollkeeper_cl.xml \ ${DB2OMF} ${SRC[1].abspath(env)}""" #--stringparam db2omf.dtd '-//OASIS//DTD DocBook XML V4.3//EN' \ Task.simple_task_type('xsltproc2po', xslt_magic, color='BLUE') def detect(conf): conf.check_tool('gnu_dirs glib2 dbus') sgml2man = conf.find_program('docbook2man', var='SGML2MAN') def getstr(varname): return getattr(Options.options, varname, '') # addefine also sets the variable to the env conf.define('GNOMELOCALEDIR', os.path.join(conf.env['DATADIR'], 'locale')) xml2po = conf.find_program('xml2po', var='XML2PO') xsltproc2po = conf.find_program('xsltproc', var='XSLTPROC2PO') conf.env['XML2POFLAGS'] = '-e -p' conf.env['SCROLLKEEPER_DATADIR'] = Utils.cmd_output("scrollkeeper-config --pkgdatadir", silent=1).strip() conf.env['DB2OMF'] = Utils.cmd_output("/usr/bin/pkg-config --variable db2omf gnome-doc-utils", silent=1).strip() def set_options(opt): opt.add_option('--want-rpath', type='int', default=1, dest='want_rpath', help='set rpath to 1 or 0 [Default 1]') tevent-0.9.34/third_party/waf/wafadmin/Tools/gnu_dirs.py0000660000000000000000000001003312520121120023207 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 """ To use this module do not forget to call opt.tool_options('gnu_dirs') AND conf.check_tool('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: * PREFIX : architecture-independent files [/usr/local] * EXEC_PREFIX : architecture-dependent files [PREFIX] * BINDIR : user executables [EXEC_PREFIX/bin] * SBINDIR : user executables [EXEC_PREFIX/sbin] * LIBEXECDIR : program executables [EXEC_PREFIX/libexec] * SYSCONFDIR : read-only single-machine data [PREFIX/etc] * SHAREDSTATEDIR : modifiable architecture-independent data [PREFIX/com] * LOCALSTATEDIR : modifiable single-machine data [PREFIX/var] * LIBDIR : object code libraries [EXEC_PREFIX/lib] * INCLUDEDIR : C header files [PREFIX/include] * OLDINCLUDEDIR : C header files for non-gcc [/usr/include] * DATAROOTDIR : read-only arch.-independent data root [PREFIX/share] * DATADIR : read-only architecture-independent data [DATAROOTDIR] * INFODIR : info documentation [DATAROOTDIR/info] * LOCALEDIR : locale-dependent data [DATAROOTDIR/locale] * MANDIR : man documentation [DATAROOTDIR/man] * DOCDIR : documentation root [DATAROOTDIR/doc/telepathy-glib] * HTMLDIR : html documentation [DOCDIR] * DVIDIR : dvi documentation [DOCDIR] * PDFDIR : pdf documentation [DOCDIR] * PSDIR : ps documentation [DOCDIR] """ import Utils, Options _options = [x.split(', ') for x in ''' bindir, user executables, ${EXEC_PREFIX}/bin sbindir, system admin executables, ${EXEC_PREFIX}/sbin libexecdir, program executables, ${EXEC_PREFIX}/libexec sysconfdir, read-only single-machine data, ${PREFIX}/etc sharedstatedir, modifiable architecture-independent data, ${PREFIX}/com localstatedir, modifiable single-machine data, ${PREFIX}/var libdir, object code libraries, ${EXEC_PREFIX}/lib includedir, C header files, ${PREFIX}/include oldincludedir, C header files for non-gcc, /usr/include datarootdir, read-only arch.-independent data root, ${PREFIX}/share datadir, read-only architecture-independent data, ${DATAROOTDIR} infodir, info documentation, ${DATAROOTDIR}/info localedir, locale-dependent data, ${DATAROOTDIR}/locale mandir, man documentation, ${DATAROOTDIR}/man docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} htmldir, html documentation, ${DOCDIR} dvidir, dvi documentation, ${DOCDIR} pdfdir, pdf documentation, ${DOCDIR} psdir, ps documentation, ${DOCDIR} '''.split('\n') if x] def detect(conf): def get_param(varname, default): return getattr(Options.options, varname, '') or default env = conf.env env['EXEC_PREFIX'] = get_param('EXEC_PREFIX', env['PREFIX']) env['PACKAGE'] = Utils.g_module.APPNAME 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), env) except TypeError: complete = False if not complete: lst = [name for name, _, _ in _options if not env[name.upper()]] raise Utils.WafError('Variable substitution failure %r' % lst) def set_options(opt): inst_dir = opt.add_option_group('Installation directories', '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 [Default: ${PREFIX}]', default = '', dest = 'EXEC_PREFIX') dirs_options = opt.add_option_group('Pre-defined installation directories', '') for name, help, default in _options: option_name = '--' + name str_default = default str_help = '%s [Default: %s]' % (help, str_default) dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) tevent-0.9.34/third_party/waf/wafadmin/Tools/gob2.py0000660000000000000000000000053512520121120022234 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 import TaskGen TaskGen.declare_chain( name = 'gob2', rule = '${GOB2} -o ${TGT[0].bld_dir(env)} ${GOB2FLAGS} ${SRC}', ext_in = '.gob', ext_out = '.c' ) def detect(conf): gob2 = conf.find_program('gob2', var='GOB2', mandatory=True) conf.env['GOB2'] = gob2 conf.env['GOB2FLAGS'] = '' tevent-0.9.34/third_party/waf/wafadmin/Tools/gxx.py0000660000000000000000000000761312520121120022215 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 import os, sys import Configure, Options, Utils import ccroot, ar from Configure import conftest @conftest def find_gxx(conf): cxx = conf.find_program(['g++', 'c++'], var='CXX', mandatory=True) cxx = conf.cmd_to_list(cxx) ccroot.get_cc_version(conf, cxx, gcc=True) conf.env.CXX_NAME = 'gcc' conf.env.CXX = cxx @conftest def gxx_common_flags(conf): v = conf.env # CPPFLAGS CXXDEFINES _CXXINCFLAGS _CXXDEFFLAGS v['CXXFLAGS_DEBUG'] = ['-g'] v['CXXFLAGS_RELEASE'] = ['-O2'] v['CXX_SRC_F'] = '' v['CXX_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = '' v['CXXLNK_TGT_F'] = ['-o', ''] # shell hack for -MD v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['CXXDEFINES_ST'] = '-D%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Wl,-Bdynamic' v['STATICLIB_MARKER'] = '-Wl,-Bstatic' v['FULLSTATIC_MARKER'] = '-static' # program v['program_PATTERN'] = '%s' # shared library v['shlib_CXXFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro v['shlib_LINKFLAGS'] = ['-shared'] v['shlib_PATTERN'] = 'lib%s.so' # static lib v['staticlib_LINKFLAGS'] = ['-Wl,-Bstatic'] v['staticlib_PATTERN'] = 'lib%s.a' # osx stuff v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] v['CCFLAGS_MACBUNDLE'] = ['-fPIC'] v['macbundle_PATTERN'] = '%s.bundle' @conftest def gxx_modifier_win32(conf): v = conf.env v['program_PATTERN'] = '%s.exe' v['shlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' dest_arch = v['DEST_CPU'] v['shlib_CXXFLAGS'] = [] v.append_value('shlib_CXXFLAGS', '-DDLL_EXPORT') # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea # 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') @conftest def gxx_modifier_cygwin(conf): gxx_modifier_win32(conf) v = conf.env v['shlib_PATTERN'] = 'cyg%s.dll' v.append_value('shlib_LINKFLAGS', '-Wl,--enable-auto-image-base') @conftest def gxx_modifier_darwin(conf): v = conf.env v['shlib_CXXFLAGS'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['shlib_LINKFLAGS'] = ['-dynamiclib'] v['shlib_PATTERN'] = 'lib%s.dylib' v['staticlib_LINKFLAGS'] = [] v['SHLIB_MARKER'] = '' v['STATICLIB_MARKER'] = '' v['SONAME_ST'] = '' @conftest def gxx_modifier_aix(conf): v = conf.env v['program_LINKFLAGS'] = ['-Wl,-brtl'] v['shlib_LINKFLAGS'] = ['-shared', '-Wl,-brtl,-bexpfull'] v['SHLIB_MARKER'] = '' @conftest def gxx_modifier_openbsd(conf): conf.env['SONAME_ST'] = [] @conftest def gxx_modifier_platform(conf): # * 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. dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() gxx_modifier_func = globals().get('gxx_modifier_' + dest_os) if gxx_modifier_func: gxx_modifier_func(conf) def detect(conf): conf.find_gxx() conf.find_cpp() conf.find_ar() conf.gxx_common_flags() conf.gxx_modifier_platform() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() tevent-0.9.34/third_party/waf/wafadmin/Tools/icc.py0000660000000000000000000000143512520121120022141 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Stian Selnes, 2008 # Thomas Nagy 2009 import os, sys import Configure, Options, Utils import ccroot, ar, gcc from Configure import conftest @conftest def find_icc(conf): if sys.platform == 'cygwin': conf.fatal('The Intel compiler does not work on Cygwin') 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('icc', var='CC') if not cc: cc = conf.find_program('ICL', var='CC') if not cc: conf.fatal('Intel C Compiler (icc) was not found') cc = conf.cmd_to_list(cc) ccroot.get_cc_version(conf, cc, icc=True) v['CC'] = cc v['CC_NAME'] = 'icc' detect = ''' find_icc find_ar gcc_common_flags gcc_modifier_platform cc_load_tools cc_add_flags link_add_flags ''' tevent-0.9.34/third_party/waf/wafadmin/Tools/icpc.py0000660000000000000000000000135512520121120022322 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy 2009 import os, sys import Configure, Options, Utils import ccroot, ar, gxx from Configure import conftest @conftest def find_icpc(conf): if sys.platform == 'cygwin': conf.fatal('The Intel compiler does not work on Cygwin') v = conf.env cxx = None if v['CXX']: cxx = v['CXX'] elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] if not cxx: cxx = conf.find_program('icpc', var='CXX') if not cxx: conf.fatal('Intel C++ Compiler (icpc) was not found') cxx = conf.cmd_to_list(cxx) ccroot.get_cc_version(conf, cxx, icc=True) v['CXX'] = cxx v['CXX_NAME'] = 'icc' detect = ''' find_icpc find_ar gxx_common_flags gxx_modifier_platform cxx_load_tools cxx_add_flags link_add_flags ''' tevent-0.9.34/third_party/waf/wafadmin/Tools/intltool.py0000660000000000000000000001124012520121120023242 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) "intltool support" import os, re import Configure, TaskGen, Task, Utils, Runner, Options, Build, config_c from TaskGen import feature, before, taskgen from Logs import error """ Usage: bld(features='intltool_in', source='a.po b.po', podir='po', cache='.intlcache', flags='') """ class intltool_in_taskgen(TaskGen.task_gen): """deprecated""" def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @before('apply_core') @feature('intltool_in') def iapply_intltool_in_f(self): try: self.meths.remove('apply_core') except ValueError: pass for i in self.to_list(self.source): node = self.path.find_resource(i) podir = getattr(self, 'podir', 'po') podirnode = self.path.find_dir(podir) if not podirnode: error("could not find the podir %r" % podir) continue cache = getattr(self, 'intlcache', '.intlcache') self.env['INTLCACHE'] = os.path.join(self.path.bldpath(self.env), podir, cache) self.env['INTLPODIR'] = podirnode.srcpath(self.env) self.env['INTLFLAGS'] = getattr(self, 'flags', ['-q', '-u', '-c']) task = self.create_task('intltool', node, node.change_ext('')) task.install_path = self.install_path class intltool_po_taskgen(TaskGen.task_gen): """deprecated""" def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('intltool_po') def apply_intltool_po(self): try: self.meths.remove('apply_core') except ValueError: pass self.default_install_path = '${LOCALEDIR}' appname = getattr(self, 'appname', 'set_your_app_name') podir = getattr(self, 'podir', '') def install_translation(task): out = task.outputs[0] filename = out.name (langname, ext) = os.path.splitext(filename) inst_file = langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo' self.bld.install_as(os.path.join(self.install_path, inst_file), out, self.env, self.chmod) linguas = self.path.find_resource(os.path.join(podir, 'LINGUAS')) if linguas: # scan LINGUAS file for locales to process file = open(linguas.abspath()) langs = [] for line in file.readlines(): # ignore lines containing comments if not line.startswith('#'): langs += line.split() file.close() 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') task.set_inputs(node) task.set_outputs(node.change_ext('.mo')) if self.bld.is_install: task.install = install_translation else: Utils.pprint('RED', "Error no LINGUAS file found in po directory") Task.simple_task_type('po', '${POCOM} -o ${TGT} ${SRC}', color='BLUE', shell=False) Task.simple_task_type('intltool', '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}', color='BLUE', after="cc_link cxx_link", shell=False) def detect(conf): pocom = conf.find_program('msgfmt') if not pocom: # if msgfmt should not be mandatory, catch the thrown exception in your wscript conf.fatal('The program msgfmt (gettext) is mandatory!') conf.env['POCOM'] = pocom # NOTE: it is possible to set INTLTOOL in the environment, but it must not have spaces in it intltool = conf.find_program('intltool-merge', var='INTLTOOL') if not intltool: # if intltool-merge should not be mandatory, catch the thrown exception in your wscript if Options.platform == 'win32': perl = conf.find_program('perl', var='PERL') if not perl: conf.fatal('The program perl (required by intltool) could not be found') intltooldir = Configure.find_file('intltool-merge', os.environ['PATH'].split(os.pathsep)) if not intltooldir: conf.fatal('The program intltool-merge (intltool, gettext-devel) is mandatory!') conf.env['INTLTOOL'] = Utils.to_list(conf.env['PERL']) + [intltooldir + os.sep + 'intltool-merge'] conf.check_message('intltool', '', True, ' '.join(conf.env['INTLTOOL'])) else: conf.fatal('The program intltool-merge (intltool, gettext-devel) is mandatory!') def getstr(varname): return getattr(Options.options, varname, '') prefix = conf.env['PREFIX'] datadir = getstr('datadir') if not datadir: datadir = os.path.join(prefix,'share') conf.define('LOCALEDIR', os.path.join(datadir, 'locale')) conf.define('DATADIR', datadir) if conf.env['CC'] or conf.env['CXX']: # Define to 1 if is present conf.check(header_name='locale.h') def set_options(opt): opt.add_option('--want-rpath', type='int', default=1, dest='want_rpath', help='set rpath to 1 or 0 [Default 1]') opt.add_option('--datadir', type='string', default='', dest='datadir', help='read-only application data') tevent-0.9.34/third_party/waf/wafadmin/Tools/javaw.py0000660000000000000000000001632012520121120022512 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2008 (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) Fortunately, the convention makes it possible to use the build dir without too many problems for the moment Inner classes must be located and cleaned when a problem arise, for the moment waf does not track the production of inner classes. Adding all the files to a task and executing it if any of the input files change is only annoying for the compilation times Compilation can be run 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/ """ import os, re from Configure import conf import TaskGen, Task, Utils, Options, Build from TaskGen import feature, before, taskgen 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('jar') @before('apply_core') def jar_files(self): basedir = getattr(self, 'basedir', '.') destfile = getattr(self, 'destfile', 'test.jar') jaropts = getattr(self, 'jaropts', []) jarcreate = getattr(self, 'jarcreate', 'cf') dir = self.path.find_dir(basedir) if not dir: raise jaropts.append('-C') jaropts.append(dir.abspath(self.env)) jaropts.append('.') out = self.path.find_or_declare(destfile) tsk = self.create_task('jar_create') tsk.set_outputs(out) tsk.inputs = [x for x in dir.find_iter(src=0, bld=1) if x.id != out.id] tsk.env['JAROPTS'] = jaropts tsk.env['JARCREATE'] = jarcreate @feature('javac') @before('apply_core') def apply_java(self): Utils.def_attrs(self, jarname='', jaropts='', classpath='', sourcepath='.', srcdir='.', source_re='**/*.java', jar_mf_attributes={}, jar_mf_classpath=[]) if getattr(self, 'source_root', None): # old stuff self.srcdir = self.source_root nodes_lst = [] if not self.classpath: if not self.env['CLASSPATH']: self.env['CLASSPATH'] = '..' + os.pathsep + '.' else: self.env['CLASSPATH'] = self.classpath srcdir_node = self.path.find_dir(self.srcdir) if not srcdir_node: raise Utils.WafError('could not find srcdir %r' % self.srcdir) src_nodes = [x for x in srcdir_node.ant_glob(self.source_re, flat=False)] bld_nodes = [x.change_ext('.class') for x in src_nodes] self.env['OUTDIR'] = [srcdir_node.bldpath(self.env)] tsk = self.create_task('javac') tsk.set_inputs(src_nodes) tsk.set_outputs(bld_nodes) if getattr(self, 'compat', None): tsk.env.append_value('JAVACFLAGS', ['-source', self.compat]) if hasattr(self, 'sourcepath'): fold = [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 = srcdir_node.srcpath() if names: tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) if self.jarname: jtsk = self.create_task('jar_create', bld_nodes, self.path.find_or_declare(self.jarname)) jtsk.set_run_after(tsk) if not self.env.JAROPTS: if self.jaropts: self.env.JAROPTS = self.jaropts else: dirs = '.' self.env.JAROPTS = ['-C', ''.join(self.env['OUTDIR']), dirs] Task.simple_task_type('jar_create', '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}', color='GREEN', shell=False) cls = Task.simple_task_type('javac', '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}', shell=False) cls.color = 'BLUE' def post_run_javac(self): """this is for cleaning the folder javac creates single files for inner classes but it is not possible to know which inner classes in advance""" par = {} for x in self.inputs: par[x.parent.id] = x.parent inner = {} for k in par.values(): path = k.abspath(self.env) lst = os.listdir(path) for u in lst: if u.find('$') >= 0: inner_class_node = k.find_or_declare(u) inner[inner_class_node.id] = inner_class_node to_add = set(inner.keys()) - set([x.id for x in self.outputs]) for x in to_add: self.outputs.append(inner[x]) self.cached = True # disable the cache here - inner classes are a problem return Task.Task.post_run(self) cls.post_run = post_run_javac def detect(conf): # If JAVA_PATH is set, we prepend it to the path list java_path = conf.environ['PATH'].split(os.pathsep) v = conf.env if 'JAVA_HOME' in conf.environ: java_path = [os.path.join(conf.environ['JAVA_HOME'], 'bin')] + java_path conf.env['JAVA_HOME'] = [conf.environ['JAVA_HOME']] for x in 'javac java jar'.split(): conf.find_program(x, var=x.upper(), path_list=java_path) conf.env[x.upper()] = conf.cmd_to_list(conf.env[x.upper()]) v['JAVA_EXT'] = ['.java'] if 'CLASSPATH' in conf.environ: v['CLASSPATH'] = conf.environ['CLASSPATH'] if not v['JAR']: conf.fatal('jar is required for making java packages') if not v['JAVAC']: conf.fatal('javac is required for compiling java classes') v['JARCREATE'] = 'cf' # can use cvf @conf def check_java_class(self, classname, with_classpath=None): """Check if the specified java class is installed""" import shutil 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) java_file = open(os.path.join(javatestdir, 'Test.java'), 'w') java_file.write(class_check_source) java_file.close() # Compile the source Utils.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.log.write("%s\n" % str(cmd)) found = Utils.exec_command(cmd, shell=False, log=self.log) self.check_message('Java class %s' % classname, "", not found) shutil.rmtree(javatestdir, True) return found @conf def check_jni_headers(conf): """ Check for jni headers and libraries On success the environment variable xxx_JAVA is added for uselib """ 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] b = Build.BuildContext() b.load_dirs(conf.srcdir, conf.blddir) dir = b.root.find_dir(conf.env.JAVA_HOME[0] + '/include') f = dir.ant_glob('**/(jni|jni_md).h', flat=False) incDirs = [x.parent.abspath() for x in f] dir = b.root.find_dir(conf.env.JAVA_HOME[0]) f = dir.ant_glob('**/*jvm.(so|dll)', flat=False) libDirs = [x.parent.abspath() for x in f] or [javaHome] for i, d in enumerate(libDirs): if conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm', libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA'): break else: conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) tevent-0.9.34/third_party/waf/wafadmin/Tools/kde4.py0000660000000000000000000000444212520121120022233 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) import os, sys, re import Options, TaskGen, Task, Utils from TaskGen import taskgen, feature, after class msgfmt_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('msgfmt') def init_msgfmt(self): #langs = '' # for example "foo/fr foo/br" self.default_install_path = '${KDE4_LOCALE_INSTALL_DIR}' @feature('msgfmt') @after('init_msgfmt') def apply_msgfmt(self): 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')) if not self.bld.is_install: continue langname = lang.split('/') langname = langname[-1] task.install_path = self.install_path + os.sep + langname + os.sep + 'LC_MESSAGES' task.filename = getattr(self, 'appname', 'set_your_appname') + '.mo' task.chmod = self.chmod def detect(conf): kdeconfig = conf.find_program('kde4-config') if not kdeconfig: conf.fatal('we need kde4-config') prefix = Utils.cmd_output('%s --prefix' % kdeconfig, silent=True).strip() file = '%s/share/apps/cmake/modules/KDELibsDependencies.cmake' % prefix try: os.stat(file) except OSError: file = '%s/share/kde4/apps/cmake/modules/KDELibsDependencies.cmake' % prefix try: os.stat(file) except OSError: conf.fatal('could not open %s' % file) try: txt = Utils.readf(file) except (OSError, IOError): conf.fatal('could not read %s' % file) txt = txt.replace('\\\n', '\n') fu = re.compile('#(.*)\n') txt = fu.sub('', txt) setregexp = re.compile('([sS][eE][tT]\s*\()\s*([^\s]+)\s+\"([^"]+)\"\)') found = setregexp.findall(txt) for (_, key, val) in found: #print key, val conf.env[key] = val # well well, i could just write an interpreter for cmake files conf.env['LIB_KDECORE']='kdecore' conf.env['LIB_KDEUI'] ='kdeui' conf.env['LIB_KIO'] ='kio' conf.env['LIB_KHTML'] ='khtml' conf.env['LIB_KPARTS'] ='kparts' conf.env['LIBPATH_KDECORE'] = conf.env['KDE4_LIB_INSTALL_DIR'] conf.env['CPPPATH_KDECORE'] = conf.env['KDE4_INCLUDE_INSTALL_DIR'] conf.env.append_value('CPPPATH_KDECORE', conf.env['KDE4_INCLUDE_INSTALL_DIR']+"/KDE") conf.env['MSGFMT'] = conf.find_program('msgfmt') Task.simple_task_type('msgfmt', '${MSGFMT} ${SRC} -o ${TGT}', color='BLUE', shell=False) tevent-0.9.34/third_party/waf/wafadmin/Tools/libtool.py0000660000000000000000000002230112520121120023042 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Matthias Jahn, 2008, jahn matthias ath freenet punto de # Thomas Nagy, 2008 (ita) import sys, re, os, optparse import TaskGen, Task, Utils, preproc from Logs import error, debug, warn from TaskGen import taskgen, after, before, feature REVISION="0.1.3" """ if you want to use the code here, you must use something like this: obj = obj.create(...) obj.features.append("libtool") obj.vnum = "1.2.3" # optional, but versioned libraries are common """ # fake libtool files fakelibtool_vardeps = ['CXX', 'PREFIX'] def fakelibtool_build(task): # Writes a .la file, used by libtool env = task.env dest = open(task.outputs[0].abspath(env), 'w') sname = task.inputs[0].name fu = dest.write fu("# Generated by ltmain.sh - GNU libtool 1.5.18 - (pwn3d by BKsys II code name WAF)\n") if env['vnum']: nums = env['vnum'].split('.') libname = task.inputs[0].name name3 = libname+'.'+env['vnum'] name2 = libname+'.'+nums[0] name1 = libname fu("dlname='%s'\n" % name2) strn = " ".join([name3, name2, name1]) fu("library_names='%s'\n" % (strn) ) else: fu("dlname='%s'\n" % sname) fu("library_names='%s %s %s'\n" % (sname, sname, sname) ) fu("old_library=''\n") vars = ' '.join(env['libtoolvars']+env['LINKFLAGS']) fu("dependency_libs='%s'\n" % vars) fu("current=0\n") fu("age=0\nrevision=0\ninstalled=yes\nshouldnotlink=no\n") fu("dlopen=''\ndlpreopen=''\n") fu("libdir='%s/lib'\n" % env['PREFIX']) dest.close() return 0 def read_la_file(path): sp = re.compile(r'^([^=]+)=\'(.*)\'$') dc={} file = open(path, "r") for line in file.readlines(): try: #print sp.split(line.strip()) _, left, right, _ = sp.split(line.strip()) dc[left]=right except ValueError: pass file.close() return dc @feature("libtool") @after('apply_link') def apply_link_libtool(self): if self.type != 'program': linktask = self.link_task self.latask = self.create_task('fakelibtool', linktask.outputs, linktask.outputs[0].change_ext('.la')) if self.bld.is_install: self.bld.install_files('${PREFIX}/lib', linktask.outputs[0], self.env) @feature("libtool") @before('apply_core') def apply_libtool(self): self.env['vnum']=self.vnum paths=[] libs=[] libtool_files=[] libtool_vars=[] for l in self.env['LINKFLAGS']: if l[:2]=='-L': paths.append(l[2:]) elif l[:2]=='-l': libs.append(l[2:]) for l in libs: for p in paths: dict = read_la_file(p+'/lib'+l+'.la') linkflags2 = dict.get('dependency_libs', '') for v in linkflags2.split(): if v.endswith('.la'): libtool_files.append(v) libtool_vars.append(v) continue self.env.append_unique('LINKFLAGS', v) break self.env['libtoolvars']=libtool_vars while libtool_files: file = libtool_files.pop() dict = read_la_file(file) for v in dict['dependency_libs'].split(): if v[-3:] == '.la': libtool_files.append(v) continue self.env.append_unique('LINKFLAGS', v) Task.task_type_from_func('fakelibtool', vars=fakelibtool_vardeps, func=fakelibtool_build, color='BLUE', after="cc_link cxx_link static_link") class libtool_la_file: def __init__ (self, la_filename): self.__la_filename = la_filename #remove path and .la suffix self.linkname = str(os.path.split(la_filename)[-1])[:-3] if self.linkname.startswith("lib"): self.linkname = self.linkname[3:] # The name that we can dlopen(3). self.dlname = None # Names of this library self.library_names = None # The name of the static archive. self.old_library = None # Libraries that this one depends upon. self.dependency_libs = None # Version information for libIlmImf. self.current = None self.age = None self.revision = None # Is this an already installed library? self.installed = None # Should we warn about portability when linking against -modules? self.shouldnotlink = None # Files to dlopen/dlpreopen self.dlopen = None self.dlpreopen = None # Directory that this library needs to be installed in: self.libdir = '/usr/lib' if not self.__parse(): raise ValueError("file %s not found!!" %(la_filename)) def __parse(self): "Retrieve the variables from a file" if not os.path.isfile(self.__la_filename): return 0 la_file=open(self.__la_filename, 'r') for line in la_file: ln = line.strip() if not ln: continue if ln[0]=='#': continue (key, value) = str(ln).split('=', 1) key = key.strip() value = value.strip() if value == "no": value = False elif value == "yes": value = True else: try: value = int(value) except ValueError: value = value.strip("'") setattr(self, key, value) la_file.close() return 1 def get_libs(self): """return linkflags for this lib""" libs = [] if self.dependency_libs: libs = str(self.dependency_libs).strip().split() if libs == None: libs = [] # add la lib and libdir libs.insert(0, "-l%s" % self.linkname.strip()) libs.insert(0, "-L%s" % self.libdir.strip()) return libs def __str__(self): return '''\ dlname = "%(dlname)s" library_names = "%(library_names)s" old_library = "%(old_library)s" dependency_libs = "%(dependency_libs)s" version = %(current)s.%(age)s.%(revision)s installed = "%(installed)s" shouldnotlink = "%(shouldnotlink)s" dlopen = "%(dlopen)s" dlpreopen = "%(dlpreopen)s" libdir = "%(libdir)s"''' % self.__dict__ class libtool_config: def __init__ (self, la_filename): self.__libtool_la_file = libtool_la_file(la_filename) tmp = self.__libtool_la_file self.__version = [int(tmp.current), int(tmp.age), int(tmp.revision)] self.__sub_la_files = [] self.__sub_la_files.append(la_filename) self.__libs = None def __cmp__(self, other): """make it compareable with X.Y.Z versions (Y and Z are optional)""" if not other: return 1 othervers = [int(s) for s in str(other).split(".")] selfvers = self.__version return cmp(selfvers, othervers) def __str__(self): return "\n".join([ str(self.__libtool_la_file), ' '.join(self.__libtool_la_file.get_libs()), '* New getlibs:', ' '.join(self.get_libs()) ]) def __get_la_libs(self, la_filename): return libtool_la_file(la_filename).get_libs() def get_libs(self): """return the complete uniqe linkflags that do not contain .la files anymore""" libs_list = list(self.__libtool_la_file.get_libs()) libs_map = {} while len(libs_list) > 0: entry = libs_list.pop(0) if entry: if str(entry).endswith(".la"): ## prevents duplicate .la checks if entry not in self.__sub_la_files: self.__sub_la_files.append(entry) libs_list.extend(self.__get_la_libs(entry)) else: libs_map[entry]=1 self.__libs = libs_map.keys() return self.__libs def get_libs_only_L(self): if not self.__libs: self.get_libs() libs = self.__libs libs = [s for s in libs if str(s).startswith('-L')] return libs def get_libs_only_l(self): if not self.__libs: self.get_libs() libs = self.__libs libs = [s for s in libs if str(s).startswith('-l')] return libs def get_libs_only_other(self): if not self.__libs: self.get_libs() libs = self.__libs libs = [s for s in libs if not(str(s).startswith('-L')or str(s).startswith('-l'))] return libs def useCmdLine(): """parse cmdline args and control build""" usage = '''Usage: %prog [options] PathToFile.la example: %prog --atleast-version=2.0.0 /usr/lib/libIlmImf.la nor: %prog --libs /usr/lib/libamarok.la''' parser = optparse.OptionParser(usage) a = parser.add_option a("--version", dest = "versionNumber", action = "store_true", default = False, help = "output version of libtool-config" ) a("--debug", dest = "debug", action = "store_true", default = False, help = "enable debug" ) a("--libs", dest = "libs", action = "store_true", default = False, help = "output all linker flags" ) a("--libs-only-l", dest = "libs_only_l", action = "store_true", default = False, help = "output -l flags" ) a("--libs-only-L", dest = "libs_only_L", action = "store_true", default = False, help = "output -L flags" ) a("--libs-only-other", dest = "libs_only_other", action = "store_true", default = False, help = "output other libs (e.g. -pthread)" ) a("--atleast-version", dest = "atleast_version", default=None, help = "return 0 if the module is at least version ATLEAST_VERSION" ) a("--exact-version", dest = "exact_version", default=None, help = "return 0 if the module is exactly version EXACT_VERSION" ) a("--max-version", dest = "max_version", default=None, help = "return 0 if the module is at no newer than version MAX_VERSION" ) (options, args) = parser.parse_args() if len(args) != 1 and not options.versionNumber: parser.error("incorrect number of arguments") if options.versionNumber: print("libtool-config version %s" % REVISION) return 0 ltf = libtool_config(args[0]) if options.debug: print(ltf) if options.atleast_version: if ltf >= options.atleast_version: return 0 sys.exit(1) if options.exact_version: if ltf == options.exact_version: return 0 sys.exit(1) if options.max_version: if ltf <= options.max_version: return 0 sys.exit(1) def p(x): print(" ".join(x)) if options.libs: p(ltf.get_libs()) elif options.libs_only_l: p(ltf.get_libs_only_l()) elif options.libs_only_L: p(ltf.get_libs_only_L()) elif options.libs_only_other: p(ltf.get_libs_only_other()) return 0 if __name__ == '__main__': useCmdLine() tevent-0.9.34/third_party/waf/wafadmin/Tools/lua.py0000660000000000000000000000075012520121120022163 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Sebastian Schlingmann, 2008 # Thomas Nagy, 2008 (ita) import TaskGen from TaskGen import taskgen, feature from Constants import * TaskGen.declare_chain( name = 'luac', rule = '${LUAC} -s -o ${TGT} ${SRC}', ext_in = '.lua', ext_out = '.luac', reentrant = False, install = 'LUADIR', # env variable ) @feature('lua') def init_lua(self): self.default_chmod = O755 def detect(conf): conf.find_program('luac', var='LUAC', mandatory = True) tevent-0.9.34/third_party/waf/wafadmin/Tools/misc.py0000660000000000000000000002766412520121120022352 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) """ Custom objects: - execute a function everytime - copy a file somewhere else """ import shutil, re, os import TaskGen, Node, Task, Utils, Build, Constants from TaskGen import feature, taskgen, after, before from Logs import debug def copy_func(tsk): "Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)" env = tsk.env infile = tsk.inputs[0].abspath(env) outfile = tsk.outputs[0].abspath(env) try: shutil.copy2(infile, outfile) except (OSError, IOError): return 1 else: if tsk.chmod: os.chmod(outfile, tsk.chmod) return 0 def action_process_file_func(tsk): "Ask the function attached to the task to process it" if not tsk.fun: raise Utils.WafError('task must have a function attached to it for copy_func to work!') return tsk.fun(tsk) class cmd_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('cmd') def apply_cmd(self): "call a command everytime" if not self.fun: raise Utils.WafError('cmdobj needs a function!') tsk = Task.TaskBase() tsk.fun = self.fun tsk.env = self.env self.tasks.append(tsk) tsk.install_path = self.install_path class copy_taskgen(TaskGen.task_gen): "By default, make a file copy, if fun is provided, fun will make the copy (or call a compiler, etc)" def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('copy') @before('apply_core') def apply_copy(self): Utils.def_attrs(self, fun=copy_func) self.default_install_path = 0 lst = self.to_list(self.source) self.meths.remove('apply_core') for filename in lst: node = self.path.find_resource(filename) if not node: raise Utils.WafError('cannot find input file %s for processing' % filename) target = self.target if not target or len(lst)>1: target = node.name # TODO the file path may be incorrect newnode = self.path.find_or_declare(target) tsk = self.create_task('copy', node, newnode) tsk.fun = self.fun tsk.chmod = self.chmod tsk.install_path = self.install_path if not tsk.env: tsk.debug() raise Utils.WafError('task without an environment') def subst_func(tsk): "Substitutes variables in a .in file" m4_re = re.compile('@(\w+)@', re.M) env = tsk.env infile = tsk.inputs[0].abspath(env) outfile = tsk.outputs[0].abspath(env) code = Utils.readf(infile) # replace all % by %% to prevent errors by % signs in the input file while string formatting code = code.replace('%', '%%') s = m4_re.sub(r'%(\1)s', code) di = tsk.dict or {} if not di: names = m4_re.findall(code) for i in names: di[i] = env.get_flat(i) or env.get_flat(i.upper()) file = open(outfile, 'w') file.write(s % di) file.close() if tsk.chmod: os.chmod(outfile, tsk.chmod) class subst_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('subst') @before('apply_core') def apply_subst(self): Utils.def_attrs(self, fun=subst_func) self.default_install_path = 0 lst = self.to_list(self.source) self.meths.remove('apply_core') self.dict = getattr(self, 'dict', {}) for filename in lst: node = self.path.find_resource(filename) if not node: raise Utils.WafError('cannot find input file %s for processing' % filename) if self.target: newnode = self.path.find_or_declare(self.target) else: newnode = node.change_ext('') try: self.dict = self.dict.get_merged_dict() except AttributeError: pass if self.dict and not self.env['DICT_HASH']: self.env = self.env.copy() keys = list(self.dict.keys()) keys.sort() lst = [self.dict[x] for x in keys] self.env['DICT_HASH'] = str(Utils.h_list(lst)) tsk = self.create_task('copy', node, newnode) tsk.fun = self.fun tsk.dict = self.dict tsk.dep_vars = ['DICT_HASH'] tsk.install_path = self.install_path tsk.chmod = self.chmod if not tsk.env: tsk.debug() raise Utils.WafError('task without an environment') #################### ## command-output #### #################### class cmd_arg(object): """command-output arguments for representing files or folders""" def __init__(self, name, template='%s'): self.name = name self.template = template self.node = None class input_file(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_resource(self.name) if self.node is None: raise Utils.WafError("Input file %s not found in " % (self.name, base_path)) def get_path(self, env, absolute): if absolute: return self.template % self.node.abspath(env) else: return self.template % self.node.srcpath(env) class output_file(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_or_declare(self.name) if self.node is None: raise Utils.WafError("Output file %s not found in " % (self.name, base_path)) def get_path(self, env, absolute): if absolute: return self.template % self.node.abspath(env) else: return self.template % self.node.bldpath(env) class cmd_dir_arg(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_dir(self.name) if self.node is None: raise Utils.WafError("Directory %s not found in " % (self.name, base_path)) class input_dir(cmd_dir_arg): def get_path(self, dummy_env, dummy_absolute): return self.template % self.node.abspath() class output_dir(cmd_dir_arg): def get_path(self, env, dummy_absolute): return self.template % self.node.abspath(env) class command_output(Task.Task): color = "BLUE" def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr): Task.Task.__init__(self, env, normal=1) assert isinstance(command, (str, Node.Node)) self.command = command self.command_args = command_args self.stdin = stdin self.stdout = stdout self.cwd = cwd self.os_env = os_env self.stderr = stderr if command_node is not None: self.dep_nodes = [command_node] self.dep_vars = [] # additional environment variables to look def run(self): task = self #assert len(task.inputs) > 0 def input_path(node, template): if task.cwd is None: return template % node.bldpath(task.env) else: return template % node.abspath() def output_path(node, template): fun = node.abspath if task.cwd is None: fun = node.bldpath return template % fun(task.env) if isinstance(task.command, Node.Node): argv = [input_path(task.command, '%s')] else: argv = [task.command] for arg in task.command_args: if isinstance(arg, str): argv.append(arg) else: assert isinstance(arg, cmd_arg) argv.append(arg.get_path(task.env, (task.cwd is not None))) if task.stdin: stdin = open(input_path(task.stdin, '%s')) else: stdin = None if task.stdout: stdout = open(output_path(task.stdout, '%s'), "w") else: stdout = None if task.stderr: stderr = open(output_path(task.stderr, '%s'), "w") else: stderr = None if task.cwd is None: cwd = ('None (actually %r)' % os.getcwd()) else: cwd = repr(task.cwd) debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" % (cwd, stdin, stdout, argv)) if task.os_env is None: os_env = os.environ else: os_env = task.os_env command = Utils.pproc.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env) return command.wait() class cmd_output_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('command-output') def init_cmd_output(self): Utils.def_attrs(self, stdin = None, stdout = None, stderr = None, # the command to execute command = None, # whether it is an external command; otherwise it is assumed # to be an executable binary or script that lives in the # source or build tree. command_is_external = False, # extra parameters (argv) to pass to the command (excluding # the command itself) argv = [], # dependencies to other objects -> this is probably not what you want (ita) # values must be 'task_gen' instances (not names!) dependencies = [], # dependencies on env variable contents dep_vars = [], # input files that are implicit, i.e. they are not # stdin, nor are they mentioned explicitly in argv hidden_inputs = [], # output files that are implicit, i.e. they are not # stdout, nor are they mentioned explicitly in argv hidden_outputs = [], # change the subprocess to this cwd (must use obj.input_dir() or output_dir() here) cwd = None, # OS environment variables to pass to the subprocess # if None, use the default environment variables unchanged os_env = None) @feature('command-output') @after('init_cmd_output') def apply_cmd_output(self): if self.command is None: raise Utils.WafError("command-output missing command") if self.command_is_external: cmd = self.command cmd_node = None else: cmd_node = self.path.find_resource(self.command) assert cmd_node is not None, ('''Could not find command '%s' in source tree. Hint: if this is an external command, use command_is_external=True''') % (self.command,) cmd = cmd_node if self.cwd is None: cwd = None else: assert isinstance(cwd, CmdDirArg) self.cwd.find_node(self.path) args = [] inputs = [] outputs = [] for arg in self.argv: if isinstance(arg, cmd_arg): arg.find_node(self.path) if isinstance(arg, input_file): inputs.append(arg.node) if isinstance(arg, output_file): outputs.append(arg.node) if self.stdout is None: stdout = None else: assert isinstance(self.stdout, str) stdout = self.path.find_or_declare(self.stdout) if stdout is None: raise Utils.WafError("File %s not found" % (self.stdout,)) outputs.append(stdout) if self.stderr is None: stderr = None else: assert isinstance(self.stderr, str) stderr = self.path.find_or_declare(self.stderr) if stderr is None: raise Utils.WafError("File %s not found" % (self.stderr,)) outputs.append(stderr) if self.stdin is None: stdin = None else: assert isinstance(self.stdin, str) stdin = self.path.find_resource(self.stdin) if stdin is None: raise Utils.WafError("File %s not found" % (self.stdin,)) inputs.append(stdin) for hidden_input in self.to_list(self.hidden_inputs): node = self.path.find_resource(hidden_input) if node is None: raise Utils.WafError("File %s not found in dir %s" % (hidden_input, self.path)) inputs.append(node) for hidden_output in self.to_list(self.hidden_outputs): node = self.path.find_or_declare(hidden_output) if node is None: raise Utils.WafError("File %s not found in dir %s" % (hidden_output, self.path)) outputs.append(node) if not (inputs or getattr(self, 'no_inputs', None)): raise Utils.WafError('command-output objects must have at least one input file or give self.no_inputs') if not (outputs or getattr(self, 'no_outputs', None)): raise Utils.WafError('command-output objects must have at least one output file or give self.no_outputs') task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr) Utils.copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True) self.tasks.append(task) task.inputs = inputs task.outputs = outputs task.dep_vars = self.to_list(self.dep_vars) for dep in self.dependencies: assert dep is not self dep.post() for dep_task in dep.tasks: task.set_run_after(dep_task) if not task.inputs: # the case for svnversion, always run, and update the output nodes task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__) # TODO the case with no outputs? def post_run(self): for x in self.outputs: h = Utils.h_file(x.abspath(self.env)) self.generator.bld.node_sigs[self.env.variant()][x.id] = h def runnable_status(self): return Constants.RUN_ME Task.task_type_from_func('copy', vars=[], func=action_process_file_func) TaskGen.task_gen.classes['command-output'] = cmd_output_taskgen tevent-0.9.34/third_party/waf/wafadmin/Tools/msvc.py0000660000000000000000000006400613055076237022404 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2006 (dv) # Tamas Pal, 2007 (folti) # Nicolas Mercier, 2009 # Microsoft Visual C++/Intel C++ compiler support - beta, needs more testing # usage: # # conf.env['MSVC_VERSIONS'] = ['msvc 9.0', 'msvc 8.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0'] # conf.env['MSVC_TARGETS'] = ['x64'] # conf.check_tool('msvc') # OR conf.check_tool('msvc', funs='no_autodetect') # conf.check_lib_msvc('gdi32') # conf.check_libs_msvc('kernel32 user32', mandatory=true) # ... # obj.uselib = 'KERNEL32 USER32 GDI32' # # platforms and targets will be tested in the order they appear; # the first good configuration will be used # supported platforms : # ia64, x64, x86, x86_amd64, x86_ia64 # compilers supported : # msvc => Visual Studio, versions 7.1 (2003), 8,0 (2005), 9.0 (2008) # wsdk => Windows SDK, versions 6.0, 6.1, 7.0 # icl => Intel compiler, versions 9,10,11 # Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i) # PocketPC => Compiler/SDK for PocketPC devices (armv4/v4i) import os, sys, re, string, optparse import Utils, TaskGen, Runner, Configure, Task, Options from Logs import debug, info, warn, error from TaskGen import after, before, feature from Configure import conftest, conf import ccroot, cc, cxx, ar, winres from libtool import read_la_file try: import _winreg except: import winreg as _winreg pproc = Utils.pproc # importlibs provided by MSVC/Platform SDK. Do NOT search them.... 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() all_msvc_platforms = [ ('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'), ('x86_amd64', 'amd64'), ('x86_ia64', 'ia64') ] all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ] all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] def setup_msvc(conf, versions): 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 = conf.env['MSVC_VERSIONS'] or [v for v,_ in versions][::-1] versiondict = dict(versions) for version in desired_versions: try: targets = dict(versiondict [version]) for target in platforms: try: arch,(p1,p2,p3) = targets[target] compiler,revision = version.split() return compiler,revision,p1,p2,p3 except KeyError: continue except KeyError: continue conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)') @conf def get_msvc_version(conf, compiler, version, target, vcvars): debug('msvc: get_msvc_version: %r %r %r', compiler, version, target) batfile = os.path.join(conf.blddir, 'waf-print-msvc.bat') f = open(batfile, 'w') f.write("""@echo off set INCLUDE= set LIB= call "%s" %s echo PATH=%%PATH%% echo INCLUDE=%%INCLUDE%% echo LIB=%%LIB%% """ % (vcvars,target)) f.close() sout = Utils.cmd_output(['cmd', '/E:on', '/V:on', '/C', batfile]) lines = sout.splitlines() for x in ('Setting environment', 'Setting SDK environment', 'Intel(R) C++ Compiler'): if lines[0].find(x) != -1: break else: debug('msvc: get_msvc_version: %r %r %r -> not found', compiler, version, target) conf.fatal('msvc: Impossible to find a valid architecture for building (in get_msvc_version)') for line in lines[1:]: 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] # 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 = {} env.update(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 wich can change cl's behaviour rather catastrophically. if env.has_key('CL'): del(env['CL']) try: p = pproc.Popen([cxx, '/help'], env=env, stdout=pproc.PIPE, stderr=pproc.PIPE) out, err = p.communicate() if p.returncode != 0: raise Exception('return code: %r: %r' % (p.returncode, err)) except Exception, e: debug('msvc: get_msvc_version: %r %r %r -> failure', compiler, version, target) debug(str(e)) conf.fatal('msvc: cannot run the compiler (in get_msvc_version)') else: debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target) return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) @conf def gather_wsdk_versions(conf, versions): version_pattern = re.compile('^v..?.?\...?.?') try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') except WindowsError: try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') except WindowsError: return index = 0 while 1: try: version = _winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue try: msvc_version = _winreg.OpenKey(all_versions, version) path,type = _winreg.QueryValueEx(msvc_version,'InstallationFolder') except WindowsError: continue if os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): targets = [] for target,arch in all_msvc_platforms: try: targets.append((target, (arch, conf.get_msvc_version('wsdk', version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd'))))) except Configure.ConfigurationError: pass versions.append(('wsdk ' + version[1:], targets)) @conf def gather_msvc_versions(conf, versions): # checks SmartPhones SDKs try: ce_sdk = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') except WindowsError: try: ce_sdk = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') except WindowsError: ce_sdk = '' if ce_sdk: supported_wince_platforms = [] ce_index = 0 while 1: try: sdk_device = _winreg.EnumKey(ce_sdk, ce_index) except WindowsError: break ce_index = ce_index + 1 sdk = _winreg.OpenKey(ce_sdk, sdk_device) path,type = _winreg.QueryValueEx(sdk, 'SDKRootDir') path=str(path) path,device = os.path.split(path) if not device: path,device = os.path.split(path) for arch,compiler in all_wince_platforms: 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)) # checks MSVC version_pattern = re.compile('^..?\...?') for vcver,vcvar in [('VCExpress','exp'), ('VisualStudio','')]: try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\'+vcver) except WindowsError: try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\'+vcver) except WindowsError: continue index = 0 while 1: try: version = _winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue try: msvc_version = _winreg.OpenKey(all_versions, version + "\\Setup\\VS") path,type = _winreg.QueryValueEx(msvc_version, 'ProductDir') path=str(path) targets = [] if ce_sdk: for device,platforms in supported_wince_platforms: cetargets = [] for platform,compiler,include,lib in platforms: winCEpath = os.path.join(path, 'VC', 'ce') if os.path.isdir(winCEpath): common_bindirs,_1,_2 = conf.get_msvc_version('msvc', version, 'x86', os.path.join(path, 'Common7', 'Tools', 'vsvars32.bat')) if os.path.isdir(os.path.join(winCEpath, 'lib', platform)): bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)] + common_bindirs incdirs = [include, os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include')] libdirs = [lib, os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform)] cetargets.append((platform, (platform, (bindirs,incdirs,libdirs)))) versions.append((device+' '+version, cetargets)) if os.path.isfile(os.path.join(path, 'VC', 'vcvarsall.bat')): for target,realtarget in all_msvc_platforms[::-1]: try: targets.append((target, (realtarget, conf.get_msvc_version('msvc', version, target, os.path.join(path, 'VC', 'vcvarsall.bat'))))) except: pass elif os.path.isfile(os.path.join(path, 'Common7', 'Tools', 'vsvars32.bat')): try: targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, 'x86', os.path.join(path, 'Common7', 'Tools', 'vsvars32.bat'))))) except Configure.ConfigurationError: pass versions.append(('msvc '+version, targets)) except WindowsError: continue @conf def gather_icl_versions(conf, versions): version_pattern = re.compile('^...?.?\....?.?') try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') except WindowsError: try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') except WindowsError: return index = 0 while 1: try: version = _winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue targets = [] for target,arch in all_icl_platforms: try: icl_version = _winreg.OpenKey(all_versions, version+'\\'+target) path,type = _winreg.QueryValueEx(icl_version,'ProductDir') if os.path.isfile(os.path.join(path, 'bin', 'iclvars.bat')): try: targets.append((target, (arch, conf.get_msvc_version('intel', version, target, os.path.join(path, 'bin', 'iclvars.bat'))))) except Configure.ConfigurationError: pass except WindowsError: continue major = version[0:2] versions.append(('intel ' + major, targets)) @conf def get_msvc_versions(conf): if not conf.env.MSVC_INSTALLED_VERSIONS: lst = [] conf.gather_msvc_versions(lst) conf.gather_wsdk_versions(lst) conf.gather_icl_versions(lst) conf.env.MSVC_INSTALLED_VERSIONS = lst return conf.env.MSVC_INSTALLED_VERSIONS @conf def print_all_msvc_detected(conf): for version,targets in conf.env['MSVC_INSTALLED_VERSIONS']: info(version) for target,l in targets: info("\t"+target) def detect_msvc(conf): versions = get_msvc_versions(conf) return setup_msvc(conf, versions) @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 """ 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=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('\.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 Utils.WafError('invalid libtool object file: %s' % laf) return (None, None, None) @conf def libname_msvc(self, libname, is_static=False, mandatory=False): lib = libname.lower() lib = re.sub('\.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 == True: # 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)): debug('msvc: lib found: %s', os.path.join(path,libn)) return re.sub('\.lib$', '',libn) #if no lib can be found, just return the libname as msvc expects it if mandatory: self.fatal("The library %r could not be found" % libname) return re.sub('\.lib$', '', libname) @conf def check_lib_msvc(self, libname, is_static=False, uselib_store=None, mandatory=False): "This is the api to use" libn = self.libname_msvc(libname, is_static, mandatory) if not uselib_store: uselib_store = libname.upper() # Note: ideally we should be able to place the lib in the right env var, either STATICLIB 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['STATICLIB_MARKER']) if False and is_static: # disabled self.env['STATICLIB_' + uselib_store] = [libn] else: self.env['LIB_' + uselib_store] = [libn] @conf def check_libs_msvc(self, libnames, is_static=False, mandatory=False): for libname in Utils.to_list(libnames): self.check_lib_msvc(libname, is_static, mandatory=mandatory) @conftest def no_autodetect(conf): conf.eval_rules(detect.replace('autodetect', '')) detect = ''' autodetect find_msvc msvc_common_flags cc_load_tools cxx_load_tools cc_add_flags cxx_add_flags link_add_flags ''' @conftest def autodetect(conf): v = conf.env compiler, version, path, includes, libdirs = detect_msvc(conf) v['PATH'] = path v['CPPPATH'] = includes v['LIBPATH'] = libdirs v['MSVC_COMPILER'] = compiler 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 @conftest def find_msvc(conf): # due to path format limitations, limit operation only to native Win32. Yeah it sucks. if sys.platform != 'win32': conf.fatal('MSVC module only works under native Win32 Python! cygwin is not supported yet') v = conf.env compiler, version, path, includes, libdirs = detect_msvc(conf) compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) has_msvc_manifest = (compiler == 'msvc' and float(version) >= 8) or (compiler == 'wsdk' and float(version) >= 6) or (compiler == 'intel' and float(version) >= 11) # compiler cxx = None if v.CXX: cxx = v.CXX elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] if not cxx: cxx = conf.find_program(compiler_name, var='CXX', path_list=path, mandatory=True) cxx = conf.cmd_to_list(cxx) # before setting anything, check if the compiler is really msvc env = dict(conf.environ) env.update(PATH = ';'.join(path)) if not Utils.cmd_output([cxx, '/nologo', '/?'], silent=True, env=env): conf.fatal('the msvc compiler could not be identified') link = v.LINK_CXX if not link: link = conf.find_program(linker_name, path_list=path, mandatory=True) ar = v.AR if not ar: ar = conf.find_program(lib_name, path_list=path, mandatory=True) # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later mt = v.MT if has_msvc_manifest: mt = conf.find_program('MT', path_list=path, mandatory=True) # no more possibility of failure means the data state will be consistent # we may store the data safely now v.MSVC_MANIFEST = has_msvc_manifest v.PATH = path v.CPPPATH = includes v.LIBPATH = libdirs # c/c++ compiler v.CC = v.CXX = cxx v.CC_NAME = v.CXX_NAME = 'msvc' v.LINK = v.LINK_CXX = link if not v.LINK_CC: v.LINK_CC = v.LINK_CXX v.AR = ar v.MT = mt v.MTFLAGS = v.ARFLAGS = ['/NOLOGO'] conf.check_tool('winres') if not conf.env.WINRC: warn('Resource compiler not found. Compiling resource file is disabled') # environment flags try: v.prepend_value('CPPPATH', conf.environ['INCLUDE']) except KeyError: pass try: v.prepend_value('LIBPATH', conf.environ['LIB']) except KeyError: pass @conftest def msvc_common_flags(conf): v = conf.env v['CPPFLAGS'] = ['/W3', '/nologo'] v['CCDEFINES_ST'] = '/D%s' v['CXXDEFINES_ST'] = '/D%s' # TODO just use _WIN32, which defined by the compiler itself! v['CCDEFINES'] = ['WIN32'] # avoid using this, any compiler predefines the _WIN32 marcro anyway v['CXXDEFINES'] = ['WIN32'] # avoid using this, any compiler predefines the _WIN32 marcro anyway v['_CCINCFLAGS'] = [] v['_CCDEFFLAGS'] = [] v['_CXXINCFLAGS'] = [] v['_CXXDEFFLAGS'] = [] v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['/c', '/Fo'] v['CXX_SRC_F'] = '' v['CXX_TGT_F'] = ['/c', '/Fo'] v['CPPPATH_ST'] = '/I%s' # template for adding include paths v['AR_TGT_F'] = v['CCLNK_TGT_F'] = v['CXXLNK_TGT_F'] = '/OUT:' # Subsystem specific flags v['CPPFLAGS_CONSOLE'] = ['/SUBSYSTEM:CONSOLE'] v['CPPFLAGS_NATIVE'] = ['/SUBSYSTEM:NATIVE'] v['CPPFLAGS_POSIX'] = ['/SUBSYSTEM:POSIX'] v['CPPFLAGS_WINDOWS'] = ['/SUBSYSTEM:WINDOWS'] v['CPPFLAGS_WINDOWSCE'] = ['/SUBSYSTEM:WINDOWSCE'] # CRT specific flags v['CPPFLAGS_CRT_MULTITHREADED'] = ['/MT'] v['CPPFLAGS_CRT_MULTITHREADED_DLL'] = ['/MD'] # TODO these are defined by the compiler itself! v['CPPDEFINES_CRT_MULTITHREADED'] = ['_MT'] # this is defined by the compiler itself! v['CPPDEFINES_CRT_MULTITHREADED_DLL'] = ['_MT', '_DLL'] # these are defined by the compiler itself! v['CPPFLAGS_CRT_MULTITHREADED_DBG'] = ['/MTd'] v['CPPFLAGS_CRT_MULTITHREADED_DLL_DBG'] = ['/MDd'] # TODO these are defined by the compiler itself! v['CPPDEFINES_CRT_MULTITHREADED_DBG'] = ['_DEBUG', '_MT'] # these are defined by the compiler itself! v['CPPDEFINES_CRT_MULTITHREADED_DLL_DBG'] = ['_DEBUG', '_MT', '_DLL'] # these are defined by the compiler itself! # compiler debug levels v['CCFLAGS'] = ['/TC'] v['CCFLAGS_OPTIMIZED'] = ['/O2', '/DNDEBUG'] v['CCFLAGS_RELEASE'] = ['/O2', '/DNDEBUG'] v['CCFLAGS_DEBUG'] = ['/Od', '/RTC1', '/ZI'] v['CCFLAGS_ULTRADEBUG'] = ['/Od', '/RTC1', '/ZI'] v['CXXFLAGS'] = ['/TP', '/EHsc'] v['CXXFLAGS_OPTIMIZED'] = ['/O2', '/DNDEBUG'] v['CXXFLAGS_RELEASE'] = ['/O2', '/DNDEBUG'] v['CXXFLAGS_DEBUG'] = ['/Od', '/RTC1', '/ZI'] v['CXXFLAGS_ULTRADEBUG'] = ['/Od', '/RTC1', '/ZI'] # linker v['LIB'] = [] v['LIB_ST'] = '%s.lib' # template for adding libs v['LIBPATH_ST'] = '/LIBPATH:%s' # template for adding libpaths v['STATICLIB_ST'] = 'lib%s.lib' # Note: to be able to distinguish between a static lib and a dll import lib, it's a good pratice to name the static lib 'lib%s.lib' and the dll import lib '%s.lib' v['STATICLIBPATH_ST'] = '/LIBPATH:%s' v['LINKFLAGS'] = ['/NOLOGO'] if v['MSVC_MANIFEST']: v.append_value('LINKFLAGS', '/MANIFEST') v['LINKFLAGS_DEBUG'] = ['/DEBUG'] v['LINKFLAGS_ULTRADEBUG'] = ['/DEBUG'] # shared library v['shlib_CCFLAGS'] = [''] v['shlib_CXXFLAGS'] = [''] v['shlib_LINKFLAGS']= ['/DLL'] v['shlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = '%s.lib' v['IMPLIB_ST'] = '/IMPLIB:%s' # static library v['staticlib_LINKFLAGS'] = [''] v['staticlib_PATTERN'] = 'lib%s.lib' # Note: to be able to distinguish between a static lib and a dll import lib, it's a good pratice to name the static lib 'lib%s.lib' and the dll import lib '%s.lib' # program v['program_PATTERN'] = '%s.exe' ####################################################################################################### ##### conf above, build below @after('apply_link') @feature('c', 'cc', 'cxx') def apply_flags_msvc(self): if self.env.CC_NAME != 'msvc' or not self.link_task: return subsystem = getattr(self, 'subsystem', '') if subsystem: subsystem = '/subsystem:%s' % subsystem flags = 'cstaticlib' in self.features and 'ARFLAGS' or 'LINKFLAGS' self.env.append_value(flags, subsystem) if getattr(self, 'link_task', None) and not 'cstaticlib' in self.features: for f in self.env.LINKFLAGS: d = f.lower() if d[1:] == 'debug': pdbnode = self.link_task.outputs[0].change_ext('.pdb') pdbfile = pdbnode.bldpath(self.env) self.link_task.outputs.append(pdbnode) self.bld.install_files(self.install_path, [pdbnode], env=self.env) break @feature('cprogram', 'cshlib', 'cstaticlib') @after('apply_lib_vars') @before('apply_obj_vars') def apply_obj_vars_msvc(self): if self.env['CC_NAME'] != 'msvc': return try: self.meths.remove('apply_obj_vars') except ValueError: pass libpaths = getattr(self, 'libpaths', []) if not libpaths: self.libpaths = libpaths env = self.env app = env.append_unique cpppath_st = env['CPPPATH_ST'] lib_st = env['LIB_ST'] staticlib_st = env['STATICLIB_ST'] libpath_st = env['LIBPATH_ST'] staticlibpath_st = env['STATICLIBPATH_ST'] for i in env['LIBPATH']: app('LINKFLAGS', libpath_st % i) if not libpaths.count(i): libpaths.append(i) for i in env['LIBPATH']: app('LINKFLAGS', staticlibpath_st % i) if not libpaths.count(i): libpaths.append(i) # i doubt that anyone will make a fully static binary anyway if not env['FULLSTATIC']: if env['STATICLIB'] or env['LIB']: app('LINKFLAGS', env['SHLIB_MARKER']) # TODO does SHLIB_MARKER work? for i in env['STATICLIB']: app('LINKFLAGS', staticlib_st % i) for i in env['LIB']: app('LINKFLAGS', lib_st % i) # split the manifest file processing from the link task, like for the rc processing @feature('cprogram', 'cshlib') @after('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: 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.link_task.do_manifest = True def exec_mf(self): env = self.env mtool = env['MT'] if not mtool: return 0 self.do_manifest = False outfile = self.outputs[0].bldpath(env) manifest = None for out_node in self.outputs: if out_node.name.endswith('.manifest'): manifest = out_node.bldpath(env) break if manifest is None: # 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 = '' if 'cprogram' in self.generator.features: mode = '1' elif 'cshlib' in self.generator.features: mode = '2' debug('msvc: embedding manifest') #flags = ' '.join(env['MTFLAGS'] or []) lst = [] lst.extend([env['MT']]) lst.extend(Utils.to_list(env['MTFLAGS'])) lst.extend(Utils.to_list("-manifest")) lst.extend(Utils.to_list(manifest)) lst.extend(Utils.to_list("-outputresource:%s;%s" % (outfile, mode))) #cmd='%s %s -manifest "%s" -outputresource:"%s";#%s' % (mtool, flags, # manifest, outfile, mode) lst = [lst] return self.exec_command(*lst) ########## stupid evil command modification: concatenate the tokens /Fx, /doc, and /x: with the next token def exec_command_msvc(self, *k, **kw): "instead of quoting all the paths and keep using the shell, we can just join the options msvc is interested in" if self.env['CC_NAME'] == 'msvc': if isinstance(k[0], list): lst = [] carry = '' for a in k[0]: if len(a) == 3 and a.startswith('/F') or a == '/doc' or a[-1] == ':': carry = a else: lst.append(carry + a) carry = '' k = [lst] env = dict(os.environ) env.update(PATH = ';'.join(self.env['PATH'])) kw['env'] = env ret = self.generator.bld.exec_command(*k, **kw) if ret: return ret if getattr(self, 'do_manifest', None): ret = exec_mf(self) return ret for k in 'cc cxx winrc cc_link cxx_link static_link qxx'.split(): cls = Task.TaskBase.classes.get(k, None) if cls: cls.exec_command = exec_command_msvc tevent-0.9.34/third_party/waf/wafadmin/Tools/nasm.py0000660000000000000000000000247212520121120022343 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008 """ Nasm processing """ import os import TaskGen, Task, Utils from TaskGen import taskgen, before, extension nasm_str = '${NASM} ${NASM_FLAGS} ${NASM_INCLUDES} ${SRC} -o ${TGT}' EXT_NASM = ['.s', '.S', '.asm', '.ASM', '.spp', '.SPP'] @before('apply_link') def apply_nasm_vars(self): # flags if hasattr(self, 'nasm_flags'): for flag in self.to_list(self.nasm_flags): self.env.append_value('NASM_FLAGS', flag) # includes - well, if we suppose it works with c processing if hasattr(self, 'includes'): for inc in self.to_list(self.includes): node = self.path.find_dir(inc) if not node: raise Utils.WafError('cannot find the dir' + inc) self.env.append_value('NASM_INCLUDES', '-I%s' % node.srcpath(self.env)) self.env.append_value('NASM_INCLUDES', '-I%s' % node.bldpath(self.env)) @extension(EXT_NASM) def nasm_file(self, node): try: obj_ext = self.obj_ext except AttributeError: obj_ext = '_%d.o' % self.idx task = self.create_task('nasm', node, node.change_ext(obj_ext)) self.compiled_tasks.append(task) self.meths.append('apply_nasm_vars') # create our action here Task.simple_task_type('nasm', nasm_str, color='BLUE', ext_out='.o', shell=False) def detect(conf): nasm = conf.find_program(['nasm', 'yasm'], var='NASM', mandatory=True) tevent-0.9.34/third_party/waf/wafadmin/Tools/ocaml.py0000660000000000000000000002160412520121120022476 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) "ocaml support" import os, re import TaskGen, Utils, Task, Build from Logs import error from TaskGen import taskgen, feature, before, after, extension EXT_MLL = ['.mll'] EXT_MLY = ['.mly'] EXT_MLI = ['.mli'] EXT_MLC = ['.c'] EXT_ML = ['.ml'] open_re = re.compile('^\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(0) return '' return foo.sub(repl, txt) def scan(self): node = self.inputs[0] code = filter_comments(node.read(self.env)) 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'] class ocaml_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @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('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.copy() if self.islibrary: self.native_env['OCALINKFLAGS'] = '-a' self.bytecode_env = None if self.type in bytecode_lst: self.bytecode_env = self.env.copy() 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('apply_vars_ml') @after('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 self.bld.rescan(node) 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('apply_core') def apply_vars_ml(self): for i in self.incpaths_lst: if self.bytecode_env: app = self.bytecode_env.append_value app('OCAMLPATH', '-I') app('OCAMLPATH', i.srcpath(self.env)) app('OCAMLPATH', '-I') app('OCAMLPATH', i.bldpath(self.env)) if self.native_env: app = self.native_env.append_value app('OCAMLPATH', '-I') app('OCAMLPATH', i.bldpath(self.env)) app('OCAMLPATH', '-I') app('OCAMLPATH', i.srcpath(self.env)) 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('apply_core') 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.obj = self 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.obj = self 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'), env=self.native_env) self.mlltasks.append(mll_task) self.allnodes.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')], env=self.native_env) self.mlytasks.append(mly_task) self.allnodes.append(mly_task.outputs[0]) task = self.create_task('ocamlcmi', mly_task.outputs[1], mly_task.outputs[1].change_ext('.cmi'), env=self.native_env) @extension(EXT_MLI) def mli_hook(self, node): task = self.create_task('ocamlcmi', node, node.change_ext('.cmi'), env=self.native_env) self.mlitasks.append(task) @extension(EXT_MLC) def mlc_hook(self, node): task = self.create_task('ocamlcc', node, node.change_ext('.o'), env=self.native_env) 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'), env=self.native_env) task.obj = self 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'), env=self.bytecode_env) task.obj = self 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.obj.bytecode_tasks else: alltasks = self.obj.native_tasks self.signature() # ensure that files are scanned - unfortunately tree = self.generator.bld env = self.env for node in self.inputs: lst = tree.node_deps[self.unique_id()] 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) b = Task.simple_task_type cls = b('ocamlx', '${OCAMLOPT} ${OCAMLPATH} ${OCAMLFLAGS} ${INCLUDES} -c -o ${TGT} ${SRC}', color='GREEN', shell=False) cls.runnable_status = compile_may_start cls.scan = scan b = Task.simple_task_type cls = b('ocaml', '${OCAMLC} ${OCAMLPATH} ${OCAMLFLAGS} ${INCLUDES} -c -o ${TGT} ${SRC}', color='GREEN', shell=False) cls.runnable_status = compile_may_start cls.scan = scan b('ocamlcmi', '${OCAMLC} ${OCAMLPATH} ${INCLUDES} -o ${TGT} -c ${SRC}', color='BLUE', before="ocaml ocamlcc ocamlx") b('ocamlcc', 'cd ${TGT[0].bld_dir(env)} && ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLPATH} ${INCLUDES} -c ${SRC[0].abspath(env)}', color='GREEN') b('ocamllex', '${OCAMLLEX} ${SRC} -o ${TGT}', color='BLUE', before="ocamlcmi ocaml ocamlcc") b('ocamlyacc', '${OCAMLYACC} -b ${TGT[0].bld_base(env)} ${SRC}', color='BLUE', before="ocamlcmi ocaml ocamlcc") def link_may_start(self): if not getattr(self, 'order', ''): # now reorder the inputs given the task dependencies if getattr(self, 'bytecode', 0): alltasks = self.obj.bytecode_tasks else: alltasks = self.obj.native_tasks # 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) act = b('ocalink', '${OCAMLC} -o ${TGT} ${INCLUDES} ${OCALINKFLAGS} ${SRC}', color='YELLOW', after="ocaml ocamlcc") act.runnable_status = link_may_start act = b('ocalinkx', '${OCAMLOPT} -o ${TGT} ${INCLUDES} ${OCALINKFLAGS_OPT} ${SRC}', color='YELLOW', after="ocamlx ocamlcc") act.runnable_status = link_may_start def detect(conf): opt = conf.find_program('ocamlopt', var='OCAMLOPT') occ = conf.find_program('ocamlc', var='OCAMLC') 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') v['OCAMLYACC'] = conf.find_program('ocamlyacc', var='OCAMLYACC') v['OCAMLFLAGS'] = '' v['OCAMLLIB'] = Utils.cmd_output(conf.env['OCAMLC']+' -where').strip()+os.sep v['LIBPATH_OCAML'] = Utils.cmd_output(conf.env['OCAMLC']+' -where').strip()+os.sep v['CPPPATH_OCAML'] = Utils.cmd_output(conf.env['OCAMLC']+' -where').strip()+os.sep v['LIB_OCAML'] = 'camlrun' tevent-0.9.34/third_party/waf/wafadmin/Tools/osx.py0000660000000000000000000001331112617125140022225 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy 2008 """MacOSX related tools To compile an executable into a Mac application bundle (a .app), set its 'mac_app' attribute obj.mac_app = True To make a bundled shared library (a .bundle), set the 'mac_bundle' attribute: obj.mac_bundle = True """ import os, shutil, sys, platform import TaskGen, Task, Build, Options, Utils from TaskGen import taskgen, feature, after, before from Logs import error, debug # plist template app_info = ''' CFBundlePackageType APPL CFBundleGetInfoString Created by Waf CFBundleSignature ???? NOTE THIS IS A GENERATED FILE, DO NOT MODIFY CFBundleExecutable %s ''' # see WAF issue 285 # and also http://trac.macports.org/ticket/17059 @feature('c', 'cc', 'cxx') @before('apply_lib_vars') def set_macosx_deployment_target(self): 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 sys.platform == 'darwin': os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2]) @feature('c', 'cc', 'cxx') @after('apply_lib_vars') def apply_framework(self): for x in self.to_list(self.env['FRAMEWORKPATH']): frameworkpath_st = '-F%s' self.env.append_unique('CXXFLAGS', frameworkpath_st % x) self.env.append_unique('CCFLAGS', frameworkpath_st % x) self.env.append_unique('LINKFLAGS', frameworkpath_st % x) for x in self.to_list(self.env['FRAMEWORK']): self.env.append_value('LINKFLAGS', ['-framework', x]) @taskgen def create_bundle_dirs(self, name, out): bld = self.bld dir = out.parent.get_dir(name) if not dir: dir = out.__class__(name, out.parent, 1) bld.rescan(dir) contents = out.__class__('Contents', dir, 1) bld.rescan(contents) macos = out.__class__('MacOS', contents, 1) bld.rescan(macos) 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 @taskgen @after('apply_link') @feature('cprogram') def create_task_macapp(self): """Use env['MACAPP'] to force *all* executables to be transformed into Mac applications or use obj.mac_app = True to build specific targets as Mac apps""" if self.env['MACAPP'] or getattr(self, 'mac_app', False): apptask = self.create_task('macapp') apptask.set_inputs(self.link_task.outputs) 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]) apptask.set_outputs([n1]) apptask.chmod = 0755 apptask.install_path = os.path.join(self.install_path, name, 'Contents', 'MacOS') self.apptask = apptask @after('apply_link') @feature('cprogram') def create_task_macplist(self): """Use env['MACAPP'] to force *all* executables to be transformed into Mac applications or use obj.mac_app = True to build specific targets as Mac apps""" if self.env['MACAPP'] or getattr(self, 'mac_app', False): # check if the user specified a plist before using our template if not getattr(self, 'mac_plist', False): self.mac_plist = app_info plisttask = self.create_task('macplist') plisttask.set_inputs(self.link_task.outputs) out = self.link_task.outputs[0] self.mac_plist = self.mac_plist % (out.name) name = bundle_name_for_output(out) dir = self.create_bundle_dirs(name, out) n1 = dir.find_or_declare(['Contents', 'Info.plist']) plisttask.set_outputs([n1]) plisttask.mac_plist = self.mac_plist plisttask.install_path = os.path.join(self.install_path, name, 'Contents') self.plisttask = plisttask @after('apply_link') @feature('cshlib') def apply_link_osx(self): name = self.link_task.outputs[0].name if not self.install_path: return if getattr(self, 'vnum', None): name = name.replace('.dylib', '.%s.dylib' % self.vnum) path = os.path.join(Utils.subst_vars(self.install_path, self.env), name) if '-dynamiclib' in self.env['LINKFLAGS']: self.env.append_value('LINKFLAGS', '-install_name') self.env.append_value('LINKFLAGS', path) @before('apply_link', 'apply_lib_vars') @feature('c', 'cc', 'cxx') def apply_bundle(self): """use env['MACBUNDLE'] to force all shlibs into mac bundles or use obj.mac_bundle = True for specific targets only""" if not ('cshlib' in self.features or 'shlib' in self.features): return if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False): self.env['shlib_PATTERN'] = self.env['macbundle_PATTERN'] uselib = self.uselib = self.to_list(self.uselib) if not 'MACBUNDLE' in uselib: uselib.append('MACBUNDLE') @after('apply_link') @feature('cshlib') def apply_bundle_remove_dynamiclib(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 # TODO REMOVE IN 1.6 (global variable) app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources'] def app_build(task): env = task.env shutil.copy2(task.inputs[0].srcpath(env), task.outputs[0].abspath(env)) return 0 def plist_build(task): env = task.env f = open(task.outputs[0].abspath(env), "w") f.write(task.mac_plist) f.close() return 0 Task.task_type_from_func('macapp', vars=[], func=app_build, after="cxx_link cc_link static_link") Task.task_type_from_func('macplist', vars=[], func=plist_build, after="cxx_link cc_link static_link") tevent-0.9.34/third_party/waf/wafadmin/Tools/perl.py0000660000000000000000000000675212520121120022354 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # andersg at 0x63.nu 2007 import os import Task, Options, Utils from Configure import conf from TaskGen import extension, taskgen, feature, before xsubpp_str = '${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' EXT_XS = ['.xs'] @before('apply_incpaths', 'apply_type_vars', 'apply_lib_vars') @feature('perlext') def init_perlext(self): self.uselib = self.to_list(getattr(self, 'uselib', '')) if not 'PERL' in self.uselib: self.uselib.append('PERL') if not 'PERLEXT' in self.uselib: self.uselib.append('PERLEXT') self.env['shlib_PATTERN'] = self.env['perlext_PATTERN'] @extension(EXT_XS) def xsubpp_file(self, node): outnode = node.change_ext('.c') self.create_task('xsubpp', node, outnode) self.allnodes.append(outnode) Task.simple_task_type('xsubpp', xsubpp_str, color='BLUE', before='cc cxx', shell=False) @conf def check_perl_version(conf, minver=None): """ Checks if perl is installed. If installed the variable PERL will be set in environment. Perl binary can be overridden by --with-perl-binary config variable """ if getattr(Options.options, 'perlbinary', None): conf.env.PERL = Options.options.perlbinary else: conf.find_program('perl', var='PERL', mandatory=True) try: version = Utils.cmd_output([conf.env.PERL, '-e', 'printf "%vd",$^V']) except: conf.fatal('could not determine the perl version') conf.env.PERL_VERSION = version cver = '' if minver: try: ver = tuple(map(int, version.split('.'))) except: conf.fatal('unsupported perl version %r' % version) if ver < minver: conf.fatal('perl is too old') cver = '.'.join(map(str,minver)) conf.check_message('perl', cver, True, version) @conf def check_perl_module(conf, module): """ Check if specified perlmodule is installed. Minimum version can be specified by specifying it after modulename like this: conf.check_perl_module("Some::Module 2.92") """ cmd = [conf.env['PERL'], '-e', 'use %s' % module] r = Utils.pproc.call(cmd, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE) == 0 conf.check_message("perl module %s" % module, "", r) return r @conf def check_perl_ext_devel(conf): """ 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 """ if not conf.env.PERL: conf.fatal('perl detection is required first') def read_out(cmd): return Utils.to_list(Utils.cmd_output([conf.env.PERL, '-MConfig', '-e', cmd])) conf.env.LINKFLAGS_PERLEXT = read_out('print $Config{lddlflags}') conf.env.CPPPATH_PERLEXT = read_out('print "$Config{archlib}/CORE"') conf.env.CCFLAGS_PERLEXT = read_out('print "$Config{ccflags} $Config{cccdlflags}"') conf.env.XSUBPP = read_out('print "$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}"') conf.env.EXTUTILS_TYPEMAP = read_out('print "$Config{privlib}/ExtUtils/typemap"') conf.env.perlext_PATTERN = '%s.' + read_out('print $Config{dlext}')[0] if getattr(Options.options, 'perlarchdir', None): conf.env.ARCHDIR_PERL = Options.options.perlarchdir else: conf.env.ARCHDIR_PERL = read_out('print $Config{sitearch}')[0] def set_options(opt): 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) tevent-0.9.34/third_party/waf/wafadmin/Tools/preproc.py0000660000000000000000000005256212520121120023064 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2009 (ita) """ C/C++ preprocessor for finding dependencies Reasons for using the Waf preprocessor by default 1. Some c/c++ extensions (Qt) require a custom preprocessor for obtaining the dependencies (.moc files) 2. Not all compilers provide .d files for obtaining the dependencies (portability) 3. A naive file scanner will not catch the constructs such as "#include foo()" 4. A naive file scanner will catch unnecessary dependencies (change an unused header -> recompile everything) Regarding the speed concerns: a. the preprocessing is performed only when files must be compiled b. the macros are evaluated only for #if/#elif/#include c. the time penalty is about 10% d. system headers are not scanned 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 though, and it cannot be used with Qt builds. A dumb file scanner will be added in the future, so we will have most bahaviours. """ # TODO: more varargs, pragma once # TODO: dumb file scanner tracking all includes import re, sys, os, string import Logs, Build, Utils from Logs import debug, error import traceback class PreprocError(Utils.WafError): pass POPFILE = '-' recursion_limit = 5000 "do not loop too much on header inclusion" go_absolute = 0 "set to 1 to track headers on files in /usr/include - else absolute paths are ignored" standard_includes = ['/usr/include'] if sys.platform == "win32": standard_includes = [] use_trigraphs = 0 'apply the trigraph rules first' strict_quotes = 0 "Keep <> for system includes (do not search for those includes)" g_optrans = { 'not':'!', 'and':'&&', 'bitand':'&', 'and_eq':'&=', 'or':'||', 'bitor':'|', 'or_eq':'|=', 'xor':'^', 'xor_eq':'^=', 'compl':'~', } "these ops are for c++, to reset, set an empty dict" # 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) re_mac = re.compile("^[a-zA-Z_]\w*") re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') re_pragma_once = re.compile('^\s*once\s*', re.IGNORECASE) re_nl = re.compile('\\\\\r*\n', re.MULTILINE) re_cpp = re.compile( r"""(/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)|//[^\n]*|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|.[^/"'\\]*)""", re.MULTILINE) trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')] chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39} NUM = 'i' OP = 'O' IDENT = 'T' STR = 's' CHAR = 'c' tok_types = [NUM, STR, IDENT, OP] 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'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]', ] re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M) accepted = 'a' ignored = 'i' undefined = 'u' skipped = 's' def repl(m): if m.group(1): return ' ' s = m.group(2) if s is None: return '' return s def filter_comments(filename): # return a list of tuples : keyword, line code = Utils.readf(filename) 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 [(m.group(2), m.group(3)) for m in re.finditer(re_lines, code)] prec = {} # op -> number, needed for such expressions: #if 1 && 2 != 0 ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ','] for x in range(len(ops)): syms = ops[x] for u in syms.split(): prec[u] = x def reduce_nums(val_1, val_2, val_op): """apply arithmetic rules and try to return an integer result""" #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 = a|b elif d=='||': c = int(a or b) elif d=='&': c = a&b elif d=='&&': c = int(a and 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 = int(a > b) elif d=='>=': c = int(a >= b) elif d=='^': c = int(a^b) elif d=='<<': c = a<>': c = a>>b else: c = 0 return c def get_num(lst): 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 == '~': 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): 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 == '&&' and not num: return (num, []) elif v == '||' and num: return (num, []) elif 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 (#if/#elif conditions)""" num, lst = get_term(lst) return (NUM, num) def stringize(lst): """use for converting a list of tokens to a string""" lst = [str(v2) for (p2, v2) in lst] return "".join(lst) def paste_tokens(t1, t2): """ here is what we can paste: a ## b -> ab > ## = -> >= a ## 2 -> a2 """ 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""" 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] for x in xrange(len(to_add)): lst.insert(i, to_add[x]) 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 %s" % p) 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__': # TODO not sure # 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 xrange(len(accu)-1, -1, -1): lst.insert(i, accu[x]) i += 1 def eval_macro(lst, adefs): """reduce the tokens from the list lst, and try to return a 0/1 result""" reduce_tokens(lst, adefs, []) if not lst: raise PreprocError("missing tokens to evaluate") (p, v) = reduce_eval(lst) return int(v) != 0 def extract_macro(txt): """process a macro definition from "#define f(x, y) x * y" into a function or a simple macro without arguments""" t = tokenize(txt) if re_fun.search(txt): p, name = t[0] p, v = t[1] if p != OP: raise PreprocError("expected open parenthesis") 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] return (v, [[], t[1:]]) re_include = re.compile('^\s*(<(?P.*)>|"(?P.*)")') def extract_include(txt, defs): """process a line in the form "#include foo" to return a string representing the file""" m = re_include.search(txt) if m: if m.group('a'): return '<', m.group('a') if m.group('b'): return '"', m.group('b') # 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 %s" % txt) if len(toks) == 1: if toks[0][0] == STR: return '"', toks[0][1] else: if toks[0][1] == '<' and toks[-1][1] == '>': return stringize(toks).lstrip('<').rstrip('>') raise PreprocError("could not parse include %s." % txt) def parse_char(txt): 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 '%s'" % txt) @Utils.run_once 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: try: v = g_optrans[v]; name = OP except KeyError: # c++ specific if 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 tokenize(s): """convert a string into a list of tokens (shlex.split does not apply to c/c++/d)""" return tokenize_private(s)[:] @Utils.run_once def define_name(line): return re_mac.match(line).group(0) class c_parser(object): def __init__(self, nodepaths=None, defines=None): #self.lines = txt.split('\n') self.lines = [] if defines is None: self.defs = {} else: self.defs = dict(defines) # make a copy self.state = [] self.env = None # needed for the variant when searching for files self.count_files = 0 self.currentnode_stack = [] self.nodepaths = nodepaths or [] self.nodes = [] self.names = [] # file added self.curfile = '' self.ban_includes = set([]) def cached_find_resource(self, node, filename): try: nd = node.bld.cache_nd except: nd = node.bld.cache_nd = {} tup = (node.id, filename) try: return nd[tup] except KeyError: ret = node.find_resource(filename) nd[tup] = ret return ret def tryfind(self, filename): self.curfile = filename # for msvc it should be a for loop on the whole stack found = self.cached_find_resource(self.currentnode_stack[-1], filename) for n in self.nodepaths: if found: break found = self.cached_find_resource(n, filename) if found: self.nodes.append(found) if filename[-4:] != '.moc': self.addlines(found) else: if not filename in self.names: self.names.append(filename) return found def addlines(self, node): self.currentnode_stack.append(node.parent) filepath = node.abspath(self.env) self.count_files += 1 if self.count_files > recursion_limit: raise PreprocError("recursion limit exceeded") pc = self.parse_cache debug('preproc: reading file %r', filepath) try: lns = pc[filepath] except KeyError: pass else: self.lines.extend(lns) return try: lines = filter_comments(filepath) lines.append((POPFILE, '')) lines.reverse() pc[filepath] = lines # cache the lines filtered self.lines.extend(lines) except IOError: raise PreprocError("could not read the file %s" % filepath) except Exception: if Logs.verbose > 0: error("parsing %s failed" % filepath) traceback.print_exc() def start(self, node, env): debug('preproc: scanning %s (in %s)', node.name, node.parent.name) self.env = env variant = node.variant(env) bld = node.__class__.bld try: self.parse_cache = bld.parse_cache except AttributeError: bld.parse_cache = {} self.parse_cache = bld.parse_cache self.addlines(node) if env['DEFLINES']: lst = [('define', x) for x in env['DEFLINES']] lst.reverse() self.lines.extend(lst) while self.lines: (kind, line) = self.lines.pop() if kind == POPFILE: self.currentnode_stack.pop() continue try: self.process_line(kind, line) except Exception, e: if Logs.verbose: debug('preproc: line parsing failed (%s): %s %s', e, line, Utils.ex_stack()) def process_line(self, token, line): """ WARNING: a new state must be added for if* because the endif """ ve = Logs.verbose if ve: debug('preproc: line is %s - %s state is %s', token, line, self.state) state = self.state # make certain we define the state if we are about to enter in an if block if token in ['ifdef', 'ifndef', 'if']: state.append(undefined) elif token == 'endif': state.pop() # skip lines when in a dead 'if' branch, wait for the endif if not token in ['else', 'elif', 'endif']: if skipped in self.state or ignored in self.state: return 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(0) in self.defs: state[-1] = accepted else: state[-1] = ignored elif token == 'ifndef': m = re_mac.match(line) if m and m.group(0) in self.defs: state[-1] = ignored else: state[-1] = accepted elif token == 'include' or token == 'import': (kind, inc) = extract_include(line, self.defs) if inc in self.ban_includes: return if token == 'import': self.ban_includes.add(inc) if ve: debug('preproc: include found %s (%s) ', inc, kind) if kind == '"' or not strict_quotes: self.tryfind(inc) 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[define_name(line)] = line except: raise PreprocError("invalid define line %s" % line) elif token == 'undef': m = re_mac.match(line) if m and m.group(0) in self.defs: self.defs.__delitem__(m.group(0)) #print "undef %s" % name elif token == 'pragma': if re_pragma_once.match(line.lower()): self.ban_includes.add(self.curfile) def get_deps(node, env, nodepaths=[]): """ Get the dependencies using a c/c++ preprocessor, this is required for finding dependencies of the kind #include some_macro() """ gruik = c_parser(nodepaths) gruik.start(node, env) return (gruik.nodes, gruik.names) #################### dumb dependency scanner re_inc = re.compile(\ '^[ \t]*(#|%:)[ \t]*(include)[ \t]*(.*)\r*$', re.IGNORECASE | re.MULTILINE) def lines_includes(filename): code = Utils.readf(filename) 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 [(m.group(2), m.group(3)) for m in re.finditer(re_inc, code)] def get_deps_simple(node, env, nodepaths=[], defines={}): """ Get the dependencies by just looking recursively at the #include statements """ nodes = [] names = [] def find_deps(node): lst = lines_includes(node.abspath(env)) for (_, line) in lst: (t, filename) = extract_include(line, defines) if filename in names: continue if filename.endswith('.moc'): names.append(filename) found = None for n in nodepaths: if found: break found = n.find_resource(filename) if not found: if not filename in names: names.append(filename) elif not found in nodes: nodes.append(found) find_deps(node) find_deps(node) return (nodes, names) tevent-0.9.34/third_party/waf/wafadmin/Tools/python.py0000660000000000000000000003456312520121120022734 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007 (ita) # Gustavo Carneiro (gjc), 2007 "Python support" import os, sys import TaskGen, Utils, Options from Logs import debug, warn, info from TaskGen import extension, before, after, feature from Configure import conf from config_c import parse_flags EXT_PY = ['.py'] FRAG_2 = ''' #include "Python.h" #ifdef __cplusplus extern "C" { #endif void Py_Initialize(void); void Py_Finalize(void); #ifdef __cplusplus } #endif int main() { Py_Initialize(); Py_Finalize(); return 0; } ''' @feature('pyext') @before('apply_incpaths', 'apply_lib_vars', 'apply_type_vars', 'apply_bundle') @after('vars_target_cshlib') def init_pyext(self): self.default_install_path = '${PYTHONARCHDIR}' self.uselib = self.to_list(getattr(self, 'uselib', '')) if not 'PYEXT' in self.uselib: self.uselib.append('PYEXT') self.env['MACBUNDLE'] = True @before('apply_link', 'apply_lib_vars', 'apply_type_vars') @after('apply_bundle') @feature('pyext') def pyext_shlib_ext(self): # override shlib_PATTERN set by the osx module self.env['shlib_PATTERN'] = self.env['pyext_PATTERN'] @before('apply_incpaths', 'apply_lib_vars', 'apply_type_vars') @feature('pyembed') def init_pyembed(self): self.uselib = self.to_list(getattr(self, 'uselib', '')) if not 'PYEMBED' in self.uselib: self.uselib.append('PYEMBED') @extension(EXT_PY) def process_py(self, node): if not (self.bld.is_install and self.install_path): return def inst_py(ctx): install_pyfile(self, node) self.bld.add_post_fun(inst_py) def install_pyfile(self, node): path = self.bld.get_install_path(self.install_path + os.sep + node.name, self.env) self.bld.install_files(self.install_path, [node], self.env, self.chmod, postpone=False) if self.bld.is_install < 0: info("* removing byte compiled python files") for x in 'co': try: os.remove(path + x) except OSError: pass if self.bld.is_install > 0: if self.env['PYC'] or self.env['PYO']: info("* byte compiling %r" % path) if self.env['PYC']: program = (""" import sys, py_compile for pyfile in sys.argv[1:]: py_compile.compile(pyfile, pyfile + 'c') """) argv = [self.env['PYTHON'], '-c', program, path] ret = Utils.pproc.Popen(argv).wait() if ret: raise Utils.WafError('bytecode compilation failed %r' % path) if self.env['PYO']: program = (""" import sys, py_compile for pyfile in sys.argv[1:]: py_compile.compile(pyfile, pyfile + 'o') """) argv = [self.env['PYTHON'], self.env['PYFLAGS_OPT'], '-c', program, path] ret = Utils.pproc.Popen(argv).wait() if ret: raise Utils.WafError('bytecode compilation failed %r' % path) # COMPAT class py_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @before('apply_core') @after('vars_target_cprogram', 'vars_target_cshlib') @feature('py') def init_py(self): self.default_install_path = '${PYTHONDIR}' def _get_python_variables(python_exe, variables, imports=['import sys']): """Run a python interpreter and print some variables""" program = list(imports) 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 proc = Utils.pproc.Popen([python_exe, "-c", '\n'.join(program)], stdout=Utils.pproc.PIPE, env=os_env) output = proc.communicate()[0].split("\n") # do not touch, python3 if proc.returncode: if Options.options.verbose: warn("Python program to extract python configuration variables failed:\n%s" % '\n'.join(["line %03i: %s" % (lineno+1, line) for lineno, line in enumerate(program)])) raise RuntimeError return_values = [] for s in output: 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 check_python_headers(conf, mandatory=True): """Check for headers and libraries necessary to extend or embed python. On success the environment variables xxx_PYEXT and xxx_PYEMBED are added for uselib PYEXT: for compiling python extensions PYEMBED: for embedding a python interpreter""" if not conf.env['CC_NAME'] and not conf.env['CXX_NAME']: conf.fatal('load a compiler first (gcc, g++, ..)') if not conf.env['PYTHON_VERSION']: conf.check_python_version() env = conf.env python = env['PYTHON'] if not python: conf.fatal('could not find the python executable') ## On Mac OSX we need to use mac bundles for python plugins if Options.platform == 'darwin': conf.check_tool('osx') try: # Get some python configuration variables using distutils v = 'prefix SO SYSLIBS LDFLAGS SHLIBS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDVERSION'.split() (python_prefix, python_SO, python_SYSLIBS, python_LDFLAGS, python_SHLIBS, python_LIBDIR, python_LIBPL, INCLUDEPY, Py_ENABLE_SHARED, python_MACOSX_DEPLOYMENT_TARGET, python_LDVERSION) = \ _get_python_variables(python, ["get_config_var('%s') or ''" % x for x in v], ['from distutils.sysconfig import get_config_var']) except RuntimeError: conf.fatal("Python development headers not found (-v for details).") conf.log.write("""Configuration returned from %r: python_prefix = %r python_SO = %r python_SYSLIBS = %r python_LDFLAGS = %r python_SHLIBS = %r python_LIBDIR = %r python_LIBPL = %r INCLUDEPY = %r Py_ENABLE_SHARED = %r MACOSX_DEPLOYMENT_TARGET = %r LDVERSION = %r """ % (python, python_prefix, python_SO, python_SYSLIBS, python_LDFLAGS, python_SHLIBS, python_LIBDIR, python_LIBPL, INCLUDEPY, Py_ENABLE_SHARED, python_MACOSX_DEPLOYMENT_TARGET, python_LDVERSION)) # Allow some python overrides from env vars for cross-compiling os_env = dict(os.environ) override_python_LDFLAGS = os_env.get('python_LDFLAGS', None) if override_python_LDFLAGS is not None: conf.log.write("python_LDFLAGS override from environment = %r\n" % (override_python_LDFLAGS)) python_LDFLAGS = override_python_LDFLAGS override_python_LIBDIR = os_env.get('python_LIBDIR', None) if override_python_LIBDIR is not None: conf.log.write("python_LIBDIR override from environment = %r\n" % (override_python_LIBDIR)) python_LIBDIR = override_python_LIBDIR if python_MACOSX_DEPLOYMENT_TARGET: conf.env['MACOSX_DEPLOYMENT_TARGET'] = python_MACOSX_DEPLOYMENT_TARGET conf.environ['MACOSX_DEPLOYMENT_TARGET'] = python_MACOSX_DEPLOYMENT_TARGET env['pyext_PATTERN'] = '%s'+python_SO # Check for python libraries for embedding if python_SYSLIBS is not None: for lib in python_SYSLIBS.split(): if lib.startswith('-l'): lib = lib[2:] # strip '-l' env.append_value('LIB_PYEMBED', lib) if python_SHLIBS is not None: for lib in python_SHLIBS.split(): if lib.startswith('-l'): env.append_value('LIB_PYEMBED', lib[2:]) # strip '-l' else: env.append_value('LINKFLAGS_PYEMBED', lib) if Options.platform != 'darwin' and python_LDFLAGS: parse_flags(python_LDFLAGS, 'PYEMBED', env) result = False if not python_LDVERSION: python_LDVERSION = env['PYTHON_VERSION'] name = 'python' + python_LDVERSION if python_LIBDIR is not None: path = [python_LIBDIR] conf.log.write("\n\n# Trying LIBDIR: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path) if not result and python_LIBPL is not None: conf.log.write("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") path = [python_LIBPL] result = conf.check(lib=name, uselib='PYEMBED', libpath=path) if not result: conf.log.write("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") path = [os.path.join(python_prefix, "libs")] name = 'python' + python_LDVERSION.replace('.', '') result = conf.check(lib=name, uselib='PYEMBED', libpath=path) if result: env['LIBPATH_PYEMBED'] = path env.append_value('LIB_PYEMBED', name) else: conf.log.write("\n\n### LIB NOT FOUND\n") # under certain conditions, python extensions must link to # python libraries, not just python embedding programs. if (sys.platform == 'win32' or sys.platform.startswith('os2') or sys.platform == 'darwin' or Py_ENABLE_SHARED): env['LIBPATH_PYEXT'] = env['LIBPATH_PYEMBED'] env['LIB_PYEXT'] = env['LIB_PYEMBED'] # We check that pythonX.Y-config exists, and if it exists we # use it to get only the includes, else fall back to distutils. python_config = conf.find_program( 'python%s-config' % ('.'.join(env['PYTHON_VERSION'].split('.')[:2])), var='PYTHON_CONFIG') if not python_config: python_config = conf.find_program( 'python-config-%s' % ('.'.join(env['PYTHON_VERSION'].split('.')[:2])), var='PYTHON_CONFIG') includes = [] if python_config: for incstr in Utils.cmd_output("%s --includes" % (python_config,)).strip().split(): # strip the -I or /I if (incstr.startswith('-I') or incstr.startswith('/I')): incstr = incstr[2:] # append include path, unless already given if incstr not in includes: includes.append(incstr) conf.log.write("Include path for Python extensions " "(found via python-config --includes): %r\n" % (includes,)) env['CPPPATH_PYEXT'] = includes env['CPPPATH_PYEMBED'] = includes else: conf.log.write("Include path for Python extensions " "(found via distutils module): %r\n" % (INCLUDEPY,)) env['CPPPATH_PYEXT'] = [INCLUDEPY] env['CPPPATH_PYEMBED'] = [INCLUDEPY] # Code using the Python API needs to be compiled with -fno-strict-aliasing if env['CC_NAME'] == 'gcc': env.append_value('CCFLAGS_PYEMBED', '-fno-strict-aliasing') env.append_value('CCFLAGS_PYEXT', '-fno-strict-aliasing') if env['CXX_NAME'] == 'gcc': env.append_value('CXXFLAGS_PYEMBED', '-fno-strict-aliasing') env.append_value('CXXFLAGS_PYEXT', '-fno-strict-aliasing') # See if it compiles conf.check(define_name='HAVE_PYTHON_H', uselib='PYEMBED', fragment=FRAG_2, errmsg='Could not find the python development headers', mandatory=mandatory) @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 is defined, pointing to the site-packages directory appropriate for this python version, where modules/packages/extensions should be installed. """ assert minver is None or isinstance(minver, tuple) python = conf.env['PYTHON'] if not python: conf.fatal('could not find the python executable') # Get python version string cmd = [python, "-c", "import sys\nfor x in sys.version_info: print(str(x))"] debug('python: Running python command %r' % cmd) proc = Utils.pproc.Popen(cmd, stdout=Utils.pproc.PIPE, shell=False) lines = proc.communicate()[0].split() assert len(lines) == 5, "found %i 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.environ: pydir = conf.environ['PYTHONDIR'] else: if sys.platform == 'win32': (python_LIBDEST, pydir) = \ _get_python_variables(python, ["get_config_var('LIBDEST') or ''", "get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']], ['from distutils.sysconfig import get_config_var, get_python_lib']) else: python_LIBDEST = None (pydir,) = \ _get_python_variables(python, ["get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']], ['from distutils.sysconfig import get_config_var, get_python_lib']) 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.environ: pyarchdir = conf.environ['PYTHONARCHDIR'] else: (pyarchdir,) = _get_python_variables(python, ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']], ['from distutils.sysconfig import get_config_var, get_python_lib']) 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 # Feedback pyver_full = '.'.join(map(str, pyver_tuple[:3])) if minver is None: conf.check_message_custom('Python version', '', pyver_full) else: minver_str = '.'.join(map(str, minver)) conf.check_message('Python version', ">= %s" % minver_str, result, option=pyver_full) if not result: conf.fatal('The python version is too old (%r)' % pyver_full) @conf def check_python_module(conf, module_name): """ Check if the selected python interpreter can import the given python module. """ result = not Utils.pproc.Popen([conf.env['PYTHON'], "-c", "import %s" % module_name], stderr=Utils.pproc.PIPE, stdout=Utils.pproc.PIPE).wait() conf.check_message('Python module', module_name, result) if not result: conf.fatal('Could not find the python module %r' % module_name) def detect(conf): if not conf.env.PYTHON: conf.env.PYTHON = sys.executable python = conf.find_program('python', var='PYTHON') if not python: conf.fatal('Could not find the path of the python executable') if conf.env.PYTHON != sys.executable: warn("python executable '%s' different from sys.executable '%s'" % (conf.env.PYTHON, sys.executable)) v = conf.env v['PYCMD'] = '"import sys, py_compile;py_compile.compile(sys.argv[1], sys.argv[2])"' v['PYFLAGS'] = '' v['PYFLAGS_OPT'] = '-O' v['PYC'] = getattr(Options.options, 'pyc', 1) v['PYO'] = getattr(Options.options, 'pyo', 1) def set_options(opt): opt.add_option('--nopyc', action='store_false', default=1, help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]', dest = 'pyc') opt.add_option('--nopyo', action='store_false', default=1, help='Do not install optimised compiled .pyo files (configuration) [Default:install]', dest='pyo') tevent-0.9.34/third_party/waf/wafadmin/Tools/qt4.py0000660000000000000000000003451712520121120022122 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) """ Qt4 support If QT4_ROOT is given (absolute path), the configuration will look in it first This module also demonstrates how to add tasks dynamically (when the build has started) """ 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 import ccroot, cxx import TaskGen, Task, Utils, Runner, Options, Node, Configure from TaskGen import taskgen, feature, after, extension from Logs import error from Constants import * MOC_H = ['.h', '.hpp', '.hxx', '.hh'] EXT_RCC = ['.qrc'] EXT_UI = ['.ui'] EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C'] class qxx_task(Task.Task): "A cpp task that may create a moc task dynamically" before = ['cxx_link', 'static_link'] def __init__(self, *k, **kw): Task.Task.__init__(self, *k, **kw) self.moc_done = 0 def scan(self): (nodes, names) = ccroot.scan(self) # for some reasons (variants) the moc node may end in the list of node deps for x in nodes: if x.name.endswith('.moc'): nodes.remove(x) names.append(x.relpath_gen(self.inputs[0].parent)) return (nodes, names) def runnable_status(self): if self.moc_done: # if there is a moc task, delay the computation of the file signature for t in self.run_after: if not t.hasrun: return ASK_LATER # the moc file enters in the dependency calculation # so we need to recompute the signature when the moc file is present self.signature() return Task.Task.runnable_status(self) else: # yes, really, there are people who generate cxx files for t in self.run_after: if not t.hasrun: return ASK_LATER self.add_moc_tasks() return ASK_LATER def add_moc_tasks(self): node = self.inputs[0] tree = node.__class__.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') moctasks=[] mocfiles=[] variant = node.variant(self.env) try: tmp_lst = tree.raw_deps[self.unique_id()] tree.raw_deps[self.unique_id()] = [] except KeyError: tmp_lst = [] for d in tmp_lst: if not d.endswith('.moc'): continue # paranoid check if d in mocfiles: error("paranoia owns") continue # process that base.moc only once mocfiles.append(d) # find the extension (performed only when the .cpp has changes) base2 = d[:-4] for path in [node.parent] + self.generator.env['INC_PATHS']: tree.rescan(path) vals = getattr(Options.options, 'qt_header_ext', '') or MOC_H for ex in vals: h_node = path.find_resource(base2 + ex) if h_node: break else: continue break else: raise Utils.WafError("no header found for %s which is a moc file" % str(d)) m_node = h_node.change_ext('.moc') tree.node_deps[(self.inputs[0].parent.id, self.env.variant(), m_node.name)] = h_node # create the task task = Task.TaskBase.classes['moc'](self.env, normal=0) task.set_inputs(h_node) task.set_outputs(m_node) generator = tree.generator generator.outstanding.insert(0, task) generator.total += 1 moctasks.append(task) # remove raw deps except the moc files to save space (optimization) tmp_lst = tree.raw_deps[self.unique_id()] = mocfiles # look at the file inputs, it is set right above lst = tree.node_deps.get(self.unique_id(), ()) for d in lst: name = d.name if name.endswith('.moc'): task = Task.TaskBase.classes['moc'](self.env, normal=0) task.set_inputs(tree.node_deps[(self.inputs[0].parent.id, self.env.variant(), name)]) # 1st element in a tuple task.set_outputs(d) generator = tree.generator generator.outstanding.insert(0, task) generator.total += 1 moctasks.append(task) # simple scheduler dependency: run the moc task before others self.run_after = moctasks self.moc_done = 1 run = Task.TaskBase.classes['cxx'].__dict__['run'] def translation_update(task): outs = [a.abspath(task.env) for a in task.outputs] outs = " ".join(outs) lupdate = task.env['QT_LUPDATE'] for x in task.inputs: file = x.abspath(task.env) cmd = "%s %s -ts %s" % (lupdate, file, outs) Utils.pprint('BLUE', cmd) task.generator.bld.exec_command(cmd) class XMLHandler(ContentHandler): 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(''.join(self.buf)) def characters(self, cars): self.buf.append(cars) def scan(self): "add the dependency on the files referenced in the qrc" node = self.inputs[0] parser = make_parser() curHandler = XMLHandler() parser.setContentHandler(curHandler) fi = open(self.inputs[0].abspath(self.env)) parser.parse(fi) 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) @extension(EXT_RCC) def create_rcc_task(self, node): "hook for rcc files" rcnode = node.change_ext('_rc.cpp') rcctask = self.create_task('rcc', node, rcnode) cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) self.compiled_tasks.append(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])] return uictask class qt4_taskgen(cxx.cxx_taskgen): def __init__(self, *k, **kw): cxx.cxx_taskgen.__init__(self, *k, **kw) self.features.append('qt4') @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('apply_link') def apply_qt4(self): if getattr(self, 'lang', None): update = getattr(self, 'update', None) lst=[] trans=[] for l in self.to_list(self.lang): if not isinstance(l, Node.Node): l = self.path.find_resource(l+'.ts') t = self.create_task('ts2qm', l, l.change_ext('.qm')) lst.append(t.outputs[0]) if update: trans.append(t.inputs[0]) trans_qt4 = getattr(Options.options, 'trans_qt4', False) if update and trans_qt4: # we need the cpp files given, except the rcc task we create after # FIXME may be broken u = Task.TaskCmd(translation_update, self.env, 2) u.inputs = [a.inputs[0] for a in self.compiled_tasks] u.outputs = trans if getattr(self, 'langname', None): t = Task.TaskBase.classes['qm2rcc'](self.env) t.set_inputs(lst) t.set_outputs(self.path.find_or_declare(self.langname+'.qrc')) t.path = self.path k = create_rcc_task(self, t.outputs[0]) self.link_task.inputs.append(k.outputs[0]) self.env.append_value('MOC_FLAGS', self.env._CXXDEFFLAGS) self.env.append_value('MOC_FLAGS', self.env._CXXINCFLAGS) @extension(EXT_QT4) def cxx_hook(self, node): # create the compilation task: cpp or cc try: obj_ext = self.obj_ext except AttributeError: obj_ext = '_%d.o' % self.idx task = self.create_task('qxx', node, node.change_ext(obj_ext)) self.compiled_tasks.append(task) return task def process_qm2rcc(task): outfile = task.outputs[0].abspath(task.env) f = open(outfile, 'w') f.write('\n\n') for k in task.inputs: f.write(' ') #f.write(k.name) f.write(k.path_to_parent(task.path)) f.write('\n') f.write('\n') f.close() b = Task.simple_task_type b('moc', '${QT_MOC} ${MOC_FLAGS} ${SRC} ${MOC_ST} ${TGT}', color='BLUE', vars=['QT_MOC', 'MOC_FLAGS'], shell=False) cls = b('rcc', '${QT_RCC} -name ${SRC[0].name} ${SRC[0].abspath(env)} ${RCC_ST} -o ${TGT}', color='BLUE', before='cxx moc qxx_task', after="qm2rcc", shell=False) cls.scan = scan b('ui4', '${QT_UIC} ${SRC} -o ${TGT}', color='BLUE', before='cxx moc qxx_task', shell=False) b('ts2qm', '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}', color='BLUE', before='qm2rcc', shell=False) Task.task_type_from_func('qm2rcc', vars=[], func=process_qm2rcc, color='BLUE', before='rcc', after='ts2qm') def detect_qt4(conf): env = conf.env opt = Options.options qtdir = getattr(opt, 'qtdir', '') qtbin = getattr(opt, 'qtbin', '') qtlibs = getattr(opt, 'qtlibs', '') useframework = getattr(opt, 'use_qt4_osxframework', True) paths = [] # the path to qmake has been given explicitely if qtbin: paths = [qtbin] # the qt directory has been given - we deduce the qt binary path if not qtdir: qtdir = conf.environ.get('QT4_ROOT', '') qtbin = os.path.join(qtdir, 'bin') 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 = os.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']: qmake = conf.find_program(qmk, path_list=paths) if qmake: try: version = Utils.cmd_output([qmake, '-query', 'QT_VERSION']).strip() except ValueError: pass else: if version: new_ver = version.split('.') if new_ver > prev_ver: cand = qmake prev_ver = new_ver if cand: qmake = cand else: conf.fatal('could not find qmake for qt4') conf.env.QMAKE = qmake qtincludes = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_HEADERS']).strip() qtdir = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_PREFIX']).strip() + os.sep qtbin = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_BINS']).strip() + os.sep if not qtlibs: try: qtlibs = Utils.cmd_output([qmake, '-query', 'QT_INSTALL_LIBS']).strip() + os.sep except ValueError: qtlibs = os.path.join(qtdir, 'lib') def find_bin(lst, var): for f in lst: ret = conf.find_program(f, path_list=paths) if ret: env[var]=ret break vars = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtWebKit Qt3Support".split() find_bin(['uic-qt3', 'uic3'], 'QT_UIC3') find_bin(['uic-qt4', 'uic'], 'QT_UIC') if not env['QT_UIC']: conf.fatal('cannot find the uic compiler for qt4') try: version = Utils.cmd_output(env['QT_UIC'] + " -version 2>&1").strip() except ValueError: conf.fatal('your uic compiler is for qt3, add uic for qt4 to your path') version = version.replace('Qt User Interface Compiler ','') version = version.replace('User Interface Compiler for Qt', '') if version.find(" 3.") != -1: conf.check_message('uic version', '(too old)', 0, option='(%s)'%version) sys.exit(1) conf.check_message('uic version', '', 1, option='(%s)'%version) find_bin(['moc-qt4', 'moc'], 'QT_MOC') find_bin(['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'] vars_debug = [a+'_debug' for a in vars] try: conf.find_program('pkg-config', var='pkgconfig', path_list=paths, mandatory=True) except Configure.ConfigurationError: for lib in vars_debug+vars: uselib = lib.upper() d = (lib.find('_debug') > 0) and 'd' or '' # original author seems to prefer static to shared libraries for (pat, kind) in ((conf.env.staticlib_PATTERN, 'STATIC'), (conf.env.shlib_PATTERN, '')): conf.check_message_1('Checking for %s %s' % (lib, kind)) for ext in ['', '4']: path = os.path.join(qtlibs, pat % (lib + d + ext)) if os.path.exists(path): env.append_unique(kind + 'LIB_' + uselib, lib + d + ext) conf.check_message_2('ok ' + path, 'GREEN') break path = os.path.join(qtbin, pat % (lib + d + ext)) if os.path.exists(path): env.append_unique(kind + 'LIB_' + uselib, lib + d + ext) conf.check_message_2('ok ' + path, 'GREEN') break else: conf.check_message_2('not found', 'YELLOW') continue break env.append_unique('LIBPATH_' + uselib, qtlibs) env.append_unique('CPPPATH_' + uselib, qtincludes) env.append_unique('CPPPATH_' + uselib, qtincludes + os.sep + lib) else: for i in vars_debug+vars: try: conf.check_cfg(package=i, args='--cflags --libs --silence-errors', path=conf.env.pkgconfig) except ValueError: pass # the libpaths are set nicely, unfortunately they make really long command-lines # remove the qtcore ones from qtgui, etc 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(vars, 'LIBPATH_QTCORE') process_lib(vars_debug, 'LIBPATH_QTCORE_DEBUG') # rpath if wanted want_rpath = getattr(Options.options, 'want_rpath', 1) if want_rpath: 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(vars, 'LIBPATH_QTCORE') process_rpath(vars_debug, 'LIBPATH_QTCORE_DEBUG') env['QTLOCALE'] = str(env['PREFIX'])+'/share/locale' def detect(conf): detect_qt4(conf) def set_options(opt): opt.add_option('--want-rpath', type='int', default=1, dest='want_rpath', help='set rpath to 1 or 0 [Default 1]') 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) if sys.platform == "darwin": opt.add_option('--no-qt4-framework', action="store_false", help='do not use the framework version of Qt4 in OS X', dest='use_qt4_osxframework',default=True) opt.add_option('--translate', action="store_true", help="collect translation strings", dest="trans_qt4", default=False) tevent-0.9.34/third_party/waf/wafadmin/Tools/ruby.py0000660000000000000000000000727612520121120022375 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # daniel.svensson at purplescout.se 2008 import os import Task, Options, Utils from TaskGen import before, feature, after from Configure import conf @feature('rubyext') @before('apply_incpaths', 'apply_type_vars', 'apply_lib_vars', 'apply_bundle') @after('default_cc', 'vars_target_cshlib') def init_rubyext(self): self.default_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('apply_link') def apply_ruby_so_name(self): self.env['shlib_PATTERN'] = self.env['rubyext_PATTERN'] @conf def check_ruby_version(conf, minver=()): """ Checks if ruby is installed. If installed the variable RUBY will be set in environment. Ruby binary can be overridden by --with-ruby-binary config variable """ if Options.options.rubybinary: conf.env.RUBY = Options.options.rubybinary else: conf.find_program("ruby", var="RUBY", mandatory=True) ruby = conf.env.RUBY try: version = Utils.cmd_output([ruby, '-e', 'puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() except: conf.fatal('could not determine ruby version') conf.env.RUBY_VERSION = version try: ver = tuple(map(int, version.split("."))) except: conf.fatal('unsupported ruby version %r' % version) cver = '' if minver: if ver < minver: conf.fatal('ruby is too old') cver = ".".join([str(x) for x in minver]) conf.check_message('ruby', cver, True, version) @conf def check_ruby_ext_devel(conf): if not conf.env.RUBY: conf.fatal('ruby detection is required first') if not conf.env.CC_NAME and not conf.env.CXX_NAME: conf.fatal('load a c/c++ compiler first') version = tuple(map(int, conf.env.RUBY_VERSION.split("."))) def read_out(cmd): return Utils.to_list(Utils.cmd_output([conf.env.RUBY, '-rrbconfig', '-e', cmd])) def read_config(key): return read_out('puts Config::CONFIG[%r]' % key) ruby = conf.env['RUBY'] archdir = read_config('archdir') cpppath = archdir if version >= (1, 9, 0): ruby_hdrdir = read_config('rubyhdrdir') cpppath += ruby_hdrdir cpppath += [os.path.join(ruby_hdrdir[0], read_config('arch')[0])] conf.check(header_name='ruby.h', includes=cpppath, mandatory=True, errmsg='could not find ruby header file') conf.env.LIBPATH_RUBYEXT = read_config('libdir') conf.env.LIBPATH_RUBYEXT += archdir conf.env.CPPPATH_RUBYEXT = cpppath conf.env.CCFLAGS_RUBYEXT = read_config("CCDLFLAGS") conf.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:] conf.env.LINKFLAGS_RUBYEXT = flags conf.env.LINKFLAGS_RUBYEXT += read_config("LIBS") conf.env.LINKFLAGS_RUBYEXT += read_config("LIBRUBYARG_SHARED") if Options.options.rubyarchdir: conf.env.ARCHDIR_RUBY = Options.options.rubyarchdir else: conf.env.ARCHDIR_RUBY = read_config('sitearchdir')[0] if Options.options.rubylibdir: conf.env.LIBDIR_RUBY = Options.options.rubylibdir else: conf.env.LIBDIR_RUBY = read_config('sitelibdir')[0] def set_options(opt): 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') tevent-0.9.34/third_party/waf/wafadmin/Tools/suncc.py0000660000000000000000000000352212520121120022515 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) # Ralf Habacker, 2006 (rh) import os, optparse import Utils, Options, Configure import ccroot, ar from Configure import conftest @conftest def find_scc(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('gcc', var='CC') if not cc: cc = conf.find_program('cc', var='CC') if not cc: conf.fatal('suncc was not found') cc = conf.cmd_to_list(cc) try: if not Utils.cmd_output(cc + ['-flags']): conf.fatal('suncc %r was not found' % cc) except ValueError: conf.fatal('suncc -flags could not be executed') v['CC'] = cc v['CC_NAME'] = 'sun' @conftest def scc_common_flags(conf): v = conf.env # CPPFLAGS CCDEFINES _CCINCFLAGS _CCDEFFLAGS v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o', ''] v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = '' v['CCLNK_TGT_F'] = ['-o', ''] # solaris hack, separate the -o from the target v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['CCDEFINES_ST'] = '-D%s' v['SONAME_ST'] = '-Wl,-h -Wl,%s' v['SHLIB_MARKER'] = '-Bdynamic' v['STATICLIB_MARKER'] = '-Bstatic' # program v['program_PATTERN'] = '%s' # shared library v['shlib_CCFLAGS'] = ['-Kpic', '-DPIC'] v['shlib_LINKFLAGS'] = ['-G'] v['shlib_PATTERN'] = 'lib%s.so' # static lib v['staticlib_LINKFLAGS'] = ['-Bstatic'] v['staticlib_PATTERN'] = 'lib%s.a' detect = ''' find_scc find_cpp find_ar scc_common_flags cc_load_tools cc_add_flags link_add_flags ''' tevent-0.9.34/third_party/waf/wafadmin/Tools/suncxx.py0000660000000000000000000000346012520121120022733 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) # Ralf Habacker, 2006 (rh) import os, optparse import Utils, Options, Configure import ccroot, ar from Configure import conftest @conftest def find_sxx(conf): v = conf.env cc = None if v['CXX']: cc = v['CXX'] elif 'CXX' in conf.environ: cc = conf.environ['CXX'] if not cc: cc = conf.find_program('c++', var='CXX') if not cc: conf.fatal('sunc++ was not found') cc = conf.cmd_to_list(cc) try: if not Utils.cmd_output(cc + ['-flags']): conf.fatal('sunc++ %r was not found' % cc) except ValueError: conf.fatal('sunc++ -flags could not be executed') v['CXX'] = cc v['CXX_NAME'] = 'sun' @conftest def sxx_common_flags(conf): v = conf.env # CPPFLAGS CXXDEFINES _CXXINCFLAGS _CXXDEFFLAGS v['CXX_SRC_F'] = '' v['CXX_TGT_F'] = ['-c', '-o', ''] v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = '' v['CXXLNK_TGT_F'] = ['-o', ''] # solaris hack, separate the -o from the target v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['CXXDEFINES_ST'] = '-D%s' v['SONAME_ST'] = '-Wl,-h -Wl,%s' v['SHLIB_MARKER'] = '-Bdynamic' v['STATICLIB_MARKER'] = '-Bstatic' # program v['program_PATTERN'] = '%s' # shared library v['shlib_CXXFLAGS'] = ['-Kpic', '-DPIC'] v['shlib_LINKFLAGS'] = ['-G'] v['shlib_PATTERN'] = 'lib%s.so' # static lib v['staticlib_LINKFLAGS'] = ['-Bstatic'] v['staticlib_PATTERN'] = 'lib%s.a' detect = ''' find_sxx find_cpp find_ar sxx_common_flags cxx_load_tools cxx_add_flags link_add_flags ''' tevent-0.9.34/third_party/waf/wafadmin/Tools/tex.py0000660000000000000000000001607112520121120022205 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) "TeX/LaTeX/PDFLaTeX support" import os, re import Utils, TaskGen, Task, Runner, Build from TaskGen import feature, before from Logs import error, warn, debug re_tex = re.compile(r'\\(?Pinclude|input|import|bringin|lstinputlisting){(?P[^{}]*)}', re.M) def scan(self): node = self.inputs[0] env = self.env nodes = [] names = [] if not node: return (nodes, names) code = Utils.readf(node.abspath(env)) curdirnode = self.curdirnode abs = curdirnode.abspath() for match in re_tex.finditer(code): path = match.group('file') if path: for k in ['', '.tex', '.ltx']: # add another loop for the tex include paths? debug('tex: trying %s%s' % (path, k)) try: os.stat(abs+os.sep+path+k) except OSError: continue found = path+k node = curdirnode.find_resource(found) if node: nodes.append(node) else: debug('tex: could not find %s' % path) names.append(path) debug("tex: found the following : %s and names %s" % (nodes, names)) return (nodes, names) latex_fun, _ = Task.compile_fun('latex', '${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) pdflatex_fun, _ = Task.compile_fun('pdflatex', '${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) bibtex_fun, _ = Task.compile_fun('bibtex', '${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False) makeindex_fun, _ = Task.compile_fun('bibtex', '${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}', shell=False) g_bibtex_re = re.compile('bibdata', re.M) def tex_build(task, command='LATEX'): env = task.env bld = task.generator.bld if not env['PROMPT_LATEX']: env.append_value('LATEXFLAGS', '-interaction=batchmode') env.append_value('PDFLATEXFLAGS', '-interaction=batchmode') fun = latex_fun if command == 'PDFLATEX': fun = pdflatex_fun node = task.inputs[0] reldir = node.bld_dir(env) #lst = [] #for c in Utils.split_path(reldir): # if c: lst.append('..') #srcfile = os.path.join(*(lst + [node.srcpath(env)])) #sr2 = os.path.join(*(lst + [node.parent.srcpath(env)])) srcfile = node.abspath(env) sr2 = node.parent.abspath() + os.pathsep + node.parent.abspath(env) + os.pathsep aux_node = node.change_ext('.aux') idx_node = node.change_ext('.idx') nm = aux_node.name docuname = nm[ : len(nm) - 4 ] # 4 is the size of ".aux" # important, set the cwd for everybody task.cwd = task.inputs[0].parent.abspath(task.env) warn('first pass on %s' % command) task.env.env = {'TEXINPUTS': sr2} task.env.SRCFILE = srcfile ret = fun(task) if ret: return ret # look in the .aux file if there is a bibfile to process try: ct = Utils.readf(aux_node.abspath(env)) except (OSError, IOError): error('error bibtex scan') else: fo = g_bibtex_re.findall(ct) # there is a .aux file to process if fo: warn('calling bibtex') task.env.env = {'BIBINPUTS': sr2, 'BSTINPUTS': sr2} task.env.SRCFILE = docuname ret = bibtex_fun(task) if ret: error('error when calling bibtex %s' % docuname) return ret # look on the filesystem if there is a .idx file to process try: idx_path = idx_node.abspath(env) os.stat(idx_path) except OSError: error('error file.idx scan') else: warn('calling makeindex') task.env.SRCFILE = idx_node.name task.env.env = {} ret = makeindex_fun(task) if ret: error('error when calling makeindex %s' % idx_path) return ret hash = '' i = 0 while i < 10: # prevent against infinite loops - one never knows i += 1 # watch the contents of file.aux prev_hash = hash try: hash = Utils.h_file(aux_node.abspath(env)) except KeyError: error('could not read aux.h -> %s' % aux_node.abspath(env)) pass # debug #print "hash is, ", hash, " ", old_hash # stop if file.aux does not change anymore if hash and hash == prev_hash: break # run the command warn('calling %s' % command) task.env.env = {'TEXINPUTS': sr2 + os.pathsep} task.env.SRCFILE = srcfile ret = fun(task) if ret: error('error when calling %s %s' % (command, latex_fun)) return ret return None # ok latex_vardeps = ['LATEX', 'LATEXFLAGS'] def latex_build(task): return tex_build(task, 'LATEX') pdflatex_vardeps = ['PDFLATEX', 'PDFLATEXFLAGS'] def pdflatex_build(task): return tex_build(task, 'PDFLATEX') class tex_taskgen(TaskGen.task_gen): def __init__(self, *k, **kw): TaskGen.task_gen.__init__(self, *k, **kw) @feature('tex') @before('apply_core') def apply_tex(self): if not getattr(self, 'type', None) in ['latex', 'pdflatex']: self.type = 'pdflatex' tree = self.bld outs = Utils.to_list(getattr(self, 'outs', [])) # prompt for incomplete files (else the batchmode is used) self.env['PROMPT_LATEX'] = getattr(self, 'prompt', 1) 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 in deps_lst: deps_lst.append(n) self.source = self.to_list(self.source) for filename in self.source: base, ext = os.path.splitext(filename) node = self.path.find_resource(filename) if not node: raise Utils.WafError('cannot find %s' % filename) 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')) task.env = self.env task.curdirnode = self.path # add the manual dependencies if deps_lst: variant = node.variant(self.env) try: lst = tree.node_deps[task.unique_id()] for n in deps_lst: if not n in lst: lst.append(n) except KeyError: tree.node_deps[task.unique_id()] = deps_lst if self.type == 'latex': if 'ps' in outs: tsk = self.create_task('dvips', task.outputs, node.change_ext('.ps')) tsk.env.env = {'TEXINPUTS' : node.parent.abspath() + os.pathsep + self.path.abspath() + os.pathsep + self.path.abspath(self.env)} if 'pdf' in outs: tsk = self.create_task('dvipdf', task.outputs, node.change_ext('.pdf')) tsk.env.env = {'TEXINPUTS' : node.parent.abspath() + os.pathsep + self.path.abspath() + os.pathsep + self.path.abspath(self.env)} elif self.type == 'pdflatex': if 'ps' in outs: self.create_task('pdf2ps', task.outputs, node.change_ext('.ps')) self.source = [] def detect(conf): v = conf.env for p in 'tex latex pdflatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): conf.find_program(p, var=p.upper()) v[p.upper()+'FLAGS'] = '' v['DVIPSFLAGS'] = '-Ppdf' b = Task.simple_task_type b('tex', '${TEX} ${TEXFLAGS} ${SRC}', color='BLUE', shell=False) # not used anywhere b('bibtex', '${BIBTEX} ${BIBTEXFLAGS} ${SRC}', color='BLUE', shell=False) # not used anywhere b('dvips', '${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}', color='BLUE', after="latex pdflatex tex bibtex", shell=False) b('dvipdf', '${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}', color='BLUE', after="latex pdflatex tex bibtex", shell=False) b('pdf2ps', '${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}', color='BLUE', after="dvipdf pdflatex", shell=False) b = Task.task_type_from_func cls = b('latex', latex_build, vars=latex_vardeps) cls.scan = scan cls = b('pdflatex', pdflatex_build, vars=pdflatex_vardeps) cls.scan = scan tevent-0.9.34/third_party/waf/wafadmin/Tools/unittestw.py0000660000000000000000000002307512520121120023455 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2006 """ Unit tests run in the shutdown() method, and for c/c++ programs One should NOT have to give parameters to programs to execute In the shutdown method, add the following code: >>> def shutdown(): ... ut = UnitTest.unit_test() ... ut.run() ... ut.print_results() Each object to use as a unit test must be a program and must have X{obj.unit_test=1} """ import os, sys import Build, TaskGen, Utils, Options, Logs, Task from TaskGen import before, after, feature from Constants import * class unit_test(object): "Unit test representation" def __init__(self): self.returncode_ok = 0 # Unit test returncode considered OK. All returncodes differing from this one # will cause the unit test to be marked as "FAILED". # The following variables are filled with data by run(). # print_results() uses these for printing the unit test summary, # but if there is need for direct access to the results, # they can be retrieved here, after calling run(). self.num_tests_ok = 0 # Number of successful unit tests self.num_tests_failed = 0 # Number of failed unit tests self.num_tests_err = 0 # Tests that have not even run self.total_num_tests = 0 # Total amount of unit tests self.max_label_length = 0 # Maximum label length (pretty-print the output) self.unit_tests = Utils.ordered_dict() # Unit test dictionary. Key: the label (unit test filename relative # to the build dir), value: unit test filename with absolute path self.unit_test_results = {} # Dictionary containing the unit test results. # Key: the label, value: result (true = success false = failure) self.unit_test_erroneous = {} # Dictionary indicating erroneous unit tests. # Key: the label, value: true = unit test has an error false = unit test is ok self.change_to_testfile_dir = False #True if the test file needs to be executed from the same dir self.want_to_see_test_output = False #True to see the stdout from the testfile (for example check suites) self.want_to_see_test_error = False #True to see the stderr from the testfile (for example check suites) self.run_if_waf_does = 'check' #build was the old default def run(self): "Run the unit tests and gather results (note: no output here)" self.num_tests_ok = 0 self.num_tests_failed = 0 self.num_tests_err = 0 self.total_num_tests = 0 self.max_label_length = 0 self.unit_tests = Utils.ordered_dict() self.unit_test_results = {} self.unit_test_erroneous = {} ld_library_path = [] # If waf is not building, don't run anything if not Options.commands[self.run_if_waf_does]: return # Get the paths for the shared libraries, and obtain the unit tests to execute for obj in Build.bld.all_task_gen: try: link_task = obj.link_task except AttributeError: pass else: lib_path = link_task.outputs[0].parent.abspath(obj.env) if lib_path not in ld_library_path: ld_library_path.append(lib_path) unit_test = getattr(obj, 'unit_test', '') if unit_test and 'cprogram' in obj.features: try: output = obj.path filename = os.path.join(output.abspath(obj.env), obj.target) srcdir = output.abspath() label = os.path.join(output.bldpath(obj.env), obj.target) self.max_label_length = max(self.max_label_length, len(label)) self.unit_tests[label] = (filename, srcdir) except KeyError: pass self.total_num_tests = len(self.unit_tests) # Now run the unit tests Utils.pprint('GREEN', 'Running the unit tests') count = 0 result = 1 for label in self.unit_tests.allkeys: file_and_src = self.unit_tests[label] filename = file_and_src[0] srcdir = file_and_src[1] count += 1 line = Build.bld.progress_line(count, self.total_num_tests, Logs.colors.GREEN, Logs.colors.NORMAL) if Options.options.progress_bar and line: sys.stderr.write(line) sys.stderr.flush() try: kwargs = {} kwargs['env'] = os.environ.copy() if self.change_to_testfile_dir: kwargs['cwd'] = srcdir if not self.want_to_see_test_output: kwargs['stdout'] = Utils.pproc.PIPE # PIPE for ignoring output if not self.want_to_see_test_error: kwargs['stderr'] = Utils.pproc.PIPE # PIPE for ignoring output if ld_library_path: v = kwargs['env'] def add_path(dct, path, var): dct[var] = os.pathsep.join(Utils.to_list(path) + [os.environ.get(var, '')]) if sys.platform == 'win32': add_path(v, ld_library_path, 'PATH') elif sys.platform == 'darwin': add_path(v, ld_library_path, 'DYLD_LIBRARY_PATH') add_path(v, ld_library_path, 'LD_LIBRARY_PATH') else: add_path(v, ld_library_path, 'LD_LIBRARY_PATH') pp = Utils.pproc.Popen(filename, **kwargs) (out, err) = pp.communicate() # uh, and the output is ignored?? - fortunately this is going to disappear result = int(pp.returncode == self.returncode_ok) if result: self.num_tests_ok += 1 else: self.num_tests_failed += 1 self.unit_test_results[label] = result self.unit_test_erroneous[label] = 0 except OSError: self.unit_test_erroneous[label] = 1 self.num_tests_err += 1 except KeyboardInterrupt: pass if Options.options.progress_bar: sys.stdout.write(Logs.colors.cursor_on) def print_results(self): "Pretty-prints a summary of all unit tests, along with some statistics" # If waf is not building, don't output anything if not Options.commands[self.run_if_waf_does]: return p = Utils.pprint # Early quit if no tests were performed if self.total_num_tests == 0: p('YELLOW', 'No unit tests present') return for label in self.unit_tests.allkeys: filename = self.unit_tests[label] err = 0 result = 0 try: err = self.unit_test_erroneous[label] except KeyError: pass try: result = self.unit_test_results[label] except KeyError: pass n = self.max_label_length - len(label) if err: n += 4 elif result: n += 7 else: n += 3 line = '%s %s' % (label, '.' * n) if err: p('RED', '%sERROR' % line) elif result: p('GREEN', '%sOK' % line) else: p('YELLOW', '%sFAILED' % line) percentage_ok = float(self.num_tests_ok) / float(self.total_num_tests) * 100.0 percentage_failed = float(self.num_tests_failed) / float(self.total_num_tests) * 100.0 percentage_erroneous = float(self.num_tests_err) / float(self.total_num_tests) * 100.0 p('NORMAL', ''' Successful tests: %i (%.1f%%) Failed tests: %i (%.1f%%) Erroneous tests: %i (%.1f%%) Total number of tests: %i ''' % (self.num_tests_ok, percentage_ok, self.num_tests_failed, percentage_failed, self.num_tests_err, percentage_erroneous, self.total_num_tests)) p('GREEN', 'Unit tests finished') ############################################################################################ """ New unit test system The targets with feature 'test' are executed after they are built bld(features='cprogram cc test', ...) To display the results: import UnitTest bld.add_post_fun(UnitTest.summary) """ import threading testlock = threading.Lock() def set_options(opt): opt.add_option('--alltests', action='store_true', default=True, help='Exec all unit tests', dest='all_tests') @feature('test') @after('apply_link', 'vars_target_cprogram') def make_test(self): if not 'cprogram' in self.features: Logs.error('test cannot be executed %s' % self) return self.default_install_path = None self.create_task('utest', self.link_task.outputs) def exec_test(self): status = 0 variant = self.env.variant() filename = self.inputs[0].abspath(self.env) self.ut_exec = getattr(self, 'ut_exec', [filename]) if getattr(self.generator, 'ut_fun', None): self.generator.ut_fun(self) try: fu = getattr(self.generator.bld, 'all_test_paths') except AttributeError: fu = os.environ.copy() self.generator.bld.all_test_paths = fu lst = [] for obj in self.generator.bld.all_task_gen: link_task = getattr(obj, 'link_task', None) if link_task and link_task.env.variant() == variant: lst.append(link_task.outputs[0].parent.abspath(obj.env)) def add_path(dct, path, var): dct[var] = os.pathsep.join(Utils.to_list(path) + [os.environ.get(var, '')]) if sys.platform == 'win32': add_path(fu, lst, 'PATH') elif sys.platform == 'darwin': add_path(fu, lst, 'DYLD_LIBRARY_PATH') add_path(fu, lst, 'LD_LIBRARY_PATH') else: add_path(fu, lst, 'LD_LIBRARY_PATH') cwd = getattr(self.generator, 'ut_cwd', '') or self.inputs[0].parent.abspath(self.env) proc = Utils.pproc.Popen(self.ut_exec, cwd=cwd, env=fu, stderr=Utils.pproc.PIPE, stdout=Utils.pproc.PIPE) (stdout, stderr) = proc.communicate() tup = (filename, proc.returncode, stdout, stderr) self.generator.utest_result = tup testlock.acquire() try: bld = self.generator.bld Logs.debug("ut: %r", tup) try: bld.utest_results.append(tup) except AttributeError: bld.utest_results = [tup] finally: testlock.release() cls = Task.task_type_from_func('utest', func=exec_test, color='PINK', ext_in='.bin') old = cls.runnable_status def test_status(self): ret = old(self) if ret == SKIP_ME and getattr(Options.options, 'all_tests', False): return RUN_ME return ret cls.runnable_status = test_status cls.quiet = 1 def summary(bld): lst = getattr(bld, 'utest_results', []) if lst: Utils.pprint('CYAN', 'execution summary') total = len(lst) tfail = len([x for x in lst if x[1]]) Utils.pprint('CYAN', ' tests that pass %d/%d' % (total-tfail, total)) for (f, code, out, err) in lst: if not code: Utils.pprint('CYAN', ' %s' % f) Utils.pprint('CYAN', ' tests that fail %d/%d' % (tfail, total)) for (f, code, out, err) in lst: if code: Utils.pprint('CYAN', ' %s' % f) tevent-0.9.34/third_party/waf/wafadmin/Tools/vala.py0000660000000000000000000002407012520121120022326 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 import os.path, shutil import Task, Runner, Utils, Logs, Build, Node, Options from TaskGen import extension, after, before EXT_VALA = ['.vala', '.gs'] class valac_task(Task.Task): vars = ("VALAC", "VALAC_VERSION", "VALAFLAGS") before = ("cc", "cxx") def run(self): env = self.env inputs = [a.srcpath(env) for a in self.inputs] valac = env['VALAC'] vala_flags = env.get_flat('VALAFLAGS') top_src = self.generator.bld.srcnode.abspath() top_bld = self.generator.bld.srcnode.abspath(env) if env['VALAC_VERSION'] > (0, 1, 6): cmd = [valac, '-C', '--quiet', vala_flags] else: cmd = [valac, '-C', vala_flags] if self.threading: cmd.append('--thread') if self.profile: cmd.append('--profile=%s' % self.profile) if self.target_glib: cmd.append('--target-glib=%s' % self.target_glib) features = self.generator.features if 'cshlib' in features or 'cstaticlib' in features: output_dir = self.outputs[0].bld_dir(env) cmd.append('--library ' + self.target) if env['VALAC_VERSION'] >= (0, 7, 0): for x in self.outputs: if x.name.endswith('.h'): cmd.append('--header ' + x.bldpath(self.env)) cmd.append('--basedir ' + top_src) cmd.append('-d ' + top_bld) if env['VALAC_VERSION'] > (0, 7, 2) and hasattr(self, 'gir'): cmd.append('--gir=%s.gir' % self.gir) else: output_dir = self.outputs[0].bld_dir(env) cmd.append('-d %s' % output_dir) for vapi_dir in self.vapi_dirs: cmd.append('--vapidir=%s' % vapi_dir) for package in self.packages: cmd.append('--pkg %s' % package) for package in self.packages_private: cmd.append('--pkg %s' % package) cmd.append(" ".join(inputs)) result = self.generator.bld.exec_command(" ".join(cmd)) if not 'cprogram' in features: # generate the .deps file if self.packages: filename = os.path.join(self.generator.path.abspath(env), "%s.deps" % self.target) deps = open(filename, 'w') for package in self.packages: deps.write(package + '\n') deps.close() # handle vala 0.1.6 who doesn't honor --directory for the generated .vapi self._fix_output("../%s.vapi" % self.target) # handle vala >= 0.1.7 who has a weid definition for --directory self._fix_output("%s.vapi" % self.target) # handle vala >= 0.2.0 who doesn't honor --directory for the generated .gidl self._fix_output("%s.gidl" % self.target) # handle vala >= 0.3.6 who doesn't honor --directory for the generated .gir self._fix_output("%s.gir" % self.target) if hasattr(self, 'gir'): self._fix_output("%s.gir" % self.gir) first = None for node in self.outputs: if not first: first = node else: if first.parent.id != node.parent.id: # issue #483 if env['VALAC_VERSION'] < (0, 7, 0): shutil.move(first.parent.abspath(self.env) + os.sep + node.name, node.abspath(self.env)) return result def install(self): bld = self.generator.bld features = self.generator.features if self.attr("install_path") and ("cshlib" in features or "cstaticlib" in features): headers_list = [o for o in self.outputs if o.suffix() == ".h"] vapi_list = [o for o in self.outputs if (o.suffix() in (".vapi", ".deps"))] gir_list = [o for o in self.outputs if o.suffix() == ".gir"] for header in headers_list: top_src = self.generator.bld.srcnode package = self.env['PACKAGE'] try: api_version = Utils.g_module.API_VERSION except AttributeError: version = Utils.g_module.VERSION.split(".") if version[0] == "0": api_version = "0." + version[1] else: api_version = version[0] + ".0" install_path = '${INCLUDEDIR}/%s-%s/%s' % (package, api_version, header.relpath_gen(top_src)) bld.install_as(install_path, header, self.env) bld.install_files('${DATAROOTDIR}/vala/vapi', vapi_list, self.env) bld.install_files('${DATAROOTDIR}/gir-1.0', gir_list, self.env) def _fix_output(self, output): top_bld = self.generator.bld.srcnode.abspath(self.env) try: src = os.path.join(top_bld, output) dst = self.generator.path.abspath (self.env) shutil.move(src, dst) except: pass @extension(EXT_VALA) def vala_file(self, node): valatask = getattr(self, "valatask", None) # there is only one vala task and it compiles all vala files .. :-/ if not valatask: valatask = self.create_task('valac') self.valatask = valatask self.includes = Utils.to_list(getattr(self, 'includes', [])) self.uselib = self.to_list(self.uselib) valatask.packages = [] valatask.packages_private = Utils.to_list(getattr(self, 'packages_private', [])) valatask.vapi_dirs = [] valatask.target = self.target valatask.threading = False valatask.install_path = self.install_path valatask.profile = getattr (self, 'profile', 'gobject') valatask.target_glib = None #Deprecated packages = Utils.to_list(getattr(self, 'packages', [])) vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', [])) includes = [] if hasattr(self, 'uselib_local'): local_packages = Utils.to_list(self.uselib_local) seen = [] while len(local_packages) > 0: package = local_packages.pop() if package in seen: continue seen.append(package) # check if the package exists package_obj = self.name_to_obj(package) if not package_obj: raise Utils.WafError("object '%s' was not found in uselib_local (required by '%s')" % (package, self.name)) package_name = package_obj.target package_node = package_obj.path package_dir = package_node.relpath_gen(self.path) for task in package_obj.tasks: 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 package_dir not in vapi_dirs: vapi_dirs.append(package_dir) if package_dir not in includes: includes.append(package_dir) if hasattr(package_obj, 'uselib_local'): lst = self.to_list(package_obj.uselib_local) lst.reverse() local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages valatask.packages = packages for vapi_dir in vapi_dirs: try: valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath()) valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath(self.env)) except AttributeError: Logs.warn("Unable to locate Vala API directory: '%s'" % vapi_dir) self.includes.append(node.bld.srcnode.abspath()) self.includes.append(node.bld.srcnode.abspath(self.env)) for include in includes: try: self.includes.append(self.path.find_dir(include).abspath()) self.includes.append(self.path.find_dir(include).abspath(self.env)) except AttributeError: Logs.warn("Unable to locate include directory: '%s'" % include) if valatask.profile == 'gobject': if hasattr(self, 'target_glib'): Logs.warn ('target_glib on vala tasks is deprecated --vala-target-glib=MAJOR.MINOR from the vala tool options') if getattr(Options.options, 'vala_target_glib', None): valatask.target_glib = Options.options.vala_target_glib if not 'GOBJECT' in self.uselib: self.uselib.append('GOBJECT') if hasattr(self, 'threading'): if valatask.profile == 'gobject': valatask.threading = self.threading if not 'GTHREAD' in self.uselib: self.uselib.append('GTHREAD') else: #Vala doesn't have threading support for dova nor posix Logs.warn("Profile %s does not have threading support" % valatask.profile) if hasattr(self, 'gir'): valatask.gir = self.gir env = valatask.env output_nodes = [] c_node = node.change_ext('.c') output_nodes.append(c_node) self.allnodes.append(c_node) if env['VALAC_VERSION'] < (0, 7, 0): output_nodes.append(node.change_ext('.h')) else: if not 'cprogram' in self.features: output_nodes.append(self.path.find_or_declare('%s.h' % self.target)) if not 'cprogram' in self.features: output_nodes.append(self.path.find_or_declare('%s.vapi' % self.target)) if env['VALAC_VERSION'] > (0, 7, 2): if hasattr(self, 'gir'): output_nodes.append(self.path.find_or_declare('%s.gir' % self.gir)) elif env['VALAC_VERSION'] > (0, 3, 5): output_nodes.append(self.path.find_or_declare('%s.gir' % self.target)) elif env['VALAC_VERSION'] > (0, 1, 7): output_nodes.append(self.path.find_or_declare('%s.gidl' % self.target)) if valatask.packages: output_nodes.append(self.path.find_or_declare('%s.deps' % self.target)) valatask.inputs.append(node) valatask.outputs.extend(output_nodes) def detect(conf): min_version = (0, 1, 6) min_version_str = "%d.%d.%d" % min_version valac = conf.find_program('valac', var='VALAC', mandatory=True) if not conf.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 conf.check_cfg(**pkg_args) if not conf.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 conf.check_cfg(**pkg_args) try: output = Utils.cmd_output(valac + " --version", silent=True) version = output.split(' ', 1)[-1].strip().split(".")[0:3] version = [int(x) for x in version] valac_version = tuple(version) except Exception: valac_version = (0, 0, 0) conf.check_message('program version', 'valac >= ' + min_version_str, valac_version >= min_version, "%d.%d.%d" % valac_version) conf.check_tool('gnu_dirs') if valac_version < min_version: conf.fatal("valac version too old to be used with this tool") return conf.env['VALAC_VERSION'] = valac_version conf.env['VALAFLAGS'] = '' def set_options (opt): 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') tevent-0.9.34/third_party/waf/wafadmin/Tools/winres.py0000660000000000000000000000240512520121120022710 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Brant Young, 2007 "This hook is called when the class cpp/cc task generator encounters a '.rc' file: X{.rc -> [.res|.rc.o]}" import os, sys, re import TaskGen, Task from Utils import quote_whitespace from TaskGen import extension EXT_WINRC = ['.rc'] winrc_str = '${WINRC} ${_CPPDEFFLAGS} ${_CCDEFFLAGS} ${WINRCFLAGS} ${_CPPINCFLAGS} ${_CCINCFLAGS} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' @extension(EXT_WINRC) def rc_file(self, node): 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)) self.compiled_tasks.append(rctask) # create our action, for use with rc file Task.simple_task_type('winrc', winrc_str, color='BLUE', before='cc cxx', shell=False) def detect(conf): v = conf.env winrc = v['WINRC'] v['WINRC_TGT_F'] = '-o' v['WINRC_SRC_F'] = '-i' # find rc.exe if not winrc: if v['CC_NAME'] in ['gcc', 'cc', 'g++', 'c++']: winrc = conf.find_program('windres', var='WINRC', path_list = v['PATH']) elif v['CC_NAME'] == 'msvc': winrc = conf.find_program('RC', var='WINRC', path_list = v['PATH']) v['WINRC_TGT_F'] = '/fo' v['WINRC_SRC_F'] = '' if not winrc: conf.fatal('winrc was not found!') v['WINRCFLAGS'] = '' tevent-0.9.34/third_party/waf/wafadmin/Tools/xlc.py0000660000000000000000000000377012520121120022175 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2008 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 import os, sys import Configure, Options, Utils import ccroot, ar from Configure import conftest @conftest def find_xlc(conf): cc = conf.find_program(['xlc_r', 'xlc'], var='CC', mandatory=True) cc = conf.cmd_to_list(cc) conf.env.CC_NAME = 'xlc' conf.env.CC = cc @conftest def find_cpp(conf): v = conf.env cpp = None if v['CPP']: cpp = v['CPP'] elif 'CPP' in conf.environ: cpp = conf.environ['CPP'] #if not cpp: cpp = v['CC'] v['CPP'] = cpp @conftest def xlc_common_flags(conf): v = conf.env # CPPFLAGS CCDEFINES _CCINCFLAGS _CCDEFFLAGS v['CCFLAGS_DEBUG'] = ['-g'] v['CCFLAGS_RELEASE'] = ['-O2'] v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = '' v['CCLNK_TGT_F'] = ['-o', ''] # shell hack for -MD v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['CCDEFINES_ST'] = '-D%s' v['SONAME_ST'] = '' v['SHLIB_MARKER'] = '' v['STATICLIB_MARKER'] = '' v['FULLSTATIC_MARKER'] = '-static' # program v['program_LINKFLAGS'] = ['-Wl,-brtl'] v['program_PATTERN'] = '%s' # shared library v['shlib_CCFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro v['shlib_LINKFLAGS'] = ['-G', '-Wl,-brtl,-bexpfull'] v['shlib_PATTERN'] = 'lib%s.so' # static lib v['staticlib_LINKFLAGS'] = '' v['staticlib_PATTERN'] = 'lib%s.a' def detect(conf): conf.find_xlc() conf.find_cpp() conf.find_ar() conf.xlc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() tevent-0.9.34/third_party/waf/wafadmin/Tools/xlcxx.py0000660000000000000000000000402312520121120022545 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 import os, sys import Configure, Options, Utils import ccroot, ar from Configure import conftest @conftest def find_xlcxx(conf): cxx = conf.find_program(['xlc++_r', 'xlc++'], var='CXX', mandatory=True) cxx = conf.cmd_to_list(cxx) conf.env.CXX_NAME = 'xlc++' conf.env.CXX = cxx @conftest def find_cpp(conf): v = conf.env cpp = None if v['CPP']: cpp = v['CPP'] elif 'CPP' in conf.environ: cpp = conf.environ['CPP'] #if not cpp: cpp = v['CXX'] v['CPP'] = cpp @conftest def xlcxx_common_flags(conf): v = conf.env # CPPFLAGS CXXDEFINES _CXXINCFLAGS _CXXDEFFLAGS v['CXXFLAGS_DEBUG'] = ['-g'] v['CXXFLAGS_RELEASE'] = ['-O2'] v['CXX_SRC_F'] = '' v['CXX_TGT_F'] = ['-c', '-o', ''] # shell hack for -MD v['CPPPATH_ST'] = '-I%s' # template for adding include paths # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = '' v['CXXLNK_TGT_F'] = ['-o', ''] # shell hack for -MD v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STATICLIB_ST'] = '-l%s' v['STATICLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['CXXDEFINES_ST'] = '-D%s' v['SONAME_ST'] = '' v['SHLIB_MARKER'] = '' v['STATICLIB_MARKER'] = '' v['FULLSTATIC_MARKER'] = '-static' # program v['program_LINKFLAGS'] = ['-Wl,-brtl'] v['program_PATTERN'] = '%s' # shared library v['shlib_CXXFLAGS'] = ['-fPIC', '-DPIC'] # avoid using -DPIC, -fPIC aleady defines the __PIC__ macro v['shlib_LINKFLAGS'] = ['-G', '-Wl,-brtl,-bexpfull'] v['shlib_PATTERN'] = 'lib%s.so' # static lib v['staticlib_LINKFLAGS'] = '' v['staticlib_PATTERN'] = 'lib%s.a' def detect(conf): conf.find_xlcxx() conf.find_cpp() conf.find_ar() conf.xlcxx_common_flags() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() tevent-0.9.34/third_party/waf/wafadmin/Utils.py0000660000000000000000000004520112617125140021417 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) """ Utilities, the stable ones are the following: * h_file: compute a unique value for a file (hash), it uses the module fnv if it is installed (see waf/utils/fnv & http://code.google.com/p/waf/wiki/FAQ) else, md5 (see the python docs) For large projects (projects with more than 15000 files) or slow hard disks and filesystems (HFS) it is possible to use a hashing based on the path and the size (may give broken cache results) The method h_file MUST raise an OSError if the file is a folder import stat def h_file(filename): st = os.lstat(filename) if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file') m = Utils.md5() m.update(str(st.st_mtime)) m.update(str(st.st_size)) m.update(filename) return m.digest() To replace the function in your project, use something like this: import Utils Utils.h_file = h_file * h_list * h_fun * get_term_cols * ordered_dict """ import os, sys, imp, string, errno, traceback, inspect, re, shutil, datetime, gc # In python 3.0 we can get rid of all this try: from UserDict import UserDict except ImportError: from collections import UserDict if sys.hexversion >= 0x2060000 or os.name == 'java': import subprocess as pproc else: import pproc import Logs from Constants import * try: from collections import deque except ImportError: class deque(list): def popleft(self): return self.pop(0) is_win32 = sys.platform == 'win32' try: # defaultdict in python 2.5 from collections import defaultdict as DefaultDict except ImportError: class DefaultDict(dict): def __init__(self, default_factory): super(DefaultDict, self).__init__() self.default_factory = default_factory def __getitem__(self, key): try: return super(DefaultDict, self).__getitem__(key) except KeyError: value = self.default_factory() self[key] = value return value class WafError(Exception): def __init__(self, *args): self.args = args try: self.stack = traceback.extract_stack() except: pass Exception.__init__(self, *args) def __str__(self): return str(len(self.args) == 1 and self.args[0] or self.args) class WscriptError(WafError): def __init__(self, message, wscript_file=None): if wscript_file: self.wscript_file = wscript_file self.wscript_line = None else: try: (self.wscript_file, self.wscript_line) = self.locate_error() except: (self.wscript_file, self.wscript_line) = (None, None) msg_file_line = '' if self.wscript_file: msg_file_line = "%s:" % self.wscript_file if self.wscript_line: msg_file_line += "%s:" % self.wscript_line err_message = "%s error: %s" % (msg_file_line, message) WafError.__init__(self, err_message) def locate_error(self): stack = traceback.extract_stack() stack.reverse() for frame in stack: file_name = os.path.basename(frame[0]) is_wscript = (file_name == WSCRIPT_FILE or file_name == WSCRIPT_BUILD_FILE) if is_wscript: return (frame[0], frame[1]) return (None, None) indicator = is_win32 and '\x1b[A\x1b[K%s%s%s\r' or '\x1b[K%s%s%s\r' try: from fnv import new as md5 import Constants Constants.SIG_NIL = 'signofnv' def h_file(filename): m = md5() try: m.hfile(filename) x = m.digest() if x is None: raise OSError("not a file") return x except SystemError: raise OSError("not a file" + filename) except ImportError: try: try: from hashlib import md5 except ImportError: from md5 import md5 def h_file(filename): f = open(filename, 'rb') m = md5() while (filename): filename = f.read(100000) m.update(filename) f.close() return m.digest() except ImportError: # portability fixes may be added elsewhere (although, md5 should be everywhere by now) md5 = None def readf(fname, m='r', encoding='ISO8859-1'): """backported from waf 1.8""" if sys.hexversion > 0x3000000 and not 'b' in m: m += 'b' f = open(fname, m) try: txt = f.read() finally: f.close() if encoding: txt = txt.decode(encoding) else: txt = txt.decode() else: f = open(fname, m) try: txt = f.read() finally: f.close() return txt def writef(fname, data, m='w', encoding='ISO8859-1'): """backported from waf 1.8""" if sys.hexversion > 0x3000000 and not 'b' in m: data = data.encode(encoding) m += 'b' f = open(fname, m) try: f.write(data) finally: f.close() class ordered_dict(UserDict): def __init__(self, dict = None): self.allkeys = [] UserDict.__init__(self, dict) def __delitem__(self, key): self.allkeys.remove(key) UserDict.__delitem__(self, key) def __setitem__(self, key, item): if key not in self.allkeys: self.allkeys.append(key) UserDict.__setitem__(self, key, item) def exec_command(s, **kw): if 'log' in kw: kw['stdout'] = kw['stderr'] = kw['log'] del(kw['log']) kw['shell'] = isinstance(s, str) try: proc = pproc.Popen(s, **kw) return proc.wait() except OSError: return -1 if is_win32: def exec_command(s, **kw): if 'log' in kw: kw['stdout'] = kw['stderr'] = kw['log'] del(kw['log']) kw['shell'] = isinstance(s, str) if len(s) > 2000: startupinfo = pproc.STARTUPINFO() startupinfo.dwFlags |= pproc.STARTF_USESHOWWINDOW kw['startupinfo'] = startupinfo try: if 'stdout' not in kw: kw['stdout'] = pproc.PIPE kw['stderr'] = pproc.PIPE kw['universal_newlines'] = True proc = pproc.Popen(s,**kw) (stdout, stderr) = proc.communicate() Logs.info(stdout) if stderr: Logs.error(stderr) return proc.returncode else: proc = pproc.Popen(s,**kw) return proc.wait() except OSError: return -1 listdir = os.listdir if is_win32: def listdir_win32(s): if re.match('^[A-Za-z]:$', s): # os.path.isdir fails if s contains only the drive name... (x:) s += os.sep if not os.path.isdir(s): e = OSError() e.errno = errno.ENOENT raise e return os.listdir(s) listdir = listdir_win32 def waf_version(mini = 0x010000, maxi = 0x100000): "Halts if the waf version is wrong" ver = HEXVERSION try: min_val = mini + 0 except TypeError: min_val = int(mini.replace('.', '0'), 16) if min_val > ver: Logs.error("waf version should be at least %s (%s found)" % (mini, ver)) sys.exit(1) try: max_val = maxi + 0 except TypeError: max_val = int(maxi.replace('.', '0'), 16) if max_val < ver: Logs.error("waf version should be at most %s (%s found)" % (maxi, ver)) sys.exit(1) def python_24_guard(): if sys.hexversion < 0x20400f0 or sys.hexversion >= 0x3000000: raise ImportError("Waf requires Python >= 2.3 but the raw source requires Python 2.4, 2.5 or 2.6") def ex_stack(): exc_type, exc_value, tb = sys.exc_info() if Logs.verbose > 1: exc_lines = traceback.format_exception(exc_type, exc_value, tb) return ''.join(exc_lines) return str(exc_value) def to_list(sth): if isinstance(sth, str): return sth.split() else: return sth g_loaded_modules = {} "index modules by absolute path" g_module=None "the main module is special" def load_module(file_path, name=WSCRIPT_FILE): "this function requires an absolute path" try: return g_loaded_modules[file_path] except KeyError: pass module = imp.new_module(name) try: code = readf(file_path, m='rU') except (IOError, OSError): raise WscriptError('Could not read the file %r' % file_path) module.waf_hash_val = code dt = os.path.dirname(file_path) sys.path.insert(0, dt) try: exec(compile(code, file_path, 'exec'), module.__dict__) except Exception: exc_type, exc_value, tb = sys.exc_info() raise WscriptError("".join(traceback.format_exception(exc_type, exc_value, tb)), file_path) sys.path.remove(dt) g_loaded_modules[file_path] = module return module def set_main_module(file_path): "Load custom options, if defined" global g_module g_module = load_module(file_path, 'wscript_main') g_module.root_path = file_path try: g_module.APPNAME except: g_module.APPNAME = 'noname' try: g_module.VERSION except: g_module.VERSION = '1.0' # note: to register the module globally, use the following: # sys.modules['wscript_main'] = g_module def to_hashtable(s): "used for importing env files" tbl = {} lst = s.split('\n') for line in lst: if not line: continue mems = line.split('=') tbl[mems[0]] = mems[1] return tbl def get_term_cols(): "console width" return 80 try: import struct, fcntl, termios except ImportError: pass else: if Logs.got_tty: def myfun(): dummy_lines, cols = struct.unpack("HHHH", \ fcntl.ioctl(sys.stderr.fileno(),termios.TIOCGWINSZ , \ struct.pack("HHHH", 0, 0, 0, 0)))[:2] return cols # we actually try the function once to see if it is suitable try: myfun() except: pass else: get_term_cols = myfun rot_idx = 0 rot_chr = ['\\', '|', '/', '-'] "the rotation character in the progress bar" def split_path(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.split(re_sp, path)[2:] ret[0] = '\\' + ret[0] return ret return re.split(re_sp, path) if sys.platform == 'cygwin': split_path = split_path_cygwin elif is_win32: split_path = split_path_win32 def copy_attrs(orig, dest, names, only_if_set=False): for a in to_list(names): u = getattr(orig, a, ()) if u or not only_if_set: setattr(dest, a, u) def def_attrs(cls, **kw): ''' set attributes for class. @param cls [any class]: the class to update the given attributes in. @param kw [dictionary]: dictionary of attributes names and values. if the given class hasn't one (or more) of these attributes, add the attribute with its value to the class. ''' for k, v in kw.iteritems(): if not hasattr(cls, k): setattr(cls, k, v) def quote_define_name(path): fu = re.compile("[^a-zA-Z0-9]").sub("_", path) fu = fu.upper() return fu def quote_whitespace(path): return (path.strip().find(' ') > 0 and '"%s"' % path or path).replace('""', '"') def trimquotes(s): if not s: return '' s = s.rstrip() if s[0] == "'" and s[-1] == "'": return s[1:-1] return s def h_list(lst): m = md5() m.update(str(lst)) return m.digest() def h_fun(fun): try: return fun.code except AttributeError: try: h = inspect.getsource(fun) except IOError: h = "nocode" try: fun.code = h except AttributeError: pass return h def pprint(col, str, label='', sep='\n'): "print messages in color" sys.stderr.write("%s%s%s %s%s" % (Logs.colors(col), str, Logs.colors.NORMAL, label, sep)) def check_dir(path): """If a folder doesn't exists, create it.""" if not os.path.isdir(path): try: os.makedirs(path) except OSError, e: if not os.path.isdir(path): raise WafError("Cannot create the folder '%s' (error: %s)" % (path, e)) 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'] = pproc.PIPE if silent: kw['stderr'] = pproc.PIPE try: p = pproc.Popen(cmd, **kw) output = p.communicate()[0] except OSError, 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 reg_subst = re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") def subst_vars(expr, params): "substitute ${PREFIX}/bin in /usr/local/bin" def repl_var(m): if m.group(1): return '\\' if m.group(2): return '$' try: # environments may contain lists return params.get_flat(m.group(3)) except AttributeError: return params[m.group(3)] return reg_subst.sub(repl_var, expr) def unversioned_sys_platform_to_binary_format(unversioned_sys_platform): "infers the binary format from the unversioned_sys_platform name." if unversioned_sys_platform in ('linux', 'freebsd', 'netbsd', 'openbsd', 'sunos', 'gnu'): return 'elf' elif unversioned_sys_platform == 'darwin': return 'mac-o' elif unversioned_sys_platform in ('win32', 'cygwin', 'uwin', 'msys'): return 'pe' # TODO we assume all other operating systems are elf, which is not true. # we may set this to 'unknown' and have ccroot and other tools handle the case "gracefully" (whatever that means). return 'elf' def unversioned_sys_platform(): """returns an unversioned name from sys.platform. sys.plaform is not very well defined and depends directly on the python source tree. The version appended to the names is unreliable as it's taken from the build environment at the time python was built, i.e., it's possible to get freebsd7 on a freebsd8 system. So we remove the version from the name, except for special cases where the os has a stupid name like os2 or win32. Some possible values of sys.platform are, amongst others: aix3 aix4 atheos beos5 darwin freebsd2 freebsd3 freebsd4 freebsd5 freebsd6 freebsd7 generic gnu0 irix5 irix6 linux2 mac netbsd1 next3 os2emx riscos sunos5 unixware7 Investigating the python source tree may reveal more values. """ s = sys.platform if s == '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 'hpux' elif s in ('SunOS', 'Solaris'): return 'sunos' else: s = s.lower() if s == 'win32' or s.endswith('os2') and s != 'sunos2': return s return re.split('\d+$', s)[0] #@deprecated('use unversioned_sys_platform instead') def detect_platform(): """this function has been in the Utils module for some time. It's hard to guess what people have used it for. It seems its goal is to return an unversionned sys.platform, but it's not handling all platforms. For example, the version is not removed on freebsd and netbsd, amongst others. """ s = sys.platform # known POSIX for x in 'cygwin linux irix sunos hpux aix darwin gnu'.split(): # sys.platform may be linux2 if s.find(x) >= 0: return x # unknown POSIX if os.name in 'posix java os2'.split(): return os.name return s def load_tool(tool, tooldir=None): ''' load_tool: import a Python module, optionally using several directories. @param tool [string]: name of tool to import. @param tooldir [list]: directories to look for the tool. @return: the loaded module. Warning: this function is not thread-safe: plays with sys.path, so must run in sequence. ''' if tooldir: assert isinstance(tooldir, list) sys.path = tooldir + sys.path else: tooldir = [] try: return __import__(tool) finally: for dt in tooldir: sys.path.remove(dt) def nada(*k, **kw): """A function that does nothing""" pass def diff_path(top, subdir): """difference between two absolute paths""" top = os.path.normpath(top).replace('\\', '/').split('/') subdir = os.path.normpath(subdir).replace('\\', '/').split('/') if len(top) == len(subdir): return '' diff = subdir[len(top) - len(subdir):] return os.path.join(*diff) class Context(object): """A base class for commands to be executed from Waf scripts""" def set_curdir(self, dir): self.curdir_ = dir def get_curdir(self): try: return self.curdir_ except AttributeError: self.curdir_ = os.getcwd() return self.get_curdir() curdir = property(get_curdir, set_curdir) def recurse(self, dirs, name=''): """The function for calling scripts from folders, it tries to call wscript + function_name and if that file does not exist, it will call the method 'function_name' from a file named wscript the dirs can be a list of folders or a string containing space-separated folder paths """ if not name: name = inspect.stack()[1][3] if isinstance(dirs, str): dirs = to_list(dirs) for x in dirs: if os.path.isabs(x): nexdir = x else: nexdir = os.path.join(self.curdir, x) base = os.path.join(nexdir, WSCRIPT_FILE) file_path = base + '_' + name try: txt = readf(file_path, m='rU') except (OSError, IOError): try: module = load_module(base) except OSError: raise WscriptError('No such script %s' % base) try: f = module.__dict__[name] except KeyError: raise WscriptError('No function %s defined in %s' % (name, base)) if getattr(self.__class__, 'pre_recurse', None): self.pre_recurse(f, base, nexdir) old = self.curdir self.curdir = nexdir try: f(self) finally: self.curdir = old if getattr(self.__class__, 'post_recurse', None): self.post_recurse(module, base, nexdir) else: dc = {'ctx': self} if getattr(self.__class__, 'pre_recurse', None): dc = self.pre_recurse(txt, file_path, nexdir) old = self.curdir self.curdir = nexdir try: try: exec(compile(txt, file_path, 'exec'), dc) except Exception: exc_type, exc_value, tb = sys.exc_info() raise WscriptError("".join(traceback.format_exception(exc_type, exc_value, tb)), base) finally: self.curdir = old if getattr(self.__class__, 'post_recurse', None): self.post_recurse(txt, file_path, nexdir) if is_win32: old = shutil.copy2 def copy2(src, dst): old(src, dst) shutil.copystat(src, src) setattr(shutil, 'copy2', copy2) def zip_folder(dir, zip_file_name, prefix): """ prefix represents the app to add in the archive """ import zipfile zip = zipfile.ZipFile(zip_file_name, 'w', compression=zipfile.ZIP_DEFLATED) base = os.path.abspath(dir) if prefix: if prefix[-1] != os.sep: prefix += os.sep n = len(base) for root, dirs, files in os.walk(base): for f in files: archive_name = prefix + root[n:] + os.sep + f zip.write(root + os.sep + f, archive_name, zipfile.ZIP_DEFLATED) zip.close() def get_elapsed_time(start): "Format a time delta (datetime.timedelta) using the format DdHhMmS.MSs" delta = datetime.datetime.now() - start # cast to int necessary for python 3.0 days = int(delta.days) hours = int(delta.seconds / 3600) minutes = int((delta.seconds - hours * 3600) / 60) seconds = delta.seconds - hours * 3600 - minutes * 60 \ + float(delta.microseconds) / 1000 / 1000 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) if os.name == 'java': # For Jython (they should really fix the inconsistency) try: gc.disable() gc.enable() except NotImplementedError: gc.disable = gc.enable def run_once(fun): """ decorator, make a function cache its results, use like this: @run_once def foo(k): return 345*2343 """ cache = {} def wrap(k): try: return cache[k] except KeyError: ret = fun(k) cache[k] = ret return ret wrap.__cache__ = cache return wrap tevent-0.9.34/third_party/waf/wafadmin/__init__.py0000660000000000000000000000010212520121120022030 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005 (ita) tevent-0.9.34/third_party/waf/wafadmin/ansiterm.py0000660000000000000000000001752312520121120022132 0ustar rootroot00000000000000import sys, os try: if (not sys.stderr.isatty()) or (not sys.stdout.isatty()): raise ValueError('not a tty') from ctypes import * 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_short), ("Window", SMALL_RECT), ("MaximumWindowSize", COORD)] class CONSOLE_CURSOR_INFO(Structure): _fields_ = [('dwSize',c_ulong), ('bVisible', c_int)] sbinfo = CONSOLE_SCREEN_BUFFER_INFO() csinfo = CONSOLE_CURSOR_INFO() hconsole = windll.kernel32.GetStdHandle(-11) windll.kernel32.GetConsoleScreenBufferInfo(hconsole, byref(sbinfo)) if sbinfo.Size.X < 10 or sbinfo.Size.Y < 10: raise Exception('small console') windll.kernel32.GetConsoleCursorInfo(hconsole, byref(csinfo)) except Exception: pass else: import re, threading to_int = lambda number, default: number and int(number) or default wlock = threading.Lock() STD_OUTPUT_HANDLE = -11 STD_ERROR_HANDLE = -12 class AnsiTerm(object): def __init__(self): self.hconsole = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) self.cursor_history = [] self.orig_sbinfo = CONSOLE_SCREEN_BUFFER_INFO() self.orig_csinfo = CONSOLE_CURSOR_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self.orig_sbinfo)) windll.kernel32.GetConsoleCursorInfo(hconsole, byref(self.orig_csinfo)) def screen_buffer_info(self): sbinfo = CONSOLE_SCREEN_BUFFER_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo)) return sbinfo def clear_line(self, param): mode = param and int(param) or 0 sbinfo = self.screen_buffer_info() if mode == 1: # Clear from begining 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_int() windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_char(' '), 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 begining 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_int() windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_char(' '), 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.push(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): x, sep, y = 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) ) escape_to_color = { (0, 30): 0x0, #black (0, 31): 0x4, #red (0, 32): 0x2, #green (0, 33): 0x4+0x2, #dark yellow (0, 34): 0x1, #blue (0, 35): 0x1+0x4, #purple (0, 36): 0x2+0x4, #cyan (0, 37): 0x1+0x2+0x4, #grey (1, 30): 0x1+0x2+0x4, #dark gray (1, 31): 0x4+0x8, #red (1, 32): 0x2+0x8, #light green (1, 33): 0x4+0x2+0x8, #yellow (1, 34): 0x1+0x8, #light blue (1, 35): 0x1+0x4+0x8, #light purple (1, 36): 0x1+0x2+0x8, #light cyan (1, 37): 0x1+0x2+0x4+0x8, #white } def set_color(self, param): cols = param.split(';') attr = self.orig_sbinfo.Attributes for c in cols: c = to_int(c, 0) if c in range(30,38): attr = (attr & 0xf0) | (self.escape_to_color.get((0,c), 0x7)) elif c in range(40,48): attr = (attr & 0x0f) | (self.escape_to_color.get((0,c), 0x7) << 8) elif c in range(90,98): attr = (attr & 0xf0) | (self.escape_to_color.get((1,c-60), 0x7)) elif c in range(100,108): attr = (attr & 0x0f) | (self.escape_to_color.get((1,c-60), 0x7) << 8) elif c == 1: attr |= 0x08 windll.kernel32.SetConsoleTextAttribute(self.hconsole, attr) def show_cursor(self,param): csinfo.bVisible = 1 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(csinfo)) def hide_cursor(self,param): csinfo.bVisible = 0 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(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_tokans = re.compile('(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') def write(self, text): try: wlock.acquire() for param, cmd, txt in self.ansi_tokans.findall(text): if cmd: cmd_func = self.ansi_command_table.get(cmd) if cmd_func: cmd_func(self, param) else: chars_written = c_int() if isinstance(txt, unicode): windll.kernel32.WriteConsoleW(self.hconsole, txt, len(txt), byref(chars_written), None) else: windll.kernel32.WriteConsoleA(self.hconsole, txt, len(txt), byref(chars_written), None) finally: wlock.release() def flush(self): pass def isatty(self): return True sys.stderr = sys.stdout = AnsiTerm() os.environ['TERM'] = 'vt100' tevent-0.9.34/third_party/waf/wafadmin/pproc.py0000660000000000000000000005103612520121120021430 0ustar rootroot00000000000000# borrowed from python 2.5.2c1 # Copyright (c) 2003-2005 by Peter Astrand # Licensed to PSF under a Contributor Agreement. import sys mswindows = (sys.platform == "win32") import os import types import traceback import gc class CalledProcessError(Exception): def __init__(self, returncode, cmd): self.returncode = returncode self.cmd = cmd def __str__(self): return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) if mswindows: import threading import msvcrt if 0: import pywintypes from win32api import GetStdHandle, STD_INPUT_HANDLE, \ STD_OUTPUT_HANDLE, STD_ERROR_HANDLE from win32api import GetCurrentProcess, DuplicateHandle, \ GetModuleFileName, GetVersion from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE from win32pipe import CreatePipe from win32process import CreateProcess, STARTUPINFO, \ GetExitCodeProcess, STARTF_USESTDHANDLES, \ STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 else: from _subprocess import * class STARTUPINFO: dwFlags = 0 hStdInput = None hStdOutput = None hStdError = None wShowWindow = 0 class pywintypes: error = IOError else: import select import errno import fcntl import pickle __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] try: MAXFD = os.sysconf("SC_OPEN_MAX") except: MAXFD = 256 try: False except NameError: False = 0 True = 1 _active = [] def _cleanup(): for inst in _active[:]: if inst.poll(_deadstate=sys.maxint) >= 0: try: _active.remove(inst) except ValueError: pass PIPE = -1 STDOUT = -2 def call(*popenargs, **kwargs): return Popen(*popenargs, **kwargs).wait() def check_call(*popenargs, **kwargs): retcode = call(*popenargs, **kwargs) cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] if retcode: raise CalledProcessError(retcode, cmd) return retcode def list2cmdline(seq): result = [] needquote = False for arg in seq: bs_buf = [] if result: result.append(' ') needquote = (" " in arg) or ("\t" in arg) or arg == "" if needquote: result.append('"') for c in arg: if c == '\\': bs_buf.append(c) elif c == '"': result.append('\\' * len(bs_buf)*2) bs_buf = [] result.append('\\"') else: if bs_buf: result.extend(bs_buf) bs_buf = [] result.append(c) if bs_buf: result.extend(bs_buf) if needquote: result.extend(bs_buf) result.append('"') return ''.join(result) class Popen(object): def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0): _cleanup() self._child_created = False if not isinstance(bufsize, (int, long)): raise TypeError("bufsize must be an integer") if mswindows: if preexec_fn is not None: raise ValueError("preexec_fn is not supported on Windows platforms") if close_fds: raise ValueError("close_fds is not supported on Windows platforms") else: if startupinfo is not None: raise ValueError("startupinfo is only supported on Windows platforms") if creationflags != 0: raise ValueError("creationflags is only supported on Windows platforms") self.stdin = None self.stdout = None self.stderr = None self.pid = None self.returncode = None self.universal_newlines = universal_newlines (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) = self._get_handles(stdin, stdout, stderr) self._execute_child(args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) if mswindows: if stdin is None and p2cwrite is not None: os.close(p2cwrite) p2cwrite = None if stdout is None and c2pread is not None: os.close(c2pread) c2pread = None if stderr is None and errread is not None: os.close(errread) errread = None if p2cwrite: self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) if c2pread: if universal_newlines: self.stdout = os.fdopen(c2pread, 'rU', bufsize) else: self.stdout = os.fdopen(c2pread, 'rb', bufsize) if errread: if universal_newlines: self.stderr = os.fdopen(errread, 'rU', bufsize) else: self.stderr = os.fdopen(errread, 'rb', bufsize) def _translate_newlines(self, data): data = data.replace("\r\n", "\n") data = data.replace("\r", "\n") return data def __del__(self, sys=sys): if not self._child_created: return self.poll(_deadstate=sys.maxint) if self.returncode is None and _active is not None: _active.append(self) def communicate(self, input=None): if [self.stdin, self.stdout, self.stderr].count(None) >= 2: stdout = None stderr = None if self.stdin: if input: self.stdin.write(input) self.stdin.close() elif self.stdout: stdout = self.stdout.read() elif self.stderr: stderr = self.stderr.read() self.wait() return (stdout, stderr) return self._communicate(input) if mswindows: def _get_handles(self, stdin, stdout, stderr): if stdin is None and stdout is None and stderr is None: return (None, None, None, None, None, None) p2cread, p2cwrite = None, None c2pread, c2pwrite = None, None errread, errwrite = None, None if stdin is None: p2cread = GetStdHandle(STD_INPUT_HANDLE) if p2cread is not None: pass elif stdin is None or stdin == PIPE: p2cread, p2cwrite = CreatePipe(None, 0) p2cwrite = p2cwrite.Detach() p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: p2cread = msvcrt.get_osfhandle(stdin.fileno()) p2cread = self._make_inheritable(p2cread) if stdout is None: c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) if c2pwrite is not None: pass elif stdout is None or stdout == PIPE: c2pread, c2pwrite = CreatePipe(None, 0) c2pread = c2pread.Detach() c2pread = msvcrt.open_osfhandle(c2pread, 0) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) c2pwrite = self._make_inheritable(c2pwrite) if stderr is None: errwrite = GetStdHandle(STD_ERROR_HANDLE) if errwrite is not None: pass elif stderr is None or stderr == PIPE: errread, errwrite = CreatePipe(None, 0) errread = errread.Detach() errread = msvcrt.open_osfhandle(errread, 0) elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): errwrite = msvcrt.get_osfhandle(stderr) else: errwrite = msvcrt.get_osfhandle(stderr.fileno()) errwrite = self._make_inheritable(errwrite) return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) def _make_inheritable(self, handle): return DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 0, 1, DUPLICATE_SAME_ACCESS) def _find_w9xpopen(self): w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), "w9xpopen.exe") if not os.path.exists(w9xpopen): w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), "w9xpopen.exe") if not os.path.exists(w9xpopen): raise RuntimeError("Cannot locate w9xpopen.exe, which is needed for Popen to work with your shell or platform.") return w9xpopen def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): if not isinstance(args, types.StringTypes): args = list2cmdline(args) if startupinfo is None: startupinfo = STARTUPINFO() if None not in (p2cread, c2pwrite, errwrite): startupinfo.dwFlags |= STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite if shell: startupinfo.dwFlags |= STARTF_USESHOWWINDOW startupinfo.wShowWindow = SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = comspec + " /c " + args if (GetVersion() >= 0x80000000L or os.path.basename(comspec).lower() == "command.com"): w9xpopen = self._find_w9xpopen() args = '"%s" %s' % (w9xpopen, args) creationflags |= CREATE_NEW_CONSOLE try: hp, ht, pid, tid = CreateProcess(executable, args, None, None, 1, creationflags, env, cwd, startupinfo) except pywintypes.error, e: raise WindowsError(*e.args) self._child_created = True self._handle = hp self.pid = pid ht.Close() if p2cread is not None: p2cread.Close() if c2pwrite is not None: c2pwrite.Close() if errwrite is not None: errwrite.Close() def poll(self, _deadstate=None): if self.returncode is None: if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: self.returncode = GetExitCodeProcess(self._handle) return self.returncode def wait(self): if self.returncode is None: obj = WaitForSingleObject(self._handle, INFINITE) self.returncode = GetExitCodeProcess(self._handle) return self.returncode def _readerthread(self, fh, buffer): buffer.append(fh.read()) def _communicate(self, input): stdout = None stderr = None if self.stdout: stdout = [] stdout_thread = threading.Thread(target=self._readerthread, args=(self.stdout, stdout)) stdout_thread.setDaemon(True) stdout_thread.start() if self.stderr: stderr = [] stderr_thread = threading.Thread(target=self._readerthread, args=(self.stderr, stderr)) stderr_thread.setDaemon(True) stderr_thread.start() if self.stdin: if input is not None: self.stdin.write(input) self.stdin.close() if self.stdout: stdout_thread.join() if self.stderr: stderr_thread.join() if stdout is not None: stdout = stdout[0] if stderr is not None: stderr = stderr[0] if self.universal_newlines and hasattr(file, 'newlines'): if stdout: stdout = self._translate_newlines(stdout) if stderr: stderr = self._translate_newlines(stderr) self.wait() return (stdout, stderr) else: def _get_handles(self, stdin, stdout, stderr): p2cread, p2cwrite = None, None c2pread, c2pwrite = None, None errread, errwrite = None, None if stdin is None: pass elif stdin == PIPE: p2cread, p2cwrite = os.pipe() elif isinstance(stdin, int): p2cread = stdin else: p2cread = stdin.fileno() if stdout is None: pass elif stdout == PIPE: c2pread, c2pwrite = os.pipe() elif isinstance(stdout, int): c2pwrite = stdout else: c2pwrite = stdout.fileno() if stderr is None: pass elif stderr == PIPE: errread, errwrite = os.pipe() elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): errwrite = stderr else: errwrite = stderr.fileno() return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) def _set_cloexec_flag(self, fd): try: cloexec_flag = fcntl.FD_CLOEXEC except AttributeError: cloexec_flag = 1 old = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) def _close_fds(self, but): for i in xrange(3, MAXFD): if i == but: continue try: os.close(i) except: pass def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): if isinstance(args, types.StringTypes): args = [args] else: args = list(args) if shell: args = ["/bin/sh", "-c"] + args if executable is None: executable = args[0] errpipe_read, errpipe_write = os.pipe() self._set_cloexec_flag(errpipe_write) gc_was_enabled = gc.isenabled() gc.disable() try: self.pid = os.fork() except: if gc_was_enabled: gc.enable() raise self._child_created = True if self.pid == 0: try: if p2cwrite: os.close(p2cwrite) if c2pread: os.close(c2pread) if errread: os.close(errread) os.close(errpipe_read) if p2cread: os.dup2(p2cread, 0) if c2pwrite: os.dup2(c2pwrite, 1) if errwrite: os.dup2(errwrite, 2) if p2cread and p2cread not in (0,): os.close(p2cread) if c2pwrite and c2pwrite not in (p2cread, 1): os.close(c2pwrite) if errwrite and errwrite not in (p2cread, c2pwrite, 2): os.close(errwrite) if close_fds: self._close_fds(but=errpipe_write) if cwd is not None: os.chdir(cwd) if preexec_fn: apply(preexec_fn) if env is None: os.execvp(executable, args) else: os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) os._exit(255) if gc_was_enabled: gc.enable() os.close(errpipe_write) if p2cread and p2cwrite: os.close(p2cread) if c2pwrite and c2pread: os.close(c2pwrite) if errwrite and errread: os.close(errwrite) data = os.read(errpipe_read, 1048576) os.close(errpipe_read) if data != "": os.waitpid(self.pid, 0) child_exception = pickle.loads(data) raise child_exception def _handle_exitstatus(self, sts): if os.WIFSIGNALED(sts): self.returncode = -os.WTERMSIG(sts) elif os.WIFEXITED(sts): self.returncode = os.WEXITSTATUS(sts) else: raise RuntimeError("Unknown child exit status!") def poll(self, _deadstate=None): if self.returncode is None: try: pid, sts = os.waitpid(self.pid, os.WNOHANG) if pid == self.pid: self._handle_exitstatus(sts) except os.error: if _deadstate is not None: self.returncode = _deadstate return self.returncode def wait(self): if self.returncode is None: pid, sts = os.waitpid(self.pid, 0) self._handle_exitstatus(sts) return self.returncode def _communicate(self, input): read_set = [] write_set = [] stdout = None stderr = None if self.stdin: self.stdin.flush() if input: write_set.append(self.stdin) else: self.stdin.close() if self.stdout: read_set.append(self.stdout) stdout = [] if self.stderr: read_set.append(self.stderr) stderr = [] input_offset = 0 while read_set or write_set: rlist, wlist, xlist = select.select(read_set, write_set, []) if self.stdin in wlist: bytes_written = os.write(self.stdin.fileno(), buffer(input, input_offset, 512)) input_offset += bytes_written if input_offset >= len(input): self.stdin.close() write_set.remove(self.stdin) if self.stdout in rlist: data = os.read(self.stdout.fileno(), 1024) if data == "": self.stdout.close() read_set.remove(self.stdout) stdout.append(data) if self.stderr in rlist: data = os.read(self.stderr.fileno(), 1024) if data == "": self.stderr.close() read_set.remove(self.stderr) stderr.append(data) if stdout is not None: stdout = ''.join(stdout) if stderr is not None: stderr = ''.join(stderr) if self.universal_newlines and hasattr(file, 'newlines'): if stdout: stdout = self._translate_newlines(stdout) if stderr: stderr = self._translate_newlines(stderr) self.wait() return (stdout, stderr) tevent-0.9.34/third_party/waf/wafadmin/py3kfixes.py0000660000000000000000000000744412520121120022236 0ustar rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2009 (ita) """ Fixes for py3k go here """ import os all_modifs = {} def modif(dir, name, fun): if name == '*': lst = [] for y in '. Tools 3rdparty'.split(): for x in os.listdir(os.path.join(dir, y)): if x.endswith('.py'): lst.append(y + os.sep + x) #lst = [y + os.sep + x for x in os.listdir(os.path.join(dir, y)) for y in '. Tools 3rdparty'.split() if x.endswith('.py')] for x in lst: modif(dir, x, fun) return filename = os.path.join(dir, name) f = open(filename, 'r') txt = f.read() f.close() txt = fun(txt) f = open(filename, 'w') f.write(txt) f.close() def subst(filename): def do_subst(fun): global all_modifs try: all_modifs[filename] += fun except KeyError: all_modifs[filename] = [fun] return fun return do_subst @subst('Constants.py') def r1(code): code = code.replace("'iluvcuteoverload'", "b'iluvcuteoverload'") code = code.replace("ABI=7", "ABI=37") return code @subst('Tools/ccroot.py') def r2(code): code = code.replace("p.stdin.write('\\n')", "p.stdin.write(b'\\n')") code = code.replace('p.communicate()[0]', 'p.communicate()[0].decode("utf-8")') return code @subst('Utils.py') def r3(code): code = code.replace("m.update(str(lst))", "m.update(str(lst).encode())") code = code.replace('p.communicate()[0]', 'p.communicate()[0].decode("utf-8")') return code @subst('ansiterm.py') def r33(code): code = code.replace('unicode', 'str') return code @subst('Task.py') def r4(code): code = code.replace("up(self.__class__.__name__)", "up(self.__class__.__name__.encode())") code = code.replace("up(self.env.variant())", "up(self.env.variant().encode())") code = code.replace("up(x.parent.abspath())", "up(x.parent.abspath().encode())") code = code.replace("up(x.name)", "up(x.name.encode())") code = code.replace('class TaskBase(object):\n\t__metaclass__=store_task_type', 'import binascii\n\nclass TaskBase(object, metaclass=store_task_type):') code = code.replace('keys=self.cstr_groups.keys()', 'keys=list(self.cstr_groups.keys())') code = code.replace("sig.encode('hex')", 'binascii.hexlify(sig)') code = code.replace("os.path.join(Options.cache_global,ssig)", "os.path.join(Options.cache_global,ssig.decode())") return code @subst('Build.py') def r5(code): code = code.replace("cPickle.dump(data,file,-1)", "cPickle.dump(data,file)") code = code.replace('for node in src_dir_node.childs.values():', 'for node in list(src_dir_node.childs.values()):') return code @subst('*') def r6(code): code = code.replace('xrange', 'range') code = code.replace('iteritems', 'items') code = code.replace('maxint', 'maxsize') code = code.replace('iterkeys', 'keys') code = code.replace('Error,e:', 'Error as e:') code = code.replace('Exception,e:', 'Exception as e:') return code @subst('TaskGen.py') def r7(code): code = code.replace('class task_gen(object):\n\t__metaclass__=register_obj', 'class task_gen(object, metaclass=register_obj):') return code @subst('Tools/python.py') def r8(code): code = code.replace('proc.communicate()[0]', 'proc.communicate()[0].decode("utf-8")') return code @subst('Tools/glib2.py') def r9(code): code = code.replace('f.write(c)', 'f.write(c.encode("utf-8"))') return code @subst('Tools/config_c.py') def r10(code): code = code.replace("key=kw['success']", "key=kw['success']\n\t\t\t\ttry:\n\t\t\t\t\tkey=key.decode('utf-8')\n\t\t\t\texcept:\n\t\t\t\t\tpass") code = code.replace('out=str(out)','out=out.decode("utf-8")') code = code.replace('err=str(err)','err=err.decode("utf-8")') return code @subst('Tools/d.py') def r11(code): code = code.replace('ret.strip()', 'ret.strip().decode("utf-8")') return code def fixdir(dir): global all_modifs for k in all_modifs: for v in all_modifs[k]: modif(os.path.join(dir, 'wafadmin'), k, v) #print('substitutions finished')