Signed-off-by: Xu Wang <gesaint(a)linux.vnet.ibm.com>
---
libxkutil/xmlgen.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 231 insertions(+), 0 deletions(-)
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
index 7e8801d..d1e1c94 100644
--- a/libxkutil/xmlgen.c
+++ b/libxkutil/xmlgen.c
@@ -42,6 +42,237 @@ typedef const char *(*devfn_t)(xmlNodePtr node, struct domain
*dominfo);
typedef const char *(*poolfn_t)(xmlNodePtr node, struct virt_pool *pool);
typedef const char *(*resfn_t)(xmlNodePtr node, struct virt_pool_res *res);
+/*
+ * Parse all attributes of node into xml.
+ *
+ * @node: The root node.
+ * @head: The link list saved all data to be parsed.
+ * @parent_id: Node id of attributes.
+ * @parent_name: Node name of attributes.
+ *
+ * If @parent_id or @parent_name is not as a condition, plese set them into
+ * -1 or NULL.
+ */
+static struct others *props_to_xml(xmlNodePtr node,
+ struct others *head,
+ int parent_id,
+ const char *parent_name)
+{
+ struct others *tmp = head;
+
+ if (head == NULL) {
+ CU_DEBUG("others is null.");
+ goto out;
+ }
+
+ while (tmp) {
+ if (compare_param_int(tmp->parent_id, parent_id) &&
+ compare_param_str(tmp->parent_name, parent_name) &&
+ tmp->type == TYPE_PROP &&
+ tmp->status == ACTIVE) {
+ xmlNewProp(node, BAD_CAST tmp->name, BAD_CAST tmp->value);
+ tmp->status = INACTIVE;
+ }
+ tmp = tmp->next;
+ }
+
+out:
+ return head;
+}
+
+/*
+ * Parse all data in others link list to a xml data structure.
+ * The link list returned after operation.
+ *
+ * @root: The root node of xml to be built.
+ * @head: The link list saved all data needed.
+ * @parent_id: Parent node id of root node.
+ * @parent_name: Parent node name of root node.
+ *
+ * @parent_id/@parent_name is not mandatory (please set them
+ * as -1/NULL) but others not.
+ */
+static struct others *others_to_xml(xmlNodePtr root,
+ struct others *head,
+ int parent_id,
+ const char *parent_name)
+{
+ struct others *tmp = head;
+ xmlNodePtr new_node = NULL;
+
+ if (head == NULL) {
+ CU_DEBUG("others is null.");
+ goto out;
+ }
+
+ /* fetch all node items from others to build structure of xml */
+ while (tmp) {
+ if (compare_param_int(tmp->parent_id, parent_id) &&
+ compare_param_str(tmp->parent_name, parent_name) &&
+ tmp->type == TYPE_NODE &&
+ tmp->status == ACTIVE) {
+ new_node = xmlNewChild(root, NULL,
+ BAD_CAST tmp->name,
+ BAD_CAST tmp->value);
+
+ if (new_node == NULL) {
+ CU_DEBUG("xmlNewChild failed.");
+ goto out;
+ }
+
+ tmp->status = INACTIVE;
+
+ /* find all properties of this node and build new tag in xml */
+ head = props_to_xml(new_node,
+ head,
+ tmp->id,
+ (char *)new_node->name);
+
+ /* recursive build sub node of tmp */
+ head = others_to_xml(new_node,
+ head,
+ tmp->id,
+ (char *)new_node->name);
+
+ }
+ tmp = tmp->next;
+ }
+
+out:
+ return head;
+}
+
+/*
+ * Restore data in the member of virtual device structure back to others link
+ * list. The new link list would be returned after operation finished.
+ *
+ * @head: The link list data to be added into.
+ * @id: Id of new node to be added.
+ * @name: Name of new node to be added.
+ * @value: Value of new node to be added.
+ * @type: Type of new node to be added.
+ * TYPE_NODE: The value is from a node of xml.
+ * TYPE_PROP: The value is from a attribute of a node.
+ * @parent_id: Parent node id of new node to be added.
+ * @parent_name: Parent node name of new node to be added.
+ *
+ * Among parameters above @id/@parent_id/@parent_name is not
+ * mandatory. They should be set as -1/-1/NULL if caller needn't
+ * set them.
+ */
+static struct others *add_node_to_others(struct others *head,
+ int id,
+ const char *name,
+ const char *value,
+ enum others_type type,
+ int parent_id,
+ const char *parent_name)
+{
+ struct others *tmp = head;
+ struct others *new_node = NULL;
+
+ /* Check if there is such a node with INACTIVE status in others */
+ while (tmp) {
+ if (compare_param_int(tmp->id, id) &&
+ STREQ(tmp->name, name) &&
+ tmp->type == type &&
+ compare_param_int(tmp->parent_id, parent_id) &&
+ compare_param_str(tmp->parent_name, parent_name) &&
+ tmp->status == INACTIVE) {
+ if (tmp->value) {
+ free(tmp->value);
+ }
+ if (value) {
+ tmp->value = strdup(value);
+ } else {
+ tmp->value = NULL;
+ }
+ tmp->status = ACTIVE;
+
+ return head;
+ }
+ tmp = tmp->next;
+ }
+
+ /* Create a new node */
+ new_node = calloc(1, sizeof(*new_node));
+ if (new_node == NULL) {
+ CU_DEBUG("calloc failed.");
+ return NULL;
+ }
+
+ new_node->id = id;
+
+ if (name == NULL) {
+ CU_DEBUG("name is null");
+ return NULL;
+ }
+ new_node->name = strdup(name);
+
+ if (value) {
+ new_node->value = strdup(value);
+ } else {
+ new_node->value = NULL;
+ }
+
+ new_node->type = type;
+
+ new_node->parent_id = parent_id;
+
+ if (parent_name) {
+ new_node->parent_name = strdup(parent_name);
+ } else {
+ new_node->parent_name = NULL;
+ }
+
+ if (head == NULL) {
+ new_node->next = NULL;
+ } else {
+ new_node->next = head;
+ }
+
+ return new_node;
+}
+
+static int get_id_of_others(struct others *others,
+ const char *name,
+ const char *value,
+ enum others_type type,
+ int parent_id,
+ const char *parent_name)
+{
+ struct others *tmp = others;
+
+ while (tmp) {
+ if (STREQ(tmp->name, name) &&
+ compare_param_str(tmp->value, value) &&
+ tmp->type == type &&
+ compare_param_int(tmp->parent_id, parent_id) &&
+ compare_param_str(tmp->parent_name, parent_name)) {
+ return tmp->id;
+ }
+ tmp = tmp->next;
+ }
+
+ return -1;
+}
+
+/*
+ * Check if there is node(s) with ACTIVE status. If such node(s) exists
+ * means operation failed. Some node of xml missed.
+ */
+static const char *check_others_active(struct others *others)
+{
+ while (others) {
+ if (others->status == ACTIVE) {
+ return "There are active nodes in others.";
+ }
+ others = others->next;
+ }
+
+ return NULL;
+}
+
static const char *console_xml(xmlNodePtr root, struct domain *dominfo)
{
int i;
--
1.7.1