diff --git a/include/corosync/confdb.h b/include/corosync/confdb.h index ca0d7ba3..6879383d 100644 --- a/include/corosync/confdb.h +++ b/include/corosync/confdb.h @@ -1,348 +1,364 @@ /* - * Copyright (c) 2008-2010 Red Hat, Inc. + * Copyright (c) 2008-2012 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfi@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - 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. * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #ifndef COROSYNC_CONFDB_H_DEFINED #define COROSYNC_CONFDB_H_DEFINED #include #include #ifdef __cplusplus extern "C" { #endif /** * @addtogroup confdb_corosync * * @{ */ typedef uint64_t confdb_handle_t; #define OBJECT_PARENT_HANDLE 0xFFFFFFFF00000000ULL typedef enum { CONFDB_VALUETYPE_INT16, CONFDB_VALUETYPE_UINT16, CONFDB_VALUETYPE_INT32, CONFDB_VALUETYPE_UINT32, CONFDB_VALUETYPE_INT64, CONFDB_VALUETYPE_UINT64, CONFDB_VALUETYPE_FLOAT, CONFDB_VALUETYPE_DOUBLE, CONFDB_VALUETYPE_STRING, CONFDB_VALUETYPE_ANY, } confdb_value_types_t; typedef enum { CONFDB_TRACK_DEPTH_ONE, CONFDB_TRACK_DEPTH_RECURSIVE } confdb_track_depth_t; typedef enum { OBJECT_KEY_CREATED, OBJECT_KEY_REPLACED, OBJECT_KEY_DELETED, } confdb_change_type_t; typedef enum { CONFDB_RELOAD_NOTIFY_START, CONFDB_RELOAD_NOTIFY_END, CONFDB_RELOAD_NOTIFY_FAILED } confdb_reload_type_t; typedef void (*confdb_key_change_notify_fn_t) ( confdb_handle_t handle, confdb_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name, size_t object_name_len, const void *key_name, size_t key_name_len, const void *key_value, size_t key_value_len); typedef void (*confdb_object_create_notify_fn_t) ( confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len); typedef void (*confdb_object_delete_notify_fn_t) ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len); typedef void (*confdb_reload_notify_fn_t) ( confdb_handle_t handle, confdb_reload_type_t type); typedef struct { confdb_object_create_notify_fn_t confdb_object_create_change_notify_fn; confdb_object_delete_notify_fn_t confdb_object_delete_change_notify_fn; confdb_key_change_notify_fn_t confdb_key_change_notify_fn; confdb_reload_notify_fn_t confdb_reload_notify_fn; } confdb_callbacks_t; /** @} */ /* * Create a new confdb connection */ cs_error_t confdb_initialize ( confdb_handle_t *handle, confdb_callbacks_t *callbacks); /* * Close the confdb handle */ cs_error_t confdb_finalize ( confdb_handle_t handle); /* * Write back the configuration */ cs_error_t confdb_write ( confdb_handle_t handle, char *error_text, size_t errbuf_len); /* * Reload the configuration */ cs_error_t confdb_reload ( confdb_handle_t handle, int flush, char *error_text, size_t errbuf_len); /* * Get a file descriptor on which to poll. confdb_handle_t is NOT a * file descriptor and may not be used directly. */ cs_error_t confdb_fd_get ( confdb_handle_t handle, int *fd); /* * Dispatch configuration changes */ cs_error_t confdb_dispatch ( confdb_handle_t handle, cs_dispatch_flags_t dispatch_types); /* * Change notification */ cs_error_t confdb_track_changes ( confdb_handle_t handle, hdb_handle_t object_handle, unsigned int flags); cs_error_t confdb_stop_track_changes ( confdb_handle_t handle); /* * Manipulate objects */ cs_error_t confdb_object_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle); cs_error_t confdb_object_destroy ( confdb_handle_t handle, hdb_handle_t object_handle); cs_error_t confdb_object_parent_get ( confdb_handle_t handle, hdb_handle_t object_handle, hdb_handle_t *parent_object_handle); cs_error_t confdb_object_name_get ( confdb_handle_t handle, hdb_handle_t object_handle, char *object_name, size_t *object_name_len); /* * Manipulate keys */ cs_error_t confdb_key_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len); cs_error_t confdb_key_create_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, const void *value, size_t value_len, confdb_value_types_t type); cs_error_t confdb_key_delete ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len); /* * Key queries */ cs_error_t confdb_key_get ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, void *value, size_t *value_len); cs_error_t confdb_key_get_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, void *value, size_t *value_len, confdb_value_types_t *type); +cs_error_t confdb_key_get_typed2 ( + confdb_handle_t handle, + hdb_handle_t parent_object_handle, + const char *key_name, + void **value, + size_t *value_len, + confdb_value_types_t *type); + cs_error_t confdb_key_replace ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *old_value, size_t old_value_len, const void *new_value, size_t new_value_len); cs_error_t confdb_key_increment ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value); cs_error_t confdb_key_decrement ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value); /* * Object queries * "find" loops through all objects of a given name and is also * a quick way of finding a specific object, * "iter" returns each object in sequence. */ cs_error_t confdb_object_find_start ( confdb_handle_t handle, hdb_handle_t parent_object_handle); cs_error_t confdb_object_find ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle); cs_error_t confdb_object_find_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle); cs_error_t confdb_object_iter_start ( confdb_handle_t handle, hdb_handle_t parent_object_handle); cs_error_t confdb_object_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, void *object_name, size_t *object_name_len); cs_error_t confdb_object_iter_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle); /* * Key iterator */ cs_error_t confdb_key_iter_start ( confdb_handle_t handle, hdb_handle_t object_handle); cs_error_t confdb_key_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, void *key_name, size_t *key_name_len, void *value, size_t *value_len); cs_error_t confdb_key_iter_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, char *key_name, void *value, size_t *value_len, confdb_value_types_t *type); +cs_error_t confdb_key_iter_typed2 ( + confdb_handle_t handle, + hdb_handle_t parent_object_handle, + char *key_name, + void **value, + size_t *value_len, + confdb_value_types_t *type); + /* * Get/set context variable */ cs_error_t confdb_context_get ( confdb_handle_t handle, const void **context); cs_error_t confdb_context_set ( confdb_handle_t handle, const void *context); #ifdef __cplusplus } #endif #endif /* COROSYNC_CONFDB_H_DEFINED */ diff --git a/include/corosync/ipc_confdb.h b/include/corosync/ipc_confdb.h index 856c8a67..709c6770 100644 --- a/include/corosync/ipc_confdb.h +++ b/include/corosync/ipc_confdb.h @@ -1,278 +1,330 @@ /* - * Copyright (c) 2008-2010 Red Hat, Inc. + * Copyright (c) 2008-2012 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - 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. * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #ifndef IPC_CONFDB_H_DEFINED #define IPC_CONFDB_H_DEFINED #include #include #include enum req_confdb_types { MESSAGE_REQ_CONFDB_OBJECT_CREATE = 0, MESSAGE_REQ_CONFDB_OBJECT_DESTROY = 1, MESSAGE_REQ_CONFDB_OBJECT_FIND = 2, MESSAGE_REQ_CONFDB_KEY_CREATE = 3, MESSAGE_REQ_CONFDB_KEY_GET = 4, MESSAGE_REQ_CONFDB_KEY_REPLACE = 5, MESSAGE_REQ_CONFDB_KEY_DELETE = 6, MESSAGE_REQ_CONFDB_OBJECT_ITER = 7, MESSAGE_REQ_CONFDB_OBJECT_PARENT_GET = 8, MESSAGE_REQ_CONFDB_KEY_ITER = 9, MESSAGE_REQ_CONFDB_TRACK_START = 10, MESSAGE_REQ_CONFDB_TRACK_STOP = 11, MESSAGE_REQ_CONFDB_WRITE = 12, MESSAGE_REQ_CONFDB_RELOAD = 13, MESSAGE_REQ_CONFDB_OBJECT_FIND_DESTROY = 14, MESSAGE_REQ_CONFDB_KEY_INCREMENT = 15, MESSAGE_REQ_CONFDB_KEY_DECREMENT = 16, MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED = 17, MESSAGE_REQ_CONFDB_KEY_GET_TYPED = 18, MESSAGE_REQ_CONFDB_KEY_ITER_TYPED = 19, MESSAGE_REQ_CONFDB_OBJECT_NAME_GET = 20, + MESSAGE_REQ_CONFDB_KEY_ITER_TYPED2 = 21, + MESSAGE_REQ_CONFDB_KEY_REPLACE2 = 22, + MESSAGE_REQ_CONFDB_KEY_GET_TYPED2 = 23, + MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED2 = 24, }; enum res_confdb_types { MESSAGE_RES_CONFDB_OBJECT_CREATE = 0, MESSAGE_RES_CONFDB_OBJECT_DESTROY = 1, MESSAGE_RES_CONFDB_OBJECT_FIND = 2, MESSAGE_RES_CONFDB_KEY_CREATE = 3, MESSAGE_RES_CONFDB_KEY_GET = 4, MESSAGE_RES_CONFDB_KEY_REPLACE = 5, MESSAGE_RES_CONFDB_KEY_DELETE = 6, MESSAGE_RES_CONFDB_OBJECT_ITER = 7, MESSAGE_RES_CONFDB_OBJECT_PARENT_GET = 8, MESSAGE_RES_CONFDB_KEY_ITER = 9, MESSAGE_RES_CONFDB_TRACK_START = 10, MESSAGE_RES_CONFDB_TRACK_STOP = 11, MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK = 12, MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK = 13, MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK = 14, MESSAGE_RES_CONFDB_WRITE = 15, MESSAGE_RES_CONFDB_RELOAD = 16, MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY = 17, MESSAGE_RES_CONFDB_KEY_INCREMENT = 18, MESSAGE_RES_CONFDB_KEY_DECREMENT = 19, MESSAGE_RES_CONFDB_KEY_GET_TYPED = 20, MESSAGE_RES_CONFDB_KEY_ITER_TYPED = 21, MESSAGE_RES_CONFDB_RELOAD_CALLBACK = 22, MESSAGE_RES_CONFDB_OBJECT_NAME_GET = 23, + MESSAGE_RES_CONFDB_KEY_ITER_TYPED2 = 24, + MESSAGE_RES_CONFDB_KEY_GET_TYPED2 = 25, + MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK2 = 26, }; struct req_lib_confdb_object_create { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_name_t object_name __attribute__((aligned(8))); }; struct res_lib_confdb_object_create { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); }; struct req_lib_confdb_object_destroy { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); }; struct req_lib_confdb_object_parent_get { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); }; struct res_lib_confdb_object_parent_get { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); }; struct req_lib_confdb_object_name_get { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); }; struct res_lib_confdb_object_name_get { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t object_name __attribute__((aligned(8))); }; struct req_lib_confdb_key_create { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); mar_name_t value __attribute__((aligned(8))); }; struct req_lib_confdb_key_create_typed { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); mar_name_t value __attribute__((aligned(8))); mar_int32_t type __attribute__((aligned(8))); }; +struct req_lib_confdb_key_create_typed2 { + coroipc_request_header_t header __attribute__((aligned(8))); + mar_uint64_t object_handle __attribute__((aligned(8))); + mar_name_t key_name __attribute__((aligned(8))); + mar_int32_t type __attribute__((aligned(8))); + mar_int32_t value_length __attribute__((aligned(8))); + mar_uint8_t value __attribute__((aligned(8))); /* First byte of value */ +}; + struct req_lib_confdb_key_delete { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); mar_name_t value __attribute__((aligned(8))); }; struct req_lib_confdb_key_replace { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); mar_name_t old_value __attribute__((aligned(8))); mar_name_t new_value __attribute__((aligned(8))); }; struct req_lib_confdb_object_find { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_name_t object_name __attribute__((aligned(8))); mar_uint64_t find_handle __attribute__((aligned(8))); }; struct res_lib_confdb_object_find { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_uint64_t find_handle __attribute__((aligned(8))); }; struct req_lib_confdb_object_iter { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_uint64_t find_handle __attribute__((aligned(8))); }; struct res_lib_confdb_object_iter { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t object_name __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_uint64_t find_handle __attribute__((aligned(8))); }; struct req_lib_confdb_key_iter { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_uint64_t next_entry __attribute__((aligned(8))); }; struct res_lib_confdb_key_iter { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); mar_name_t value __attribute__((aligned(8))); }; struct res_lib_confdb_key_iter_typed { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); mar_name_t value __attribute__((aligned(8))); mar_int32_t type __attribute__((aligned(8))); }; struct req_lib_confdb_key_get { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); }; struct req_lib_confdb_object_find_destroy { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t find_handle __attribute__((aligned(8))); }; struct res_lib_confdb_key_get { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t value __attribute__((aligned(8))); }; struct res_lib_confdb_key_get_typed { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t value __attribute__((aligned(8))); mar_int32_t type __attribute__((aligned(8))); }; struct res_lib_confdb_key_incdec { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint32_t value __attribute__((aligned(8))); }; struct res_lib_confdb_write { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t error __attribute__((aligned(8))); }; struct req_lib_confdb_reload { coroipc_response_header_t header __attribute__((aligned(8))); mar_int32_t flush __attribute__((aligned(8))); }; struct res_lib_confdb_reload { coroipc_response_header_t header __attribute__((aligned(8))); mar_name_t error __attribute__((aligned(8))); }; struct res_lib_confdb_key_change_callback { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint64_t change_type __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_name_t object_name __attribute__((aligned(8))); mar_name_t key_name __attribute__((aligned(8))); mar_name_t key_value __attribute__((aligned(8))); }; +struct res_lib_confdb_key_change_callback2 { + coroipc_response_header_t header __attribute__((aligned(8))); + mar_uint64_t change_type __attribute__((aligned(8))); + mar_uint64_t parent_object_handle __attribute__((aligned(8))); + mar_uint64_t object_handle __attribute__((aligned(8))); + mar_name_t object_name __attribute__((aligned(8))); + mar_name_t key_name __attribute__((aligned(8))); + mar_uint32_t key_value_length __attribute__((aligned(8))); + mar_uint8_t key_value __attribute__((aligned(8))); /* First byte of new value */ +}; + struct res_lib_confdb_object_create_callback { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_name_t name __attribute__((aligned(8))); }; struct res_lib_confdb_object_destroy_callback { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint64_t parent_object_handle __attribute__((aligned(8))); mar_name_t name __attribute__((aligned(8))); }; struct res_lib_confdb_reload_callback { coroipc_response_header_t header __attribute__((aligned(8))); mar_uint32_t type __attribute__((aligned(8))); }; struct req_lib_confdb_object_track_start { coroipc_request_header_t header __attribute__((aligned(8))); mar_uint64_t object_handle __attribute__((aligned(8))); mar_uint32_t flags __attribute__((aligned(8))); }; +struct res_lib_confdb_key_get_typed2 { + coroipc_response_header_t header __attribute__((aligned(8))); + mar_int32_t type __attribute__((aligned(8))); + mar_uint32_t value_length __attribute__((aligned(8))); + mar_uint8_t value __attribute__((aligned(8))); + // Actual value follows this +}; + +struct res_lib_confdb_key_iter_typed2 { + coroipc_response_header_t header __attribute__((aligned(8))); + mar_name_t key_name __attribute__((aligned(8))); + mar_int32_t type __attribute__((aligned(8))); + mar_int32_t value_length __attribute__((aligned(8))); + mar_uint8_t value __attribute__((aligned(8))); /* First byte of value */ +}; + +struct req_lib_confdb_key_replace2 { + coroipc_request_header_t header __attribute__((aligned(8))); + mar_uint64_t object_handle __attribute__((aligned(8))); + mar_name_t key_name __attribute__((aligned(8))); + mar_int32_t new_value_length __attribute__((aligned(8))); + mar_uint8_t new_value __attribute__((aligned(8))); /* First byte of new value */ + /* Oddly objdb doesn't use the old value, so we don't bother sending it */ +}; + #endif /* IPC_CONFDB_H_DEFINED */ diff --git a/lib/confdb.c b/lib/confdb.c index 1ea2ed0b..0dbecb96 100644 --- a/lib/confdb.c +++ b/lib/confdb.c @@ -1,1814 +1,1994 @@ /* - * Copyright (c) 2008-2010 Red Hat, Inc. + * Copyright (c) 2008-2012 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - 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. * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ /* * Provides access to data in the corosync object database */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "sa-confdb.h" #undef MIN #define MIN(x,y) ((x) < (y) ? (x) : (y)) /* Hold the information for iterators so that callers can do recursive tree traversals. each object_handle can have its own iterator */ struct iter_context { struct list_head list; hdb_handle_t parent_object_handle; hdb_handle_t find_handle; hdb_handle_t next_entry; }; struct confdb_inst { hdb_handle_t handle; int finalize; int standalone; confdb_callbacks_t callbacks; const void *context; struct list_head object_find_head; struct list_head object_iter_head; struct list_head key_iter_head; }; DECLARE_HDB_DATABASE(confdb_handle_t_db,NULL); static cs_error_t do_find_destroy(struct confdb_inst *confdb_inst, hdb_handle_t find_handle); /* Safely tidy one iterator context list */ static void free_context_list(struct confdb_inst *confdb_inst, struct list_head *list) { struct iter_context *context; struct list_head *iter, *tmp; for (iter = list->next, tmp = iter->next; iter != list; iter = tmp, tmp = iter->next) { context = list_entry (iter, struct iter_context, list); (void)do_find_destroy(confdb_inst, context->find_handle); free(context); } } static struct iter_context *find_iter_context(struct list_head *list, hdb_handle_t object_handle) { struct iter_context *context; struct list_head *iter; for (iter = list->next; iter != list; iter = iter->next) { context = list_entry (iter, struct iter_context, list); if (context->parent_object_handle == object_handle) return context; } return NULL; } /** * @defgroup confdb_corosync * @ingroup corosync * * @{ */ cs_error_t confdb_initialize ( confdb_handle_t *handle, confdb_callbacks_t *callbacks) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_create (&confdb_handle_t_db, sizeof (struct confdb_inst), handle)); if (error != CS_OK) { goto error_no_destroy; } error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, *handle, (void *)&confdb_inst)); if (error != CS_OK) { goto error_destroy; } if (getenv("COROSYNC_DEFAULT_CONFIG_IFACE")) { error = confdb_sa_init(); confdb_inst->standalone = 1; } else { error = coroipcc_service_connect ( COROSYNC_SOCKET_NAME, CONFDB_SERVICE, IPC_REQUEST_SIZE, IPC_RESPONSE_SIZE, IPC_DISPATCH_SIZE, &confdb_inst->handle); } if (error != CS_OK) goto error_put_destroy; if (callbacks) { memcpy (&confdb_inst->callbacks, callbacks, sizeof (confdb_callbacks_t)); } list_init (&confdb_inst->object_find_head); list_init (&confdb_inst->object_iter_head); list_init (&confdb_inst->key_iter_head); (void)hdb_handle_put (&confdb_handle_t_db, *handle); return (CS_OK); error_put_destroy: (void)hdb_handle_put (&confdb_handle_t_db, *handle); error_destroy: (void)hdb_handle_destroy (&confdb_handle_t_db, *handle); error_no_destroy: return (error); } cs_error_t confdb_finalize ( confdb_handle_t handle) { struct confdb_inst *confdb_inst; cs_error_t error; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* * Another thread has already started finalizing */ if (confdb_inst->finalize) { (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_ERR_BAD_HANDLE); } confdb_inst->finalize = 1; /* Free saved context handles */ free_context_list(confdb_inst, &confdb_inst->object_find_head); free_context_list(confdb_inst, &confdb_inst->object_iter_head); free_context_list(confdb_inst, &confdb_inst->key_iter_head); if (!confdb_inst->standalone) { coroipcc_service_disconnect (confdb_inst->handle); } (void)hdb_handle_destroy (&confdb_handle_t_db, handle); (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_fd_get ( confdb_handle_t handle, int *fd) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } error = coroipcc_fd_get (confdb_inst->handle, fd); (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_context_get ( confdb_handle_t handle, const void **context) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } *context = confdb_inst->context; (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_context_set ( confdb_handle_t handle, const void *context) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } confdb_inst->context = context; (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_dispatch ( confdb_handle_t handle, cs_dispatch_flags_t dispatch_types) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ struct confdb_inst *confdb_inst; confdb_callbacks_t callbacks; struct res_lib_confdb_key_change_callback *res_key_changed_pt; struct res_lib_confdb_object_create_callback *res_object_created_pt; struct res_lib_confdb_object_destroy_callback *res_object_destroyed_pt; struct res_lib_confdb_reload_callback *res_reload_pt; coroipc_response_header_t *dispatch_data; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_put; } /* * Timeout instantly for CS_DISPATCH_ONE or CS_DISPATCH_ALL and * wait indefinitely for CS_DISPATCH_BLOCKING */ if (dispatch_types == CONFDB_DISPATCH_ALL) { timeout = 0; } do { error = coroipcc_dispatch_get ( confdb_inst->handle, (void **)&dispatch_data, timeout); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { error = CS_OK; if (dispatch_types == CONFDB_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that confdbFinalize has been called. */ memcpy (&callbacks, &confdb_inst->callbacks, sizeof (confdb_callbacks_t)); /* * Dispatch incoming message */ switch (dispatch_data->id) { case MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK: if (callbacks.confdb_key_change_notify_fn == NULL) { break; } res_key_changed_pt = (struct res_lib_confdb_key_change_callback *)dispatch_data; callbacks.confdb_key_change_notify_fn(handle, res_key_changed_pt->change_type, res_key_changed_pt->object_handle, res_key_changed_pt->parent_object_handle, res_key_changed_pt->object_name.value, res_key_changed_pt->object_name.length, res_key_changed_pt->key_name.value, res_key_changed_pt->key_name.length, res_key_changed_pt->key_value.value, res_key_changed_pt->key_value.length); break; + case MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK2: + if (callbacks.confdb_key_change_notify_fn == NULL) { + break; + } + + res_key_changed_pt = (struct res_lib_confdb_key_change_callback *)dispatch_data; + + callbacks.confdb_key_change_notify_fn(handle, + res_key_changed_pt->change_type, + res_key_changed_pt->object_handle, + res_key_changed_pt->parent_object_handle, + res_key_changed_pt->object_name.value, + res_key_changed_pt->object_name.length, + res_key_changed_pt->key_name.value, + res_key_changed_pt->key_name.length, + &res_key_changed_pt->key_value.value, + res_key_changed_pt->key_value.length); + break; + case MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK: if (callbacks.confdb_object_create_change_notify_fn == NULL) { break; } res_object_created_pt = (struct res_lib_confdb_object_create_callback *)dispatch_data; callbacks.confdb_object_create_change_notify_fn(handle, res_object_created_pt->object_handle, res_object_created_pt->parent_object_handle, res_object_created_pt->name.value, res_object_created_pt->name.length); break; case MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK: if (callbacks.confdb_object_delete_change_notify_fn == NULL) { break; } res_object_destroyed_pt = (struct res_lib_confdb_object_destroy_callback *)dispatch_data; callbacks.confdb_object_delete_change_notify_fn(handle, res_object_destroyed_pt->parent_object_handle, res_object_destroyed_pt->name.value, res_object_destroyed_pt->name.length); break; case MESSAGE_RES_CONFDB_RELOAD_CALLBACK: if (callbacks.confdb_reload_notify_fn == NULL) { continue; } res_reload_pt = (struct res_lib_confdb_reload_callback *)dispatch_data; callbacks.confdb_reload_notify_fn(handle, res_reload_pt->type); break; default: coroipcc_dispatch_put (confdb_inst->handle); error = CS_ERR_LIBRARY; goto error_noput; break; } coroipcc_dispatch_put (confdb_inst->handle); /* * Determine if more messages should be processed */ if (dispatch_types == CS_DISPATCH_ONE) { cont = 0; } } while (cont); error_put: (void)hdb_handle_put (&confdb_handle_t_db, handle); error_noput: return (error); } cs_error_t confdb_object_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_create req_lib_confdb_object_create; struct res_lib_confdb_object_create res_lib_confdb_object_create; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_create(parent_object_handle, object_name, object_name_len, object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_create.header.size = sizeof (struct req_lib_confdb_object_create); req_lib_confdb_object_create.header.id = MESSAGE_REQ_CONFDB_OBJECT_CREATE; req_lib_confdb_object_create.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_object_create.object_name.value, object_name, object_name_len); req_lib_confdb_object_create.object_name.length = object_name_len; iov.iov_base = (char *)&req_lib_confdb_object_create; iov.iov_len = sizeof (struct req_lib_confdb_object_create); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_create, sizeof (struct res_lib_confdb_object_create)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_create.header.error; *object_handle = res_lib_confdb_object_create.object_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_destroy ( confdb_handle_t handle, hdb_handle_t object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_destroy req_lib_confdb_object_destroy; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_destroy(object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_destroy.header.size = sizeof (struct req_lib_confdb_object_destroy); req_lib_confdb_object_destroy.header.id = MESSAGE_REQ_CONFDB_OBJECT_DESTROY; req_lib_confdb_object_destroy.object_handle = object_handle; iov.iov_base = (char *)&req_lib_confdb_object_destroy; iov.iov_len = sizeof (struct req_lib_confdb_object_destroy); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_parent_get ( confdb_handle_t handle, hdb_handle_t object_handle, hdb_handle_t *parent_object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_parent_get req_lib_confdb_object_parent_get; struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_parent_get(object_handle, parent_object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_parent_get.header.size = sizeof (struct req_lib_confdb_object_parent_get); req_lib_confdb_object_parent_get.header.id = MESSAGE_REQ_CONFDB_OBJECT_PARENT_GET; req_lib_confdb_object_parent_get.object_handle = object_handle; iov.iov_base = (char *)&req_lib_confdb_object_parent_get; iov.iov_len = sizeof (struct req_lib_confdb_object_parent_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_parent_get, sizeof (struct res_lib_confdb_object_parent_get)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_parent_get.header.error; *parent_object_handle = res_lib_confdb_object_parent_get.parent_object_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_name_get ( confdb_handle_t handle, hdb_handle_t object_handle, char *object_name, size_t *object_name_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_name_get request; struct res_lib_confdb_object_name_get response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_name_get(object_handle, object_name, object_name_len)) error = CS_ERR_ACCESS; goto error_exit; } request.header.size = sizeof (struct req_lib_confdb_object_name_get); request.header.id = MESSAGE_REQ_CONFDB_OBJECT_NAME_GET; request.object_handle = object_handle; iov.iov_base = (char *)&request; iov.iov_len = sizeof (struct req_lib_confdb_object_name_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &response, sizeof (struct res_lib_confdb_object_name_get)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { *object_name_len = response.object_name.length; memcpy(object_name, response.object_name.value, *object_name_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } static cs_error_t do_find_destroy( struct confdb_inst *confdb_inst, hdb_handle_t find_handle) { cs_error_t error; struct iovec iov; struct req_lib_confdb_object_find_destroy req_lib_confdb_object_find_destroy; coroipc_response_header_t res; if (!find_handle) return CS_OK; if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_find_destroy(find_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_find_destroy.header.size = sizeof (struct req_lib_confdb_object_find_destroy); req_lib_confdb_object_find_destroy.header.id = MESSAGE_REQ_CONFDB_OBJECT_FIND_DESTROY; req_lib_confdb_object_find_destroy.find_handle = find_handle; iov.iov_base = (char *)&req_lib_confdb_object_find_destroy; iov.iov_len = sizeof (struct req_lib_confdb_object_find_destroy); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: return (error); } cs_error_t confdb_object_find_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct iter_context *context; cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); error = do_find_destroy(confdb_inst, context->find_handle); if (error == CS_OK) { list_del(&context->list); free(context); } (void)hdb_handle_put (&confdb_handle_t_db, handle); return error; } cs_error_t confdb_object_iter_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct iter_context *context; cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle); error = do_find_destroy(confdb_inst, context->find_handle); if (error == CS_OK) { list_del(&context->list); free(context); } (void)hdb_handle_put (&confdb_handle_t_db, handle); return error; } cs_error_t confdb_key_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_create req_lib_confdb_key_create; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_create(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_create.header.size = sizeof (struct req_lib_confdb_key_create); req_lib_confdb_key_create.header.id = MESSAGE_REQ_CONFDB_KEY_CREATE; req_lib_confdb_key_create.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_create.key_name.value, key_name, key_name_len); req_lib_confdb_key_create.key_name.length = key_name_len; memcpy(req_lib_confdb_key_create.value.value, value, value_len); req_lib_confdb_key_create.value.length = value_len; iov.iov_base = (char *)&req_lib_confdb_key_create; iov.iov_len = sizeof (struct req_lib_confdb_key_create); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_create_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, const void *value, size_t value_len, confdb_value_types_t type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; - struct req_lib_confdb_key_create_typed request; + struct req_lib_confdb_key_create_typed2 *request; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_create_typed(parent_object_handle, key_name, value, value_len, type)) error = CS_ERR_ACCESS; goto error_exit; } - request.header.size = sizeof (struct req_lib_confdb_key_create_typed); - request.header.id = MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED; - request.object_handle = parent_object_handle; - request.key_name.length = strlen(key_name)+1; - memcpy(request.key_name.value, key_name, request.key_name.length); - memcpy(request.value.value, value, value_len); - request.value.length = value_len; - request.type = type; + request = malloc(sizeof(struct req_lib_confdb_key_create_typed2)+value_len); + if (!request) { + error = CS_ERR_NO_MEMORY; + goto error_exit; + } - iov.iov_base = (char *)&request; - iov.iov_len = sizeof (struct req_lib_confdb_key_create_typed); + request->header.size = sizeof (struct req_lib_confdb_key_create_typed2) + value_len; + request->header.id = MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED2; + request->object_handle = parent_object_handle; + request->key_name.length = strlen(key_name)+1; + memcpy(request->key_name.value, key_name, request->key_name.length); + memcpy(&request->value, value, value_len); + request->value_length = value_len; + request->type = type; + + iov.iov_base = (char *)request; + iov.iov_len = request->header.size; error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_delete ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_delete req_lib_confdb_key_delete; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_delete(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_delete.header.size = sizeof (struct req_lib_confdb_key_delete); req_lib_confdb_key_delete.header.id = MESSAGE_REQ_CONFDB_KEY_DELETE; req_lib_confdb_key_delete.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_delete.key_name.value, key_name, key_name_len); req_lib_confdb_key_delete.key_name.length = key_name_len; memcpy(req_lib_confdb_key_delete.value.value, value, value_len); req_lib_confdb_key_delete.value.length = value_len; iov.iov_base = (char *)&req_lib_confdb_key_delete; iov.iov_len = sizeof (struct req_lib_confdb_key_delete); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_get ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, void *value, size_t *value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_get res_lib_confdb_key_get; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_get(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_get, sizeof (struct res_lib_confdb_key_get)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_get.header.error; if (error == CS_OK) { *value_len = res_lib_confdb_key_get.value.length; memcpy(value, res_lib_confdb_key_get.value.value, *value_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_get_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, void *value, size_t *value_len, confdb_value_types_t *type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_get_typed response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_get_typed(parent_object_handle, - key_name, value, value_len, (int*)type)) + key_name, &value, value_len, (int*)type)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET_TYPED; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; req_lib_confdb_key_get.key_name.length = strlen(key_name) + 1; memcpy(req_lib_confdb_key_get.key_name.value, key_name, req_lib_confdb_key_get.key_name.length); iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &response, sizeof (struct res_lib_confdb_key_get_typed)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { *value_len = response.value.length; *type = response.type; memcpy(value, response.value.value, *value_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } +cs_error_t confdb_key_get_typed2 ( + confdb_handle_t handle, + hdb_handle_t parent_object_handle, + const char *key_name, + void **value, + size_t *value_len, + confdb_value_types_t *type) +{ + cs_error_t error; + struct confdb_inst *confdb_inst; + struct iovec iov; + struct req_lib_confdb_key_get req_lib_confdb_key_get; + struct res_lib_confdb_key_get_typed2 *response; + void *return_address; + + error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); + if (error != CS_OK) { + return (error); + } + + if (confdb_inst->standalone) { + error = CS_OK; + + if (confdb_sa_key_get_typed(parent_object_handle, + key_name, value, value_len, (int*)type)) + error = CS_ERR_ACCESS; + goto error_exit; + } + + req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); + req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET_TYPED2; + req_lib_confdb_key_get.parent_object_handle = parent_object_handle; + req_lib_confdb_key_get.key_name.length = strlen(key_name) + 1; + memcpy(req_lib_confdb_key_get.key_name.value, key_name, req_lib_confdb_key_get.key_name.length); + + iov.iov_base = (char *)&req_lib_confdb_key_get; + iov.iov_len = sizeof (struct req_lib_confdb_key_get); + + error = coroipcc_msg_send_reply_receive_in_buf_get ( + confdb_inst->handle, + &iov, + 1, + &return_address); + response = return_address; + + if (error != CS_OK) { + goto error_exit; + } + error = response->header.error; + + if (error == CS_OK) { + if (!*value) { + /* Allow space for naughty callers to put a NUL for printing */ + *value = malloc(response->value_length+1); + if (!*value) { + error = CS_ERR_NO_MEMORY; + goto error_exit; + } + } + memcpy(*value, &response->value, response->value_length); + *value_len = response->value_length; + *type = response->type; + } + +error_exit: + (void)hdb_handle_put (&confdb_handle_t_db, handle); + + return (error); + +} + cs_error_t confdb_key_increment ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_increment(parent_object_handle, key_name, key_name_len, value)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_INCREMENT; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_incdec.header.error; if (error == CS_OK) { *value = res_lib_confdb_key_incdec.value; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_decrement ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_decrement(parent_object_handle, key_name, key_name_len, value)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_DECREMENT; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_incdec.header.error; if (error == CS_OK) { *value = res_lib_confdb_key_incdec.value; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_replace ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *old_value, size_t old_value_len, const void *new_value, size_t new_value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; - struct req_lib_confdb_key_replace req_lib_confdb_key_replace; + struct req_lib_confdb_key_replace2 *req_lib_confdb_key_replace; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_replace(parent_object_handle, key_name, key_name_len, old_value, old_value_len, new_value, new_value_len)) error = CS_ERR_ACCESS; goto error_exit; } - req_lib_confdb_key_replace.header.size = sizeof (struct req_lib_confdb_key_replace); - req_lib_confdb_key_replace.header.id = MESSAGE_REQ_CONFDB_KEY_REPLACE; - req_lib_confdb_key_replace.object_handle = parent_object_handle; - memcpy(req_lib_confdb_key_replace.key_name.value, key_name, key_name_len); - req_lib_confdb_key_replace.key_name.length = key_name_len; - memcpy(req_lib_confdb_key_replace.old_value.value, old_value, old_value_len); - req_lib_confdb_key_replace.old_value.length = old_value_len; - memcpy(req_lib_confdb_key_replace.new_value.value, new_value, new_value_len); - req_lib_confdb_key_replace.new_value.length = new_value_len; - iov.iov_base = (char *)&req_lib_confdb_key_replace; - iov.iov_len = sizeof (struct req_lib_confdb_key_replace); + req_lib_confdb_key_replace = malloc(sizeof(struct req_lib_confdb_key_replace2) + new_value_len); + + req_lib_confdb_key_replace->header.size = sizeof(struct req_lib_confdb_key_replace2) + new_value_len; + req_lib_confdb_key_replace->header.id = MESSAGE_REQ_CONFDB_KEY_REPLACE2; + req_lib_confdb_key_replace->object_handle = parent_object_handle; + memcpy(req_lib_confdb_key_replace->key_name.value, key_name, key_name_len); + req_lib_confdb_key_replace->key_name.length = key_name_len; + memcpy(&req_lib_confdb_key_replace->new_value, new_value, new_value_len); + req_lib_confdb_key_replace->new_value_length = new_value_len; + /* Oddly objdb doesn't use the old value, so we don't bother sending it */ + iov.iov_base = (char *)req_lib_confdb_key_replace; + iov.iov_len = sizeof(struct req_lib_confdb_key_replace2) + new_value_len; error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_iter_start ( confdb_handle_t handle, hdb_handle_t object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_iter_head, object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->parent_object_handle = object_handle; context->find_handle = 0; list_add(&context->list, &confdb_inst->object_iter_head); } /* Start a new find context */ if (context->find_handle) { (void)do_find_destroy(confdb_inst, context->find_handle); context->find_handle = 0; } (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_key_iter_start ( confdb_handle_t handle, hdb_handle_t object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->key_iter_head, object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->parent_object_handle = object_handle; list_add(&context->list, &confdb_inst->key_iter_head); } context->find_handle = 0; context->next_entry = 0; (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_object_find_start ( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->find_handle = 0; context->parent_object_handle = parent_object_handle; list_add(&context->list, &confdb_inst->object_find_head); } /* Start a new find context */ if (context->find_handle) { (void)do_find_destroy(confdb_inst, context->find_handle); context->find_handle = 0; } (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_object_find ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_object_find req_lib_confdb_object_find; struct res_lib_confdb_object_find res_lib_confdb_object_find; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_object_find_start first */ context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_find(parent_object_handle, &context->find_handle, object_handle, object_name, object_name_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_find.header.size = sizeof (struct req_lib_confdb_object_find); req_lib_confdb_object_find.header.id = MESSAGE_REQ_CONFDB_OBJECT_FIND; req_lib_confdb_object_find.parent_object_handle = parent_object_handle; req_lib_confdb_object_find.find_handle = context->find_handle; memcpy(req_lib_confdb_object_find.object_name.value, object_name, object_name_len); req_lib_confdb_object_find.object_name.length = object_name_len; iov.iov_base = (char *)&req_lib_confdb_object_find; iov.iov_len = sizeof (struct req_lib_confdb_object_find); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_find, sizeof (struct res_lib_confdb_object_find)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_find.header.error; *object_handle = res_lib_confdb_object_find.object_handle; context->find_handle = res_lib_confdb_object_find.find_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, void *object_name, size_t *object_name_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_object_iter req_lib_confdb_object_iter; struct res_lib_confdb_object_iter res_lib_confdb_object_iter; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_object_iter_start first */ context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; *object_name_len = 0; if (confdb_sa_object_iter(parent_object_handle, &context->find_handle, object_handle, NULL, 0, object_name, object_name_len)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_object_iter.header.size = sizeof (struct req_lib_confdb_object_iter); req_lib_confdb_object_iter.header.id = MESSAGE_REQ_CONFDB_OBJECT_ITER; req_lib_confdb_object_iter.parent_object_handle = parent_object_handle; req_lib_confdb_object_iter.find_handle = context->find_handle; iov.iov_base = (char *)&req_lib_confdb_object_iter; iov.iov_len = sizeof (struct req_lib_confdb_object_iter); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_iter, sizeof (struct res_lib_confdb_object_iter)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_iter.header.error; if (error == CS_OK) { *object_name_len = res_lib_confdb_object_iter.object_name.length; memcpy(object_name, res_lib_confdb_object_iter.object_name.value, *object_name_len); *object_handle = res_lib_confdb_object_iter.object_handle; context->find_handle = res_lib_confdb_object_iter.find_handle; } sa_exit: error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, void *key_name, size_t *key_name_len, void *value, size_t *value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_key_iter req_lib_confdb_key_iter; struct res_lib_confdb_key_iter res_lib_confdb_key_iter; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_key_iter_start first */ context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_iter(parent_object_handle, context->next_entry, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter); req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER; req_lib_confdb_key_iter.parent_object_handle = parent_object_handle; req_lib_confdb_key_iter.next_entry= context->next_entry; iov.iov_base = (char *)&req_lib_confdb_key_iter; iov.iov_len = sizeof (struct req_lib_confdb_key_iter); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_iter, sizeof (struct res_lib_confdb_key_iter)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_iter.header.error; if (error == CS_OK) { char* key_name_str = (char*)key_name; *key_name_len = res_lib_confdb_key_iter.key_name.length; memcpy(key_name, res_lib_confdb_key_iter.key_name.value, *key_name_len); key_name_str[res_lib_confdb_key_iter.key_name.length] = '\0'; *value_len = res_lib_confdb_key_iter.value.length; memcpy(value, res_lib_confdb_key_iter.value.value, *value_len); } sa_exit: context->next_entry++; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_iter_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, char *key_name, void *value, size_t *value_len, confdb_value_types_t *type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_key_iter req_lib_confdb_key_iter; struct res_lib_confdb_key_iter_typed response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_key_iter_start first */ context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_iter_typed(parent_object_handle, context->next_entry, key_name, - value, value_len, (int*)type)) + &value, value_len, (int*)type)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter); req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER_TYPED; req_lib_confdb_key_iter.parent_object_handle = parent_object_handle; req_lib_confdb_key_iter.next_entry= context->next_entry; iov.iov_base = (char *)&req_lib_confdb_key_iter; iov.iov_len = sizeof (struct req_lib_confdb_key_iter); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &response, sizeof (struct res_lib_confdb_key_iter_typed)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { memcpy(key_name, response.key_name.value, response.key_name.length); key_name[response.key_name.length] = '\0'; *value_len = response.value.length; memcpy(value, response.value.value, *value_len); *type = response.type; } sa_exit: context->next_entry++; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } +cs_error_t confdb_key_iter_typed2 ( + confdb_handle_t handle, + hdb_handle_t parent_object_handle, + char *key_name, + void **value, + size_t *value_len, + confdb_value_types_t *type) +{ + cs_error_t error; + struct confdb_inst *confdb_inst; + struct iovec iov; + struct iter_context *context; + struct req_lib_confdb_key_iter req_lib_confdb_key_iter; + struct res_lib_confdb_key_iter_typed2 *response; + void *return_address; + + error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); + if (error != CS_OK) { + return (error); + } + + /* You MUST call confdb_key_iter_start first */ + context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle); + if (!context) { + error = CS_ERR_CONTEXT_NOT_FOUND; + goto error_exit; + } + + if (confdb_inst->standalone) { + error = CS_OK; + if (confdb_sa_key_iter_typed(parent_object_handle, + context->next_entry, + key_name, + value, value_len, (int*)type)) + error = CS_ERR_ACCESS; + goto sa_exit; + } + + req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter); + req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER_TYPED2; + req_lib_confdb_key_iter.parent_object_handle = parent_object_handle; + req_lib_confdb_key_iter.next_entry= context->next_entry; + + iov.iov_base = (char *)&req_lib_confdb_key_iter; + iov.iov_len = sizeof (struct req_lib_confdb_key_iter); + + error = coroipcc_msg_send_reply_receive_in_buf_get ( + confdb_inst->handle, + &iov, + 1, + &return_address); + response = return_address; + + if (error != CS_OK) { + goto error_exit; + } + error = response->header.error; + + if (error == CS_OK) { + if (!*value) { + /* Allow space for naughty callers to put a NUL for printing */ + *value = malloc(response->value_length+1); + if (!*value) { + error = CS_ERR_NO_MEMORY; + goto error_exit; + } + } + memcpy(key_name, response->key_name.value, response->key_name.length); + key_name[response->key_name.length] = '\0'; + memcpy(*value, &response->value, response->value_length); + *value_len = response->value_length; + *type = response->type; + } + +sa_exit: + context->next_entry++; + +error_exit: + (void)hdb_handle_put (&confdb_handle_t_db, handle); + + return (error); +} + cs_error_t confdb_write ( confdb_handle_t handle, char *error_text, size_t errbuf_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; coroipc_request_header_t req; struct res_lib_confdb_write res_lib_confdb_write; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { /* FIXME: set error_text */ return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_write(error_text, errbuf_len)) error = CS_ERR_ACCESS; goto error_exit; } req.size = sizeof (coroipc_request_header_t); req.id = MESSAGE_REQ_CONFDB_WRITE; iov.iov_base = (char *)&req; iov.iov_len = sizeof (coroipc_request_header_t); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_write, sizeof (struct res_lib_confdb_write)); if (error != CS_OK) { /* FIXME: set error_text */ goto error_exit; } error = res_lib_confdb_write.header.error; if (res_lib_confdb_write.error.length) { memcpy(error_text, res_lib_confdb_write.error.value, MIN(res_lib_confdb_write.error.length,errbuf_len)); error_text[errbuf_len-1] = '\0'; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_reload ( confdb_handle_t handle, int flush, char *error_text, size_t errbuf_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct res_lib_confdb_reload res_lib_confdb_reload; struct req_lib_confdb_reload req_lib_confdb_reload; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { /* FIXME: set error_text */ return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_reload(flush, error_text, errbuf_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_reload.header.size = sizeof (req_lib_confdb_reload); req_lib_confdb_reload.header.id = MESSAGE_REQ_CONFDB_RELOAD; req_lib_confdb_reload.flush = flush; iov.iov_base = (char *)&req_lib_confdb_reload; iov.iov_len = sizeof (req_lib_confdb_reload); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_reload, sizeof (struct res_lib_confdb_reload)); if (error != CS_OK) { /* FIXME: set error_text */ goto error_exit; } error = res_lib_confdb_reload.header.error; if(res_lib_confdb_reload.error.length) { memcpy(error_text, res_lib_confdb_reload.error.value, MIN(res_lib_confdb_reload.error.length,errbuf_len)); error_text[errbuf_len-1] = '\0'; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_track_changes ( confdb_handle_t handle, hdb_handle_t object_handle, unsigned int flags) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_track_start req; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_exit; } req.header.size = sizeof (struct req_lib_confdb_object_track_start); req.header.id = MESSAGE_REQ_CONFDB_TRACK_START; req.object_handle = object_handle; req.flags = flags; iov.iov_base = (char *)&req; iov.iov_len = sizeof (struct req_lib_confdb_object_track_start); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_stop_track_changes (confdb_handle_t handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; coroipc_request_header_t req; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_exit; } req.size = sizeof (coroipc_request_header_t); req.id = MESSAGE_REQ_CONFDB_TRACK_STOP; iov.iov_base = (char *)&req; iov.iov_len = sizeof (coroipc_request_header_t); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } diff --git a/lib/sa-confdb.c b/lib/sa-confdb.c index 03995e34..9a11418b 100644 --- a/lib/sa-confdb.c +++ b/lib/sa-confdb.c @@ -1,449 +1,464 @@ /* - * Copyright (c) 2008, 2009 Red Hat, Inc. + * Copyright (c) 2008, 2012 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - 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. * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ /* * Provides stand-alone access to data in the corosync object database * when aisexec is not running. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sa-confdb.h" static struct objdb_iface_ver0 *objdb; static int num_config_modules; static struct config_iface_ver0 *config_modules[128]; void main_get_config_modules(struct config_iface_ver0 ***modules, int *num); static int load_objdb(void) { hdb_handle_t objdb_handle; void *objdb_p; int res; /* * Load the object database interface */ res = lcr_ifact_reference ( &objdb_handle, "objdb", 0, &objdb_p, (void *)0); if (res == -1) { return -1; } objdb = (struct objdb_iface_ver0 *)objdb_p; objdb->objdb_init (); return CS_OK; } static int load_config(void) { char *config_iface; char *iface; int res; hdb_handle_t config_handle; hdb_handle_t config_version = 0; void *config_p; struct config_iface_ver0 *config; const char *error_string; char *strtok_savept; /* User's bootstrap config service */ config_iface = getenv("COROSYNC_DEFAULT_CONFIG_IFACE"); if (!config_iface) { if ((config_iface = strdup("corosync_parser")) == NULL) { return -1; } } /* Make a copy so we can deface it with strtok */ if ((config_iface = strdup(config_iface)) == NULL) { return -1; } iface = strtok_r (config_iface, ":", &strtok_savept); while (iface) { res = lcr_ifact_reference ( &config_handle, iface, config_version, &config_p, 0); config = (struct config_iface_ver0 *)config_p; if (res == -1) { return -1; } res = config->config_readconfig(objdb, &error_string); if (res == -1) { return -1; } config_modules[num_config_modules++] = config; iface = strtok_r (NULL, ":", &strtok_savept); } free(config_iface); return CS_OK; } /* Needed by objdb when it writes back the configuration */ void main_get_config_modules(struct config_iface_ver0 ***modules, int *num) { *modules = config_modules; *num = num_config_modules; } int confdb_sa_init (void) { int res; res = load_objdb(); if (res != CS_OK) return res; res = load_config(); return res; } int confdb_sa_object_create ( hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { return objdb->object_create(parent_object_handle, object_handle, object_name, object_name_len); } int confdb_sa_object_destroy ( hdb_handle_t object_handle) { return objdb->object_destroy(object_handle); } int confdb_sa_object_parent_get ( hdb_handle_t object_handle, hdb_handle_t *parent_object_handle) { return objdb->object_parent_get(object_handle, parent_object_handle); } int confdb_sa_object_name_get( hdb_handle_t object_handle, char *object_name, size_t *object_name_len) { return objdb->object_name_get(object_handle, object_name, object_name_len); } int confdb_sa_key_create ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { return objdb->object_key_create(parent_object_handle, key_name, key_name_len, value, value_len); } int confdb_sa_key_create_typed ( hdb_handle_t parent_object_handle, const char *key_name, const void *value, size_t value_len, int type) { return objdb->object_key_create_typed(parent_object_handle, key_name, value, value_len, type); } int confdb_sa_key_delete ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { return objdb->object_key_delete(parent_object_handle, key_name, key_name_len); } int confdb_sa_key_get ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, void *value, size_t *value_len) { int res; void *kvalue; res = objdb->object_key_get(parent_object_handle, key_name, key_name_len, &kvalue, value_len); if (!res) { memcpy(value, kvalue, *value_len); } return res; } int confdb_sa_key_get_typed ( hdb_handle_t parent_object_handle, const char *key_name, - void *value, + void **value, size_t *value_len, int *type) { int res; void *kvalue; res = objdb->object_key_get_typed(parent_object_handle, key_name, &kvalue, value_len, (objdb_value_types_t*)type); if (!res) { - memcpy(value, kvalue, *value_len); + if (!*value) { + *value = malloc(*value_len); + if (!*value) { + res = CS_ERR_NO_MEMORY; + } + } + if (*value) { + memcpy(*value, kvalue, *value_len); + } } return res; } int confdb_sa_key_increment ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { int res; res = objdb->object_key_increment(parent_object_handle, key_name, key_name_len, value); return res; } int confdb_sa_key_decrement ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { int res; res = objdb->object_key_decrement(parent_object_handle, key_name, key_name_len, value); return res; } int confdb_sa_key_replace ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *old_value, size_t old_value_len, const void *new_value, size_t new_value_len) { return objdb->object_key_replace(parent_object_handle, key_name, key_name_len, new_value, new_value_len); } int confdb_sa_write (char *error_text, size_t errbuf_len) { const char *errtext; int ret; ret = objdb->object_write_config(&errtext); if (!ret) { strncpy(error_text, errtext, errbuf_len); if (errbuf_len > 0) error_text[errbuf_len-1] = '\0'; } return ret; } int confdb_sa_reload ( int flush, char *error_text, size_t errbuf_len) { char *errtext; int ret; ret = objdb->object_reload_config(flush, (const char **) &errtext); if (!ret) { strncpy(error_text, errtext, errbuf_len); if (errbuf_len > 0) error_text[errbuf_len-1] = '\0'; } return ret; } int confdb_sa_object_find ( hdb_handle_t parent_object_handle, hdb_handle_t *find_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len) { int res; if (!*find_handle) { objdb->object_find_create(parent_object_handle, object_name, object_name_len, find_handle); } res = objdb->object_find_next(*find_handle, object_handle); return res; } int confdb_sa_object_iter ( hdb_handle_t parent_object_handle, hdb_handle_t *find_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len, void *found_object_name, size_t *found_object_name_len) { int res; if (!*find_handle) { objdb->object_find_create(parent_object_handle, object_name, object_name_len, find_handle); } res = objdb->object_find_next(*find_handle, object_handle); /* Return object name if we were called as _iter */ if (!res) { objdb->object_name_get(*object_handle, found_object_name, found_object_name_len); } return res; } int confdb_sa_key_iter ( hdb_handle_t parent_object_handle, hdb_handle_t start_pos, void *key_name, size_t *key_name_len, void *value, size_t *value_len) { int res; void *kname, *kvalue; res = objdb->object_key_iter_from(parent_object_handle, start_pos, &kname, key_name_len, &kvalue, value_len); if (!res) { memcpy(key_name, kname, *key_name_len); memcpy(value, kvalue, *value_len); } return res; } int confdb_sa_key_iter_typed ( hdb_handle_t parent_object_handle, hdb_handle_t start_pos, char *key_name, - void *value, + void **value, size_t *value_len, int *type) { int res; void *kname; void *kvalue; size_t key_name_len; res = objdb->object_key_iter_from(parent_object_handle, start_pos, &kname, &key_name_len, &kvalue, value_len); if (!res) { memcpy(key_name, kname, key_name_len); key_name[key_name_len] = '\0'; - memcpy(value, kvalue, *value_len); - - objdb->object_key_get_typed(parent_object_handle, - key_name, - &kvalue, value_len, (objdb_value_types_t*)type); + if (!*value) { + *value = malloc(*value_len); + if (!*value) { + res = CS_ERR_NO_MEMORY; + } + } + if (*value) { + memcpy(*value, kvalue, *value_len); + objdb->object_key_get_typed(parent_object_handle, + key_name, + &kvalue, value_len, (objdb_value_types_t*)type); + } } return res; } int confdb_sa_find_destroy(hdb_handle_t find_handle) { return objdb->object_find_destroy(find_handle); } diff --git a/lib/sa-confdb.h b/lib/sa-confdb.h index 61a0fa75..439c760f 100644 --- a/lib/sa-confdb.h +++ b/lib/sa-confdb.h @@ -1,112 +1,112 @@ /* - * Copyright (c) 2008, 2009 Red Hat, Inc. + * Copyright (c) 2008, 2012 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - 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. * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ extern int confdb_sa_init(void); extern int confdb_sa_object_create(hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle); extern int confdb_sa_object_destroy(hdb_handle_t object_handle); extern int confdb_sa_object_parent_get(hdb_handle_t object_handle, hdb_handle_t *parent_object_handle); extern int confdb_sa_object_name_get(hdb_handle_t object_handle, char *object_name, size_t *object_name_len); extern int confdb_sa_key_create(hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len); extern int confdb_sa_key_create_typed (hdb_handle_t parent_object_handle, const char *key_name, const void *value, size_t value_len, int type); extern int confdb_sa_key_delete(hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len); extern int confdb_sa_key_get(hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, void *value, size_t *value_len); extern int confdb_sa_key_get_typed(hdb_handle_t parent_object_handle, const char *key_name, - void *value, + void **value, size_t *value_len, int *type); extern int confdb_sa_key_replace(hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *old_value, size_t old_value_len, const void *new_value, size_t new_value_len); extern int confdb_sa_object_find(hdb_handle_t parent_object_handle, hdb_handle_t *find_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len); extern int confdb_sa_object_iter(hdb_handle_t parent_object_handle, hdb_handle_t *find_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len, void *found_object_name, size_t *found_object_name_len); extern int confdb_sa_key_iter(hdb_handle_t parent_object_handle, hdb_handle_t start_pos, void *key_name, size_t *key_name_len, void *value, size_t *value_len); extern int confdb_sa_key_iter_typed (hdb_handle_t parent_object_handle, hdb_handle_t start_pos, char *key_name, - void *value, + void **value, size_t *value_len, int *type); extern int confdb_sa_key_increment(hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value); extern int confdb_sa_key_decrement(hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value); extern int confdb_sa_find_destroy(hdb_handle_t find_handle); extern int confdb_sa_write(char *error_text, size_t errbuf_len); extern int confdb_sa_reload(int flush, char *error_text, size_t errbuf_len); diff --git a/services/confdb.c b/services/confdb.c index 39dbd939..1559604a 100644 --- a/services/confdb.c +++ b/services/confdb.c @@ -1,1092 +1,1263 @@ /* - * Copyright (c) 2008-2010 Red Hat, Inc. + * Copyright (c) 2008-2012 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - 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. * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS AND CONTIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOGSYS_DECLARE_SUBSYS ("CONFDB"); static hdb_handle_t * m2h (mar_uint64_t *m) { /* FIXME enable the following when/if we use gnulib: (it's a compile-time assertion; i.e., zero run-time cost) verify (sizeof (*m) == sizeof (hdb_handle_t)); */ return (void *) m; } static struct corosync_api_v1 *api; static int notify_pipe[2]; struct confdb_ipc_message_holder { void *conn; size_t mlen; struct list_head list; char msg[]; }; DECLARE_LIST_INIT(confdb_ipc_message_holder_list_head); pthread_mutex_t confdb_ipc_message_holder_list_mutex = PTHREAD_MUTEX_INITIALIZER; static int confdb_exec_init_fn ( struct corosync_api_v1 *corosync_api); static int confdb_exec_exit_fn(void); static int fd_set_nonblocking(int fd); static int objdb_notify_dispatch(hdb_handle_t handle, int fd, int revents, void *data); static int confdb_lib_init_fn (void *conn); static int confdb_lib_exit_fn (void *conn); static void message_handler_req_lib_confdb_object_create (void *conn, const void *message); static void message_handler_req_lib_confdb_object_destroy (void *conn, const void *message); static void message_handler_req_lib_confdb_object_find_destroy (void *conn, const void *message); static void message_handler_req_lib_confdb_key_create (void *conn, const void *message); static void message_handler_req_lib_confdb_key_create_typed (void *conn, - const void *message); + const void *message); +static void message_handler_req_lib_confdb_key_create_typed2 (void *conn, + const void *message); static void message_handler_req_lib_confdb_key_get (void *conn, const void *message); static void message_handler_req_lib_confdb_key_get_typed (void *conn, const void *message); + +static void message_handler_req_lib_confdb_key_get_typed2 (void *conn, + const void *message); + static void message_handler_req_lib_confdb_key_replace (void *conn, const void *message); +static void message_handler_req_lib_confdb_key_replace2 (void *conn, + const void *message); static void message_handler_req_lib_confdb_key_delete (void *conn, const void *message); + static void message_handler_req_lib_confdb_key_iter (void *conn, - const void *message); + const void *message); + static void message_handler_req_lib_confdb_key_iter_typed (void *conn, const void *message); +static void message_handler_req_lib_confdb_key_iter_typed2 (void *conn, + const void *message); + static void message_handler_req_lib_confdb_key_increment (void *conn, const void *message); static void message_handler_req_lib_confdb_key_decrement (void *conn, const void *message); static void message_handler_req_lib_confdb_object_iter (void *conn, const void *message); static void message_handler_req_lib_confdb_object_find (void *conn, const void *message); static void message_handler_req_lib_confdb_object_parent_get (void *conn, const void *message); static void message_handler_req_lib_confdb_object_name_get (void *conn, const void *message); static void message_handler_req_lib_confdb_write (void *conn, const void *message); static void message_handler_req_lib_confdb_reload (void *conn, const void *message); static void message_handler_req_lib_confdb_track_start (void *conn, const void *message); static void message_handler_req_lib_confdb_track_stop (void *conn, const void *message); static void confdb_notify_lib_of_key_change( object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_name_len, const void *key_value_pt, size_t key_value_len, void *priv_data_pt); static void confdb_notify_lib_of_new_object( hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len, void *priv_data_pt); static void confdb_notify_lib_of_destroyed_object( hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len, void *priv_data_pt); static void confdb_notify_lib_of_reload( objdb_reload_notify_type_t notify_type, int flush, void *priv_data_pt); /* * Library Handler Definition */ static struct corosync_lib_handler confdb_lib_engine[] = { { /* 0 */ .lib_handler_fn = message_handler_req_lib_confdb_object_create, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 1 */ .lib_handler_fn = message_handler_req_lib_confdb_object_destroy, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 2 */ .lib_handler_fn = message_handler_req_lib_confdb_object_find, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 3 */ .lib_handler_fn = message_handler_req_lib_confdb_key_create, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 4 */ .lib_handler_fn = message_handler_req_lib_confdb_key_get, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 5 */ .lib_handler_fn = message_handler_req_lib_confdb_key_replace, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 6 */ .lib_handler_fn = message_handler_req_lib_confdb_key_delete, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 7 */ .lib_handler_fn = message_handler_req_lib_confdb_object_iter, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 8 */ .lib_handler_fn = message_handler_req_lib_confdb_object_parent_get, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 9 */ .lib_handler_fn = message_handler_req_lib_confdb_key_iter, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 10 */ .lib_handler_fn = message_handler_req_lib_confdb_track_start, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 11 */ .lib_handler_fn = message_handler_req_lib_confdb_track_stop, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 12 */ .lib_handler_fn = message_handler_req_lib_confdb_write, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 13 */ .lib_handler_fn = message_handler_req_lib_confdb_reload, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 14 */ .lib_handler_fn = message_handler_req_lib_confdb_object_find_destroy, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 15 */ .lib_handler_fn = message_handler_req_lib_confdb_key_increment, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 16 */ .lib_handler_fn = message_handler_req_lib_confdb_key_decrement, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 17 */ .lib_handler_fn = message_handler_req_lib_confdb_key_create_typed, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 18 */ .lib_handler_fn = message_handler_req_lib_confdb_key_get_typed, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 19 */ .lib_handler_fn = message_handler_req_lib_confdb_key_iter_typed, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 20 */ .lib_handler_fn = message_handler_req_lib_confdb_object_name_get, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, + { /* 21 */ + .lib_handler_fn = message_handler_req_lib_confdb_key_iter_typed2, + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED + }, + { /* 22 */ + .lib_handler_fn = message_handler_req_lib_confdb_key_replace2, + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED + }, + { /* 23 */ + .lib_handler_fn = message_handler_req_lib_confdb_key_get_typed2, + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED + }, + { /* 24 */ + .lib_handler_fn = message_handler_req_lib_confdb_key_create_typed2, + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED + }, }; struct corosync_service_engine confdb_service_engine = { .name = "corosync cluster config database access v1.01", .id = CONFDB_SERVICE, .priority = 1, .private_data_size = 0, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED, .allow_inquorate = CS_LIB_ALLOW_INQUORATE, .lib_init_fn = confdb_lib_init_fn, .lib_exit_fn = confdb_lib_exit_fn, .lib_engine = confdb_lib_engine, .lib_engine_count = sizeof (confdb_lib_engine) / sizeof (struct corosync_lib_handler), .exec_init_fn = confdb_exec_init_fn, .exec_exit_fn = confdb_exec_exit_fn, }; /* * Dynamic loader definition */ static struct corosync_service_engine *confdb_get_service_engine_ver0 (void); static struct corosync_service_engine_iface_ver0 confdb_service_engine_iface = { .corosync_get_service_engine_ver0 = confdb_get_service_engine_ver0 }; static struct lcr_iface corosync_confdb_ver0[1] = { { .name = "corosync_confdb", .version = 0, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = NULL } }; static struct lcr_comp confdb_comp_ver0 = { .iface_count = 1, .ifaces = corosync_confdb_ver0 }; static struct corosync_service_engine *confdb_get_service_engine_ver0 (void) { return (&confdb_service_engine); } #ifdef COROSYNC_SOLARIS void corosync_lcr_component_register (void); void corosync_lcr_component_register (void) { #else __attribute__ ((constructor)) static void corosync_lcr_component_register (void) { #endif lcr_interfaces_set (&corosync_confdb_ver0[0], &confdb_service_engine_iface); lcr_component_register (&confdb_comp_ver0); } static int confdb_exec_exit_fn(void) { api->poll_dispatch_delete(api->poll_handle_get(), notify_pipe[0]); close(notify_pipe[0]); close(notify_pipe[1]); return 0; } static int confdb_exec_init_fn ( struct corosync_api_v1 *corosync_api) { int i; #ifdef COROSYNC_SOLARIS logsys_subsys_init(); #endif api = corosync_api; if (pipe(notify_pipe) != 0) { return -1; } for (i = 0; i < 2; i++) { if (fd_set_nonblocking (notify_pipe[i]) == -1) { return -1; } } return api->poll_dispatch_add(api->poll_handle_get(), notify_pipe[0], POLLIN, NULL, objdb_notify_dispatch); } static int confdb_lib_init_fn (void *conn) { log_printf(LOGSYS_LEVEL_DEBUG, "lib_init_fn: conn=%p\n", conn); return (0); } static int confdb_lib_exit_fn (void *conn) { log_printf(LOGSYS_LEVEL_DEBUG, "exit_fn for conn=%p\n", conn); /* cleanup the object trackers for this client. */ api->object_track_stop(confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, confdb_notify_lib_of_reload, conn); return (0); } static int fd_set_nonblocking(int fd) { int flags; int res; flags = fcntl (fd, F_GETFL); if (flags == -1) { return -1; } flags |= O_NONBLOCK; res = fcntl (fd, F_SETFL, flags); return res; } static void message_handler_req_lib_confdb_object_create (void *conn, const void *message) { const struct req_lib_confdb_object_create *req_lib_confdb_object_create = message; struct res_lib_confdb_object_create res_lib_confdb_object_create; hdb_handle_t object_handle; int ret = CS_OK; if (api->object_create(req_lib_confdb_object_create->parent_object_handle, &object_handle, req_lib_confdb_object_create->object_name.value, req_lib_confdb_object_create->object_name.length)) ret = CS_ERR_ACCESS; res_lib_confdb_object_create.object_handle = object_handle; res_lib_confdb_object_create.header.size = sizeof(res_lib_confdb_object_create); res_lib_confdb_object_create.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE; res_lib_confdb_object_create.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_create, sizeof(res_lib_confdb_object_create)); } static void message_handler_req_lib_confdb_object_destroy (void *conn, const void *message) { const struct req_lib_confdb_object_destroy *req_lib_confdb_object_destroy = message; coroipc_response_header_t res; int ret = CS_OK; if (api->object_destroy(req_lib_confdb_object_destroy->object_handle)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_object_find_destroy (void *conn, const void *message) { const struct req_lib_confdb_object_find_destroy *req_lib_confdb_object_find_destroy = message; coroipc_response_header_t res; int ret = CS_OK; if (api->object_find_destroy(req_lib_confdb_object_find_destroy->find_handle)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_create (void *conn, const void *message) { const struct req_lib_confdb_key_create *req_lib_confdb_key_create = message; coroipc_response_header_t res; int ret = CS_OK; if (api->object_key_create(req_lib_confdb_key_create->object_handle, req_lib_confdb_key_create->key_name.value, req_lib_confdb_key_create->key_name.length, req_lib_confdb_key_create->value.value, req_lib_confdb_key_create->value.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_CREATE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_create_typed (void *conn, const void *message) { const struct req_lib_confdb_key_create_typed *req_lib_confdb_key_create = message; coroipc_response_header_t res; int ret = CS_OK; if (api->object_key_create_typed(req_lib_confdb_key_create->object_handle, (char*)req_lib_confdb_key_create->key_name.value, req_lib_confdb_key_create->value.value, req_lib_confdb_key_create->value.length, req_lib_confdb_key_create->type)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_CREATE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_get (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_get res_lib_confdb_key_get; size_t value_len; void *value; int ret = CS_OK; if (api->object_key_get(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &value, &value_len)) ret = CS_ERR_ACCESS; else { - memcpy(res_lib_confdb_key_get.value.value, value, value_len); + if (value_len > CS_MAX_NAME_LENGTH) { + ret = CS_ERR_TOO_BIG; + } else { + memcpy(res_lib_confdb_key_get.value.value, value, value_len); + } res_lib_confdb_key_get.value.length = value_len; } res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get); res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET; res_lib_confdb_key_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get)); } static void message_handler_req_lib_confdb_key_get_typed (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_get_typed res_lib_confdb_key_get; size_t value_len; void *value; int ret = CS_OK; objdb_value_types_t type; char * key_name = (char*)req_lib_confdb_key_get->key_name.value; key_name[req_lib_confdb_key_get->key_name.length] = '\0'; if (api->object_key_get_typed(req_lib_confdb_key_get->parent_object_handle, key_name, &value, &value_len, &type)) ret = CS_ERR_ACCESS; else { - memcpy(res_lib_confdb_key_get.value.value, value, value_len); + if (value_len > CS_MAX_NAME_LENGTH) { + ret = CS_ERR_TOO_BIG; + } else { + memcpy(res_lib_confdb_key_get.value.value, value, value_len); + } res_lib_confdb_key_get.value.length = value_len; res_lib_confdb_key_get.type = type; - } res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get); res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET_TYPED; res_lib_confdb_key_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get)); } +static void message_handler_req_lib_confdb_key_get_typed2 (void *conn, + const void *message) +{ + const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; + struct res_lib_confdb_key_get_typed2 res_lib_confdb_key_get; + struct res_lib_confdb_key_get_typed2 *res = &res_lib_confdb_key_get; + size_t value_len; + void *value; + int ret = CS_OK; + objdb_value_types_t type; + char * key_name = (char*)req_lib_confdb_key_get->key_name.value; + key_name[req_lib_confdb_key_get->key_name.length] = '\0'; + + if (api->object_key_get_typed(req_lib_confdb_key_get->parent_object_handle, + key_name, + &value, + &value_len, &type)) { + ret = CS_ERR_ACCESS; + res->header.size = sizeof(res_lib_confdb_key_get); + } + else { + res = alloca(sizeof(struct res_lib_confdb_key_get_typed2) + value_len); + + memcpy(&res->value, value, value_len); + res->value_length = value_len; + res->type = type; + + res->header.size = sizeof(struct res_lib_confdb_key_get_typed2)+value_len; + res->header.error = ret; + } + res->header.id = MESSAGE_RES_CONFDB_KEY_GET_TYPED2; + res->header.error = ret; + + api->ipc_response_send(conn, res, res->header.size); + +} static void message_handler_req_lib_confdb_key_increment (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; int ret = CS_OK; if (api->object_key_increment(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &res_lib_confdb_key_incdec.value)) ret = CS_ERR_ACCESS; res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_INCREMENT; res_lib_confdb_key_incdec.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec)); } static void message_handler_req_lib_confdb_key_decrement (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; int ret = CS_OK; if (api->object_key_decrement(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &res_lib_confdb_key_incdec.value)) ret = CS_ERR_ACCESS; res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_DECREMENT; res_lib_confdb_key_incdec.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec)); } static void message_handler_req_lib_confdb_key_replace (void *conn, const void *message) { const struct req_lib_confdb_key_replace *req_lib_confdb_key_replace = message; coroipc_response_header_t res; int ret = CS_OK; if (api->object_key_replace(req_lib_confdb_key_replace->object_handle, req_lib_confdb_key_replace->key_name.value, req_lib_confdb_key_replace->key_name.length, req_lib_confdb_key_replace->new_value.value, req_lib_confdb_key_replace->new_value.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_REPLACE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_delete (void *conn, const void *message) { const struct req_lib_confdb_key_delete *req_lib_confdb_key_delete = message; coroipc_response_header_t res; int ret = CS_OK; if (api->object_key_delete(req_lib_confdb_key_delete->object_handle, req_lib_confdb_key_delete->key_name.value, req_lib_confdb_key_delete->key_name.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_DELETE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_object_parent_get (void *conn, const void *message) { const struct req_lib_confdb_object_parent_get *req_lib_confdb_object_parent_get = message; struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get; hdb_handle_t object_handle; int ret = CS_OK; if (api->object_parent_get(req_lib_confdb_object_parent_get->object_handle, &object_handle)) ret = CS_ERR_ACCESS; res_lib_confdb_object_parent_get.parent_object_handle = object_handle; res_lib_confdb_object_parent_get.header.size = sizeof(res_lib_confdb_object_parent_get); res_lib_confdb_object_parent_get.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE; res_lib_confdb_object_parent_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_parent_get, sizeof(res_lib_confdb_object_parent_get)); } static void message_handler_req_lib_confdb_object_name_get (void *conn, const void *message) { const struct req_lib_confdb_object_name_get *request = message; struct res_lib_confdb_object_name_get response; int ret = CS_OK; char object_name[CS_MAX_NAME_LENGTH]; size_t object_name_len; if (api->object_name_get(request->object_handle, object_name, &object_name_len)) { ret = CS_ERR_ACCESS; } response.object_name.length = object_name_len; strncpy((char*)response.object_name.value, object_name, CS_MAX_NAME_LENGTH); response.object_name.value[CS_MAX_NAME_LENGTH-1] = '\0'; response.header.size = sizeof(response); response.header.id = MESSAGE_RES_CONFDB_OBJECT_NAME_GET; response.header.error = ret; api->ipc_response_send(conn, &response, sizeof(response)); } static void message_handler_req_lib_confdb_key_iter (void *conn, const void *message) { const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message; struct res_lib_confdb_key_iter res_lib_confdb_key_iter; void *key_name; size_t key_name_len; void *value; size_t value_len; int ret = CS_OK; if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle, req_lib_confdb_key_iter->next_entry, &key_name, &key_name_len, &value, &value_len)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len); - memcpy(res_lib_confdb_key_iter.value.value, value, value_len); + if (value_len > CS_MAX_NAME_LENGTH) { + ret = CS_ERR_TOO_BIG; + } else { + memcpy(res_lib_confdb_key_iter.value.value, value, value_len); + } res_lib_confdb_key_iter.key_name.length = key_name_len; res_lib_confdb_key_iter.value.length = value_len; } res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter); res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER; res_lib_confdb_key_iter.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter)); } static void message_handler_req_lib_confdb_key_iter_typed (void *conn, const void *message) { const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message; struct res_lib_confdb_key_iter_typed res_lib_confdb_key_iter; void *key_name; size_t key_name_len; void *value; size_t value_len; int ret = CS_OK; objdb_value_types_t my_type; if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle, req_lib_confdb_key_iter->next_entry, &key_name, &key_name_len, &value, &value_len)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len); - memcpy(res_lib_confdb_key_iter.value.value, value, value_len); + if (value_len > CS_MAX_NAME_LENGTH) { + ret = CS_ERR_TOO_BIG; + } else { + memcpy(res_lib_confdb_key_iter.value.value, value, value_len); + } res_lib_confdb_key_iter.key_name.length = key_name_len; res_lib_confdb_key_iter.key_name.value[key_name_len] = '\0'; res_lib_confdb_key_iter.value.length = value_len; api->object_key_get_typed(req_lib_confdb_key_iter->parent_object_handle, (const char*)res_lib_confdb_key_iter.key_name.value, &value, &value_len, &my_type); res_lib_confdb_key_iter.type = my_type; } res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter); res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER_TYPED; res_lib_confdb_key_iter.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter)); } +static void message_handler_req_lib_confdb_key_iter_typed2 (void *conn, + const void *message) +{ + const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message; + struct res_lib_confdb_key_iter_typed2 res_lib_confdb_key_iter; + struct res_lib_confdb_key_iter_typed2 *res = &res_lib_confdb_key_iter; + void *key_name; + size_t key_name_len; + void *value; + size_t value_len; + int ret = CS_OK; + objdb_value_types_t my_type; + + if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle, + req_lib_confdb_key_iter->next_entry, + &key_name, + &key_name_len, + &value, + &value_len)) { + ret = CS_ERR_ACCESS; + res->header.size = sizeof(res_lib_confdb_key_iter); + } + else { + res = alloca(sizeof(struct res_lib_confdb_key_iter_typed2) + value_len); + + memcpy(res->key_name.value, key_name, key_name_len); + res->key_name.length = key_name_len; + res->key_name.value[key_name_len] = '\0'; + memcpy(&res->value, value, value_len); + res->value_length = value_len; + + api->object_key_get_typed(req_lib_confdb_key_iter->parent_object_handle, + (const char*)res->key_name.value, + &value, + &value_len, + &my_type); + res->type = my_type; + + res->header.size = sizeof(res_lib_confdb_key_iter)+value_len; + } + res->header.id = MESSAGE_RES_CONFDB_KEY_ITER_TYPED2; + res->header.error = ret; + + api->ipc_response_send(conn, res, res->header.size); +} + static void message_handler_req_lib_confdb_object_iter (void *conn, const void *message) { const struct req_lib_confdb_object_iter *req_lib_confdb_object_iter = message; struct res_lib_confdb_object_iter res_lib_confdb_object_iter; size_t object_name_len; int ret = CS_OK; if (!req_lib_confdb_object_iter->find_handle) { if (api->object_find_create(req_lib_confdb_object_iter->parent_object_handle, NULL, 0, m2h(&res_lib_confdb_object_iter.find_handle)) == -1) { ret = CS_ERR_ACCESS; goto response_send; } } else res_lib_confdb_object_iter.find_handle = req_lib_confdb_object_iter->find_handle; if (api->object_find_next(res_lib_confdb_object_iter.find_handle, m2h(&res_lib_confdb_object_iter.object_handle))) { ret = CS_ERR_ACCESS; api->object_find_destroy(res_lib_confdb_object_iter.find_handle); } else { if (api->object_name_get(res_lib_confdb_object_iter.object_handle, (char *)res_lib_confdb_object_iter.object_name.value, &object_name_len) == -1) { ret = CS_ERR_ACCESS; goto response_send; } else { res_lib_confdb_object_iter.object_name.length = object_name_len; } } response_send: res_lib_confdb_object_iter.header.size = sizeof(res_lib_confdb_object_iter); res_lib_confdb_object_iter.header.id = MESSAGE_RES_CONFDB_OBJECT_ITER; res_lib_confdb_object_iter.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_iter, sizeof(res_lib_confdb_object_iter)); } static void message_handler_req_lib_confdb_object_find (void *conn, const void *message) { const struct req_lib_confdb_object_find *req_lib_confdb_object_find = message; struct res_lib_confdb_object_find res_lib_confdb_object_find; int ret = CS_OK; if (!req_lib_confdb_object_find->find_handle) { if (api->object_find_create(req_lib_confdb_object_find->parent_object_handle, req_lib_confdb_object_find->object_name.value, req_lib_confdb_object_find->object_name.length, m2h(&res_lib_confdb_object_find.find_handle)) == -1) { ret = CS_ERR_ACCESS; goto response_send; } } else res_lib_confdb_object_find.find_handle = req_lib_confdb_object_find->find_handle; if (api->object_find_next(res_lib_confdb_object_find.find_handle, m2h(&res_lib_confdb_object_find.object_handle))) { ret = CS_ERR_ACCESS; api->object_find_destroy(res_lib_confdb_object_find.find_handle); } response_send: res_lib_confdb_object_find.header.size = sizeof(res_lib_confdb_object_find); res_lib_confdb_object_find.header.id = MESSAGE_RES_CONFDB_OBJECT_FIND; res_lib_confdb_object_find.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_find, sizeof(res_lib_confdb_object_find)); } static void message_handler_req_lib_confdb_write (void *conn, const void *message) { struct res_lib_confdb_write res_lib_confdb_write; int ret = CS_OK; const char *error_string = NULL; if (api->object_write_config(&error_string)) ret = CS_ERR_ACCESS; res_lib_confdb_write.header.size = sizeof(res_lib_confdb_write); res_lib_confdb_write.header.id = MESSAGE_RES_CONFDB_WRITE; res_lib_confdb_write.header.error = ret; if (error_string) { strcpy((char *)res_lib_confdb_write.error.value, error_string); res_lib_confdb_write.error.length = strlen(error_string) + 1; } else res_lib_confdb_write.error.length = 0; api->ipc_response_send(conn, &res_lib_confdb_write, sizeof(res_lib_confdb_write)); } static void message_handler_req_lib_confdb_reload (void *conn, const void *message) { const struct req_lib_confdb_reload *req_lib_confdb_reload = message; struct res_lib_confdb_reload res_lib_confdb_reload; int ret = CS_OK; const char *error_string = NULL; if (api->object_reload_config(req_lib_confdb_reload->flush, &error_string)) ret = CS_ERR_ACCESS; res_lib_confdb_reload.header.size = sizeof(res_lib_confdb_reload); res_lib_confdb_reload.header.id = MESSAGE_RES_CONFDB_RELOAD; res_lib_confdb_reload.header.error = ret; if(error_string) { strcpy((char *)res_lib_confdb_reload.error.value, error_string); res_lib_confdb_reload.error.length = strlen(error_string) + 1; } else res_lib_confdb_reload.error.length = 0; api->ipc_response_send(conn, &res_lib_confdb_reload, sizeof(res_lib_confdb_reload)); } static int objdb_notify_dispatch(hdb_handle_t handle, int fd, int revents, void *data) { struct confdb_ipc_message_holder *holder; ssize_t rc; char pipe_cmd; if (revents & POLLHUP) { return -1; } pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex); retry_read: rc = read(fd, &pipe_cmd, sizeof(pipe_cmd)); if (rc == sizeof(pipe_cmd)) { goto retry_read; /* Flush whole buffer */ } if (rc == -1) { if (errno == EINTR) { goto retry_read; } if (errno != EAGAIN && errno != EWOULDBLOCK) { goto unlock_exit; } } else { goto unlock_exit; /* rc != -1 && rc != 1 -> end of file */ } while (!list_empty (&confdb_ipc_message_holder_list_head)) { holder = list_entry (confdb_ipc_message_holder_list_head.next, struct confdb_ipc_message_holder, list); list_del (&holder->list); /* * All list operations are done now, so unlock list mutex to * prevent deadlock in IPC. */ pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); api->ipc_dispatch_send(holder->conn, holder->msg, holder->mlen); api->ipc_refcnt_dec(holder->conn); free(holder); /* * Next operation is again list one, so lock list again. */ pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex); } unlock_exit: pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); return 0; } static int32_t ipc_dispatch_send_from_poll_thread(void *conn, const void *msg, size_t mlen) { struct confdb_ipc_message_holder *holder; ssize_t written; size_t holder_size; char pipe_cmd; api->ipc_refcnt_inc(conn); holder_size = sizeof (*holder) + mlen; holder = malloc (holder_size); if (holder == NULL) { api->ipc_refcnt_dec(conn); return -1; } memset(holder, 0, holder_size); holder->conn = conn; holder->mlen = mlen; memcpy(holder->msg, msg, mlen); list_init(&holder->list); pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex); list_add_tail (&holder->list, &confdb_ipc_message_holder_list_head); pipe_cmd = 'M'; /* Message */ retry_write: written = write(notify_pipe[1], &pipe_cmd, sizeof(pipe_cmd)); if (written == -1) { if (errno == EINTR) { goto retry_write; } if (errno != EAGAIN && errno != EWOULDBLOCK) { /* * Different error then EINTR or BLOCK -> exit with error */ goto refcnt_del_unlock_exit; } } else if (written != sizeof (pipe_cmd)) { goto refcnt_del_unlock_exit; } pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); return 0; refcnt_del_unlock_exit: list_del (&holder->list); free(holder); api->ipc_refcnt_dec(conn); pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); return -1; } static void confdb_notify_lib_of_key_change(object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_name_len, const void *key_value_pt, size_t key_value_len, void *priv_data_pt) { - struct res_lib_confdb_key_change_callback res; + struct res_lib_confdb_key_change_callback2 *res; - res.header.size = sizeof(res); - res.header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK; - res.header.error = CS_OK; + res = alloca(sizeof(struct res_lib_confdb_key_change_callback2) + key_value_len); + + res->header.size = sizeof(struct res_lib_confdb_key_change_callback2) + key_value_len; + res->header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK2; + res->header.error = CS_OK; // handle & type - res.change_type = change_type; - res.parent_object_handle = parent_object_handle; - res.object_handle = object_handle; + res->change_type = change_type; + res->parent_object_handle = parent_object_handle; + res->object_handle = object_handle; //object - memcpy(res.object_name.value, object_name_pt, object_name_len); - res.object_name.length = object_name_len; + memcpy(res->object_name.value, object_name_pt, object_name_len); + res->object_name.length = object_name_len; //key name - memcpy(res.key_name.value, key_name_pt, key_name_len); - res.key_name.length = key_name_len; + memcpy(res->key_name.value, key_name_pt, key_name_len); + res->key_name.length = key_name_len; //key value - memcpy(res.key_value.value, key_value_pt, key_value_len); - res.key_value.length = key_value_len; + memcpy(&res->key_value, key_value_pt, key_value_len); + res->key_value_length = key_value_len; - ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); + ipc_dispatch_send_from_poll_thread(priv_data_pt, res, res->header.size); } static void confdb_notify_lib_of_new_object(hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len, void *priv_data_pt) { struct res_lib_confdb_object_create_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK; res.header.error = CS_OK; res.parent_object_handle = parent_object_handle; res.object_handle = object_handle; memcpy(res.name.value, name_pt, name_len); res.name.length = name_len; ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); } static void confdb_notify_lib_of_destroyed_object( hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len, void *priv_data_pt) { struct res_lib_confdb_object_destroy_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK; res.header.error = CS_OK; res.parent_object_handle = parent_object_handle; memcpy(res.name.value, name_pt, name_len); res.name.length = name_len; ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); } static void confdb_notify_lib_of_reload(objdb_reload_notify_type_t notify_type, int flush, void *priv_data_pt) { struct res_lib_confdb_reload_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_RELOAD_CALLBACK; res.header.error = CS_OK; res.type = notify_type; ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); } static void message_handler_req_lib_confdb_track_start (void *conn, const void *message) { const struct req_lib_confdb_object_track_start *req = message; coroipc_response_header_t res; api->object_track_start(req->object_handle, req->flags, confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, confdb_notify_lib_of_reload, conn); res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_TRACK_START; res.error = CS_OK; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_track_stop (void *conn, const void *message) { coroipc_response_header_t res; api->object_track_stop(confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, confdb_notify_lib_of_reload, conn); res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_TRACK_STOP; res.error = CS_OK; api->ipc_response_send(conn, &res, sizeof(res)); } + +static void message_handler_req_lib_confdb_key_create_typed2 (void *conn, + const void *message) +{ + const struct req_lib_confdb_key_create_typed2 *req_lib_confdb_key_create + = message; + coroipc_response_header_t res; + int ret = CS_OK; + + if (api->object_key_create_typed(req_lib_confdb_key_create->object_handle, + (char*)req_lib_confdb_key_create->key_name.value, + &req_lib_confdb_key_create->value, + req_lib_confdb_key_create->value_length, + req_lib_confdb_key_create->type)) + ret = CS_ERR_ACCESS; + + res.size = sizeof(res); + res.id = MESSAGE_RES_CONFDB_KEY_CREATE; + res.error = ret; + api->ipc_response_send(conn, &res, sizeof(res)); +} + + +static void message_handler_req_lib_confdb_key_replace2 (void *conn, + const void *message) +{ + const struct req_lib_confdb_key_replace2 *req_lib_confdb_key_replace + = message; + coroipc_response_header_t res; + int ret = CS_OK; + + if (api->object_key_replace(req_lib_confdb_key_replace->object_handle, + req_lib_confdb_key_replace->key_name.value, + req_lib_confdb_key_replace->key_name.length, + &req_lib_confdb_key_replace->new_value, + req_lib_confdb_key_replace->new_value_length)) + ret = CS_ERR_ACCESS; + + res.size = sizeof(res); + res.id = MESSAGE_RES_CONFDB_KEY_REPLACE; + res.error = ret; + api->ipc_response_send(conn, &res, sizeof(res)); +} diff --git a/tools/corosync-objctl.c b/tools/corosync-objctl.c index d7909bb2..3e2bd4c8 100644 --- a/tools/corosync-objctl.c +++ b/tools/corosync-objctl.c @@ -1,936 +1,945 @@ /* * Copyright (c) 2008 Allied Telesis Labs NZ + * (c) 2012 Red Hat, Inc. * * All rights reserved. * * Author: Angus Salkeld * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - 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. * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #define SEPERATOR '.' #define SEPERATOR_STR "." -#define OBJ_NAME_SIZE 512 +#define OBJ_NAME_SIZE 4096 typedef enum { ACTION_READ, ACTION_WRITE, ACTION_CREATE, ACTION_CREATE_KEY, ACTION_DELETE, ACTION_PRINT_ALL, ACTION_PRINT_DEFAULT, ACTION_TRACK, } action_types_t; typedef enum { FIND_OBJECT_ONLY, FIND_OBJECT_OR_KEY, FIND_KEY_ONLY } find_object_of_type_t; static void tail_key_changed(confdb_handle_t handle, confdb_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name, size_t object_name_len, const void *key_name, size_t key_name_len, const void *key_value, size_t key_value_len); static void tail_object_created(confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len); static void tail_object_deleted(confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len); static void create_object(confdb_handle_t handle, char * name_pt); static void create_object_key(confdb_handle_t handle, char * name_pt); static void write_key(confdb_handle_t handle, char * path_pt); static void get_parent_name(const char * name_pt, char * parent_name); static confdb_callbacks_t callbacks = { .confdb_key_change_notify_fn = tail_key_changed, .confdb_object_create_change_notify_fn = tail_object_created, .confdb_object_delete_change_notify_fn = tail_object_deleted, }; static int debug = 0; static int show_binary = 0; static int action; static void print_binary_key (char *value, size_t value_len) { size_t i; char c; for (i = 0; i < value_len; i++) { c = value[i]; if (c >= ' ' && c < 0x7f && c != '\\') { fputc (c, stdout); } else { if (c == '\\') { printf ("\\\\"); } else { printf ("\\x%02X", c); } } } printf ("\n"); } static void print_key (char *key_name, void *value, size_t value_len, confdb_value_types_t type) { switch (type) { case CONFDB_VALUETYPE_INT16: printf ("%s=%hd\n", key_name, *(int16_t*)value); break; case CONFDB_VALUETYPE_UINT16: printf ("%s=%hu\n", key_name, *(uint16_t*)value); break; case CONFDB_VALUETYPE_INT32: printf ("%s=%d\n", key_name, *(int32_t*)value); break; case CONFDB_VALUETYPE_UINT32: printf ("%s=%u\n", key_name, *(uint32_t*)value); break; case CONFDB_VALUETYPE_INT64: printf ("%s=%"PRIi64"\n", key_name, *(int64_t*)value); break; case CONFDB_VALUETYPE_UINT64: printf ("%s=%"PRIu64"\n", key_name, *(uint64_t*)value); break; case CONFDB_VALUETYPE_FLOAT: printf ("%s=%f\n", key_name, *(float*)value); break; case CONFDB_VALUETYPE_DOUBLE: printf ("%s=%f\n", key_name, *(double*)value); break; case CONFDB_VALUETYPE_STRING: printf ("%s=%s\n", key_name, (char*)value); break; default: case CONFDB_VALUETYPE_ANY: if (!show_binary) { printf ("%s=**binary**(%d)\n", key_name, type); } else { printf ("%s=", key_name); print_binary_key ((char *)value, value_len); } break; } } /* Recursively dump the object tree */ static void print_config_tree(confdb_handle_t handle, hdb_handle_t parent_object_handle, char * parent_name) { hdb_handle_t object_handle; char object_name[OBJ_NAME_SIZE]; size_t object_name_len; char key_name[OBJ_NAME_SIZE]; - char key_value[OBJ_NAME_SIZE]; + char output_string[OBJ_NAME_SIZE]; + char *key_value=NULL;/* Dynamically allocated value */ size_t key_value_len; cs_error_t res; int children_printed; confdb_value_types_t type; /* Show the keys */ res = confdb_key_iter_start(handle, parent_object_handle); if (res != CS_OK) { fprintf(stderr, "error resetting key iterator for object "HDB_X_FORMAT" %d\n", parent_object_handle, res); exit(EXIT_FAILURE); } children_printed = 0; - while ( (res = confdb_key_iter_typed(handle, + while ( (res = confdb_key_iter_typed2(handle, parent_object_handle, key_name, - key_value, + (void**)&key_value, &key_value_len, &type)) == CS_OK) { key_value[key_value_len] = '\0'; if (parent_name != NULL) printf("%s%c", parent_name, SEPERATOR); print_key(key_name, key_value, key_value_len, type); + free(key_value); + key_value = NULL; children_printed++; } /* Show sub-objects */ res = confdb_object_iter_start(handle, parent_object_handle); if (res != CS_OK) { fprintf(stderr, "error resetting object iterator for object "HDB_X_FORMAT" %d\n", parent_object_handle, res); exit(EXIT_FAILURE); } while ( (res = confdb_object_iter(handle, parent_object_handle, &object_handle, object_name, &object_name_len)) == CS_OK) { object_name[object_name_len] = '\0'; if (parent_name != NULL) { - snprintf(key_value, OBJ_NAME_SIZE, "%s%c%s", parent_name, SEPERATOR, object_name); + snprintf(output_string, OBJ_NAME_SIZE, "%s%c%s", parent_name, SEPERATOR, object_name); } else { if ((action == ACTION_PRINT_DEFAULT) && strcmp(object_name, "internal_configuration") == 0) continue; - snprintf(key_value, OBJ_NAME_SIZE, "%s", object_name); + snprintf(output_string, OBJ_NAME_SIZE, "%s", object_name); } - print_config_tree(handle, object_handle, key_value); + print_config_tree(handle, object_handle, output_string); children_printed++; } if (children_printed == 0 && parent_name != NULL) { printf("%s\n", parent_name); } } static cs_error_t reload_db(confdb_handle_t handle) { char error[1024]; cs_error_t ret; ret = confdb_reload(handle, 0, error, sizeof(error) - 1); if (ret != CONFDB_OK) { fprintf (stderr, "Error reloading DB %d\n", ret); } return ret; } static int read_in_config_file (char * filename) { confdb_handle_t handle; int result; int ignore; int c; FILE* fh; char buf[1024]; char * line; char * end; char parent_name[OBJ_NAME_SIZE]; if (access (filename, R_OK) != 0) { perror ("Couldn't access file."); return -1; } fh = fopen(filename, "r"); if (fh == NULL) { perror ("Couldn't open file."); return -1; } result = confdb_initialize (&handle, &callbacks); if (result != CONFDB_OK) { fprintf (stderr, "Could not initialize objdb library. Error %d\n", result); fclose (fh); return -1; } while (fgets (buf, 1024, fh) != NULL) { /* find the first real character, if it is * a '#' then ignore this line. * else process. * if no real characters then also ignore. */ ignore = 1; for (c = 0; c < 1024; c++) { if (isblank (buf[c])) continue; if (buf[c] == '#' || buf[c] == '\n') { ignore = 1; break; } ignore = 0; line = &buf[c]; break; } if (ignore == 1) continue; /* kill the \n */ end = strchr (line, '\n'); if (end != NULL) *end = '\0'; if (debug == 2) printf ("%d: %s\n", __LINE__, line); /* find the parent object */ get_parent_name(line, parent_name); if (debug == 2) printf ("%d: %s\n", __LINE__, parent_name); /* create the object */ create_object (handle, parent_name); /* write the attribute */ write_key (handle, line); } reload_db(handle); confdb_finalize (handle); fclose (fh); return 0; } static int print_all(void) { confdb_handle_t handle; int result; result = confdb_initialize (&handle, &callbacks); if (result != CS_OK) { fprintf (stderr, "Could not initialize objdb library. Error %d\n", result); return 1; } print_config_tree(handle, OBJECT_PARENT_HANDLE, NULL); result = confdb_finalize (handle); return 0; } static int print_help(void) { printf("\n"); printf ("usage: corosync-objctl [-b] object%ckey ... Print an object\n", SEPERATOR); printf (" corosync-objctl -c object%cchild_obj ... Create Object\n", SEPERATOR); printf (" corosync-objctl -d object%cchild_obj ... Delete object\n", SEPERATOR); printf (" corosync-objctl -w object%cchild_obj.key=value ... Create a key\n", SEPERATOR); printf (" corosync-objctl -n object%cchild_obj.key=value ... Create a new object with the key\n", SEPERATOR); printf (" corosync-objctl -t object%cchild_obj ... Track changes\n", SEPERATOR); printf (" corosync-objctl [-b] -a Print all objects\n"); printf (" corosync-objctl -p Load in config from the specified file.\n"); printf("\n"); return 0; } static cs_error_t validate_name(char * obj_name_pt) { if ((strchr (obj_name_pt, SEPERATOR) == NULL) && (strchr (obj_name_pt, '=') == NULL)) return CS_OK; else return CS_ERR_INVALID_PARAM; } static void get_parent_name(const char * name_pt, char * parent_name) { char * tmp; strcpy(parent_name, name_pt); /* first remove the value (it could be a file path */ tmp = strchr(parent_name, '='); if (tmp != NULL) { *tmp = '\0'; tmp--; while (isblank (*tmp)) { *tmp = '\0'; tmp--; } } /* then truncate the child name */ tmp = strrchr(parent_name, SEPERATOR); if (tmp != NULL) *tmp = '\0'; } static void get_key(const char * name_pt, char * key_name, char * key_value) { char * tmp = (char*)name_pt; char str_copy[OBJ_NAME_SIZE]; char * copy_tmp = str_copy; int equals_seen = 0; int in_quotes = 0; /* strip out spaces when not in quotes */ while (*tmp != '\0') { if (*tmp == '=') equals_seen = 1; if (equals_seen && *tmp == '"') { if (in_quotes) in_quotes = 0; else in_quotes = 1; } if (*tmp != ' ' || in_quotes) { *copy_tmp = *tmp; copy_tmp++; } tmp++; } *copy_tmp = '\0'; /* first remove the value (it could have a SEPERATOR in it */ tmp = strchr(str_copy, '='); if (tmp != NULL && strlen(tmp) > 0) { strcpy(key_value, tmp+1); *tmp = '\0'; } else { key_value[0] = '\0'; } /* then remove the name */ tmp = strrchr(str_copy, SEPERATOR); if (tmp == NULL) tmp = str_copy; strcpy(key_name, tmp+1); } static cs_error_t find_object (confdb_handle_t handle, char * name_pt, find_object_of_type_t type, hdb_handle_t * out_handle) { char * obj_name_pt; char * save_pt; hdb_handle_t obj_handle; confdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE; char tmp_name[OBJ_NAME_SIZE]; cs_error_t res = CS_OK; strncpy (tmp_name, name_pt, sizeof (tmp_name)); tmp_name[sizeof (tmp_name) - 1] = '\0'; obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt); while (obj_name_pt != NULL) { res = confdb_object_find_start(handle, parent_object_handle); if (res != CS_OK) { fprintf (stderr, "Could not start object_find %d\n", res); exit (EXIT_FAILURE); } res = confdb_object_find(handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) { return res; } parent_object_handle = obj_handle; obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt); } *out_handle = parent_object_handle; return res; } static void read_object(confdb_handle_t handle, char * name_pt) { char parent_name[OBJ_NAME_SIZE]; hdb_handle_t obj_handle; cs_error_t res; get_parent_name(name_pt, parent_name); res = find_object (handle, name_pt, FIND_OBJECT_OR_KEY, &obj_handle); if (res == CS_OK) { print_config_tree(handle, obj_handle, parent_name); } } static void write_key(confdb_handle_t handle, char * path_pt) { hdb_handle_t obj_handle; char parent_name[OBJ_NAME_SIZE]; char key_name[OBJ_NAME_SIZE]; char key_value[OBJ_NAME_SIZE]; char old_key_value[OBJ_NAME_SIZE]; + char *old_key_value_ptr = old_key_value; size_t old_key_value_len; cs_error_t res; confdb_value_types_t type; /* find the parent object */ get_parent_name(path_pt, parent_name); get_key(path_pt, key_name, key_value); if (debug == 1) printf ("%d: key:\"%s\", value:\"%s\"\n", __LINE__, key_name, key_value); if (validate_name(key_name) != CS_OK) { fprintf(stderr, "Incorrect key name, can not have \"=\" or \"%c\"\n", SEPERATOR); exit(EXIT_FAILURE); } res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle); if (res != CS_OK) { fprintf(stderr, "Can't find parent object of \"%s\"\n", path_pt); exit(EXIT_FAILURE); } /* get the current key */ - res = confdb_key_get_typed (handle, + res = confdb_key_get_typed2 (handle, obj_handle, key_name, - old_key_value, + (void**)&old_key_value_ptr, &old_key_value_len, &type); + if (debug == 1 && res==CS_OK) + printf ("%d: key:\"%s\", old value:\"%s\"\n", + __LINE__, key_name, old_key_value); + if (res == CS_OK) { /* replace the current value */ res = confdb_key_replace (handle, obj_handle, key_name, strlen(key_name), old_key_value, old_key_value_len, key_value, strlen(key_value)+1); if (res != CS_OK) fprintf(stderr, "Failed to replace the key %s=%s. Error %d\n", key_name, key_value, res); } else { /* not there, create a new key */ res = confdb_key_create_typed (handle, obj_handle, key_name, key_value, strlen(key_value)+1, CONFDB_VALUETYPE_STRING); if (res != CS_OK) fprintf(stderr, "Failed to create the key %s=%s. Error %d\n", key_name, key_value, res); } } static void create_object(confdb_handle_t handle, char * name_pt) { char * obj_name_pt; char * save_pt; hdb_handle_t obj_handle; hdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE; char tmp_name[OBJ_NAME_SIZE]; cs_error_t res; strncpy (tmp_name, name_pt, sizeof (tmp_name)); tmp_name[sizeof (tmp_name) - 1] = '\0'; obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt); while (obj_name_pt != NULL) { res = confdb_object_find_start(handle, parent_object_handle); if (res != CS_OK) { fprintf (stderr, "Could not start object_find %d\n", res); exit (EXIT_FAILURE); } res = confdb_object_find(handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) { if (validate_name(obj_name_pt) != CS_OK) { fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n", obj_name_pt); exit(EXIT_FAILURE); } if (debug) printf ("%s:%d: %s\n", __func__,__LINE__, obj_name_pt); res = confdb_object_create (handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) fprintf(stderr, "Failed to create object \"%s\". Error %d.\n", obj_name_pt, res); } parent_object_handle = obj_handle; obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt); } } static void create_object_key(confdb_handle_t handle, char *name_pt) { char * obj_name_pt; char * new_obj_name_pt; char * save_pt; hdb_handle_t obj_handle; hdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE; char tmp_name[OBJ_NAME_SIZE]; cs_error_t res; char parent_name[OBJ_NAME_SIZE]; char key_name[OBJ_NAME_SIZE]; char key_value[OBJ_NAME_SIZE]; get_parent_name(name_pt, parent_name); get_key(name_pt, key_name, key_value); strncpy (tmp_name, parent_name, sizeof (tmp_name)); tmp_name[sizeof (tmp_name) - 1] = '\0'; obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt); /* * Create parent object tree */ while (obj_name_pt != NULL) { res = confdb_object_find_start(handle, parent_object_handle); if (res != CS_OK) { fprintf (stderr, "Could not start object_find %d\n", res); exit (EXIT_FAILURE); } new_obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt); res = confdb_object_find(handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK || new_obj_name_pt == NULL) { if (validate_name(obj_name_pt) != CS_OK) { fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n", obj_name_pt); exit(EXIT_FAILURE); } if (debug) printf ("%s:%d: %s\n", __func__,__LINE__, obj_name_pt); res = confdb_object_create (handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) { fprintf(stderr, "Failed to create object \"%s\". Error %d.\n", obj_name_pt, res); } } parent_object_handle = obj_handle; obj_name_pt = new_obj_name_pt; } /* * Create key */ res = confdb_key_create_typed (handle, obj_handle, key_name, key_value, strlen(key_value)+1, CONFDB_VALUETYPE_STRING); if (res != CS_OK) { fprintf(stderr, "Failed to create the key %s=%s. Error %d\n", key_name, key_value, res); } } /* Print "?" in place of any non-printable byte of OBJ. */ static void print_name (FILE *fp, const void *obj, size_t obj_len) { const char *p = obj; size_t i; for (i = 0; i < obj_len; i++) { int c = *p++; if (!isprint (c)) { c = '?'; } fputc (c, fp); } } static void tail_key_changed(confdb_handle_t handle, confdb_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_name_len, const void *key_value_pt, size_t key_value_len) { /* printf("key_changed> %.*s.%.*s=%.*s\n", */ fputs("key_changed> ", stdout); print_name (stdout, object_name_pt, object_name_len); fputs(".", stdout); print_name (stdout, key_name_pt, key_name_len); fputs("=", stdout); print_name (stdout, key_value_pt, key_value_len); fputs("\n", stdout); } static void tail_object_created(confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len) { fputs("object_created>", stdout); print_name(stdout, name_pt, name_len); fputs("\n", stdout); } static void tail_object_deleted(confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len) { fputs("object_deleted>", stdout); print_name(stdout, name_pt, name_len); fputs("\n", stdout); } static void listen_for_object_changes(confdb_handle_t handle) { int result; fd_set read_fds; int select_fd; int quit = CS_FALSE; FD_ZERO (&read_fds); if (confdb_fd_get (handle, &select_fd) != CS_OK) { printf ("can't get the confdb selector object.\n"); return; } printf ("Type \"q\" to finish\n"); do { FD_SET (select_fd, &read_fds); FD_SET (STDIN_FILENO, &read_fds); result = select (select_fd + 1, &read_fds, 0, 0, 0); if (result == -1) { perror ("select\n"); } if (FD_ISSET (STDIN_FILENO, &read_fds)) { char inbuf[3]; if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) quit = CS_TRUE; else if (strncmp(inbuf, "q", 1) == 0) quit = CS_TRUE; } if (FD_ISSET (select_fd, &read_fds)) { if (confdb_dispatch (handle, CONFDB_DISPATCH_ALL) != CS_OK) exit(1); } } while (result && quit == CS_FALSE); (void)confdb_stop_track_changes(handle); } static void track_object(confdb_handle_t handle, char * name_pt) { cs_error_t res; hdb_handle_t obj_handle; res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle); if (res != CS_OK) { fprintf (stderr, "Could not find object \"%s\". Error %d\n", name_pt, res); return; } res = confdb_track_changes (handle, obj_handle, CONFDB_TRACK_DEPTH_RECURSIVE); if (res != CS_OK) { fprintf (stderr, "Could not enable tracking on object \"%s\". Error %d\n", name_pt, res); return; } } static void stop_tracking(confdb_handle_t handle) { cs_error_t res; res = confdb_stop_track_changes (handle); if (res != CS_OK) { fprintf (stderr, "Could not stop tracking. Error %d\n", res); return; } } static void delete_object(confdb_handle_t handle, char * name_pt) { cs_error_t res; hdb_handle_t obj_handle; res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle); if (res == CS_OK) { res = confdb_object_destroy (handle, obj_handle); if (res != CS_OK) fprintf(stderr, "Failed to find object \"%s\" to delete. Error %d\n", name_pt, res); } else { char parent_name[OBJ_NAME_SIZE]; char key_name[OBJ_NAME_SIZE]; char key_value[OBJ_NAME_SIZE]; /* find the parent object */ get_parent_name(name_pt, parent_name); get_key(name_pt, key_name, key_value); res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle); if (res != CS_OK) { fprintf(stderr, "Failed to find the key's parent object \"%s\". Error %d\n", parent_name, res); exit (EXIT_FAILURE); } res = confdb_key_delete (handle, obj_handle, key_name, strlen(key_name), key_value, strlen(key_value)); if (res != CS_OK) fprintf(stderr, "Failed to delete key \"%s=%s\" from object \"%s\". Error %d\n", key_name, key_value, parent_name, res); } } int main (int argc, char *argv[]) { confdb_handle_t handle; cs_error_t result; int c; action = ACTION_READ; for (;;){ c = getopt (argc,argv,"habwncvdtp:"); if (c==-1) { break; } switch (c) { case 'v': debug++; break; case 'h': return print_help(); break; case 'a': action = ACTION_PRINT_ALL; break; case 'b': show_binary++; break; case 'p': return read_in_config_file (optarg); break; case 'c': action = ACTION_CREATE; break; case 'd': action = ACTION_DELETE; break; case 'w': action = ACTION_WRITE; break; case 'n': action = ACTION_CREATE_KEY; break; case 't': action = ACTION_TRACK; break; default : action = ACTION_READ; break; } } if (argc == 1) { action = ACTION_PRINT_DEFAULT; return print_all(); } else if (action == ACTION_PRINT_ALL) { return print_all(); } else if (optind >= argc) { fprintf(stderr, "Expected an object path after options\n"); exit(EXIT_FAILURE); } result = confdb_initialize (&handle, &callbacks); if (result != CS_OK) { fprintf (stderr, "Failed to initialize the objdb API. Error %d\n", result); exit (EXIT_FAILURE); } while (optind < argc) { switch (action) { case ACTION_READ: read_object(handle, argv[optind++]); break; case ACTION_WRITE: write_key(handle, argv[optind++]); break; case ACTION_CREATE: create_object(handle, argv[optind++]); break; case ACTION_CREATE_KEY: create_object_key(handle, argv[optind++]); break; case ACTION_DELETE: delete_object(handle, argv[optind++]); break; case ACTION_TRACK: track_object(handle, argv[optind++]); break; } } if (action == ACTION_TRACK) { listen_for_object_changes(handle); stop_tracking(handle); } else { reload_db(handle); } result = confdb_finalize (handle); if (result != CS_OK) { fprintf (stderr, "Error finalizing objdb API. Error %d\n", result); exit(EXIT_FAILURE); } return 0; }