dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / isns / isnsd / xml / data.c
blob5887e81b45cf3e6e5bc160512a5eca8f9f9ed339
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <libgen.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <libxml/parser.h>
40 #include <libxml/xpath.h>
42 #include "isns_server.h"
43 #include "isns_obj.h"
44 #include "isns_log.h"
46 #if LIBXML_VERSION >= 20904
47 #define XMLSTRING_CAST (const char *)
48 #else
49 #define XMLSTRING_CAST (const xmlChar *)
50 #endif
53 * external variables
55 extern const int NUM_OF_ATTRS[MAX_OBJ_TYPE_FOR_SIZE];
56 extern const int TYPE_OF_PARENT[MAX_OBJ_TYPE_FOR_SIZE];
57 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
59 extern char data_store[MAXPATHLEN];
62 * local variables
64 static xmlDocPtr xml_doc = NULL;
65 static char *xml_file = NULL;
66 static char *xml_tmp_file = NULL;
67 static char *xml_bak_file = NULL;
69 static const int OBJ_DTD_ORDER[MAX_OBJ_TYPE_FOR_SIZE] = {
71 1, /* OBJ_ENTITY */
72 2, /* OBJ_ISCSI */
73 3, /* OBJ_PORTAL */
74 4, /* OBJ_PG */
75 5, /* OBJ_DD */
76 6, /* OBJ_DDS */
77 0, /* MAX_OBJ_TYPE */
78 0, /* OBJ_DUMMY1 */
79 0, /* OBJ_DUMMY2 */
80 0, /* OBJ_DUMMY3 */
81 0, /* OBJ_DUMMY4 */
82 12, /* OBJ_ASSOC_ISCSI */
83 14, /* OBJ_ASSOC_DD */
86 #define DEF_XML_ROOT(ISNS_DATA, VENDOR, SMI, VERSION, ONE_DOT_O) \
87 (xmlChar *)ISNS_DATA, \
88 (xmlChar *)VENDOR, \
89 (xmlChar *)SMI, \
90 (xmlChar *)VERSION, \
91 (xmlChar *)ONE_DOT_O
92 static const xmlChar *xml_root[] = {
93 #include "data.def"
96 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) (xmlChar *)TAG,
97 static const xmlChar* xmlTag[] = {
98 #include "data.def"
101 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) TYPE,
102 static const char *xmlType[] = {
103 #include "data.def"
106 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) ARG1,
107 static const int xmlArg1[] = {
108 #include "data.def"
111 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) ARG2,
112 static const int xmlArg2[] = {
113 #include "data.def"
116 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) TYPE,
117 static const unsigned char xmlPropType[] = {
118 #include "data.def"
121 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) (xmlChar *)NAME,
122 static const xmlChar *xmlPropName[] = {
123 #include "data.def"
126 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) TAG,
127 static const int xmlPropTag[] = {
128 #include "data.def"
131 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) ID,
132 static const int xmlPropID[] = {
133 #include "data.def"
136 #define ARRAY_LENGTH(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0]))
139 * ****************************************************************************
141 * get_index_by_name:
142 * find the index in the global tables for the name of an attribute.
144 * name - the name of an attribute.
145 * return - index or -1 for error.
147 * ****************************************************************************
149 static int
150 get_index_by_name(
151 const xmlChar *name
154 int i;
155 for (i = 0; i < ARRAY_LENGTH(xmlTag); i++) {
156 if (xmlStrEqual(xmlTag[i], name)) {
157 return (i);
160 return (-1);
164 * ****************************************************************************
166 * get_index_by_otype:
167 * find the index in the global tables for the type of an object.
169 * name - the type of an object.
170 * return - index or -1 for error.
172 * ****************************************************************************
174 static int
175 get_index_by_otype(
176 int otype
179 int i;
180 for (i = 0; i < ARRAY_LENGTH(xmlTag); i++) {
181 if (xmlArg1[i] == otype && xmlType[i][0] == 'o') {
182 return (i);
185 return (-1);
189 * ****************************************************************************
191 * get_index_by_tag:
192 * find the index in the global tables for the tag of an attribute.
194 * name - the tag of an attribute.
195 * return - index or -1 for error.
197 * ****************************************************************************
199 static int
200 get_index_by_tag(
201 int tag
204 int i;
205 for (i = 0; i < ARRAY_LENGTH(xmlTag); i++) {
206 if (xmlArg1[i] == tag &&
207 xmlType[i][0] != 'o' &&
208 xmlType[i][0] != 'a') {
209 return (i);
212 return (-1);
216 * ****************************************************************************
218 * get_xml_doc:
219 * open the xml file and assign the global xml doc if the xml file
220 * is not opened, set the doc pointer with the opened xml file for
221 * returnning.
223 * docp - the doc pointer for returning.
224 * return - error code.
226 * ****************************************************************************
228 static int
229 get_xml_doc(
230 xmlDocPtr *docp
233 int ec = 0;
235 if (xml_doc == NULL) {
236 /* validate the xml file */
238 /* open the xml file */
239 xml_doc = xmlParseFile(xml_file);
242 *docp = xml_doc;
244 if (xml_doc == NULL) {
245 ec = ISNS_RSP_INTERNAL_ERROR;
248 return (ec);
252 * ****************************************************************************
254 * close_xml_doc:
255 * close the global xml doc and ignore any changes that has been
256 * made in it.
258 * ****************************************************************************
260 static void
261 close_xml_doc(
264 if (xml_doc) {
265 /* just close it */
266 xmlFreeDoc(xml_doc);
267 xml_doc = NULL;
272 * ****************************************************************************
274 * convert_xml2attr:
275 * convert a xml data to a TLV format isns attribute.
277 * tag - the tag of attribute.
278 * type - the data type of the xml data.
279 * value - the xml data.
280 * attr - TLV format attribute for returning.
281 * return - error code.
283 * ****************************************************************************
285 static int
286 convert_xml2attr(
287 const int tag,
288 const unsigned char type,
289 xmlChar *value,
290 isns_attr_t *attr
293 uint32_t len;
294 int ec = 0;
296 attr->tag = tag;
297 switch (type) {
298 case 'u':
299 /* 4-bytes non-negative integer */
300 attr->len = 4;
301 attr->value.ui = atoi((const char *)value);
302 break;
303 case 's':
304 /* literal string */
305 len = strlen((char *)value);
306 len += 4 - (len % 4);
307 attr->len = len;
308 attr->value.ptr = (uchar_t *)malloc(attr->len);
309 if (attr->value.ptr != NULL) {
310 (void) strcpy((char *)attr->value.ptr,
311 (char *)value);
312 } else {
313 ec = ISNS_RSP_INTERNAL_ERROR;
315 break;
316 case 'p':
317 /* IPv6 block data */
318 attr->len = sizeof (in6_addr_t);
319 attr->value.ip = (in6_addr_t *)malloc(attr->len);
320 if (attr->value.ip != NULL) {
321 (void) inet_pton(AF_INET6,
322 (char *)value,
323 attr->value.ip);
324 } else {
325 ec = ISNS_RSP_INTERNAL_ERROR;
327 break;
328 default:
329 break;
332 return (ec);
336 * ****************************************************************************
338 * convert_attr2xml:
339 * convert a TLV format isns attribute to xml node format.
341 * node - the xml node where the new node is being added to.
342 * attr - the TLV format attribute.
343 * name - the name of the attribute in xml node.
344 * type - the data type of the attribute.
345 * elm_flag - 0: adding a xml attlist.
346 * 1: adding a xml child node.
347 * 2: adding a previous sibling node.
348 * 3: adding a xml content node.
349 * 4: adding a xml attribute.
350 * return - xml node.
352 * ****************************************************************************
354 static xmlNodePtr
355 convert_attr2xml(
356 xmlNodePtr node,
357 const isns_attr_t *attr,
358 const xmlChar *name,
359 const char type,
360 const int elm_flag
363 xmlChar buff[INET6_ADDRSTRLEN + 1] = { 0 };
364 xmlChar *value = NULL;
365 xmlNodePtr child = NULL;
367 switch (type) {
368 case 'u':
369 /* 4-bytes non-negative integer */
370 if (xmlStrPrintf(buff, sizeof (buff),
371 XMLSTRING_CAST "%u",
372 attr->value.ui) > 0) {
373 value = (xmlChar *)&buff;
375 break;
376 case 's':
377 /* literal string */
378 value = (xmlChar *)attr->value.ptr;
379 break;
380 case 'p':
381 /* IPv6 block data */
382 value = (xmlChar *)inet_ntop(AF_INET6,
383 (char *)attr->value.ip,
384 (char *)buff,
385 sizeof (buff));
386 break;
387 default:
388 break;
391 if (!value) {
392 return (NULL);
395 switch (elm_flag) {
396 case 0: /* attlist */
397 if (xmlSetProp(node, name, value)) {
398 child = node;
400 break;
401 case 1: /* child element */
402 child = xmlNewChild(node, NULL, name, value);
403 break;
404 case 2: /* prev sibling element */
405 child = xmlNewNode(NULL, name);
406 if (child != NULL &&
407 xmlAddPrevSibling(node, child) == NULL) {
408 xmlFreeNode(child);
409 node = NULL;
410 } else {
411 node = child;
413 /* LINTED E_CASE_FALLTHRU */
414 case 3: /* set content */
415 if (node) {
416 xmlNodeSetContent(node, value);
418 child = node;
419 break;
420 case 4: /* new attr value */
421 if (xmlSetProp(node, name, value)) {
422 child = node;
424 break;
425 default:
426 ASSERT(0);
427 break;
430 return (child);
434 * ****************************************************************************
436 * parse_xml_prop:
437 * parse the properties of a xml node and convert them to the attributes
438 * of an isns object, these xml properties are the UID attribute and
439 * key attributes of the isns object.
441 * node - the xml node that contains the properties.
442 * obj - the isns object.
443 * i - the index of the attribute in the global tables.
444 * return - error code.
446 * ****************************************************************************
448 static int
449 parse_xml_prop(
450 xmlNodePtr node,
451 isns_obj_t *obj,
452 int i
455 int ec = 0;
456 const char *props = &xmlType[i][1];
457 const xmlChar *prop_name;
458 xmlChar *prop_value;
459 unsigned char prop_type;
460 int prop_tag;
461 int prop_id;
462 char prop;
463 int j;
465 j = 0;
466 prop = props[j ++];
467 while (ec == 0 &&
468 prop >= 'a' && prop <= 'z') {
469 prop -= 'a';
470 prop_id = xmlPropID[prop];
471 prop_tag = xmlPropTag[prop];
472 prop_name = xmlPropName[prop];
473 prop_type = xmlPropType[prop];
474 prop_value = xmlGetProp(node, prop_name);
476 if (prop_value) {
477 ec = convert_xml2attr(
478 prop_tag,
479 prop_type,
480 prop_value,
481 &(obj->attrs[prop_id]));
482 xmlFree(prop_value);
484 prop = props[j ++];
487 return (ec);
491 * ****************************************************************************
493 * parse_xml_attr:
494 * parse a xml node and convert it to one isns object attribute.
495 * this attribute is the non-key attribute of the isns object.
497 * node - the xml node.
498 * obj - the isns object.
499 * i - the index of the attribute in the global tables.
500 * return - error code.
502 * ****************************************************************************
504 static int
505 parse_xml_attr(
506 xmlNodePtr node,
507 isns_obj_t *obj,
508 int i
511 int ec = 0;
512 const unsigned char attr_type = xmlType[i][0];
513 const int attr_tag = xmlArg1[i];
514 const int attr_id = xmlArg2[i];
515 xmlChar *attr_value;
517 attr_value = xmlNodeGetContent(node);
519 if (attr_value) {
520 ec = convert_xml2attr(
521 attr_tag,
522 attr_type,
523 attr_value,
524 &(obj->attrs[attr_id]));
525 xmlFree(attr_value);
528 return (ec);
532 * ****************************************************************************
534 * parse_xml_obj:
535 * parse one isns object from the xml doc.
537 * nodep - the pointer of the xml node for parsing.
538 * objp - the pointer of isns object for returning.
539 * return - error code.
541 * ****************************************************************************
543 static int
544 parse_xml_obj(
545 xmlNodePtr *nodep,
546 isns_obj_t **objp
549 int ec = 0;
550 int i, j;
552 xmlNodePtr node = *nodep;
553 xmlNodePtr children;
555 isns_obj_t *obj = *objp;
557 while (node && ec == 0) {
558 if (node->type == XML_ELEMENT_NODE) {
559 children = node->children;
560 i = get_index_by_name(node->name);
561 ASSERT(i >= 0);
562 j = xmlType[i][0];
563 if (j == 'o' && obj == NULL) {
564 obj = obj_calloc(xmlArg1[i]);
565 if (obj == NULL) {
566 ec = ISNS_RSP_INTERNAL_ERROR;
567 break;
569 if ((ec = parse_xml_prop(node, obj, i)) == 0 &&
570 (children == NULL ||
571 (ec = parse_xml_obj(&children, &obj)) ==
572 0)) {
573 if (children != NULL &&
574 children != node->children) {
575 *nodep = children;
577 *objp = obj;
578 } else {
579 free_object(obj);
581 break;
582 /* LINTED E_NOP_IF_STMT */
583 } else if (j == 'o') {
584 } else if (j != 0) {
585 ASSERT(obj);
586 if (children != NULL) {
587 ec = parse_xml_attr(children, obj, i);
588 *nodep = children;
589 } else {
590 /* assign a default value */
591 *nodep = node;
593 } else {
594 /* unknown xml node */
595 break;
597 /* LINTED E_NOP_ELSE_STMT */
598 } else {
599 /* carry return or blank spaces, skip it */
601 node = node->next;
604 return (ec);
608 * ****************************************************************************
610 * locate_xml_node:
611 * locate the xml node from xml doc by matching the object UID.
613 * doc - the xml doc.
614 * otype - the matching object type.
615 * match_uid - the matching object UID.
616 * node - the pointer of matched xml node for returning.
617 * context - the xml context for matching process.
618 * result - the xml result for matching process.
619 * return - error code.
621 * ****************************************************************************
623 static int
624 locate_xml_node(
625 xmlDocPtr doc,
626 int otype,
627 int match_uid,
628 xmlNodePtr *node,
629 xmlXPathContextPtr *context,
630 xmlXPathObjectPtr *result
633 int ec = 0;
635 xmlNodeSetPtr nodeset;
636 xmlNodePtr curr;
637 xmlChar expr[32] = { (xmlChar)'/', (xmlChar)'/', 0 };
639 char prop;
640 const xmlChar *prop_name;
641 xmlChar *prop_value;
642 int uid;
644 int i, j;
646 *node = NULL;
648 i = get_index_by_otype(otype);
649 ASSERT(i >= 0);
651 *context = xmlXPathNewContext(doc);
653 if (*context &&
654 xmlStrPrintf(&expr[2], 30, XMLSTRING_CAST "%s",
655 xmlTag[i]) != -1) {
656 *result = xmlXPathEvalExpression(expr, *context);
657 if (*result) {
658 prop = xmlArg2[i] - 'a';
659 prop_name = xmlPropName[prop];
660 ASSERT(xmlPropType[prop] == 'u');
661 nodeset = (*result)->nodesetval;
662 for (j = 0;
663 nodeset && (j < nodeset->nodeNr);
664 j++) {
665 curr = nodeset->nodeTab[j];
666 prop_value = xmlGetProp(curr, prop_name);
667 if (prop_value) {
668 uid = atoi((const char *)prop_value);
669 xmlFree(prop_value);
670 if (uid == match_uid) {
671 /* found it */
672 *node = curr;
673 return (ec);
677 } else {
678 ec = ISNS_RSP_INTERNAL_ERROR;
680 } else {
681 ec = ISNS_RSP_INTERNAL_ERROR;
684 if (*result) {
685 xmlXPathFreeObject(*result);
686 *result = NULL;
688 if (*context) {
689 xmlXPathFreeContext(*context);
690 *context = NULL;
693 return (ec);
697 * ****************************************************************************
699 * make_xml_node:
700 * generate a xml node for presenting an isns object.
702 * obj - an isns object.
703 * return - the xml node.
705 * ****************************************************************************
707 static xmlNodePtr
708 make_xml_node(
709 const isns_obj_t *obj
712 const isns_attr_t *attr;
714 xmlNodePtr node;
715 const char *props;
716 char prop;
717 const xmlChar *name;
718 unsigned char type;
719 int prop_id;
720 int i, j;
722 i = get_index_by_otype(obj->type);
723 ASSERT(i >= 0);
724 node = xmlNewNode(NULL, xmlTag[i]);
725 if (!node) {
726 return (NULL);
729 /* generate xml attributes of the node */
730 props = &xmlType[i][1];
731 prop = *(props ++);
732 while (prop >= 'a' && prop <= 'z') {
733 prop -= 'a';
734 prop_id = xmlPropID[prop];
735 name = xmlPropName[prop];
736 type = xmlPropType[prop];
737 attr = &obj->attrs[prop_id];
738 if (!convert_attr2xml(node, attr, name, type, 0)) {
739 xmlFreeNode(node);
740 return (NULL);
742 /* attr->tag = 0; */
743 prop = *(props ++);
746 /* generate sub elements for isns attributes of the object */
747 i = 0;
748 while (i < NUM_OF_ATTRS[obj->type]) {
749 attr = &obj->attrs[i ++];
750 j = get_index_by_tag(attr->tag);
751 if (j >= 0) {
752 name = xmlTag[j];
753 type = xmlType[j][0];
754 if (!convert_attr2xml(node, attr, name, type, 1)) {
755 xmlFreeNode(node);
756 return (NULL);
761 return (node);
765 * ****************************************************************************
767 * xml_init_data:
768 * initialization of the xml data store.
770 * return - error code.
772 * ****************************************************************************
774 static int
775 xml_init_data(
778 #define XML_PATH "/etc/isns"
779 #define XML_FILE_NAME "/isnsdata.xml"
780 #define XML_DOT_TMP ".tmp"
781 #define XML_DOT_BAK ".bak"
783 int fd;
784 xmlDocPtr doc;
785 xmlNodePtr root;
787 int len;
788 char *xml_path, *p = NULL;
790 char *cwd = NULL;
792 int has_bak = 0;
794 /* cannot reset the xml file when server is running */
795 if (xml_file != NULL) {
796 return (1);
799 /* set the data store file name along with the backup */
800 /* file name and temporary file name */
801 len = strlen(data_store);
802 if (len > 0) {
803 xml_file = data_store;
804 p = strdup(xml_file);
805 xml_bak_file = (char *)malloc(len + 5);
806 xml_tmp_file = (char *)malloc(len + 5);
807 if (p != NULL &&
808 xml_bak_file != NULL &&
809 xml_tmp_file != NULL) {
810 xml_path = dirname(p);
811 (void) strcpy(xml_bak_file, xml_file);
812 (void) strcat(xml_bak_file, XML_DOT_BAK);
813 (void) strcpy(xml_tmp_file, xml_file);
814 (void) strcat(xml_tmp_file, XML_DOT_TMP);
815 } else {
816 return (1);
818 } else {
819 xml_path = XML_PATH;
820 xml_file = XML_PATH XML_FILE_NAME;
821 xml_bak_file = XML_PATH XML_FILE_NAME XML_DOT_BAK;
822 xml_tmp_file = XML_PATH XML_FILE_NAME XML_DOT_TMP;
825 /* save current working directory */
826 cwd = getcwd(NULL, MAXPATHLEN);
827 if (cwd == NULL) {
828 return (1);
830 /* check access permission on data store directory */
831 if (chdir(xml_path) != 0) {
832 if (errno == ENOENT) {
833 if (mkdir(xml_path, S_IRWXU) != 0 ||
834 chdir(xml_path) != 0) {
835 return (1);
837 } else {
838 return (1);
841 /* go back to original working directory */
842 (void) chdir(cwd);
843 free(cwd);
844 free(p);
846 /* do not keep blank spaces */
847 (void) xmlKeepBlanksDefault(0);
849 /* remove the tmp file if it exists */
850 if (access(xml_tmp_file, F_OK) == 0) {
851 (void) remove(xml_tmp_file);
854 /* test if we can write the bak file */
855 fd = open(xml_bak_file, O_RDWR);
856 if (fd == -1) {
857 fd = open(xml_bak_file, O_RDWR | O_CREAT,
858 S_IRUSR | S_IWUSR);
859 if (fd == -1) {
860 return (1);
861 } else {
862 (void) close(fd);
863 (void) remove(xml_bak_file);
865 } else {
866 has_bak = 1;
867 (void) close(fd);
870 /* Test if we have the data store file, create an empty */
871 /* data store if we do not have the data store file and */
872 /* the backup data store. */
873 fd = open(xml_file, O_RDWR);
874 if (fd == -1) {
875 if (has_bak == 0) {
876 doc = xmlNewDoc(BAD_CAST "1.0");
877 root = xmlNewNode(NULL, xml_root[0]);
878 if (doc != NULL &&
879 root != NULL &&
880 xmlSetProp(root, xml_root[1], xml_root[2]) !=
881 NULL &&
882 xmlSetProp(root, xml_root[3], xml_root[4]) !=
883 NULL) {
884 (void) xmlDocSetRootElement(doc, root);
885 if (xmlSaveFormatFile(xml_file, doc, 1) == -1) {
886 xmlFreeDoc(doc);
887 return (-1);
889 xmlFreeDoc(doc);
890 } else {
891 if (doc != NULL) {
892 xmlFreeDoc(doc);
894 if (root != NULL) {
895 xmlFreeNode(root);
897 return (1);
899 } else {
900 isnslog(LOG_WARNING, "get_xml_doc",
901 "initializing with backup data");
902 if (rename(xml_bak_file, xml_file) != 0) {
903 return (1);
906 } else {
907 (void) close(fd);
910 return (0);
914 * ****************************************************************************
916 * xml_load_obj:
917 * load an isns object from the xml data store.
919 * p - the pointer of current xml node.
920 * objp - the pointer of the object for returning.
921 * level - the direction of xml parsing for returning.
922 * return - error code.
924 * ****************************************************************************
926 static int
927 xml_load_obj(
928 void **p,
929 isns_obj_t **objp,
930 uchar_t *level
933 xmlDocPtr doc = NULL;
934 xmlNodePtr node = (xmlNodePtr)*p;
935 int ec = 0;
937 *objp = NULL;
939 if (node == NULL) {
940 *level = '^';
941 ec = get_xml_doc(&doc);
942 if (doc == NULL) {
943 return (ec);
945 node = xmlDocGetRootElement(doc);
946 if (node != NULL) {
947 node = node->children;
949 } else if (node->children != NULL) {
950 *level = '>';
951 node = node->children;
952 } else if (node->next != NULL) {
953 *level = 'v';
954 node = node->next;
955 } else {
956 *level = 'v';
957 while (node != NULL && node->next == NULL) {
958 if (node->type == XML_ELEMENT_NODE) {
959 *level = '<';
961 node = node->parent;
963 if (node != NULL) {
964 node = node->next;
968 /* there is a node, parse it */
969 if (node) {
970 ec = parse_xml_obj(&node, objp);
971 *p = (void *)node;
974 if (ec == 0 && *objp != NULL) {
975 ec = update_deref_obj(*objp);
976 if (ec != 0) {
977 free_object(*objp);
978 *objp = NULL;
982 /* no object available, close the xml doc */
983 if (*objp == NULL) {
984 (void) close_xml_doc();
987 return (ec);
991 * ****************************************************************************
993 * xml_add_obj:
994 * add an isns object to the xml data store.
996 * obj - the object being added.
997 * return - error code.
999 * ****************************************************************************
1001 static int
1002 xml_add_obj(
1003 const isns_obj_t *obj
1006 int ec = 0;
1008 xmlDocPtr doc;
1009 xmlXPathContextPtr context = NULL;
1010 xmlXPathObjectPtr result = NULL;
1011 xmlNodePtr node, prev;
1012 xmlNodePtr candidate;
1014 uint32_t puid, parent_type;
1016 int i;
1018 /* get the xml doc */
1019 ec = get_xml_doc(&doc);
1020 if (doc == NULL) {
1021 goto add_done;
1024 /* create the candidate node */
1025 candidate = make_xml_node(obj);
1026 if (candidate == NULL) {
1027 ec = ISNS_RSP_INTERNAL_ERROR;
1028 goto add_done;
1031 /* locate the position */
1032 parent_type = TYPE_OF_PARENT[obj->type];
1033 if (parent_type > 0) {
1034 puid = get_parent_uid(obj);
1035 ec = locate_xml_node(doc, parent_type, puid,
1036 &node, &context, &result);
1037 } else {
1038 node = xmlDocGetRootElement(doc);
1041 /* cannot locate the point for inserting the node */
1042 if (node == NULL) {
1043 xmlFreeNode(candidate);
1044 ec = ISNS_RSP_INTERNAL_ERROR;
1045 goto add_done;
1048 /* add it with the apporiate child order */
1049 if (node->children) {
1050 node = node->children;
1051 while (node) {
1052 if (node->type == XML_ELEMENT_NODE) {
1053 i = get_index_by_name(node->name);
1054 ASSERT(i >= 0);
1055 if (xmlType[i][0] == 'o' &&
1056 OBJ_DTD_ORDER[xmlArg1[i]] >=
1057 OBJ_DTD_ORDER[obj->type]) {
1058 break;
1061 prev = node;
1062 node = node->next;
1064 if (node == NULL) {
1065 node = xmlAddNextSibling(prev, candidate);
1066 } else {
1067 node = xmlAddPrevSibling(node, candidate);
1069 } else {
1070 node = xmlAddChild(node, candidate);
1073 if (node == NULL) {
1074 /* Failed, free the candidate node. */
1075 xmlFreeNode(candidate);
1076 ec = ISNS_RSP_INTERNAL_ERROR;
1079 add_done:
1080 if (result) {
1081 xmlXPathFreeObject(result);
1083 if (context) {
1084 xmlXPathFreeContext(context);
1087 return (ec);
1091 * ****************************************************************************
1093 * xml_modify_obj:
1094 * modify an isns object in the xml data store.
1096 * obj - the new object.
1097 * return - error code.
1099 * ****************************************************************************
1101 static int
1102 xml_modify_obj(
1103 const isns_obj_t *obj
1106 int ec = 0;
1107 xmlDocPtr doc;
1108 xmlXPathContextPtr context = NULL;
1109 xmlXPathObjectPtr result = NULL;
1110 xmlNodePtr node, child;
1111 const char *props;
1112 char prop;
1113 int prop_id;
1114 int prop_tag;
1115 const xmlChar *name;
1116 unsigned char type;
1117 const isns_attr_t *attr;
1118 int i, j, k;
1119 int make_child;
1121 /* get the doc pointer */
1122 ec = get_xml_doc(&doc);
1123 if (doc == NULL) {
1124 return (ec);
1127 /* locate the node for the object */
1128 i = get_index_by_otype(obj->type);
1129 ASSERT(i >= 0);
1130 prop = xmlArg2[i] - 'a';
1131 prop_id = xmlPropID[prop];
1132 attr = &obj->attrs[prop_id];
1133 ec = locate_xml_node(doc,
1134 obj->type,
1135 attr->value.ui,
1136 &node, &context, &result);
1138 /* modify it */
1139 if (node != NULL) {
1140 props = &xmlType[i][1];
1141 prop = *(props ++);
1142 while (prop >= 'a' && prop <= 'z') {
1143 prop -= 'a';
1144 prop_id = xmlPropID[prop];
1145 prop_tag = xmlPropTag[prop];
1146 attr = &obj->attrs[prop_id];
1147 /* no need to update the key attributes, skip it. */
1148 /* btw, dd and dd-set names are non-key attributes. */
1149 if (prop_tag == ISNS_DD_NAME_ATTR_ID ||
1150 prop_tag == ISNS_DD_SET_NAME_ATTR_ID) {
1151 name = xmlPropName[prop];
1152 type = xmlPropType[prop];
1153 if (!convert_attr2xml(node,
1154 attr, name, type, 4)) {
1155 ec = ISNS_RSP_INTERNAL_ERROR;
1156 goto modify_done;
1159 /* attr->tag = 0; */
1160 prop = *(props ++);
1162 /* set the child */
1163 child = node->children;
1164 if (child == NULL) {
1165 make_child = 1;
1166 } else {
1167 make_child = 0;
1169 for (i = 0; i < NUM_OF_ATTRS[obj->type]; i++) {
1170 attr = &obj->attrs[i];
1171 j = get_index_by_tag(attr->tag);
1172 if (j < 0) {
1173 continue;
1175 name = xmlTag[j];
1176 type = xmlType[j][0];
1177 if (make_child == 1) {
1178 /* make a child node */
1179 if (!convert_attr2xml(node, attr,
1180 name, type, 1)) {
1181 ec = ISNS_RSP_INTERNAL_ERROR;
1182 goto modify_done;
1184 continue;
1186 while (child) {
1187 if (child->type == XML_ELEMENT_NODE) {
1188 k = get_index_by_name(child->name);
1189 ASSERT(k >= 0);
1190 if (xmlType[k][0] == 'o' ||
1191 xmlType[k][0] == 'a' ||
1192 xmlArg1[k] > attr->tag) {
1193 if (!convert_attr2xml(child,
1194 attr, name, type, 2)) {
1195 /* internal error */
1196 ec = 11;
1197 goto modify_done;
1199 break;
1200 } else if (xmlArg1[k] == attr->tag) {
1201 /* replace content */
1202 if (!convert_attr2xml(child,
1203 attr, name, type, 3)) {
1204 /* internal error */
1205 ec = 11;
1206 goto modify_done;
1208 break;
1211 child = child->next;
1213 if (child == NULL) {
1214 /* make a child node */
1215 if (!convert_attr2xml(node, attr,
1216 name, type, 1)) {
1217 ec = ISNS_RSP_INTERNAL_ERROR;
1218 goto modify_done;
1222 } else {
1223 /* This case is for registering a node which has */
1224 /* membership in one or more non-default DD(s). */
1225 ec = xml_add_obj(obj);
1228 modify_done:
1229 if (result) {
1230 xmlXPathFreeObject(result);
1232 if (context) {
1233 xmlXPathFreeContext(context);
1236 return (ec);
1240 * ****************************************************************************
1242 * xml_delete_obj:
1243 * delete an isns object from the xml data store.
1245 * obj - the object being deleted.
1246 * return - error code.
1248 * ****************************************************************************
1250 static int
1251 xml_delete_obj(
1252 const isns_obj_t *obj
1255 int ec = 0;
1256 xmlDocPtr doc;
1257 xmlXPathContextPtr context = NULL;
1258 xmlXPathObjectPtr result = NULL;
1259 xmlNodePtr node;
1261 isns_type_t otype;
1262 uint32_t uid;
1264 /* get the xml doc */
1265 ec = get_xml_doc(&doc);
1266 if (doc == NULL) {
1267 return (ec);
1270 otype = obj->type;
1271 #ifdef WRITE_DATA_ASYNC
1272 /* it is a thin clone */
1273 uid = obj->attrs[0].value.ui;
1274 #else
1275 uid = get_obj_uid(obj);
1276 #endif
1278 /* locate the object */
1279 ec = locate_xml_node(doc,
1280 otype,
1281 uid,
1282 &node, &context, &result);
1284 /* destroy it */
1285 if (node) {
1286 xmlUnlinkNode(node);
1287 xmlFreeNode(node);
1290 if (result) {
1291 xmlXPathFreeObject(result);
1293 if (context) {
1294 xmlXPathFreeContext(context);
1297 return (ec);
1301 * ****************************************************************************
1303 * xml_delete_assoc:
1304 * delete a DD or DD-set membership from the xml data store.
1306 * assoc - the membership being deleted.
1307 * return - error code.
1309 * ****************************************************************************
1311 static int
1312 xml_delete_assoc(
1313 const isns_obj_t *assoc
1316 int ec = 0;
1317 xmlDocPtr doc;
1318 xmlXPathContextPtr context = NULL;
1319 xmlXPathObjectPtr result = NULL;
1320 xmlNodePtr node;
1322 uint32_t puid, parent_type;
1323 uint32_t uid, match_uid;
1325 char prop;
1326 const xmlChar *prop_name;
1327 xmlChar *prop_value;
1328 int i;
1330 /* get the xml doc */
1331 ec = get_xml_doc(&doc);
1332 if (doc == NULL) {
1333 return (ec);
1336 /* get the container object UID */
1337 parent_type = TYPE_OF_PARENT[assoc->type];
1338 ASSERT(parent_type != 0);
1339 puid = get_parent_uid(assoc);
1340 ASSERT(puid != 0);
1342 /* get the member object UID */
1343 i = get_index_by_otype(assoc->type);
1344 prop = xmlArg2[i] - 'a';
1345 prop_name = xmlPropName[prop];
1346 match_uid = assoc->attrs[UID_ATTR_INDEX[assoc->type]].value.ui;
1348 /* locate the container object */
1349 ec = locate_xml_node(doc, parent_type, puid,
1350 &node, &context, &result);
1352 /* get the membership nodes */
1353 if (node != NULL) {
1354 node = node->children;
1357 /* get the matching membership node */
1358 while (node) {
1359 if (node->type == XML_ELEMENT_NODE) {
1360 i = get_index_by_name(node->name);
1361 ASSERT(i >= 0);
1362 if (xmlType[i][0] == 'o' &&
1363 xmlArg1[i] == assoc->type) {
1364 prop_value = xmlGetProp(node, prop_name);
1365 if (prop_value) {
1366 uid = atoi((const char *)prop_value);
1367 xmlFree(prop_value);
1368 if (uid == match_uid) {
1369 break;
1374 node = node->next;
1377 /* destroy it */
1378 if (node) {
1379 xmlUnlinkNode(node);
1380 xmlFreeNode(node);
1383 if (result) {
1384 xmlXPathFreeObject(result);
1386 if (context) {
1387 xmlXPathFreeContext(context);
1390 return (ec);
1394 * ****************************************************************************
1396 * xml_update_commit:
1397 * backup the current written file and commit all updates from
1398 * the xml doc to the written file.
1400 * return - error code.
1402 * ****************************************************************************
1404 static int
1405 xml_update_commit(
1408 int ec = 0;
1410 if (xml_doc) {
1411 /* write to tmp file */
1412 if (xmlSaveFormatFile(xml_tmp_file, xml_doc, 1) == -1 ||
1413 /* backup the current file */
1414 rename(xml_file, xml_bak_file) != 0 ||
1415 /* rename the tmp file to the current file */
1416 rename(xml_tmp_file, xml_file) != 0) {
1417 /* failed saving file */
1418 ec = ISNS_RSP_INTERNAL_ERROR;
1420 /* close the xml_doc */
1421 xmlFreeDoc(xml_doc);
1422 xml_doc = NULL;
1425 return (ec);
1429 * ****************************************************************************
1431 * xml_update_retreat:
1432 * ignore all of updates in the xml doc.
1434 * return - 0: always successful.
1436 * ****************************************************************************
1438 static int
1439 xml_update_retreat(
1442 if (xml_doc) {
1443 /* close the xml_doc */
1444 xmlFreeDoc(xml_doc);
1445 xml_doc = NULL;
1448 return (0);