|
|
60de42 |
From c509cd07008b1f9b3402eeb7d7f3f6d504aa4fdb Mon Sep 17 00:00:00 2001
|
|
|
60de42 |
From: "Gao,Yan" <ygao@suse.com>
|
|
|
60de42 |
Date: Fri, 10 Feb 2017 15:44:16 +0100
|
|
|
60de42 |
Subject: [PATCH 1/2] Fix: libcrmcommon: Correctly compare XML comments to
|
|
|
60de42 |
prevent crmd from getting into infinite election loop
|
|
|
60de42 |
|
|
|
60de42 |
With b7fa323, crmd could still get into an infinite election loop when
|
|
|
60de42 |
there was more than one comment with the exactly same text at the same
|
|
|
60de42 |
level within a CIB XML element. For example:
|
|
|
60de42 |
|
|
|
60de42 |
'''
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
'''
|
|
|
60de42 |
|
|
|
60de42 |
Basically, it'd produce big messes if using the diff operation "move"
|
|
|
60de42 |
for XML comments in such a case.
|
|
|
60de42 |
|
|
|
60de42 |
With this commit, it strictly tries to match the XML comments at the
|
|
|
60de42 |
exactly same offsets when comparing v2 patchset, so that only the diff
|
|
|
60de42 |
operations "create" and "delete" will be used for XML comments.
|
|
|
60de42 |
---
|
|
|
60de42 |
lib/common/xml.c | 46 ++++++++++++++++++++++++++++++++--------------
|
|
|
60de42 |
1 file changed, 32 insertions(+), 14 deletions(-)
|
|
|
60de42 |
|
|
|
60de42 |
diff --git a/lib/common/xml.c b/lib/common/xml.c
|
|
|
60de42 |
index 65237c8..fd80fe1 100644
|
|
|
60de42 |
--- a/lib/common/xml.c
|
|
|
60de42 |
+++ b/lib/common/xml.c
|
|
|
60de42 |
@@ -98,7 +98,7 @@ static filter_t filter[] = {
|
|
|
60de42 |
/* *INDENT-ON* */
|
|
|
60de42 |
|
|
|
60de42 |
static xmlNode *subtract_xml_comment(xmlNode * parent, xmlNode * left, xmlNode * right, gboolean * changed);
|
|
|
60de42 |
-static xmlNode *find_xml_comment(xmlNode * root, xmlNode * search_comment);
|
|
|
60de42 |
+static xmlNode *find_xml_comment(xmlNode * root, xmlNode * search_comment, gboolean exact);
|
|
|
60de42 |
static int add_xml_comment(xmlNode * parent, xmlNode * target, xmlNode * update);
|
|
|
60de42 |
static bool __xml_acl_check(xmlNode *xml, const char *name, enum xml_private_flags mode);
|
|
|
60de42 |
const char *__xml_acl_to_text(enum xml_private_flags flags);
|
|
|
60de42 |
@@ -1555,11 +1555,11 @@ xml_accept_changes(xmlNode * xml)
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
static xmlNode *
|
|
|
60de42 |
-find_element(xmlNode *haystack, xmlNode *needle)
|
|
|
60de42 |
+find_element(xmlNode *haystack, xmlNode *needle, gboolean exact)
|
|
|
60de42 |
{
|
|
|
60de42 |
CRM_CHECK(needle != NULL, return NULL);
|
|
|
60de42 |
return (needle->type == XML_COMMENT_NODE)?
|
|
|
60de42 |
- find_xml_comment(haystack, needle)
|
|
|
60de42 |
+ find_xml_comment(haystack, needle, exact)
|
|
|
60de42 |
: find_entity(haystack, crm_element_name(needle), ID(needle));
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
@@ -1615,7 +1615,7 @@ __subtract_xml_object(xmlNode * target, xmlNode * patch)
|
|
|
60de42 |
xmlNode *target_child = cIter;
|
|
|
60de42 |
|
|
|
60de42 |
cIter = __xml_next(cIter);
|
|
|
60de42 |
- patch_child = find_element(patch, target_child);
|
|
|
60de42 |
+ patch_child = find_element(patch, target_child, FALSE);
|
|
|
60de42 |
__subtract_xml_object(target_child, patch_child);
|
|
|
60de42 |
}
|
|
|
60de42 |
free(id);
|
|
|
60de42 |
@@ -1677,7 +1677,7 @@ __add_xml_object(xmlNode * parent, xmlNode * target, xmlNode * patch)
|
|
|
60de42 |
for (patch_child = __xml_first_child(patch); patch_child != NULL;
|
|
|
60de42 |
patch_child = __xml_next(patch_child)) {
|
|
|
60de42 |
|
|
|
60de42 |
- target_child = find_element(target, patch_child);
|
|
|
60de42 |
+ target_child = find_element(target, patch_child, FALSE);
|
|
|
60de42 |
__add_xml_object(target, target_child, patch_child);
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
@@ -4026,7 +4026,7 @@ __xml_diff_object(xmlNode * old, xmlNode * new)
|
|
|
60de42 |
|
|
|
60de42 |
for (cIter = __xml_first_child(old); cIter != NULL; ) {
|
|
|
60de42 |
xmlNode *old_child = cIter;
|
|
|
60de42 |
- xmlNode *new_child = find_element(new, cIter);
|
|
|
60de42 |
+ xmlNode *new_child = find_element(new, cIter, TRUE);
|
|
|
60de42 |
|
|
|
60de42 |
cIter = __xml_next(cIter);
|
|
|
60de42 |
if(new_child) {
|
|
|
60de42 |
@@ -4041,7 +4041,7 @@ __xml_diff_object(xmlNode * old, xmlNode * new)
|
|
|
60de42 |
__xml_acl_apply(top); /* Make sure any ACLs are applied to 'candidate' */
|
|
|
60de42 |
free_xml(candidate);
|
|
|
60de42 |
|
|
|
60de42 |
- if (find_element(new, old_child) == NULL) {
|
|
|
60de42 |
+ if (find_element(new, old_child, TRUE) == NULL) {
|
|
|
60de42 |
xml_private_t *p = old_child->_private;
|
|
|
60de42 |
|
|
|
60de42 |
p->flags |= xpf_skip;
|
|
|
60de42 |
@@ -4051,7 +4051,7 @@ __xml_diff_object(xmlNode * old, xmlNode * new)
|
|
|
60de42 |
|
|
|
60de42 |
for (cIter = __xml_first_child(new); cIter != NULL; ) {
|
|
|
60de42 |
xmlNode *new_child = cIter;
|
|
|
60de42 |
- xmlNode *old_child = find_element(old, cIter);
|
|
|
60de42 |
+ xmlNode *old_child = find_element(old, cIter, TRUE);
|
|
|
60de42 |
|
|
|
60de42 |
cIter = __xml_next(cIter);
|
|
|
60de42 |
if(old_child == NULL) {
|
|
|
60de42 |
@@ -4226,18 +4226,36 @@ in_upper_context(int depth, int context, xmlNode * xml_node)
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
static xmlNode *
|
|
|
60de42 |
-find_xml_comment(xmlNode * root, xmlNode * search_comment)
|
|
|
60de42 |
+find_xml_comment(xmlNode * root, xmlNode * search_comment, gboolean exact)
|
|
|
60de42 |
{
|
|
|
60de42 |
xmlNode *a_child = NULL;
|
|
|
60de42 |
+ int search_offset = __xml_offset(search_comment);
|
|
|
60de42 |
|
|
|
60de42 |
CRM_CHECK(search_comment->type == XML_COMMENT_NODE, return NULL);
|
|
|
60de42 |
|
|
|
60de42 |
for (a_child = __xml_first_child(root); a_child != NULL; a_child = __xml_next(a_child)) {
|
|
|
60de42 |
- if (a_child->type != XML_COMMENT_NODE) {
|
|
|
60de42 |
- continue;
|
|
|
60de42 |
+ if (exact) {
|
|
|
60de42 |
+ int offset = __xml_offset(a_child);
|
|
|
60de42 |
+ xml_private_t *p = a_child->_private;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ if (offset < search_offset) {
|
|
|
60de42 |
+ continue;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ } else if (offset > search_offset) {
|
|
|
60de42 |
+ return NULL;
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+
|
|
|
60de42 |
+ if (is_set(p->flags, xpf_skip)) {
|
|
|
60de42 |
+ continue;
|
|
|
60de42 |
+ }
|
|
|
60de42 |
}
|
|
|
60de42 |
- if (safe_str_eq((const char *)a_child->content, (const char *)search_comment->content)) {
|
|
|
60de42 |
+
|
|
|
60de42 |
+ if (a_child->type == XML_COMMENT_NODE
|
|
|
60de42 |
+ && safe_str_eq((const char *)a_child->content, (const char *)search_comment->content)) {
|
|
|
60de42 |
return a_child;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ } else if (exact) {
|
|
|
60de42 |
+ return NULL;
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
@@ -4332,7 +4350,7 @@ subtract_xml_object(xmlNode * parent, xmlNode * left, xmlNode * right,
|
|
|
60de42 |
left_child = __xml_next(left_child)) {
|
|
|
60de42 |
gboolean child_changed = FALSE;
|
|
|
60de42 |
|
|
|
60de42 |
- right_child = find_element(right, left_child);
|
|
|
60de42 |
+ right_child = find_element(right, left_child, FALSE);
|
|
|
60de42 |
subtract_xml_object(diff, left_child, right_child, full, &child_changed, marker);
|
|
|
60de42 |
if (child_changed) {
|
|
|
60de42 |
*changed = TRUE;
|
|
|
60de42 |
@@ -4458,7 +4476,7 @@ add_xml_comment(xmlNode * parent, xmlNode * target, xmlNode * update)
|
|
|
60de42 |
CRM_CHECK(update->type == XML_COMMENT_NODE, return 0);
|
|
|
60de42 |
|
|
|
60de42 |
if (target == NULL) {
|
|
|
60de42 |
- target = find_xml_comment(parent, update);
|
|
|
60de42 |
+ target = find_xml_comment(parent, update, FALSE);
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
if (target == NULL) {
|
|
|
60de42 |
--
|
|
|
60de42 |
1.8.3.1
|
|
|
60de42 |
|
|
|
60de42 |
|
|
|
60de42 |
From 362f02874b6be46bf2648fb45ebc6bc636d48965 Mon Sep 17 00:00:00 2001
|
|
|
60de42 |
From: "Gao,Yan" <ygao@suse.com>
|
|
|
60de42 |
Date: Mon, 13 Feb 2017 17:47:23 +0100
|
|
|
60de42 |
Subject: [PATCH 2/2] Fix: libcrmcommon: Correctly delete XML comments
|
|
|
60de42 |
according to their positions
|
|
|
60de42 |
|
|
|
60de42 |
Previously, v2 patchset was not able to define which exact XML comments were
|
|
|
60de42 |
expected to be deleted in a CIB XML element. It was a problem if there
|
|
|
60de42 |
was more than one comment at the same level within a CIB XML element.
|
|
|
60de42 |
|
|
|
60de42 |
This commit resolves it by adding and handling a "position" field in the
|
|
|
60de42 |
diff operation "delete" for XML comments.
|
|
|
60de42 |
---
|
|
|
60de42 |
lib/common/xml.c | 121 +++++++++++++++++++++++++++++++++++++++++++++----------
|
|
|
60de42 |
1 file changed, 100 insertions(+), 21 deletions(-)
|
|
|
60de42 |
|
|
|
60de42 |
diff --git a/lib/common/xml.c b/lib/common/xml.c
|
|
|
60de42 |
index fd80fe1..6dce4cb 100644
|
|
|
60de42 |
--- a/lib/common/xml.c
|
|
|
60de42 |
+++ b/lib/common/xml.c
|
|
|
60de42 |
@@ -78,7 +78,7 @@ typedef struct xml_private_s
|
|
|
60de42 |
uint32_t flags;
|
|
|
60de42 |
char *user;
|
|
|
60de42 |
GListPtr acls;
|
|
|
60de42 |
- GListPtr deleted_paths;
|
|
|
60de42 |
+ GListPtr deleted_objs;
|
|
|
60de42 |
} xml_private_t;
|
|
|
60de42 |
|
|
|
60de42 |
typedef struct xml_acl_s {
|
|
|
60de42 |
@@ -86,6 +86,11 @@ typedef struct xml_acl_s {
|
|
|
60de42 |
char *xpath;
|
|
|
60de42 |
} xml_acl_t;
|
|
|
60de42 |
|
|
|
60de42 |
+typedef struct xml_deleted_obj_s {
|
|
|
60de42 |
+ char *path;
|
|
|
60de42 |
+ int position;
|
|
|
60de42 |
+} xml_deleted_obj_t;
|
|
|
60de42 |
+
|
|
|
60de42 |
/* *INDENT-OFF* */
|
|
|
60de42 |
|
|
|
60de42 |
static filter_t filter[] = {
|
|
|
60de42 |
@@ -275,6 +280,17 @@ __xml_acl_free(void *data)
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
static void
|
|
|
60de42 |
+__xml_deleted_obj_free(void *data)
|
|
|
60de42 |
+{
|
|
|
60de42 |
+ if(data) {
|
|
|
60de42 |
+ xml_deleted_obj_t *deleted_obj = data;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ free(deleted_obj->path);
|
|
|
60de42 |
+ free(deleted_obj);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+}
|
|
|
60de42 |
+
|
|
|
60de42 |
+static void
|
|
|
60de42 |
__xml_private_clean(xml_private_t *p)
|
|
|
60de42 |
{
|
|
|
60de42 |
if(p) {
|
|
|
60de42 |
@@ -288,9 +304,9 @@ __xml_private_clean(xml_private_t *p)
|
|
|
60de42 |
p->acls = NULL;
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
- if(p->deleted_paths) {
|
|
|
60de42 |
- g_list_free_full(p->deleted_paths, free);
|
|
|
60de42 |
- p->deleted_paths = NULL;
|
|
|
60de42 |
+ if(p->deleted_objs) {
|
|
|
60de42 |
+ g_list_free_full(p->deleted_objs, __xml_deleted_obj_free);
|
|
|
60de42 |
+ p->deleted_objs = NULL;
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
@@ -1094,10 +1110,10 @@ is_config_change(xmlNode *xml)
|
|
|
60de42 |
|
|
|
60de42 |
if(xml->doc && xml->doc->_private) {
|
|
|
60de42 |
p = xml->doc->_private;
|
|
|
60de42 |
- for(gIter = p->deleted_paths; gIter; gIter = gIter->next) {
|
|
|
60de42 |
- char *path = gIter->data;
|
|
|
60de42 |
+ for(gIter = p->deleted_objs; gIter; gIter = gIter->next) {
|
|
|
60de42 |
+ xml_deleted_obj_t *deleted_obj = gIter->data;
|
|
|
60de42 |
|
|
|
60de42 |
- if(strstr(path, "/"XML_TAG_CIB"/"XML_CIB_TAG_CONFIGURATION) != NULL) {
|
|
|
60de42 |
+ if(strstr(deleted_obj->path, "/"XML_TAG_CIB"/"XML_CIB_TAG_CONFIGURATION) != NULL) {
|
|
|
60de42 |
return TRUE;
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
@@ -1241,11 +1257,15 @@ xml_create_patchset_v2(xmlNode *source, xmlNode *target)
|
|
|
60de42 |
crm_xml_add(v, vfields[lpc], value);
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
- for(gIter = doc->deleted_paths; gIter; gIter = gIter->next) {
|
|
|
60de42 |
+ for(gIter = doc->deleted_objs; gIter; gIter = gIter->next) {
|
|
|
60de42 |
+ xml_deleted_obj_t *deleted_obj = gIter->data;
|
|
|
60de42 |
xmlNode *change = create_xml_node(patchset, XML_DIFF_CHANGE);
|
|
|
60de42 |
|
|
|
60de42 |
crm_xml_add(change, XML_DIFF_OP, "delete");
|
|
|
60de42 |
- crm_xml_add(change, XML_DIFF_PATH, gIter->data);
|
|
|
60de42 |
+ crm_xml_add(change, XML_DIFF_PATH, deleted_obj->path);
|
|
|
60de42 |
+ if (deleted_obj->position >= 0) {
|
|
|
60de42 |
+ crm_xml_add_int(change, XML_DIFF_POSITION, deleted_obj->position);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
__xml_build_changes(target, patchset);
|
|
|
60de42 |
@@ -1473,7 +1493,15 @@ xml_log_patchset(uint8_t log_level, const char *function, xmlNode * patchset)
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
} else if(strcmp(op, "delete") == 0) {
|
|
|
60de42 |
- do_crm_log_alias(log_level, __FILE__, function, __LINE__, "-- %s", xpath);
|
|
|
60de42 |
+ int position = -1;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ crm_element_value_int(change, XML_DIFF_POSITION, &position);
|
|
|
60de42 |
+ if (position >= 0) {
|
|
|
60de42 |
+ do_crm_log_alias(log_level, __FILE__, function, __LINE__, "-- %s (%d)", xpath, position);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ } else {
|
|
|
60de42 |
+ do_crm_log_alias(log_level, __FILE__, function, __LINE__, "-- %s", xpath);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
return;
|
|
|
60de42 |
@@ -1521,8 +1549,17 @@ xml_log_changes(uint8_t log_level, const char *function, xmlNode * xml)
|
|
|
60de42 |
return;
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
- for(gIter = doc->deleted_paths; gIter; gIter = gIter->next) {
|
|
|
60de42 |
- do_crm_log_alias(log_level, __FILE__, function, __LINE__, "-- %s", (char*)gIter->data);
|
|
|
60de42 |
+ for(gIter = doc->deleted_objs; gIter; gIter = gIter->next) {
|
|
|
60de42 |
+ xml_deleted_obj_t *deleted_obj = gIter->data;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ if (deleted_obj->position >= 0) {
|
|
|
60de42 |
+ do_crm_log_alias(log_level, __FILE__, function, __LINE__, "-- %s (%d)",
|
|
|
60de42 |
+ deleted_obj->path, deleted_obj->position);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ } else {
|
|
|
60de42 |
+ do_crm_log_alias(log_level, __FILE__, function, __LINE__, "-- %s",
|
|
|
60de42 |
+ deleted_obj->path);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
log_data_element(log_level, __FILE__, function, __LINE__, "+ ", xml, 0,
|
|
|
60de42 |
@@ -1881,7 +1918,7 @@ xml_apply_patchset_v1(xmlNode *xml, xmlNode *patchset, bool check_version)
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
static xmlNode *
|
|
|
60de42 |
-__first_xml_child_match(xmlNode *parent, const char *name, const char *id)
|
|
|
60de42 |
+__first_xml_child_match(xmlNode *parent, const char *name, const char *id, int position)
|
|
|
60de42 |
{
|
|
|
60de42 |
xmlNode *cIter = NULL;
|
|
|
60de42 |
|
|
|
60de42 |
@@ -1894,13 +1931,21 @@ __first_xml_child_match(xmlNode *parent, const char *name, const char *id)
|
|
|
60de42 |
continue;
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
+
|
|
|
60de42 |
+ /* The "position" makes sense only for XML comments for now */
|
|
|
60de42 |
+ if (cIter->type == XML_COMMENT_NODE
|
|
|
60de42 |
+ && position >= 0
|
|
|
60de42 |
+ && __xml_offset(cIter) != position) {
|
|
|
60de42 |
+ continue;
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+
|
|
|
60de42 |
return cIter;
|
|
|
60de42 |
}
|
|
|
60de42 |
return NULL;
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
static xmlNode *
|
|
|
60de42 |
-__xml_find_path(xmlNode *top, const char *key)
|
|
|
60de42 |
+__xml_find_path(xmlNode *top, const char *key, int target_position)
|
|
|
60de42 |
{
|
|
|
60de42 |
xmlNode *target = (xmlNode*)top->doc;
|
|
|
60de42 |
char *id = malloc(XML_BUFFER_SIZE);
|
|
|
60de42 |
@@ -1923,13 +1968,19 @@ __xml_find_path(xmlNode *top, const char *key)
|
|
|
60de42 |
|
|
|
60de42 |
} else if(tag && section) {
|
|
|
60de42 |
int f = sscanf (section, "%[^[][@id='%[^']", tag, id);
|
|
|
60de42 |
+ int current_position = -1;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ /* The "target_position" is for the target tag */
|
|
|
60de42 |
+ if (rc == 1 && target_position >= 0) {
|
|
|
60de42 |
+ current_position = target_position;
|
|
|
60de42 |
+ }
|
|
|
60de42 |
|
|
|
60de42 |
switch(f) {
|
|
|
60de42 |
case 1:
|
|
|
60de42 |
- target = __first_xml_child_match(target, tag, NULL);
|
|
|
60de42 |
+ target = __first_xml_child_match(target, tag, NULL, current_position);
|
|
|
60de42 |
break;
|
|
|
60de42 |
case 2:
|
|
|
60de42 |
- target = __first_xml_child_match(target, tag, id);
|
|
|
60de42 |
+ target = __first_xml_child_match(target, tag, id, current_position);
|
|
|
60de42 |
break;
|
|
|
60de42 |
default:
|
|
|
60de42 |
crm_trace("Aborting on %s", section);
|
|
|
60de42 |
@@ -1975,16 +2026,20 @@ xml_apply_patchset_v2(xmlNode *xml, xmlNode *patchset, bool check_version)
|
|
|
60de42 |
xmlNode *match = NULL;
|
|
|
60de42 |
const char *op = crm_element_value(change, XML_DIFF_OP);
|
|
|
60de42 |
const char *xpath = crm_element_value(change, XML_DIFF_PATH);
|
|
|
60de42 |
+ int position = -1;
|
|
|
60de42 |
|
|
|
60de42 |
crm_trace("Processing %s %s", change->name, op);
|
|
|
60de42 |
if(op == NULL) {
|
|
|
60de42 |
continue;
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
+ if(strcmp(op, "delete") == 0) {
|
|
|
60de42 |
+ crm_element_value_int(change, XML_DIFF_POSITION, &position);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
#if 0
|
|
|
60de42 |
match = get_xpath_object(xpath, xml, LOG_TRACE);
|
|
|
60de42 |
#else
|
|
|
60de42 |
- match = __xml_find_path(xml, xpath);
|
|
|
60de42 |
+ match = __xml_find_path(xml, xpath, position);
|
|
|
60de42 |
#endif
|
|
|
60de42 |
crm_trace("Performing %s on %s with %p", op, xpath, match);
|
|
|
60de42 |
|
|
|
60de42 |
@@ -2583,8 +2638,8 @@ xml_get_path(xmlNode *xml)
|
|
|
60de42 |
return NULL;
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
-void
|
|
|
60de42 |
-free_xml(xmlNode * child)
|
|
|
60de42 |
+static void
|
|
|
60de42 |
+free_xml_with_position(xmlNode * child, int position)
|
|
|
60de42 |
{
|
|
|
60de42 |
if (child != NULL) {
|
|
|
60de42 |
xmlNode *top = NULL;
|
|
|
60de42 |
@@ -2613,9 +2668,25 @@ free_xml(xmlNode * child)
|
|
|
60de42 |
char buffer[XML_BUFFER_SIZE];
|
|
|
60de42 |
|
|
|
60de42 |
if(__get_prefix(NULL, child, buffer, offset) > 0) {
|
|
|
60de42 |
+ xml_deleted_obj_t *deleted_obj = calloc(1, sizeof(xml_deleted_obj_t));
|
|
|
60de42 |
+
|
|
|
60de42 |
crm_trace("Deleting %s %p from %p", buffer, child, doc);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ deleted_obj->path = strdup(buffer);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ deleted_obj->position = -1;
|
|
|
60de42 |
+ /* Record the "position" only for XML comments for now */
|
|
|
60de42 |
+ if (child->type == XML_COMMENT_NODE) {
|
|
|
60de42 |
+ if (position >= 0) {
|
|
|
60de42 |
+ deleted_obj->position = position;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ } else {
|
|
|
60de42 |
+ deleted_obj->position = __xml_offset(child);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+
|
|
|
60de42 |
p = doc->_private;
|
|
|
60de42 |
- p->deleted_paths = g_list_append(p->deleted_paths, strdup(buffer));
|
|
|
60de42 |
+ p->deleted_objs = g_list_append(p->deleted_objs, deleted_obj);
|
|
|
60de42 |
set_doc_flag(child, xpf_dirty);
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
@@ -2629,6 +2700,13 @@ free_xml(xmlNode * child)
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
+
|
|
|
60de42 |
+void
|
|
|
60de42 |
+free_xml(xmlNode * child)
|
|
|
60de42 |
+{
|
|
|
60de42 |
+ free_xml_with_position(child, -1);
|
|
|
60de42 |
+}
|
|
|
60de42 |
+
|
|
|
60de42 |
xmlNode *
|
|
|
60de42 |
copy_xml(xmlNode * src)
|
|
|
60de42 |
{
|
|
|
60de42 |
@@ -4039,7 +4117,8 @@ __xml_diff_object(xmlNode * old, xmlNode * new)
|
|
|
60de42 |
|
|
|
60de42 |
__xml_node_clean(candidate);
|
|
|
60de42 |
__xml_acl_apply(top); /* Make sure any ACLs are applied to 'candidate' */
|
|
|
60de42 |
- free_xml(candidate);
|
|
|
60de42 |
+ /* Record the old position */
|
|
|
60de42 |
+ free_xml_with_position(candidate, __xml_offset(old_child));
|
|
|
60de42 |
|
|
|
60de42 |
if (find_element(new, old_child, TRUE) == NULL) {
|
|
|
60de42 |
xml_private_t *p = old_child->_private;
|
|
|
60de42 |
--
|
|
|
60de42 |
1.8.3.1
|
|
|
60de42 |
|