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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
32 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
39 #include <libxml/parser.h>
40 #include <libxml/xpath.h>
42 #include "isns_server.h"
46 #if LIBXML_VERSION >= 20904
47 #define XMLSTRING_CAST (const char *)
49 #define XMLSTRING_CAST (const xmlChar *)
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
];
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
] = {
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, \
92 static const xmlChar
*xml_root
[] = {
96 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) (xmlChar *)TAG,
97 static const xmlChar
* xmlTag
[] = {
101 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) TYPE,
102 static const char *xmlType
[] = {
106 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) ARG1,
107 static const int xmlArg1
[] = {
111 #define DEF_XML_DATA(TAG, TYPE, ARG1, ARG2) ARG2,
112 static const int xmlArg2
[] = {
116 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) TYPE,
117 static const unsigned char xmlPropType
[] = {
121 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) (xmlChar *)NAME,
122 static const xmlChar
*xmlPropName
[] = {
126 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) TAG,
127 static const int xmlPropTag
[] = {
131 #define DEF_XML_PROP(INDEX, TYPE, NAME, TAG, ID) ID,
132 static const int xmlPropID
[] = {
136 #define ARRAY_LENGTH(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0]))
139 * ****************************************************************************
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 * ****************************************************************************
155 for (i
= 0; i
< ARRAY_LENGTH(xmlTag
); i
++) {
156 if (xmlStrEqual(xmlTag
[i
], name
)) {
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 * ****************************************************************************
180 for (i
= 0; i
< ARRAY_LENGTH(xmlTag
); i
++) {
181 if (xmlArg1
[i
] == otype
&& xmlType
[i
][0] == 'o') {
189 * ****************************************************************************
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 * ****************************************************************************
205 for (i
= 0; i
< ARRAY_LENGTH(xmlTag
); i
++) {
206 if (xmlArg1
[i
] == tag
&&
207 xmlType
[i
][0] != 'o' &&
208 xmlType
[i
][0] != 'a') {
216 * ****************************************************************************
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
223 * docp - the doc pointer for returning.
224 * return - error code.
226 * ****************************************************************************
235 if (xml_doc
== NULL
) {
236 /* validate the xml file */
238 /* open the xml file */
239 xml_doc
= xmlParseFile(xml_file
);
244 if (xml_doc
== NULL
) {
245 ec
= ISNS_RSP_INTERNAL_ERROR
;
252 * ****************************************************************************
255 * close the global xml doc and ignore any changes that has been
258 * ****************************************************************************
272 * ****************************************************************************
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 * ****************************************************************************
288 const unsigned char type
,
299 /* 4-bytes non-negative integer */
301 attr
->value
.ui
= atoi((const char *)value
);
305 len
= strlen((char *)value
);
306 len
+= 4 - (len
% 4);
308 attr
->value
.ptr
= (uchar_t
*)malloc(attr
->len
);
309 if (attr
->value
.ptr
!= NULL
) {
310 (void) strcpy((char *)attr
->value
.ptr
,
313 ec
= ISNS_RSP_INTERNAL_ERROR
;
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
,
325 ec
= ISNS_RSP_INTERNAL_ERROR
;
336 * ****************************************************************************
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.
352 * ****************************************************************************
357 const isns_attr_t
*attr
,
363 xmlChar buff
[INET6_ADDRSTRLEN
+ 1] = { 0 };
364 xmlChar
*value
= NULL
;
365 xmlNodePtr child
= NULL
;
369 /* 4-bytes non-negative integer */
370 if (xmlStrPrintf(buff
, sizeof (buff
),
372 attr
->value
.ui
) > 0) {
373 value
= (xmlChar
*)&buff
;
378 value
= (xmlChar
*)attr
->value
.ptr
;
381 /* IPv6 block data */
382 value
= (xmlChar
*)inet_ntop(AF_INET6
,
383 (char *)attr
->value
.ip
,
396 case 0: /* attlist */
397 if (xmlSetProp(node
, name
, value
)) {
401 case 1: /* child element */
402 child
= xmlNewChild(node
, NULL
, name
, value
);
404 case 2: /* prev sibling element */
405 child
= xmlNewNode(NULL
, name
);
407 xmlAddPrevSibling(node
, child
) == NULL
) {
413 /* LINTED E_CASE_FALLTHRU */
414 case 3: /* set content */
416 xmlNodeSetContent(node
, value
);
420 case 4: /* new attr value */
421 if (xmlSetProp(node
, name
, value
)) {
434 * ****************************************************************************
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 * ****************************************************************************
456 const char *props
= &xmlType
[i
][1];
457 const xmlChar
*prop_name
;
459 unsigned char prop_type
;
468 prop
>= 'a' && prop
<= 'z') {
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
);
477 ec
= convert_xml2attr(
481 &(obj
->attrs
[prop_id
]));
491 * ****************************************************************************
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 * ****************************************************************************
512 const unsigned char attr_type
= xmlType
[i
][0];
513 const int attr_tag
= xmlArg1
[i
];
514 const int attr_id
= xmlArg2
[i
];
517 attr_value
= xmlNodeGetContent(node
);
520 ec
= convert_xml2attr(
524 &(obj
->attrs
[attr_id
]));
532 * ****************************************************************************
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 * ****************************************************************************
552 xmlNodePtr node
= *nodep
;
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
);
563 if (j
== 'o' && obj
== NULL
) {
564 obj
= obj_calloc(xmlArg1
[i
]);
566 ec
= ISNS_RSP_INTERNAL_ERROR
;
569 if ((ec
= parse_xml_prop(node
, obj
, i
)) == 0 &&
571 (ec
= parse_xml_obj(&children
, &obj
)) ==
573 if (children
!= NULL
&&
574 children
!= node
->children
) {
582 /* LINTED E_NOP_IF_STMT */
583 } else if (j
== 'o') {
586 if (children
!= NULL
) {
587 ec
= parse_xml_attr(children
, obj
, i
);
590 /* assign a default value */
594 /* unknown xml node */
597 /* LINTED E_NOP_ELSE_STMT */
599 /* carry return or blank spaces, skip it */
608 * ****************************************************************************
611 * locate the xml node from xml doc by matching the object UID.
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 * ****************************************************************************
629 xmlXPathContextPtr
*context
,
630 xmlXPathObjectPtr
*result
635 xmlNodeSetPtr nodeset
;
637 xmlChar expr
[32] = { (xmlChar
)'/', (xmlChar
)'/', 0 };
640 const xmlChar
*prop_name
;
648 i
= get_index_by_otype(otype
);
651 *context
= xmlXPathNewContext(doc
);
654 xmlStrPrintf(&expr
[2], 30, XMLSTRING_CAST
"%s",
656 *result
= xmlXPathEvalExpression(expr
, *context
);
658 prop
= xmlArg2
[i
] - 'a';
659 prop_name
= xmlPropName
[prop
];
660 ASSERT(xmlPropType
[prop
] == 'u');
661 nodeset
= (*result
)->nodesetval
;
663 nodeset
&& (j
< nodeset
->nodeNr
);
665 curr
= nodeset
->nodeTab
[j
];
666 prop_value
= xmlGetProp(curr
, prop_name
);
668 uid
= atoi((const char *)prop_value
);
670 if (uid
== match_uid
) {
678 ec
= ISNS_RSP_INTERNAL_ERROR
;
681 ec
= ISNS_RSP_INTERNAL_ERROR
;
685 xmlXPathFreeObject(*result
);
689 xmlXPathFreeContext(*context
);
697 * ****************************************************************************
700 * generate a xml node for presenting an isns object.
702 * obj - an isns object.
703 * return - the xml node.
705 * ****************************************************************************
709 const isns_obj_t
*obj
712 const isns_attr_t
*attr
;
722 i
= get_index_by_otype(obj
->type
);
724 node
= xmlNewNode(NULL
, xmlTag
[i
]);
729 /* generate xml attributes of the node */
730 props
= &xmlType
[i
][1];
732 while (prop
>= 'a' && prop
<= 'z') {
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)) {
746 /* generate sub elements for isns attributes of the object */
748 while (i
< NUM_OF_ATTRS
[obj
->type
]) {
749 attr
= &obj
->attrs
[i
++];
750 j
= get_index_by_tag(attr
->tag
);
753 type
= xmlType
[j
][0];
754 if (!convert_attr2xml(node
, attr
, name
, type
, 1)) {
765 * ****************************************************************************
768 * initialization of the xml data store.
770 * return - error code.
772 * ****************************************************************************
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"
788 char *xml_path
, *p
= NULL
;
794 /* cannot reset the xml file when server is running */
795 if (xml_file
!= NULL
) {
799 /* set the data store file name along with the backup */
800 /* file name and temporary file name */
801 len
= strlen(data_store
);
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);
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
);
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
);
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) {
841 /* go back to original working directory */
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
);
857 fd
= open(xml_bak_file
, O_RDWR
| O_CREAT
,
863 (void) remove(xml_bak_file
);
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
);
876 doc
= xmlNewDoc(BAD_CAST
"1.0");
877 root
= xmlNewNode(NULL
, xml_root
[0]);
880 xmlSetProp(root
, xml_root
[1], xml_root
[2]) !=
882 xmlSetProp(root
, xml_root
[3], xml_root
[4]) !=
884 (void) xmlDocSetRootElement(doc
, root
);
885 if (xmlSaveFormatFile(xml_file
, doc
, 1) == -1) {
900 isnslog(LOG_WARNING
, "get_xml_doc",
901 "initializing with backup data");
902 if (rename(xml_bak_file
, xml_file
) != 0) {
914 * ****************************************************************************
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 * ****************************************************************************
933 xmlDocPtr doc
= NULL
;
934 xmlNodePtr node
= (xmlNodePtr
)*p
;
941 ec
= get_xml_doc(&doc
);
945 node
= xmlDocGetRootElement(doc
);
947 node
= node
->children
;
949 } else if (node
->children
!= NULL
) {
951 node
= node
->children
;
952 } else if (node
->next
!= NULL
) {
957 while (node
!= NULL
&& node
->next
== NULL
) {
958 if (node
->type
== XML_ELEMENT_NODE
) {
968 /* there is a node, parse it */
970 ec
= parse_xml_obj(&node
, objp
);
974 if (ec
== 0 && *objp
!= NULL
) {
975 ec
= update_deref_obj(*objp
);
982 /* no object available, close the xml doc */
984 (void) close_xml_doc();
991 * ****************************************************************************
994 * add an isns object to the xml data store.
996 * obj - the object being added.
997 * return - error code.
999 * ****************************************************************************
1003 const isns_obj_t
*obj
1009 xmlXPathContextPtr context
= NULL
;
1010 xmlXPathObjectPtr result
= NULL
;
1011 xmlNodePtr node
, prev
;
1012 xmlNodePtr candidate
;
1014 uint32_t puid
, parent_type
;
1018 /* get the xml doc */
1019 ec
= get_xml_doc(&doc
);
1024 /* create the candidate node */
1025 candidate
= make_xml_node(obj
);
1026 if (candidate
== NULL
) {
1027 ec
= ISNS_RSP_INTERNAL_ERROR
;
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
);
1038 node
= xmlDocGetRootElement(doc
);
1041 /* cannot locate the point for inserting the node */
1043 xmlFreeNode(candidate
);
1044 ec
= ISNS_RSP_INTERNAL_ERROR
;
1048 /* add it with the apporiate child order */
1049 if (node
->children
) {
1050 node
= node
->children
;
1052 if (node
->type
== XML_ELEMENT_NODE
) {
1053 i
= get_index_by_name(node
->name
);
1055 if (xmlType
[i
][0] == 'o' &&
1056 OBJ_DTD_ORDER
[xmlArg1
[i
]] >=
1057 OBJ_DTD_ORDER
[obj
->type
]) {
1065 node
= xmlAddNextSibling(prev
, candidate
);
1067 node
= xmlAddPrevSibling(node
, candidate
);
1070 node
= xmlAddChild(node
, candidate
);
1074 /* Failed, free the candidate node. */
1075 xmlFreeNode(candidate
);
1076 ec
= ISNS_RSP_INTERNAL_ERROR
;
1081 xmlXPathFreeObject(result
);
1084 xmlXPathFreeContext(context
);
1091 * ****************************************************************************
1094 * modify an isns object in the xml data store.
1096 * obj - the new object.
1097 * return - error code.
1099 * ****************************************************************************
1103 const isns_obj_t
*obj
1108 xmlXPathContextPtr context
= NULL
;
1109 xmlXPathObjectPtr result
= NULL
;
1110 xmlNodePtr node
, child
;
1115 const xmlChar
*name
;
1117 const isns_attr_t
*attr
;
1121 /* get the doc pointer */
1122 ec
= get_xml_doc(&doc
);
1127 /* locate the node for the object */
1128 i
= get_index_by_otype(obj
->type
);
1130 prop
= xmlArg2
[i
] - 'a';
1131 prop_id
= xmlPropID
[prop
];
1132 attr
= &obj
->attrs
[prop_id
];
1133 ec
= locate_xml_node(doc
,
1136 &node
, &context
, &result
);
1140 props
= &xmlType
[i
][1];
1142 while (prop
>= 'a' && prop
<= 'z') {
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
;
1159 /* attr->tag = 0; */
1163 child
= node
->children
;
1164 if (child
== NULL
) {
1169 for (i
= 0; i
< NUM_OF_ATTRS
[obj
->type
]; i
++) {
1170 attr
= &obj
->attrs
[i
];
1171 j
= get_index_by_tag(attr
->tag
);
1176 type
= xmlType
[j
][0];
1177 if (make_child
== 1) {
1178 /* make a child node */
1179 if (!convert_attr2xml(node
, attr
,
1181 ec
= ISNS_RSP_INTERNAL_ERROR
;
1187 if (child
->type
== XML_ELEMENT_NODE
) {
1188 k
= get_index_by_name(child
->name
);
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 */
1200 } else if (xmlArg1
[k
] == attr
->tag
) {
1201 /* replace content */
1202 if (!convert_attr2xml(child
,
1203 attr
, name
, type
, 3)) {
1204 /* internal error */
1211 child
= child
->next
;
1213 if (child
== NULL
) {
1214 /* make a child node */
1215 if (!convert_attr2xml(node
, attr
,
1217 ec
= ISNS_RSP_INTERNAL_ERROR
;
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
);
1230 xmlXPathFreeObject(result
);
1233 xmlXPathFreeContext(context
);
1240 * ****************************************************************************
1243 * delete an isns object from the xml data store.
1245 * obj - the object being deleted.
1246 * return - error code.
1248 * ****************************************************************************
1252 const isns_obj_t
*obj
1257 xmlXPathContextPtr context
= NULL
;
1258 xmlXPathObjectPtr result
= NULL
;
1264 /* get the xml doc */
1265 ec
= get_xml_doc(&doc
);
1271 #ifdef WRITE_DATA_ASYNC
1272 /* it is a thin clone */
1273 uid
= obj
->attrs
[0].value
.ui
;
1275 uid
= get_obj_uid(obj
);
1278 /* locate the object */
1279 ec
= locate_xml_node(doc
,
1282 &node
, &context
, &result
);
1286 xmlUnlinkNode(node
);
1291 xmlXPathFreeObject(result
);
1294 xmlXPathFreeContext(context
);
1301 * ****************************************************************************
1304 * delete a DD or DD-set membership from the xml data store.
1306 * assoc - the membership being deleted.
1307 * return - error code.
1309 * ****************************************************************************
1313 const isns_obj_t
*assoc
1318 xmlXPathContextPtr context
= NULL
;
1319 xmlXPathObjectPtr result
= NULL
;
1322 uint32_t puid
, parent_type
;
1323 uint32_t uid
, match_uid
;
1326 const xmlChar
*prop_name
;
1327 xmlChar
*prop_value
;
1330 /* get the xml doc */
1331 ec
= get_xml_doc(&doc
);
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
);
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 */
1354 node
= node
->children
;
1357 /* get the matching membership node */
1359 if (node
->type
== XML_ELEMENT_NODE
) {
1360 i
= get_index_by_name(node
->name
);
1362 if (xmlType
[i
][0] == 'o' &&
1363 xmlArg1
[i
] == assoc
->type
) {
1364 prop_value
= xmlGetProp(node
, prop_name
);
1366 uid
= atoi((const char *)prop_value
);
1367 xmlFree(prop_value
);
1368 if (uid
== match_uid
) {
1379 xmlUnlinkNode(node
);
1384 xmlXPathFreeObject(result
);
1387 xmlXPathFreeContext(context
);
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 * ****************************************************************************
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
);
1429 * ****************************************************************************
1431 * xml_update_retreat:
1432 * ignore all of updates in the xml doc.
1434 * return - 0: always successful.
1436 * ****************************************************************************
1443 /* close the xml_doc */
1444 xmlFreeDoc(xml_doc
);