mirror of https://github.com/sipwise/heartbeat.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
9.3 KiB
324 lines
9.3 KiB
/*
|
|
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
|
|
*
|
|
* 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
|
|
*/
|
|
#ifndef CRM_COMMON_XML__H
|
|
#define CRM_COMMON_XML__H
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
|
|
#include <ha_msg.h>
|
|
#include <clplumbing/cl_log.h>
|
|
|
|
/* #define USE_LIBXML 1 */
|
|
#if CRM_DEV_BUILD
|
|
# define XML_PARANOIA_CHECKS 1
|
|
#else
|
|
# define XML_PARANOIA_CHECKS 0
|
|
#endif
|
|
|
|
#ifdef USE_LIBXML
|
|
# include <libxml/tree.h>
|
|
typedef xmlNode crm_data_t;
|
|
#else
|
|
typedef struct ha_msg crm_data_t;
|
|
#endif
|
|
|
|
extern gboolean add_message_xml(
|
|
HA_Message *msg, const char *field, const crm_data_t *xml);
|
|
extern crm_data_t *get_message_xml(HA_Message *msg, const char *field);
|
|
extern GHashTable *xml2list(crm_data_t *parent);
|
|
#if CRM_DEPRECATED_SINCE_2_0_3
|
|
extern GHashTable *xml2list_202(crm_data_t *parent);
|
|
#endif
|
|
extern void hash2nvpair(gpointer key, gpointer value, gpointer user_data);
|
|
extern void hash2field(gpointer key, gpointer value, gpointer user_data);
|
|
extern void hash2metafield(gpointer key, gpointer value, gpointer user_data);
|
|
|
|
extern gboolean do_id_check(crm_data_t *xml_obj, GHashTable *id_hash,
|
|
gboolean silent_add, gboolean silent_rename);
|
|
|
|
/*
|
|
* Replacement function for xmlCopyPropList which at the very least,
|
|
* doesnt work the way *I* would expect it to.
|
|
*
|
|
* Copy all the attributes/properties from src into target.
|
|
*
|
|
* Not recursive, does not return anything.
|
|
*
|
|
*/
|
|
extern void copy_in_properties(crm_data_t *target, const crm_data_t *src);
|
|
|
|
/*
|
|
* Find a child named search_path[i] at level i in the XML fragment where i=0
|
|
* is an immediate child of <i>root</i>.
|
|
*
|
|
* Terminate with success if i == len, or search_path[i] == NULL.
|
|
*
|
|
* On success, returns the sub-fragment described by search_path.
|
|
* On failure, returns NULL.
|
|
*/
|
|
extern crm_data_t *find_xml_node_nested(
|
|
crm_data_t *root, const char **search_path, int len);
|
|
|
|
|
|
/*
|
|
* Find a child named search_path[i] at level i in the XML fragment where i=0
|
|
* is an immediate child of <i>root</i>.
|
|
*
|
|
* Once the last child specified by node_path is found, find the value
|
|
* of attr_name.
|
|
*
|
|
* If <i>error<i> is set to TRUE, then it is an error for the attribute not
|
|
* to be found and the function will log accordingly.
|
|
*
|
|
* On success, returns the value of attr_name.
|
|
* On failure, returns NULL.
|
|
*/
|
|
extern const char *get_xml_attr_nested(crm_data_t *parent,
|
|
const char **node_path, int length,
|
|
const char *attr_name, gboolean error);
|
|
|
|
#define free_xml(a_node) do { \
|
|
if(a_node != NULL) { \
|
|
crm_validate_data(a_node); \
|
|
ha_msg_del(a_node); \
|
|
} \
|
|
} while(0)
|
|
|
|
void free_xml_from_parent(crm_data_t *parent, crm_data_t *a_node);
|
|
#define zap_xml_from_parent(parent, xml_obj) free_xml_from_parent(parent, xml_obj); xml_obj = NULL
|
|
|
|
|
|
/*
|
|
* Create a node named "name" as a child of "parent"
|
|
* If parent is NULL, creates an unconnected node.
|
|
*
|
|
* Returns the created node
|
|
*
|
|
*/
|
|
extern crm_data_t *create_xml_node(crm_data_t *parent, const char *name);
|
|
|
|
/*
|
|
* Make a copy of name and value and use the copied memory to create
|
|
* an attribute for node.
|
|
*
|
|
* If node, name or value are NULL, nothing is done.
|
|
*
|
|
* If name or value are an empty string, nothing is done.
|
|
*
|
|
* Returns FALSE on failure and TRUE on success.
|
|
*
|
|
*/
|
|
extern const char *crm_xml_add(
|
|
crm_data_t *node, const char *name, const char *value);
|
|
|
|
extern const char *crm_xml_add_int(
|
|
crm_data_t* node, const char *name, int value);
|
|
|
|
/*
|
|
* Unlink the node and set its doc pointer to NULL so free_xml()
|
|
* will act appropriately
|
|
*/
|
|
extern void unlink_xml_node(crm_data_t *node);
|
|
|
|
/*
|
|
* Set a timestamp attribute on a_node
|
|
*/
|
|
extern void add_xml_tstamp(crm_data_t *a_node);
|
|
|
|
/*
|
|
*
|
|
*/
|
|
extern void purge_diff_markers(crm_data_t *a_node);
|
|
|
|
/*
|
|
* Returns a deep copy of src_node
|
|
*
|
|
*/
|
|
extern crm_data_t *copy_xml(const crm_data_t *src_node);
|
|
|
|
/*
|
|
* Add a copy of xml_node to new_parent
|
|
*/
|
|
extern crm_data_t *add_node_copy(
|
|
crm_data_t *new_parent, const crm_data_t *xml_node);
|
|
|
|
extern int add_node_nocopy(crm_data_t *parent, const char *name, crm_data_t *child);
|
|
|
|
|
|
/*
|
|
* XML I/O Functions
|
|
*
|
|
* Whitespace between tags is discarded.
|
|
*/
|
|
extern crm_data_t *file2xml(FILE *input, gboolean compressed);
|
|
|
|
extern crm_data_t *stdin2xml(void);
|
|
|
|
extern crm_data_t *string2xml(const char *input);
|
|
|
|
extern int write_xml_file(
|
|
crm_data_t *xml_node, const char *filename, gboolean compress);
|
|
|
|
extern char *dump_xml_formatted(const crm_data_t *msg);
|
|
|
|
extern char *dump_xml_unformatted(const crm_data_t *msg);
|
|
|
|
extern void print_xml_formatted(
|
|
int log_level, const char *function,
|
|
const crm_data_t *an_xml_node, const char *text);
|
|
|
|
/*
|
|
* Diff related Functions
|
|
*/
|
|
extern crm_data_t *diff_xml_object(
|
|
crm_data_t *left, crm_data_t *right, gboolean suppress);
|
|
|
|
extern void log_xml_diff(unsigned int log_level, crm_data_t *diff, const char *function);
|
|
|
|
extern gboolean apply_xml_diff(
|
|
crm_data_t *old, crm_data_t *diff, crm_data_t **new);
|
|
|
|
|
|
/*
|
|
* Searching & Modifying
|
|
*/
|
|
extern crm_data_t *find_xml_node(
|
|
crm_data_t *cib, const char * node_path, gboolean must_find);
|
|
|
|
extern crm_data_t *find_entity(
|
|
crm_data_t *parent, const char *node_name, const char *id);
|
|
|
|
extern crm_data_t *subtract_xml_object(
|
|
crm_data_t *left, crm_data_t *right, const char *marker);
|
|
|
|
extern int add_xml_object(
|
|
crm_data_t *parent, crm_data_t *target, const crm_data_t *update);
|
|
|
|
extern void xml_remove_prop(crm_data_t *obj, const char *name);
|
|
|
|
extern gboolean replace_xml_child(
|
|
crm_data_t *parent, crm_data_t *child, crm_data_t *update, gboolean delete_only);
|
|
|
|
extern gboolean update_xml_child(crm_data_t *child, crm_data_t *to_update);
|
|
|
|
extern int find_xml_children(
|
|
crm_data_t **children, crm_data_t *root,
|
|
const char *tag, const char *field, const char *value,
|
|
gboolean search_matches);
|
|
|
|
/*
|
|
*
|
|
*/
|
|
extern const char *crm_element_value(const crm_data_t *data, const char *name);
|
|
extern char *crm_element_value_copy(const crm_data_t *data, const char *name);
|
|
|
|
extern const char *crm_element_name(const crm_data_t *data);
|
|
|
|
extern void xml_validate(const crm_data_t *root);
|
|
|
|
extern gboolean xml_has_children(const crm_data_t *root);
|
|
|
|
extern char *calculate_xml_digest(crm_data_t *local_cib, gboolean sort, gboolean do_filter);
|
|
|
|
extern gboolean validate_with_dtd(
|
|
crm_data_t *xml_blob, gboolean to_logs, const char *dtd_file);
|
|
|
|
#if XML_PARANOIA_CHECKS
|
|
# define crm_validate_data(obj) xml_validate(obj)
|
|
#else
|
|
# define crm_validate_data(obj) CRM_DEV_ASSERT(obj != NULL)
|
|
#endif
|
|
|
|
#define xml_child_iter(parent, child, loop_code) \
|
|
if(parent != NULL) { \
|
|
int __counter = 0; \
|
|
crm_data_t *child = NULL; \
|
|
crm_validate_data(parent); \
|
|
for (__counter = 0; __counter < parent->nfields; __counter++) { \
|
|
if(parent->types[__counter] != FT_STRUCT \
|
|
&& parent->types[__counter] != FT_UNCOMPRESS) { \
|
|
continue; \
|
|
} \
|
|
child = parent->values[__counter]; \
|
|
if(child == NULL) { \
|
|
crm_debug_4("Skipping %s == NULL", \
|
|
parent->names[__counter]); \
|
|
} else { \
|
|
loop_code; \
|
|
} \
|
|
} \
|
|
} else { \
|
|
crm_debug_4("Parent of loop was NULL"); \
|
|
}
|
|
|
|
#define xml_child_iter_filter(parent, child, filter, loop_code) \
|
|
if(parent != NULL) { \
|
|
int __counter = 0; \
|
|
crm_data_t *child = NULL; \
|
|
crm_validate_data(parent); \
|
|
for (__counter = 0; __counter < parent->nfields; __counter++) { \
|
|
if(parent->types[__counter] != FT_STRUCT \
|
|
&& parent->types[__counter] != FT_UNCOMPRESS) { \
|
|
continue; \
|
|
} \
|
|
child = parent->values[__counter]; \
|
|
if(child == NULL) { \
|
|
crm_debug_4("Skipping %s == NULL", \
|
|
parent->names[__counter]); \
|
|
} else if(filter == NULL/*constant condition*/ \
|
|
|| safe_str_eq(filter, parent->names[__counter])) { \
|
|
loop_code; \
|
|
} else { \
|
|
crm_debug_4("Skipping <%s../>", \
|
|
parent->names[__counter]); \
|
|
} \
|
|
} \
|
|
} else { \
|
|
crm_debug_4("Parent of loop was NULL"); \
|
|
}
|
|
|
|
#define xml_prop_iter(parent, prop_name, prop_value, code) if(parent != NULL) { \
|
|
const char *prop_name = NULL; \
|
|
const char *prop_value = NULL; \
|
|
int __counter = 0; \
|
|
crm_validate_data(parent); \
|
|
crm_debug_5("Searching %d fields", parent->nfields); \
|
|
for (__counter = 0; __counter < parent->nfields; __counter++) { \
|
|
crm_debug_5("Searching field %d", __counter); \
|
|
prop_name = parent->names[__counter]; \
|
|
if(parent->types[__counter] != FT_STRING) { \
|
|
continue; \
|
|
} else if(prop_name[0] == '_' \
|
|
&& prop_name[1] == '_') { \
|
|
continue; \
|
|
} \
|
|
prop_value = parent->values[__counter]; \
|
|
code; \
|
|
} \
|
|
} else { \
|
|
crm_debug_4("Parent of loop was NULL"); \
|
|
}
|
|
|
|
#endif
|