diff --git a/crm/common/ipc.c b/crm/common/ipc.c index ca1e4bcbdf..d3ee974f64 100644 --- a/crm/common/ipc.c +++ b/crm/common/ipc.c @@ -1,391 +1,474 @@ -/* $Id: ipc.c,v 1.12 2004/11/23 11:12:29 andrew Exp $ */ +/* $Id: ipc.c,v 1.13 2004/12/05 16:29:51 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include IPC_Message *create_simple_message(char *text, IPC_Channel *ch); gboolean send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg); static void free_msg_data(IPC_Message *msg); gboolean send_xmlipc_message(IPC_Channel *ipc_client, xmlNodePtr msg) { int log_level = LOG_DEBUG; char *xml_message = NULL; IPC_Message *cib_dump = NULL; gboolean res; xml_message = dump_xml_unformatted(msg); cib_dump = create_simple_message(xml_message, ipc_client); res = send_ipc_message(ipc_client, cib_dump); /* crm_free(xml_message); */ if(res == FALSE) { log_level = LOG_ERR; } do_crm_log(log_level, __FUNCTION__, "Sending IPC message (ref=%s) to %s@%s %s.", xmlGetProp(msg, XML_ATTR_REFERENCE), xmlGetProp(msg, XML_ATTR_SYSTO), xmlGetProp(msg, XML_ATTR_HOSTTO), res?"succeeded":"failed"); return res; } gboolean send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg) { int lpc = 0; gboolean all_is_good = TRUE; if (msg == NULL) { crm_err("cant send NULL message"); all_is_good = FALSE; } else if (msg->msg_len <= 0) { crm_err("cant send 0 sized message"); all_is_good = FALSE; } else if (msg->msg_len > MAXDATASIZE) { crm_err("cant send msg... too big"); all_is_good = FALSE; } crm_trace("Sending message: %s", crm_str(msg?msg->msg_body:NULL)); crm_verbose("Message is%s valid to send", all_is_good?"":" not"); if (ipc_client == NULL) { all_is_good = FALSE; } crm_verbose("IPC Client is%s set.", all_is_good?"":" not"); if (all_is_good) { while(lpc++ < MAX_IPC_FAIL && ipc_client->ops->send(ipc_client, msg) == IPC_FAIL) { crm_err("ipc channel blocked"); cl_shortsleep(); } } if (lpc == MAX_IPC_FAIL) { crm_err("Could not send IPC, message. Channel is dead."); all_is_good = FALSE; } return all_is_good; } static void free_msg_data(IPC_Message *msg) { crm_free(msg->msg_body); msg->msg_body = NULL; } IPC_Message * create_simple_message(char *text, IPC_Channel *ch) { /* char str[256]; */ IPC_Message *ack_msg = NULL; if (text == NULL) { return NULL; } ack_msg = cl_malloc(sizeof(IPC_Message)); if(ack_msg == NULL) { return NULL; } ack_msg->msg_private = NULL; ack_msg->msg_buf = NULL; ack_msg->msg_ch = ch; ack_msg->msg_body = text; ack_msg->msg_done = free_msg_data; ack_msg->msg_len = strlen(text)+1; return ack_msg; } xmlNodePtr find_xml_in_ipcmessage(IPC_Message *msg, gboolean do_free) { char *buffer = NULL; xmlDocPtr doc; xmlNodePtr root; if (msg == NULL) { crm_trace("IPC Message was empty..."); return NULL; } buffer = (char*)msg->msg_body; doc = xmlParseMemory(buffer, strlen(buffer)); if (do_free) msg->msg_done(msg); if (doc == NULL) { crm_info("IPC Message did not contain an XML buffer..."); return NULL; } root = xmlDocGetRootElement(doc); if (root == NULL) { crm_info("Root node was NULL."); return NULL; } return root; } void default_ipc_connection_destroy(gpointer user_data) { return; } +int +init_server_ipc_comms( + char *channel_name, + gboolean (*channel_client_connect)(IPC_Channel *newclient,gpointer user_data), + void (*channel_connection_destroy)(gpointer user_data)) +{ + /* the clients wait channel is the other source of events. + * This source delivers the clients connection events. + * listen to this source at a relatively lower priority. + */ + + char commpath[SOCKET_LEN]; + IPC_WaitConnection *wait_ch; + + sprintf(commpath, WORKING_DIR "/%s", channel_name); + + wait_ch = wait_channel_init(commpath); + + if (wait_ch == NULL) { + return 1; + } + + G_main_add_IPC_WaitConnection( + G_PRIORITY_LOW, wait_ch, NULL, FALSE, + channel_client_connect, channel_name, + channel_connection_destroy); + crm_debug("Listening on: %s", commpath); + + return 0; +} + +/* GCHSource* */ IPC_Channel * -init_client_ipc_comms(const char *child, - gboolean (*dispatch)(IPC_Channel* source_data - ,gpointer user_data), - crmd_client_t *client_data) +init_client_ipc_comms(const char *channel_name, + gboolean (*dispatch)( + IPC_Channel* source_data, gpointer user_data), + void *client_data) { - IPC_Channel *ch; - GHashTable * attrs; + IPC_Channel *ch = NULL; GCHSource *the_source = NULL; void *callback_data = client_data; - static char path[] = IPC_PATH_ATTR; + if(callback_data == NULL) { + callback_data = ch; + } + + ch = init_client_ipc_comms_nodispatch(channel_name); + + if(ch == NULL) { + crm_err("Setup of client connection failed," + " not adding channel to mainloop"); + + return NULL; + } + + if(dispatch == NULL) { + crm_warn("No dispatch method specified..." + "maybe you meant init_client_ipc_comms_nodispatch()?"); + } else { + crm_debug("Adding dispatch method to channel"); + + the_source = G_main_add_IPC_Channel( + G_PRIORITY_LOW, ch, FALSE, dispatch, callback_data, + default_ipc_connection_destroy); + } + + return ch; +} + +IPC_Channel * +init_client_ipc_comms_nodispatch(const char *channel_name) +{ + IPC_Channel *ch; + GHashTable *attrs; + static char path[] = IPC_PATH_ATTR; + char *commpath = NULL; int local_socket_len = 2; /* 2 = '/' + '\0' */ - local_socket_len += strlen(child); + local_socket_len += strlen(channel_name); local_socket_len += strlen(WORKING_DIR); crm_malloc(commpath, sizeof(char)*local_socket_len); if(commpath != NULL) { - sprintf(commpath, WORKING_DIR "/%s", child); + sprintf(commpath, WORKING_DIR "/%s", channel_name); commpath[local_socket_len - 1] = '\0'; crm_debug("Attempting to talk on: %s", commpath); } attrs = g_hash_table_new(g_str_hash,g_str_equal); g_hash_table_insert(attrs, path, commpath); ch = ipc_channel_constructor(IPC_ANYTYPE, attrs); g_hash_table_destroy(attrs); if (ch == NULL) { crm_crit("Could not access channel on: %s", commpath); return NULL; } else if (ch->ops->initiate_connection(ch) != IPC_OK) { crm_crit("Could not init comms on: %s", commpath); fprintf(stderr, "Could not init comms on: %s\n", commpath); return NULL; } - if(callback_data == NULL) { - callback_data = ch; - } - ch->ops->set_recv_qlen(ch, 100); ch->ops->set_send_qlen(ch, 100); - the_source = G_main_add_IPC_Channel( - G_PRIORITY_LOW, ch, FALSE, dispatch, callback_data, - default_ipc_connection_destroy); - crm_debug("Processing of %s complete", commpath); return ch; } +IPC_WaitConnection * +wait_channel_init(char daemonsocket[]) +{ + IPC_WaitConnection *wait_ch; + mode_t mask; + char path[] = IPC_PATH_ATTR; + GHashTable * attrs; + + + attrs = g_hash_table_new(g_str_hash,g_str_equal); + g_hash_table_insert(attrs, path, daemonsocket); + + mask = umask(0); + wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs); + if (wait_ch == NULL) { + cl_perror("Can't create wait channel of type %s", + IPC_ANYTYPE); + exit(1); + } + mask = umask(mask); + + g_hash_table_destroy(attrs); + + return wait_ch; +} /* * This method adds a copy of xml_response_data */ gboolean send_ipc_request(IPC_Channel *ipc_channel, xmlNodePtr msg_options, xmlNodePtr msg_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *crm_msg_reference) { gboolean was_sent = FALSE; xmlNodePtr request = NULL; request = create_request(msg_options, msg_data, host_to, sys_to, sys_from, uuid_from, crm_msg_reference); was_sent = send_xmlipc_message(ipc_channel, request); free_xml(request); return was_sent; } /* * This method adds a copy of xml_response_data */ gboolean send_ipc_reply(IPC_Channel *ipc_channel, xmlNodePtr xml_request, xmlNodePtr xml_response_data) { gboolean was_sent = FALSE; xmlNodePtr reply; reply = create_reply(xml_request, xml_response_data); if (reply != NULL) { was_sent = send_xmlipc_message(ipc_channel, reply); free_xml(reply); } return was_sent; } gboolean subsystem_msg_dispatch(IPC_Channel *sender, void *user_data) { int lpc = 0; char *buffer = NULL; IPC_Message *msg = NULL; gboolean all_is_well = TRUE; xmlNodePtr root_xml_node = NULL; const char *sys_to; const char *type; while(sender->ops->is_message_pending(sender)) { if (sender->ch_status == IPC_DISCONNECT) { /* The message which was pending for us is that * the IPC status is now IPC_DISCONNECT */ break; } if (sender->ops->recv(sender, &msg) != IPC_OK) { perror("Receive failure:"); return !all_is_well; } if (msg == NULL) { crm_err("No message this time"); continue; } lpc++; buffer = (char*)msg->msg_body; root_xml_node = string2xml(buffer); sys_to= xmlGetProp(root_xml_node, XML_ATTR_SYSTO); type = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE); if (root_xml_node == NULL) { crm_err("Root node was NULL!!"); } else if(sys_to == NULL) { crm_err("Value of %s was NULL!!", XML_ATTR_SYSTO); } else if(type == NULL) { crm_err("Value of %s was NULL!!", XML_ATTR_MSGTYPE); } else { gboolean (*process_function) (xmlNodePtr msg, IPC_Channel *sender) = NULL; process_function = user_data; if(process_function(root_xml_node, sender) == FALSE) { crm_warn("Received a message destined for %s" " by mistake", sys_to); } } free_xml(root_xml_node); root_xml_node = NULL; msg->msg_done(msg); msg = NULL; } /* clean up after a break */ if(msg != NULL) msg->msg_done(msg); if(root_xml_node != NULL) free_xml(root_xml_node); crm_verbose("Processed %d messages", lpc); if (sender->ch_status == IPC_DISCONNECT) { crm_err("The server has left us: Shutting down...NOW"); exit(1); /* shutdown properly later */ return !all_is_well; } return all_is_well; } + diff --git a/crm/common/utils.c b/crm/common/utils.c index 88386958b8..c7faf19a42 100644 --- a/crm/common/utils.c +++ b/crm/common/utils.c @@ -1,394 +1,400 @@ -/* $Id: utils.c,v 1.17 2004/09/20 12:19:27 andrew Exp $ */ +/* $Id: utils.c,v 1.18 2004/12/05 16:29:51 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXLINE 512 static uint ref_counter = 0; const char * generateReference(const char *custom1, const char *custom2) { const char *local_cust1 = custom1; const char *local_cust2 = custom2; int reference_len = 4; char *since_epoch = NULL; reference_len += 20; /* too big */ reference_len += 40; /* too big */ if(local_cust1 == NULL) local_cust1 = "_empty_"; reference_len += strlen(local_cust1); if(local_cust2 == NULL) local_cust2 = "_empty_"; reference_len += strlen(local_cust2); crm_malloc(since_epoch, reference_len*(sizeof(char))); if(since_epoch != NULL) { sprintf(since_epoch, "%s-%s-%ld-%u", local_cust1, local_cust2, (unsigned long)time(NULL), ref_counter++); } return since_epoch; } gboolean decodeNVpair(const char *srcstring, char separator, char **name, char **value) { int lpc = 0; int len = 0; const char *temp = NULL; crm_trace("Attempting to decode: [%s]", srcstring); if (srcstring != NULL) { len = strlen(srcstring); while(lpc <= len) { if (srcstring[lpc] == separator || srcstring[lpc] == '\0') { crm_malloc(*name, sizeof(char)*lpc+1); if(*name == NULL) { break; /* and return FALSE */ } strncpy(*name, srcstring, lpc); (*name)[lpc] = '\0'; /* this sucks but as the strtok manpage says.. * it *is* a bug */ len = len-lpc; len--; if(len <= 0) { *value = NULL; } else { crm_malloc(*value, sizeof(char)*len+1); if(*value == NULL) { crm_free(*name); break; /* and return FALSE */ } temp = srcstring+lpc+1; strncpy(*value, temp, len); (*value)[len] = '\0'; } return TRUE; } lpc++; } } *name = NULL; *value = NULL; return FALSE; } char * generate_hash_key(const char *crm_msg_reference, const char *sys) { int ref_len = strlen(sys?sys:"none") + strlen(crm_msg_reference) + 2; char *hash_key = NULL; crm_malloc(hash_key, sizeof(char)*(ref_len)); if(hash_key != NULL) { sprintf(hash_key, "%s_%s", sys?sys:"none", crm_msg_reference); hash_key[ref_len-1] = '\0'; crm_debug("created hash key: (%s)", hash_key); } return hash_key; } char * generate_hash_value(const char *src_node, const char *src_subsys) { int ref_len; char *hash_value; if (src_node == NULL || src_subsys == NULL) { return NULL; } if (strcmp(CRM_SYSTEM_DC, src_subsys) == 0) { hash_value = crm_strdup(src_subsys); if (!hash_value) { crm_err("memory allocation failed in " "generate_hash_value()\n"); return NULL; } return hash_value; } ref_len = strlen(src_subsys) + strlen(src_node) + 2; crm_malloc(hash_value, sizeof(char)*(ref_len)); if (!hash_value) { crm_err("memory allocation failed in " "generate_hash_value()\n"); return NULL; } snprintf(hash_value, ref_len-1, "%s_%s", src_node, src_subsys); hash_value[ref_len-1] = '\0';/* make sure it is null terminated */ crm_info("created hash value: (%s)", hash_value); return hash_value; } gboolean decode_hash_value(gpointer value, char **node, char **subsys) { char *char_value = (char*)value; int value_len = strlen(char_value); crm_info("Decoding hash value: (%s:%d)", char_value, value_len); if (strcmp(CRM_SYSTEM_DC, (char*)value) == 0) { *node = NULL; *subsys = (char*)crm_strdup(char_value); if (*subsys == NULL) { crm_err("memory allocation failed in " "decode_hash_value()\n"); return FALSE; } crm_info("Decoded value: (%s:%d)", *subsys, (int)strlen(*subsys)); return TRUE; } else if (char_value != NULL) { if (decodeNVpair(char_value, '_', node, subsys)) { return TRUE; } else { *node = NULL; *subsys = NULL; return FALSE; } } return FALSE; } char * crm_itoa(int an_int) { int len = 32; char *buffer = NULL; crm_malloc(buffer, sizeof(char)*(len+1)); if(buffer != NULL) { snprintf(buffer, len, "%d", an_int); } return buffer; } unsigned int crm_log_level = LOG_INFO; /* returns the old value */ unsigned int set_crm_log_level(unsigned int level) { unsigned int old = crm_log_level; while(crm_log_level < level) { alter_debug(DEBUG_INC); } while(crm_log_level > level) { alter_debug(DEBUG_DEC); } return old; } unsigned int get_crm_log_level(void) { return crm_log_level; } void do_crm_log(int log_level, const char *function, const char *fmt, ...) { int log_as = log_level; gboolean do_log = FALSE; if(log_level < LOG_INFO) { do_log = TRUE; } else if(log_level <= crm_log_level) { do_log = TRUE; if(log_level != LOG_INFO) { log_as = LOG_DEBUG; } } if(do_log) { va_list ap; char buf[MAXLINE]; int nbytes; memset(buf, EOS, sizeof(buf)-1); /* buf[MAXLINE-1] = EOS; */ va_start(ap, fmt); nbytes=vsnprintf(buf, sizeof(buf)-1, fmt, ap); va_end(ap); if(function == NULL) { cl_log(log_as, "[%d] %s", log_level, buf); } else { cl_log(log_as, "(%s [%d]) %s", function,log_level,buf); } } } int compare_version(const char *version1, const char *version2) { int lpc = 0; char *step1 = NULL, *step2 = NULL; char *rest1 = NULL, *rest2 = NULL; if(version1 != NULL) { rest1 = crm_strdup(version1); } else { version1 = ""; } if(version2 != NULL) { rest2 = crm_strdup(version2); } else { version2 = ""; } while(1) { int cmp = 0; int step1_i = 0; int step2_i = 0; char *tmp1 = NULL, *tmp2 = NULL; decodeNVpair(rest1, '.', &step1, &tmp1); decodeNVpair(rest2, '.', &step2, &tmp2); if(step1 != NULL) { step1_i = atoi(step1); } if(step2 != NULL) { step2_i = atoi(step2); } if(step1_i < step2_i){ cmp = -1; } else if (step1_i > step2_i){ cmp = 1; } crm_trace("compare[%d (%d)]: %d(%s) %d(%s)", lpc++, cmp, step1_i, crm_str(step1), step2_i, crm_str(step2)); crm_free(rest1); crm_free(rest2); rest1 = tmp1; rest2 = tmp2; if(step1 == NULL && step2 == NULL) { break; } crm_free(step1); crm_free(step2); if(cmp < 0) { crm_verbose("%s < %s", version1, version2); return -1; } else if(cmp > 0) { crm_verbose("%s > %s", version1, version2); return 1; } } crm_verbose("%s == %s", version1, version2); return 0; } gboolean do_stderr = FALSE; void alter_debug(int nsig) { CL_SIGNAL(DEBUG_INC, alter_debug); CL_SIGNAL(DEBUG_DEC, alter_debug); switch(nsig) { case DEBUG_INC: if(do_stderr == FALSE && crm_log_level == LOG_INFO) { do_stderr = TRUE; cl_log_enable_stderr(do_stderr); break; } crm_log_level++; fprintf(stderr, "Upped log level to %d\n", crm_log_level); cl_log(LOG_INFO, "Upped log level to %d\n", crm_log_level); break; case DEBUG_DEC: if(do_stderr && crm_log_level == LOG_INFO) { do_stderr = FALSE; cl_log_enable_stderr(do_stderr); break; } crm_log_level--; fprintf(stderr, "Reduced log level to %d\n", crm_log_level); cl_log(LOG_INFO, "Reduced log level to %d\n", crm_log_level); break; default: fprintf(stderr, "Unknown signal %d\n", nsig); cl_log(LOG_ERR, "Unknown signal %d\n", nsig); break; } } + + +void g_hash_destroy_str(gpointer data) +{ + crm_free(data); +} diff --git a/crm/common/xml.c b/crm/common/xml.c index a624a649c0..1303c15d38 100644 --- a/crm/common/xml.c +++ b/crm/common/xml.c @@ -1,732 +1,737 @@ -/* $Id: xml.c,v 1.19 2004/10/21 18:25:42 andrew Exp $ */ +/* $Id: xml.c,v 1.20 2004/12/05 16:29:51 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void dump_array(int log_level, const char *message, const char **array, int depth); xmlNodePtr find_xml_node(xmlNodePtr root, const char * search_path) { if(search_path == NULL) { crm_warn("Will never find "); return NULL; } xml_child_iter( root, a_child, search_path, crm_trace("returning node (%s).", xmlGetNodePath(a_child)); crm_trace("contents\t%s", dump_xml_formatted(a_child)); crm_trace("found in\t%s", dump_xml_formatted(root)); return a_child; ); crm_warn("Could not find %s in %s.", search_path, xmlGetNodePath(root)); return NULL; } xmlNodePtr find_xml_node_nested(xmlNodePtr root, const char **search_path, int len) { int j; gboolean is_found = TRUE; xmlNodePtr match = NULL; xmlNodePtr lastMatch = root; if(search_path == NULL || search_path[0] == NULL) { crm_warn("Will never find NULL"); return NULL; } dump_array(LOG_TRACE, "Looking for.", search_path, len); for (j=0; j < len; ++j) { if (search_path[j] == NULL) { /* a NULL also means stop searching */ break; } match = find_xml_node(lastMatch, search_path[j]); if(match == NULL) { is_found = FALSE; break; } else { lastMatch = match; } } if (is_found) { crm_trace("returning node (%s).", xmlGetNodePath(lastMatch)); crm_trace("found\t%s", dump_xml_formatted(lastMatch)); crm_trace("in \t%s", dump_xml_formatted(root)); return lastMatch; } dump_array(LOG_WARNING, "Could not find the full path to the node you specified.", search_path, len); crm_warn("Closest point was node (%s) starting from %s.", xmlGetNodePath(lastMatch), root?root->name:NULL); return NULL; } const char * get_xml_attr(xmlNodePtr parent, const char *node_name, const char *attr_name, gboolean error) { if(node_name == NULL) { /* get it from the current node */ return get_xml_attr_nested(parent, NULL, 0, attr_name, error); } return get_xml_attr_nested(parent, &node_name, 1, attr_name, error); } const char * get_xml_attr_nested(xmlNodePtr parent, const char **node_path, int length, const char *attr_name, gboolean error) { const char *attr_value = NULL; xmlNodePtr attr_parent = NULL; if(parent == NULL) { crm_err("Can not find attribute %s in NULL parent", attr_name); return NULL; } if(attr_name == NULL || strlen(attr_name) == 0) { crm_err("Can not find attribute with no name in %s", xmlGetNodePath(parent)); return NULL; } if(length == 0) { attr_parent = parent; } else { attr_parent = find_xml_node_nested(parent, node_path, length); if(attr_parent == NULL && error) { crm_err("No node at the path you specified."); return NULL; } } attr_value = xmlGetProp(attr_parent, attr_name); if((attr_value == NULL || strlen(attr_value) == 0) && error) { crm_err( "No value present for %s at %s", attr_name, xmlGetNodePath(attr_parent)); return NULL; } return attr_value; } xmlNodePtr set_xml_attr( xmlNodePtr parent, const char *node_name, const char *attr_name, const char *attr_value, gboolean create) { xmlNodePtr node = parent; xmlAttrPtr result = NULL; if(node_name != NULL) { crm_trace("Setting %s=%s at [%s [%s]]", attr_name, attr_value, xmlGetNodePath(parent), node_name); node = find_xml_node(parent, node_name); if(node == NULL && create) { node = create_xml_node(parent, node_name); if(parent == NULL) { parent = node; } } } if(node == NULL) { crm_warn("Can not set attribute on NULL node"); return NULL; } result = set_xml_property_copy(node, attr_name, attr_value); if(result == NULL) { crm_warn("Could not set %s=%s at %s (found in %s)", attr_name, attr_value, xmlGetNodePath(node), xmlGetNodePath(parent)); } return parent; } xmlNodePtr find_entity(xmlNodePtr parent, const char *node_name, const char *id, gboolean siblings) { while(parent != NULL) { xml_child_iter( parent, a_child, node_name, if(id == NULL || safe_str_eq(id,xmlGetProp(a_child,XML_ATTR_ID))){ crm_debug("returning node (%s).", xmlGetNodePath(a_child)); return a_child; } ); if(siblings) { parent = parent->next; } else { break; } } crm_warn("node <%s id=%s> not found in %s.", node_name, id, xmlGetNodePath(parent)); return NULL; } void copy_in_properties(xmlNodePtr target, xmlNodePtr src) { if(src == NULL) { crm_err("No node to copy properties from"); } else if (src->properties == NULL) { crm_info("No properties to copy"); } else if (target == NULL) { crm_err("No node to copy properties into"); } else { #ifndef USE_BUGGY_LIBXML xmlAttrPtr prop_iter = NULL; prop_iter = src->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(src, local_prop_name); set_xml_property_copy(target, local_prop_name, local_prop_value); prop_iter = prop_iter->next; } #else xmlCopyPropList(target, src->properties); #endif } return; } xmlNodePtr add_node_copy(xmlNodePtr new_parent, xmlNodePtr xml_node) { xmlNodePtr node_copy = NULL; if(xml_node != NULL && new_parent != NULL) { node_copy = copy_xml_node_recursive(xml_node); xmlAddChild(new_parent, node_copy); } else if(xml_node == NULL) { crm_err("Could not add copy of NULL node"); } else { crm_err("Could not add copy of node to NULL parent"); } return node_copy; } xmlAttrPtr set_xml_property_copy(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { const char *parent_name = NULL; const char *local_name = NULL; const char *local_value = NULL; xmlAttrPtr ret_value = NULL; if(node != NULL) { parent_name = node->name; } crm_trace("[%s] Setting %s to %s",crm_str(parent_name), name, value); if (name == NULL || strlen(name) <= 0) { ret_value = NULL; } else if(node == NULL || parent_name == NULL) { ret_value = NULL; } else if (value == NULL || strlen(value) <= 0) { ret_value = NULL; xmlUnsetProp(node, local_name); /* set_node_tstamp(node); */ } else { local_value = crm_strdup(value); local_name = crm_strdup(name); xmlUnsetProp(node, local_name); ret_value = xmlSetProp(node, local_name, local_value); /* set_node_tstamp(node); */ } return ret_value; } xmlNodePtr create_xml_node(xmlNodePtr parent, const char *name) { const char *local_name = NULL; const char *parent_name = NULL; xmlNodePtr ret_value = NULL; if (name == NULL || strlen(name) < 1) { ret_value = NULL; } else { local_name = crm_strdup(name); if(parent == NULL) ret_value = xmlNewNode(NULL, local_name); else { parent_name = parent->name; ret_value = xmlNewChild(parent, NULL, local_name, NULL); } } crm_trace("Created node [%s [%s]]", crm_str(parent_name), crm_str(local_name)); /* set_node_tstamp(ret_value); */ return ret_value; } void unlink_xml_node(xmlNodePtr node) { xmlUnlinkNode(node); /* this helps us with frees and really should be being done by * the library call */ node->doc = NULL; } void free_xml(xmlNodePtr a_node) { if(a_node == NULL) { ; /* nothing to do */ } else if (a_node->doc != NULL) { xmlFreeDoc(a_node->doc); } else { /* make sure the node is unlinked first */ xmlUnlinkNode(a_node); xmlFreeNode(a_node); } return; } void set_node_tstamp(xmlNodePtr a_node) { char *since_epoch = NULL; time_t a_time = time(NULL); if(a_time == (time_t)-1) { cl_perror("set_node_tstamp(): Invalid time returned"); return; } crm_malloc(since_epoch, 128*(sizeof(char))); if(since_epoch != NULL) { sprintf(since_epoch, "%ld", (unsigned long)a_time); xmlUnsetProp(a_node, XML_ATTR_TSTAMP); xmlSetProp(a_node, XML_ATTR_TSTAMP, since_epoch); } } xmlNodePtr copy_xml_node_recursive(xmlNodePtr src_node) { #if XML_TRACE const char *local_name = NULL; xmlNodePtr local_node = NULL, local_child = NULL; xmlAttrPtr prop_iter = NULL; if(src_node != NULL && src_node->name != NULL) { local_node = create_xml_node(NULL, src_node->name); prop_iter = src_node->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(src_node, local_prop_name); set_xml_property_copy(local_node, local_prop_name, local_prop_value); prop_iter = prop_iter->next; } xml_child_iter( node_iter, src_node, NULL, local_child = copy_xml_node_recursive(node_iter); if(local_child != NULL) { xmlAddChild(local_node, local_child); crm_trace("Copied node [%s [%s]", local_name, local_child->name); } ); crm_trace("Returning [%s]", local_node->name); return local_node; } crm_trace("Returning null"); return NULL; #else xmlNodePtr new_xml = xmlCopyNode(src_node, 1); /* set_node_tstamp(new_xml); */ return new_xml; #endif } xmlNodePtr string2xml(const char *input) { char ch = 0; - int lpc = 0, input_len = strlen(input); + int lpc = 0, input_len = 0; gboolean more = TRUE; gboolean inTag = FALSE; xmlNodePtr xml_object = NULL; const char *the_xml; xmlDocPtr doc; + xmlBufferPtr xml_buffer = NULL; - xmlBufferPtr xml_buffer = xmlBufferCreate(); + if(input == NULL || (input_len = strlen(input)) < 0) { + return NULL; + } + + xml_buffer = xmlBufferCreate(); for(lpc = 0; (lpc < input_len) && more; lpc++) { ch = input[lpc]; switch(ch) { case EOF: case 0: ch = 0; more = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '>': case '<': inTag = TRUE; if(ch == '>') inTag = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '\n': case '\t': case ' ': ch = ' '; if(inTag) { xmlBufferAdd(xml_buffer, &ch, 1); } break; default: xmlBufferAdd(xml_buffer, &ch, 1); break; } } xmlInitParser(); the_xml = xmlBufferContent(xml_buffer); doc = xmlParseMemory(the_xml, strlen(the_xml)); xmlCleanupParser(); if (doc == NULL) { crm_err("Malformed XML [xml=%s]", the_xml); xmlBufferFree(xml_buffer); return NULL; } xmlBufferFree(xml_buffer); xml_object = xmlDocGetRootElement(doc); return xml_object; } xmlNodePtr file2xml(FILE *input) { char ch = 0; gboolean more = TRUE; gboolean inTag = FALSE; xmlNodePtr xml_object = NULL; xmlBufferPtr xml_buffer = xmlBufferCreate(); const char *the_xml; xmlDocPtr doc; if(input == NULL) { crm_err("File pointer was NULL"); return NULL; } while (more) { ch = fgetc(input); /* crm_debug("Got [%c]", ch); */ switch(ch) { case EOF: case 0: ch = 0; more = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '>': case '<': inTag = TRUE; if(ch == '>') inTag = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '\n': case '\t': case ' ': ch = ' '; if(inTag) { xmlBufferAdd(xml_buffer, &ch, 1); } break; default: xmlBufferAdd(xml_buffer, &ch, 1); break; } } xmlInitParser(); the_xml = xmlBufferContent(xml_buffer); doc = xmlParseMemory(the_xml, strlen(the_xml)); xmlCleanupParser(); if (doc == NULL) { crm_err("Malformed XML [xml=%s]", the_xml); xmlBufferFree(xml_buffer); return NULL; } xmlBufferFree(xml_buffer); xml_object = xmlDocGetRootElement(doc); crm_xml_devel(xml_object, "Created fragment"); return xml_object; } void dump_array(int log_level, const char *message, const char **array, int depth) { int j; if(message != NULL) { do_crm_log(log_level, __FUNCTION__, "%s", message); } do_crm_log(log_level, __FUNCTION__, "Contents of the array:"); if(array == NULL || array[0] == NULL || depth == 0) { do_crm_log(log_level, __FUNCTION__, "\t"); return; } for (j=0; j < depth && array[j] != NULL; j++) { if (array[j] == NULL) break; do_crm_log(log_level, __FUNCTION__, "\t--> (%s).", array[j]); } } int write_xml_file(xmlNodePtr xml_node, const char *filename) { int res = 0; xmlDocPtr foo = NULL; char now_str[26]; time_t now; crm_debug("Writing XML out to %s", filename); if (xml_node == NULL) { return -1; } else if (xml_node->doc == NULL) { crm_trace("Creating doc pointer for %s", xml_node->name); foo = xmlNewDoc("1.0"); xmlDocSetRootElement(foo, xml_node); xmlSetTreeDoc(xml_node, foo); } now = time(NULL); ctime_r(&now, now_str); set_xml_property_copy(xml_node, "last_written",now_str); /* save it. * set arg 3 to 0 to disable line breaks,1 to enable * res == num bytes saved */ res = xmlSaveFormatFile(filename, xml_node->doc, 1); /* for some reason, reading back after saving with * line-breaks doesnt go real well */ crm_debug("Saved %d bytes to the Cib as XML", res); return res; } char * dump_xml_formatted(xmlNodePtr an_xml_node) { int len = 0; xmlChar *xml_buffer = NULL; char *buffer = NULL; xmlDocPtr foo = NULL; xmlNodePtr xml_node = copy_xml_node_recursive(an_xml_node); if (xml_node == NULL) { return NULL; } else { /* reset the doc pointer */ crm_trace("Creating doc pointer for %s", xml_node->name); foo = xmlNewDoc("1.0"); xmlDocSetRootElement(foo, xml_node); xmlSetTreeDoc(xml_node, foo); crm_trace("Doc pointer set for %s", xml_node->name); } crm_trace("Initializing Parser"); xmlInitParser(); crm_trace("Dumping data"); xmlDocDumpFormatMemory(xml_node->doc, &xml_buffer, &len,1); crm_trace("Cleaning up parser"); xmlCleanupParser(); crm_trace("Copying memory into crm_ space"); if(xml_buffer != NULL && len > 0) { /* copy the text into crm_ memory */ buffer = crm_strdup(xml_buffer); xmlFree(xml_buffer); } crm_trace("Buffer coppied"); free_xml(xml_node); return buffer; } void print_xml_formatted (int log_level, const char *function, xmlNodePtr msg, const char *text) { char *msg_buffer; if(msg == NULL) { do_crm_log(log_level, function, "%s: %s", crm_str(text), ""); return; } crm_trace("dumping XML to char *"); msg_buffer = dump_xml_formatted(msg); do_crm_log(log_level, function, "%s: %s", crm_str(text), crm_str(msg_buffer)); crm_trace("Freeing char * buffer"); crm_free(msg_buffer); crm_trace("Free-d char * buffer"); return; } char * dump_xml_unformatted(xmlNodePtr an_xml_node) { int len = 0; xmlBufferPtr xml_buffer; xmlChar *buffer = NULL; if (an_xml_node == NULL) { return NULL; } crm_trace("Initializing Parser"); xmlInitParser(); crm_trace("Dumping data"); xml_buffer = xmlBufferCreate(); len = xmlNodeDump(xml_buffer, an_xml_node->doc, an_xml_node, 0, 0); if(len < 0) { crm_err("Error dumping xml"); xmlBufferFree(xml_buffer); return NULL; } buffer = (xmlChar*)crm_strdup(xmlBufferContent(xml_buffer)); xmlBufferFree(xml_buffer); if (!buffer) { crm_err("memory allocation failed"); } crm_trace("Cleaning up parser"); xmlCleanupParser(); return buffer; }