10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51914Scasper * Common Development and Distribution License (the "License").
61914Scasper * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11411SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <errno.h>
270Sstevel@tonic-gate #include <fcntl.h>
280Sstevel@tonic-gate #include <limits.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include <thread.h>
330Sstevel@tonic-gate #include <time.h>
340Sstevel@tonic-gate #include <unistd.h>
350Sstevel@tonic-gate
360Sstevel@tonic-gate #include <sys/mman.h>
370Sstevel@tonic-gate #include <sys/stat.h>
380Sstevel@tonic-gate #include <sys/time.h>
390Sstevel@tonic-gate #include <sys/types.h>
400Sstevel@tonic-gate #include <sys/utsname.h>
410Sstevel@tonic-gate
420Sstevel@tonic-gate #include <libxml/debugXML.h>
430Sstevel@tonic-gate #include <libxml/parser.h>
440Sstevel@tonic-gate #include <libxml/tree.h>
450Sstevel@tonic-gate #include <libxml/xmlerror.h>
460Sstevel@tonic-gate #include <libxml/xpath.h>
470Sstevel@tonic-gate #include <libxml/xmlmemory.h>
480Sstevel@tonic-gate
490Sstevel@tonic-gate #include <pool.h>
500Sstevel@tonic-gate #include "pool_internal.h"
510Sstevel@tonic-gate #include "pool_impl.h"
520Sstevel@tonic-gate #include "pool_xml_impl.h"
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * libpool XML Manipulation Routines
560Sstevel@tonic-gate *
570Sstevel@tonic-gate * pool_xml.c implements the XML manipulation routines used by the libpool
580Sstevel@tonic-gate * XML datastore. The functions are grouped into the following logical areas
590Sstevel@tonic-gate * - Result Sets
600Sstevel@tonic-gate * The XPath API is used to search the XML document represented by a
610Sstevel@tonic-gate * configuration. The results of XPath queries are represented through
620Sstevel@tonic-gate * pool_result_set_t structures as part of the abstraction of the datastore
630Sstevel@tonic-gate * representation. (see pool.c comment for more details)
640Sstevel@tonic-gate *
650Sstevel@tonic-gate * - Property Manipulation
660Sstevel@tonic-gate * Validated XML (XML associated with a DTD) does not allow the introduction
670Sstevel@tonic-gate * of attributes which are not recognised by the DTD. This is a limitation
680Sstevel@tonic-gate * since we want to allow libpool to associate an arbitrary number of
690Sstevel@tonic-gate * properties with an element. The property manipulation code overcomes this
700Sstevel@tonic-gate * limitation by allowing property sub-elements to be created and manipulated
710Sstevel@tonic-gate * through a single API so that they are indistinguishable from attributes
720Sstevel@tonic-gate * to the libpool user.
730Sstevel@tonic-gate *
740Sstevel@tonic-gate * - XML Element/Attribute Manipulation
750Sstevel@tonic-gate * These routines manipulate XML elements and attributes and are the routines
760Sstevel@tonic-gate * which interact most directly with libxml.
770Sstevel@tonic-gate *
780Sstevel@tonic-gate * - File Processing/IO
790Sstevel@tonic-gate * Since libpool must present its data in a consistent fashion, we have to
800Sstevel@tonic-gate * implement file locking above libxml. These routines allow us to lock files
810Sstevel@tonic-gate * during processing and maintain data integrity between processes. Note
820Sstevel@tonic-gate * that locks are at the process scope and are advisory (see fcntl).
830Sstevel@tonic-gate *
840Sstevel@tonic-gate * - Utilities
850Sstevel@tonic-gate * Sundry utility functions that aren't easily categorised.
860Sstevel@tonic-gate */
870Sstevel@tonic-gate
880Sstevel@tonic-gate #define MAX_PROP_SIZE 1024 /* Size of property buffer */
890Sstevel@tonic-gate /*
900Sstevel@tonic-gate * The PAGE_READ_SIZE value is used to determine the size of the input buffer
910Sstevel@tonic-gate * used to parse XML files.
920Sstevel@tonic-gate */
930Sstevel@tonic-gate #define PAGE_READ_SIZE 8192
940Sstevel@tonic-gate #define ELEM_TYPE_COUNT 6 /* Count of Element types */
950Sstevel@tonic-gate
960Sstevel@tonic-gate typedef struct dtype_tbl
970Sstevel@tonic-gate {
980Sstevel@tonic-gate xmlChar *dt_name;
990Sstevel@tonic-gate int dt_type;
1000Sstevel@tonic-gate } dtype_tbl_t;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate typedef struct elem_type_tbl
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate xmlChar *ett_elem;
1050Sstevel@tonic-gate dtype_tbl_t (*ett_dtype)[];
1060Sstevel@tonic-gate } elem_type_tbl_t;
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate extern int xmlDoValidityCheckingDefaultValue;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate * The _xml_lock is used to lock the state of libpool during
1120Sstevel@tonic-gate * xml initialisation operations.
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate static mutex_t _xml_lock;
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate const char *element_class_tags[] = {
1170Sstevel@tonic-gate "any",
1180Sstevel@tonic-gate "system",
1190Sstevel@tonic-gate "pool",
1200Sstevel@tonic-gate "res_comp",
1210Sstevel@tonic-gate "res_agg",
1220Sstevel@tonic-gate "comp",
1230Sstevel@tonic-gate NULL
1240Sstevel@tonic-gate };
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate static const char *data_type_tags[] = {
1270Sstevel@tonic-gate "uint",
1280Sstevel@tonic-gate "int",
1290Sstevel@tonic-gate "float",
1300Sstevel@tonic-gate "boolean",
1310Sstevel@tonic-gate "string"
1320Sstevel@tonic-gate };
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate const char *dtd_location = "file:///usr/share/lib/xml/dtd/rm_pool.dtd.1";
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate static elem_type_tbl_t elem_tbl[ELEM_TYPE_COUNT] = {0};
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate /* libpool initialisation indicator */
1390Sstevel@tonic-gate static int _libpool_xml_initialised = PO_FALSE;
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate /*
1420Sstevel@tonic-gate * Utility functions
1430Sstevel@tonic-gate */
1440Sstevel@tonic-gate /*
1450Sstevel@tonic-gate * Those functions which are not static are shared with pool_kernel.c
1460Sstevel@tonic-gate * They provide the required XML support for exporting a kernel
1470Sstevel@tonic-gate * configuration as an XML document.
1480Sstevel@tonic-gate */
1490Sstevel@tonic-gate void xml_init(void);
1500Sstevel@tonic-gate static int create_shadow(xmlNodePtr node);
1510Sstevel@tonic-gate static int pool_xml_free_doc(pool_conf_t *conf);
1520Sstevel@tonic-gate static int prop_sort(const void *a, const void *b);
1530Sstevel@tonic-gate static int dtd_exists(const char *path);
1540Sstevel@tonic-gate static void build_dtype_accelerator(void);
1550Sstevel@tonic-gate static dtype_tbl_t (*build_dtype_tbl(const xmlChar *rawdata))[];
1560Sstevel@tonic-gate static int get_fast_dtype(xmlNodePtr node, xmlChar *name);
1570Sstevel@tonic-gate static int pool_assoc_default_resource_type(pool_t *,
1580Sstevel@tonic-gate pool_resource_elem_class_t);
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate /*
1610Sstevel@tonic-gate * XML Data access and navigation APIs
1620Sstevel@tonic-gate */
1630Sstevel@tonic-gate static int pool_build_xpath_buf(pool_xml_connection_t *, const pool_elem_t *,
1640Sstevel@tonic-gate pool_elem_class_t, pool_value_t **, char_buf_t *, int);
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate * SHARED WITH pool_kernel.c for XML export support
1670Sstevel@tonic-gate */
1680Sstevel@tonic-gate xmlNodePtr node_create(xmlNodePtr parent, const xmlChar *name);
1690Sstevel@tonic-gate static xmlNodePtr node_create_with_id(xmlNodePtr parent, const xmlChar *name);
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate /* Configuration */
1720Sstevel@tonic-gate static int pool_xml_close(pool_conf_t *);
1730Sstevel@tonic-gate static int pool_xml_validate(const pool_conf_t *, pool_valid_level_t);
1740Sstevel@tonic-gate static int pool_xml_commit(pool_conf_t *conf);
1750Sstevel@tonic-gate static int pool_xml_export(const pool_conf_t *conf, const char *location,
1760Sstevel@tonic-gate pool_export_format_t fmt);
1770Sstevel@tonic-gate static int pool_xml_rollback(pool_conf_t *conf);
1780Sstevel@tonic-gate static pool_result_set_t *pool_xml_exec_query(const pool_conf_t *conf,
1790Sstevel@tonic-gate const pool_elem_t *src, const char *src_attr,
1800Sstevel@tonic-gate pool_elem_class_t classes, pool_value_t **props);
1810Sstevel@tonic-gate static int pool_xml_remove(pool_conf_t *conf);
1820Sstevel@tonic-gate static int pool_xml_res_transfer(pool_resource_t *, pool_resource_t *,
1830Sstevel@tonic-gate uint64_t);
1840Sstevel@tonic-gate static int pool_xml_res_xtransfer(pool_resource_t *, pool_resource_t *,
1850Sstevel@tonic-gate pool_component_t **);
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate /* Connections */
1880Sstevel@tonic-gate static void pool_xml_connection_free(pool_xml_connection_t *prov);
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate /* Result Sets */
1910Sstevel@tonic-gate static pool_xml_result_set_t *pool_xml_result_set_alloc(const pool_conf_t *);
1920Sstevel@tonic-gate static void pool_xml_result_set_free(pool_xml_result_set_t *rs);
1930Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_next(pool_result_set_t *set);
1940Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_prev(pool_result_set_t *set);
1950Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_first(pool_result_set_t *set);
1960Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_last(pool_result_set_t *set);
1970Sstevel@tonic-gate static int pool_xml_rs_set_index(pool_result_set_t *set, int index);
1980Sstevel@tonic-gate static int pool_xml_rs_get_index(pool_result_set_t *set);
1990Sstevel@tonic-gate static int pool_xml_rs_count(pool_result_set_t *set);
2000Sstevel@tonic-gate static int pool_xml_rs_close(pool_result_set_t *set);
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate /* Element (and sub-type) */
2030Sstevel@tonic-gate static void pool_xml_elem_init(pool_conf_t *conf, pool_xml_elem_t *elem,
2040Sstevel@tonic-gate pool_elem_class_t, pool_resource_elem_class_t, pool_component_elem_class_t);
2050Sstevel@tonic-gate static int pool_xml_elem_wrap(xmlNodePtr node, pool_elem_class_t class,
2060Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t);
2070Sstevel@tonic-gate static pool_elem_t *pool_xml_elem_create(pool_conf_t *, pool_elem_class_t,
2080Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t);
2090Sstevel@tonic-gate static int pool_xml_elem_remove(pool_elem_t *pe);
2100Sstevel@tonic-gate static int pool_xml_set_container(pool_elem_t *, pool_elem_t *);
2110Sstevel@tonic-gate static pool_elem_t *pool_xml_get_container(const pool_elem_t *);
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate * Pool element specific
2150Sstevel@tonic-gate */
2160Sstevel@tonic-gate static int pool_xml_pool_associate(pool_t *, const pool_resource_t *);
2170Sstevel@tonic-gate static int pool_xml_pool_dissociate(pool_t *, const pool_resource_t *);
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate * Resource elements specific
2210Sstevel@tonic-gate */
2220Sstevel@tonic-gate static int pool_xml_resource_is_system(const pool_resource_t *);
2230Sstevel@tonic-gate static int pool_xml_resource_can_associate(const pool_resource_t *);
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /* Properties */
2260Sstevel@tonic-gate static pool_value_class_t pool_xml_get_property(const pool_elem_t *,
2270Sstevel@tonic-gate const char *, pool_value_t *);
2280Sstevel@tonic-gate static int pool_xml_put_property(pool_elem_t *, const char *,
2290Sstevel@tonic-gate const pool_value_t *);
2300Sstevel@tonic-gate static int pool_xml_rm_property(pool_elem_t *, const char *);
2310Sstevel@tonic-gate static xmlNodePtr property_create(xmlNodePtr, const char *,
2320Sstevel@tonic-gate pool_value_class_t);
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate /* Internal Attribute/Property manipulation */
2350Sstevel@tonic-gate static int pool_is_xml_attr(xmlDocPtr, const char *, const char *);
2360Sstevel@tonic-gate static pool_value_class_t pool_xml_get_attr(xmlNodePtr node, xmlChar *name,
2370Sstevel@tonic-gate pool_value_t *value);
2380Sstevel@tonic-gate int pool_xml_set_attr(xmlNodePtr node, xmlChar *name,
2390Sstevel@tonic-gate const pool_value_t *value);
2400Sstevel@tonic-gate static pool_value_class_t pool_xml_get_prop(xmlNodePtr node, xmlChar *name,
2410Sstevel@tonic-gate pool_value_t *value);
2420Sstevel@tonic-gate int pool_xml_set_prop(xmlNodePtr node, xmlChar *name,
2430Sstevel@tonic-gate const pool_value_t *value);
2440Sstevel@tonic-gate static pool_value_t **pool_xml_get_properties(const pool_elem_t *, uint_t *);
2450Sstevel@tonic-gate /* XML Error handling */
2460Sstevel@tonic-gate void pool_error_func(void *ctx, const char *msg, ...);
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate /* XML File Input Processing */
2490Sstevel@tonic-gate static int pool_xml_open_file(pool_conf_t *conf);
2500Sstevel@tonic-gate static int pool_xml_parse_document(pool_conf_t *);
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate * Initialise this module
2540Sstevel@tonic-gate */
2550Sstevel@tonic-gate void
xml_init()2560Sstevel@tonic-gate xml_init()
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate (void) mutex_lock(&_xml_lock);
2590Sstevel@tonic-gate if (_libpool_xml_initialised == PO_TRUE) {
2600Sstevel@tonic-gate (void) mutex_unlock(&_xml_lock);
2610Sstevel@tonic-gate return;
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate xmlInitParser();
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate /*
2660Sstevel@tonic-gate * DTD validation, with line numbers.
2670Sstevel@tonic-gate */
268*11411SSurya.Prakki@Sun.COM (void) xmlLineNumbersDefault(1);
2690Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
2700Sstevel@tonic-gate xmlDoValidityCheckingDefaultValue = 1;
2710Sstevel@tonic-gate /* Try to improve indentation and readability */
272*11411SSurya.Prakki@Sun.COM (void) xmlKeepBlanksDefault(0);
2730Sstevel@tonic-gate /* Send all XML errors to our debug handler */
2740Sstevel@tonic-gate xmlSetGenericErrorFunc(NULL, pool_error_func);
2750Sstevel@tonic-gate /* Load up DTD element a-dtype data to improve performance */
2760Sstevel@tonic-gate build_dtype_accelerator();
2770Sstevel@tonic-gate _libpool_xml_initialised = PO_TRUE;
2780Sstevel@tonic-gate (void) mutex_unlock(&_xml_lock);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate /*
2820Sstevel@tonic-gate * Get the next ID for this configuration
2830Sstevel@tonic-gate */
2840Sstevel@tonic-gate static int
get_unique_id(xmlNodePtr node,char * id)2850Sstevel@tonic-gate get_unique_id(xmlNodePtr node, char *id)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
2880Sstevel@tonic-gate uint64_t nid = 0;
2890Sstevel@tonic-gate if (node->doc->_private) {
2900Sstevel@tonic-gate if (pool_get_ns_property(
2910Sstevel@tonic-gate pool_conf_to_elem((pool_conf_t *)node->doc->_private),
2920Sstevel@tonic-gate "_next_id", &val) == POC_UINT)
2930Sstevel@tonic-gate (void) pool_value_get_uint64(&val, &nid);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate if (snprintf(id, KEY_BUFFER_SIZE, "id_%llx", nid) > KEY_BUFFER_SIZE) {
2960Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
2970Sstevel@tonic-gate return (PO_FAIL);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate pool_value_set_uint64(&val, ++nid);
3000Sstevel@tonic-gate return (pool_put_ns_property(
3010Sstevel@tonic-gate pool_conf_to_elem((pool_conf_t *)node->doc->_private), "_next_id",
3020Sstevel@tonic-gate &val));
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate /* Document building functions */
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /*
3080Sstevel@tonic-gate * node_create() creates a child node of type name of the supplied parent in
3090Sstevel@tonic-gate * the supplied document. If the parent or document is NULL, create the node
3100Sstevel@tonic-gate * but do not associate it with a parent or document.
3110Sstevel@tonic-gate */
3120Sstevel@tonic-gate xmlNodePtr
node_create(xmlNodePtr parent,const xmlChar * name)3130Sstevel@tonic-gate node_create(xmlNodePtr parent, const xmlChar *name)
3140Sstevel@tonic-gate {
3150Sstevel@tonic-gate xmlNodePtr node;
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate if (parent == NULL)
3180Sstevel@tonic-gate node = xmlNewNode(NULL, name);
3190Sstevel@tonic-gate else
3200Sstevel@tonic-gate node = xmlNewChild(parent, NULL, name, NULL);
3210Sstevel@tonic-gate return (node);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate * node_create_with_id() creates a child node of type name of the supplied
3260Sstevel@tonic-gate * parent with the ref_id generated by get_unique_id(). Actual node creation
3270Sstevel@tonic-gate * is performed by node_create() and this function just sets the ref_id
3280Sstevel@tonic-gate * property to the value of the id.
3290Sstevel@tonic-gate */
3300Sstevel@tonic-gate static xmlNodePtr
node_create_with_id(xmlNodePtr parent,const xmlChar * name)3310Sstevel@tonic-gate node_create_with_id(xmlNodePtr parent, const xmlChar *name)
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate char id[KEY_BUFFER_SIZE]; /* Must be big enough for key below */
3340Sstevel@tonic-gate xmlNodePtr node = node_create(parent, name);
3350Sstevel@tonic-gate if (node != NULL) {
3360Sstevel@tonic-gate if (get_unique_id(node, id) != PO_SUCCESS) {
3370Sstevel@tonic-gate xmlUnlinkNode(node);
3380Sstevel@tonic-gate xmlFreeNode(node); /* recurses all children */
3390Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
3400Sstevel@tonic-gate return (NULL);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate if (xmlSetProp(node, BAD_CAST c_ref_id, BAD_CAST id) == NULL) {
3430Sstevel@tonic-gate xmlUnlinkNode(node);
3440Sstevel@tonic-gate xmlFreeNode(node); /* recurses all children */
3450Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
3460Sstevel@tonic-gate return (NULL);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate return (node);
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /* Supporting Data Conversion Routines */
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate /* XML Parser Utility Functions */
3550Sstevel@tonic-gate
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate * Handler for XML Errors. Called by libxml at libxml Error.
3580Sstevel@tonic-gate */
3590Sstevel@tonic-gate /*ARGSUSED*/
3600Sstevel@tonic-gate void
pool_error_func(void * ctx,const char * msg,...)3610Sstevel@tonic-gate pool_error_func(void *ctx, const char *msg, ...)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate va_list ap;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate va_start(ap, msg);
3660Sstevel@tonic-gate do_dprintf(msg, ap);
3670Sstevel@tonic-gate va_end(ap);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate * Free the shadowed elements from within the supplied document and then
3720Sstevel@tonic-gate * free the document. This function should always be called when freeing
3730Sstevel@tonic-gate * a pool document to ensure that all "shadow" resources are reclaimed.
3740Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
3750Sstevel@tonic-gate */
3760Sstevel@tonic-gate static int
pool_xml_free_doc(pool_conf_t * conf)3770Sstevel@tonic-gate pool_xml_free_doc(pool_conf_t *conf)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate /* Only do any of this if there is a document */
3800Sstevel@tonic-gate if (((pool_xml_connection_t *)conf->pc_prov)->pxc_doc != NULL) {
3810Sstevel@tonic-gate pool_elem_t *pe;
3820Sstevel@tonic-gate pool_result_set_t *rs;
3830Sstevel@tonic-gate /* Delete all the "shadowed" children of the doc */
3840Sstevel@tonic-gate rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_ANY, NULL);
3850Sstevel@tonic-gate if (rs == NULL) {
3860Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
3870Sstevel@tonic-gate return (PO_FAIL);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate * Work out the element type and free the elem
3920Sstevel@tonic-gate */
3930Sstevel@tonic-gate free(pe);
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate (void) pool_rs_close(rs);
3960Sstevel@tonic-gate xmlFreeDoc(((pool_xml_connection_t *)conf->pc_prov)->pxc_doc);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc = NULL;
3990Sstevel@tonic-gate return (PO_SUCCESS);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate /*
4030Sstevel@tonic-gate * Remove an element from the document. Note that only three types of elements
4040Sstevel@tonic-gate * can be removed, res, comp and pools. comp are moved around to the
4050Sstevel@tonic-gate * default res when a res is deleted.
4060Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
4070Sstevel@tonic-gate */
4080Sstevel@tonic-gate static int
pool_xml_elem_remove(pool_elem_t * pe)4090Sstevel@tonic-gate pool_xml_elem_remove(pool_elem_t *pe)
4100Sstevel@tonic-gate {
4110Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe;
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate * You can only destroy three elements: pools, resources and
4150Sstevel@tonic-gate * components.
4160Sstevel@tonic-gate */
4170Sstevel@tonic-gate switch (pe->pe_class) {
4180Sstevel@tonic-gate case PEC_POOL:
4190Sstevel@tonic-gate case PEC_RES_COMP:
4200Sstevel@tonic-gate case PEC_RES_AGG:
4210Sstevel@tonic-gate case PEC_COMP:
4220Sstevel@tonic-gate if (pxe->pxe_node) {
4230Sstevel@tonic-gate xmlUnlinkNode(pxe->pxe_node);
4240Sstevel@tonic-gate xmlFreeNode(pxe->pxe_node); /* recurses all children */
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate free(pxe);
4270Sstevel@tonic-gate break;
4280Sstevel@tonic-gate default:
4290Sstevel@tonic-gate break;
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate return (PO_SUCCESS);
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate /*
4350Sstevel@tonic-gate * Create a property element.
4360Sstevel@tonic-gate */
4370Sstevel@tonic-gate static xmlNodePtr
property_create(xmlNodePtr parent,const char * name,pool_value_class_t type)4380Sstevel@tonic-gate property_create(xmlNodePtr parent, const char *name, pool_value_class_t type)
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate xmlNodePtr element;
4420Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate if ((element = node_create(parent, BAD_CAST "property")) == NULL) {
4450Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
4460Sstevel@tonic-gate return (NULL);
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate if (pool_value_set_string(&val, name) != PO_SUCCESS) {
4490Sstevel@tonic-gate xmlFree(element);
4500Sstevel@tonic-gate return (NULL);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate (void) pool_xml_set_attr(element, BAD_CAST c_name, &val);
4530Sstevel@tonic-gate if (pool_value_set_string(&val, data_type_tags[type]) != PO_SUCCESS) {
4540Sstevel@tonic-gate xmlFree(element);
4550Sstevel@tonic-gate return (NULL);
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate (void) pool_xml_set_attr(element, BAD_CAST c_type, &val);
4580Sstevel@tonic-gate return (element);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate /*
4620Sstevel@tonic-gate * External clients need to be able to put/get properties and this is the
4630Sstevel@tonic-gate * way to do it.
4640Sstevel@tonic-gate * This function is an interceptor, since it will *always* try to manipulate
4650Sstevel@tonic-gate * an attribute first. If the attribute doesn't exist, then it will treat
4660Sstevel@tonic-gate * the request as a property request.
4670Sstevel@tonic-gate */
4680Sstevel@tonic-gate static pool_value_class_t
pool_xml_get_property(const pool_elem_t * pe,const char * name,pool_value_t * val)4690Sstevel@tonic-gate pool_xml_get_property(const pool_elem_t *pe, const char *name,
4700Sstevel@tonic-gate pool_value_t *val)
4710Sstevel@tonic-gate {
4720Sstevel@tonic-gate pool_value_class_t type;
4730Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe;
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate /*
4760Sstevel@tonic-gate * "type" is a special attribute which is not visible ever outside of
4770Sstevel@tonic-gate * libpool. Use the specific type accessor function.
4780Sstevel@tonic-gate */
4790Sstevel@tonic-gate if (strcmp(name, c_type) == 0) {
4800Sstevel@tonic-gate return (pool_xml_get_attr(pxe->pxe_node, BAD_CAST name,
4810Sstevel@tonic-gate val));
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate if (is_ns_property(pe, name) != NULL) { /* in ns */
4840Sstevel@tonic-gate if ((type = pool_xml_get_attr(pxe->pxe_node,
4850Sstevel@tonic-gate BAD_CAST property_name_minus_ns(pe, name), val))
4860Sstevel@tonic-gate == POC_INVAL)
4870Sstevel@tonic-gate return (pool_xml_get_prop(pxe->pxe_node, BAD_CAST name,
4880Sstevel@tonic-gate val));
4890Sstevel@tonic-gate } else
4900Sstevel@tonic-gate return (pool_xml_get_prop(pxe->pxe_node, BAD_CAST name, val));
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate return (type);
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate * Put a property on an element. Check if the property is an attribute,
4970Sstevel@tonic-gate * if it is update that value. If not add a property element.
4980Sstevel@tonic-gate *
4990Sstevel@tonic-gate * There are three possible conditions here:
5000Sstevel@tonic-gate * - the name is a ns
5010Sstevel@tonic-gate * - the name is an attribute
5020Sstevel@tonic-gate * - the name isn't an attribute
5030Sstevel@tonic-gate * - the name is not a ns
5040Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
5050Sstevel@tonic-gate */
5060Sstevel@tonic-gate static int
pool_xml_put_property(pool_elem_t * pe,const char * name,const pool_value_t * val)5070Sstevel@tonic-gate pool_xml_put_property(pool_elem_t *pe, const char *name,
5080Sstevel@tonic-gate const pool_value_t *val)
5090Sstevel@tonic-gate {
5100Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe;
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate /*
5130Sstevel@tonic-gate * "type" is a special attribute which is not visible ever outside of
5140Sstevel@tonic-gate * libpool. Use the specific type accessor function.
5150Sstevel@tonic-gate */
5160Sstevel@tonic-gate if (strcmp(name, c_type) == 0) {
5170Sstevel@tonic-gate return (pool_xml_set_attr(pxe->pxe_node, BAD_CAST name,
5180Sstevel@tonic-gate val));
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate if (is_ns_property(pe, name) != NULL) { /* in ns */
5210Sstevel@tonic-gate if (pool_xml_set_attr(pxe->pxe_node,
5220Sstevel@tonic-gate BAD_CAST property_name_minus_ns(pe, name), val) == PO_FAIL)
5230Sstevel@tonic-gate return (pool_xml_set_prop(pxe->pxe_node, BAD_CAST name,
5240Sstevel@tonic-gate val));
5250Sstevel@tonic-gate } else
5260Sstevel@tonic-gate return (pool_xml_set_prop(pxe->pxe_node, BAD_CAST name, val));
5270Sstevel@tonic-gate return (PO_SUCCESS);
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate * Remove a property from an element. Check if the property is an attribute,
5320Sstevel@tonic-gate * if it is fail. Otherwise remove the property subelement.
5330Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
5340Sstevel@tonic-gate */
5350Sstevel@tonic-gate static int
pool_xml_rm_property(pool_elem_t * pe,const char * name)5360Sstevel@tonic-gate pool_xml_rm_property(pool_elem_t *pe, const char *name)
5370Sstevel@tonic-gate {
5380Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe;
5390Sstevel@tonic-gate xmlXPathContextPtr ctx;
5400Sstevel@tonic-gate xmlXPathObjectPtr path;
5410Sstevel@tonic-gate char buf[MAX_PROP_SIZE];
5420Sstevel@tonic-gate int ret;
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate if (xmlHasProp(pxe->pxe_node, BAD_CAST name) != NULL) {
5450Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
5460Sstevel@tonic-gate return (PO_FAIL);
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate /* use xpath to find the node with the appropriate value for name */
5500Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "property[@name=\"%s\"]", name);
5510Sstevel@tonic-gate if ((ctx = xmlXPathNewContext(pxe->pxe_node->doc)) == NULL) {
5520Sstevel@tonic-gate pool_seterror(POE_PUTPROP);
5530Sstevel@tonic-gate return (PO_FAIL);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate ctx->node = pxe->pxe_node;
5560Sstevel@tonic-gate path = xmlXPathEval(BAD_CAST buf, ctx);
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate if (path && (path->type == XPATH_NODESET) &&
5590Sstevel@tonic-gate (path->nodesetval->nodeNr == 1)) {
5600Sstevel@tonic-gate xmlUnlinkNode(path->nodesetval->nodeTab[0]);
5610Sstevel@tonic-gate xmlFreeNode(path->nodesetval->nodeTab[0]);
5620Sstevel@tonic-gate ret = PO_SUCCESS;
5630Sstevel@tonic-gate } else {
5640Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
5650Sstevel@tonic-gate ret = PO_FAIL;
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate xmlXPathFreeObject(path);
5680Sstevel@tonic-gate xmlXPathFreeContext(ctx);
5690Sstevel@tonic-gate return (ret);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * Get the data type for an attribute name from the element node. The data
5740Sstevel@tonic-gate * type is returned and the value of the attribute updates the supplied value
5750Sstevel@tonic-gate * pointer.
5760Sstevel@tonic-gate */
5770Sstevel@tonic-gate static pool_value_class_t
pool_xml_get_attr(xmlNodePtr node,xmlChar * name,pool_value_t * value)5780Sstevel@tonic-gate pool_xml_get_attr(xmlNodePtr node, xmlChar *name, pool_value_t *value)
5790Sstevel@tonic-gate {
5800Sstevel@tonic-gate pool_value_class_t data_type;
5810Sstevel@tonic-gate xmlChar *data;
5820Sstevel@tonic-gate uint64_t uval;
5830Sstevel@tonic-gate int64_t ival;
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate if (xmlHasProp(node, name) == NULL && pool_is_xml_attr(node->doc,
5860Sstevel@tonic-gate (const char *) node->name, (const char *) name) == PO_FALSE) {
5870Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
5880Sstevel@tonic-gate return (POC_INVAL);
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate if (xmlHasProp(node, BAD_CAST c_a_dtype) == NULL) {
5910Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
5920Sstevel@tonic-gate return (POC_INVAL);
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate data = xmlGetProp(node, name);
5950Sstevel@tonic-gate data_type = get_fast_dtype(node, name);
5960Sstevel@tonic-gate if (data_type != POC_STRING && data == NULL) {
5970Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
5980Sstevel@tonic-gate return (POC_INVAL);
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate switch (data_type) {
6010Sstevel@tonic-gate case POC_UINT:
6020Sstevel@tonic-gate errno = 0;
6030Sstevel@tonic-gate uval = strtoull((char *)data, NULL, 0);
6040Sstevel@tonic-gate if (errno != 0) {
6050Sstevel@tonic-gate data_type = POC_INVAL;
6060Sstevel@tonic-gate }
6070Sstevel@tonic-gate else
6080Sstevel@tonic-gate pool_value_set_uint64(value, uval);
6090Sstevel@tonic-gate break;
6100Sstevel@tonic-gate case POC_INT:
6110Sstevel@tonic-gate errno = 0;
6120Sstevel@tonic-gate ival = strtoll((char *)data, NULL, 0);
6130Sstevel@tonic-gate if (errno != 0) {
6140Sstevel@tonic-gate data_type = POC_INVAL;
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate else
6170Sstevel@tonic-gate pool_value_set_int64(value, ival);
6180Sstevel@tonic-gate break;
6190Sstevel@tonic-gate case POC_DOUBLE:
6200Sstevel@tonic-gate pool_value_set_double(value, atof((const char *)data));
6210Sstevel@tonic-gate break;
6220Sstevel@tonic-gate case POC_BOOL:
6230Sstevel@tonic-gate if (strcmp((const char *)data, "true") == 0)
6240Sstevel@tonic-gate pool_value_set_bool(value, PO_TRUE);
6250Sstevel@tonic-gate else
6260Sstevel@tonic-gate pool_value_set_bool(value, PO_FALSE);
6270Sstevel@tonic-gate break;
6280Sstevel@tonic-gate case POC_STRING:
6290Sstevel@tonic-gate if (pool_value_set_string(value, data ?
6300Sstevel@tonic-gate (const char *)data : "") != PO_SUCCESS) {
6310Sstevel@tonic-gate xmlFree(data);
6320Sstevel@tonic-gate return (POC_INVAL);
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate break;
6350Sstevel@tonic-gate case POC_INVAL:
6360Sstevel@tonic-gate default:
6370Sstevel@tonic-gate break;
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate xmlFree(data);
6400Sstevel@tonic-gate return (data_type);
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate * Set the data type for an attribute name from the element node. The
6450Sstevel@tonic-gate * supplied value is used to update the designated name using the data
6460Sstevel@tonic-gate * type supplied.
6470Sstevel@tonic-gate */
6480Sstevel@tonic-gate int
pool_xml_set_attr(xmlNodePtr node,xmlChar * name,const pool_value_t * value)6490Sstevel@tonic-gate pool_xml_set_attr(xmlNodePtr node, xmlChar *name, const pool_value_t *value)
6500Sstevel@tonic-gate {
6510Sstevel@tonic-gate xmlChar buf[MAX_PROP_SIZE] = {0};
6520Sstevel@tonic-gate uint64_t ures;
6530Sstevel@tonic-gate int64_t ires;
6540Sstevel@tonic-gate uchar_t bres;
6550Sstevel@tonic-gate double dres;
6560Sstevel@tonic-gate const char *sres;
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate pool_value_class_t data_type;
6590Sstevel@tonic-gate
6600Sstevel@tonic-gate if (xmlHasProp(node, name) == NULL && pool_is_xml_attr(node->doc,
6610Sstevel@tonic-gate (const char *) node->name, (const char *) name) == PO_FALSE) {
6620Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
6630Sstevel@tonic-gate return (PO_FAIL);
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate if (xmlHasProp(node, BAD_CAST c_a_dtype) == NULL) {
6670Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
6680Sstevel@tonic-gate return (PO_FAIL);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate data_type = get_fast_dtype(node, name);
6710Sstevel@tonic-gate if (data_type != value->pv_class) {
6720Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
6730Sstevel@tonic-gate return (PO_FAIL);
6740Sstevel@tonic-gate }
6750Sstevel@tonic-gate switch (value->pv_class) {
6760Sstevel@tonic-gate case POC_UINT:
6770Sstevel@tonic-gate (void) pool_value_get_uint64(value, &ures);
6780Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%llu",
6790Sstevel@tonic-gate (u_longlong_t)ures);
6800Sstevel@tonic-gate break;
6810Sstevel@tonic-gate case POC_INT:
6820Sstevel@tonic-gate (void) pool_value_get_int64(value, &ires);
6830Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%lld",
6840Sstevel@tonic-gate (longlong_t)ires);
6850Sstevel@tonic-gate break;
6860Sstevel@tonic-gate case POC_DOUBLE:
6870Sstevel@tonic-gate (void) pool_value_get_double(value, &dres);
6880Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%f", dres);
6890Sstevel@tonic-gate break;
6900Sstevel@tonic-gate case POC_BOOL:
6910Sstevel@tonic-gate (void) pool_value_get_bool(value, &bres);
6920Sstevel@tonic-gate if (bres == PO_FALSE)
6930Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf),
6940Sstevel@tonic-gate "false");
6950Sstevel@tonic-gate else
6960Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf),
6970Sstevel@tonic-gate "true");
6980Sstevel@tonic-gate break;
6990Sstevel@tonic-gate case POC_STRING:
7000Sstevel@tonic-gate (void) pool_value_get_string(value, &sres);
7010Sstevel@tonic-gate if (sres != NULL)
7020Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%s",
7030Sstevel@tonic-gate sres);
7040Sstevel@tonic-gate break;
7050Sstevel@tonic-gate case POC_INVAL:
7060Sstevel@tonic-gate default:
7070Sstevel@tonic-gate break;
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate if (xmlSetProp(node, name, buf) == NULL) {
7100Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
7110Sstevel@tonic-gate return (PO_FAIL);
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate return (PO_SUCCESS);
7140Sstevel@tonic-gate }
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate /*
7170Sstevel@tonic-gate * Get the data type for a property name from the element node. The data
7180Sstevel@tonic-gate * type is returned and the value of the property updates the supplied value
7190Sstevel@tonic-gate * pointer. The user is responsible for freeing the memory associated with
7200Sstevel@tonic-gate * a string.
7210Sstevel@tonic-gate */
7220Sstevel@tonic-gate static pool_value_class_t
pool_xml_get_prop(xmlNodePtr node,xmlChar * name,pool_value_t * value)7230Sstevel@tonic-gate pool_xml_get_prop(xmlNodePtr node, xmlChar *name, pool_value_t *value)
7240Sstevel@tonic-gate {
7250Sstevel@tonic-gate pool_value_class_t data_type;
7260Sstevel@tonic-gate xmlChar *data, *node_data;
7270Sstevel@tonic-gate xmlXPathContextPtr ctx;
7280Sstevel@tonic-gate xmlXPathObjectPtr path;
7290Sstevel@tonic-gate char buf[MAX_PROP_SIZE];
7300Sstevel@tonic-gate int64_t uval;
7310Sstevel@tonic-gate int64_t ival;
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate /* use xpath to find the node with the appropriate value for name */
7340Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "property[@name=\"%s\"]", name);
7350Sstevel@tonic-gate if ((ctx = xmlXPathNewContext(node->doc)) == NULL) {
7360Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
7370Sstevel@tonic-gate return (POC_INVAL);
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate ctx->node = node;
7400Sstevel@tonic-gate path = xmlXPathEval(BAD_CAST buf, ctx);
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate if (path && (path->type == XPATH_NODESET) &&
7430Sstevel@tonic-gate (path->nodesetval->nodeNr == 1)) {
7440Sstevel@tonic-gate int i;
7450Sstevel@tonic-gate if (xmlHasProp(path->nodesetval->nodeTab[0],
7460Sstevel@tonic-gate BAD_CAST c_type) == NULL) {
7470Sstevel@tonic-gate xmlXPathFreeObject(path);
7480Sstevel@tonic-gate xmlXPathFreeContext(ctx);
7490Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
7500Sstevel@tonic-gate return (POC_INVAL);
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate /* type is a string representation of the type */
7530Sstevel@tonic-gate data = xmlGetProp(path->nodesetval->nodeTab[0],
7540Sstevel@tonic-gate BAD_CAST c_type);
7550Sstevel@tonic-gate node_data = xmlNodeGetContent(path->nodesetval->nodeTab[0]);
7560Sstevel@tonic-gate data_type = POC_INVAL;
7570Sstevel@tonic-gate for (i = 0; i < (sizeof (data_type_tags) /
7580Sstevel@tonic-gate sizeof (data_type_tags[0])); i++) {
7590Sstevel@tonic-gate if (strcmp((char *)data, data_type_tags[i]) == 0) {
7600Sstevel@tonic-gate data_type = i;
7610Sstevel@tonic-gate break;
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate }
7640Sstevel@tonic-gate switch (data_type) {
7650Sstevel@tonic-gate case POC_UINT:
7660Sstevel@tonic-gate errno = 0;
7670Sstevel@tonic-gate uval = strtoull((char *)node_data, NULL, 0);
7680Sstevel@tonic-gate if (errno != 0)
7690Sstevel@tonic-gate data_type = POC_INVAL;
7700Sstevel@tonic-gate else
7710Sstevel@tonic-gate pool_value_set_uint64(value, uval);
7720Sstevel@tonic-gate break;
7730Sstevel@tonic-gate case POC_INT:
7740Sstevel@tonic-gate errno = 0;
7750Sstevel@tonic-gate ival = strtoll((char *)node_data, NULL, 0);
7760Sstevel@tonic-gate if (errno != 0)
7770Sstevel@tonic-gate data_type = POC_INVAL;
7780Sstevel@tonic-gate else
7790Sstevel@tonic-gate pool_value_set_int64(value, ival);
7800Sstevel@tonic-gate break;
7810Sstevel@tonic-gate case POC_DOUBLE:
7820Sstevel@tonic-gate pool_value_set_double(value,
7830Sstevel@tonic-gate atof((const char *)node_data));
7840Sstevel@tonic-gate break;
7850Sstevel@tonic-gate case POC_BOOL:
7860Sstevel@tonic-gate if (strcmp((const char *)node_data, "true")
7870Sstevel@tonic-gate == 0)
7880Sstevel@tonic-gate pool_value_set_bool(value, PO_TRUE);
7890Sstevel@tonic-gate else
7900Sstevel@tonic-gate pool_value_set_bool(value, PO_FALSE);
7910Sstevel@tonic-gate break;
7920Sstevel@tonic-gate case POC_STRING:
7930Sstevel@tonic-gate if (pool_value_set_string(value,
7940Sstevel@tonic-gate (const char *)node_data) != PO_SUCCESS) {
7950Sstevel@tonic-gate data_type = POC_INVAL;
7960Sstevel@tonic-gate break;
7970Sstevel@tonic-gate }
7980Sstevel@tonic-gate break;
7990Sstevel@tonic-gate case POC_INVAL:
8000Sstevel@tonic-gate default:
8010Sstevel@tonic-gate break;
8020Sstevel@tonic-gate }
8030Sstevel@tonic-gate xmlFree(data);
8040Sstevel@tonic-gate xmlFree(node_data);
8050Sstevel@tonic-gate xmlXPathFreeObject(path);
8060Sstevel@tonic-gate xmlXPathFreeContext(ctx);
8070Sstevel@tonic-gate return (data_type);
8080Sstevel@tonic-gate } else { /* No property exists, clean up and return */
8090Sstevel@tonic-gate xmlXPathFreeObject(path);
8100Sstevel@tonic-gate xmlXPathFreeContext(ctx);
8110Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
8120Sstevel@tonic-gate return (POC_INVAL);
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate /*
8170Sstevel@tonic-gate * Set the data type for a property name from the element node. The
8180Sstevel@tonic-gate * supplied value is used to update the designated name using the data
8190Sstevel@tonic-gate * type supplied.
8200Sstevel@tonic-gate */
8210Sstevel@tonic-gate int
pool_xml_set_prop(xmlNodePtr node,xmlChar * name,const pool_value_t * value)8220Sstevel@tonic-gate pool_xml_set_prop(xmlNodePtr node, xmlChar *name, const pool_value_t *value)
8230Sstevel@tonic-gate {
8240Sstevel@tonic-gate /* First check if we have a property with this name (and type???). */
8250Sstevel@tonic-gate xmlXPathContextPtr ctx;
8260Sstevel@tonic-gate xmlXPathObjectPtr path;
8270Sstevel@tonic-gate xmlChar buf[MAX_PROP_SIZE];
8280Sstevel@tonic-gate xmlNodePtr element;
8290Sstevel@tonic-gate uint64_t ures;
8300Sstevel@tonic-gate int64_t ires;
8310Sstevel@tonic-gate uchar_t bres;
8320Sstevel@tonic-gate double dres;
8330Sstevel@tonic-gate const char *sres;
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate /* use xpath to find the node with the appropriate value for name */
8360Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "property[@name=\"%s\"]",
8370Sstevel@tonic-gate name);
8380Sstevel@tonic-gate if ((ctx = xmlXPathNewContext(node->doc)) == NULL) {
8390Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
8400Sstevel@tonic-gate return (PO_FAIL);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate ctx->node = node;
8430Sstevel@tonic-gate path = xmlXPathEval(buf, ctx);
8440Sstevel@tonic-gate if (path == NULL || path->type != XPATH_NODESET) {
8450Sstevel@tonic-gate xmlXPathFreeObject(path);
8460Sstevel@tonic-gate xmlXPathFreeContext(ctx);
8470Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
8480Sstevel@tonic-gate return (PO_FAIL);
8490Sstevel@tonic-gate } else {
8500Sstevel@tonic-gate if (path->nodesetval->nodeNr == 0)
8510Sstevel@tonic-gate element = property_create
8520Sstevel@tonic-gate (node, (const char *)name, value->pv_class);
8530Sstevel@tonic-gate else if (path->nodesetval->nodeNr == 1) {
8540Sstevel@tonic-gate int i;
8550Sstevel@tonic-gate xmlChar *data;
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate element = path->nodesetval->nodeTab[0];
8580Sstevel@tonic-gate if (xmlHasProp(element, BAD_CAST c_type) == NULL) {
8590Sstevel@tonic-gate xmlXPathFreeObject(path);
8600Sstevel@tonic-gate xmlXPathFreeContext(ctx);
8610Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
8620Sstevel@tonic-gate return (PO_FAIL);
8630Sstevel@tonic-gate }
8640Sstevel@tonic-gate data = xmlGetProp(element, BAD_CAST c_type);
8650Sstevel@tonic-gate for (i = 0; i < (sizeof (data_type_tags) /
8660Sstevel@tonic-gate sizeof (data_type_tags[0])); i++)
8670Sstevel@tonic-gate if (strcmp((char *)data, data_type_tags[i])
8680Sstevel@tonic-gate == 0) {
8690Sstevel@tonic-gate break;
8700Sstevel@tonic-gate }
8710Sstevel@tonic-gate xmlFree(data);
8720Sstevel@tonic-gate if (value->pv_class != i) {
8730Sstevel@tonic-gate xmlXPathFreeObject(path);
8740Sstevel@tonic-gate xmlXPathFreeContext(ctx);
8750Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
8760Sstevel@tonic-gate return (PO_FAIL);
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate } else {
8790Sstevel@tonic-gate xmlXPathFreeObject(path);
8800Sstevel@tonic-gate xmlXPathFreeContext(ctx);
8810Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
8820Sstevel@tonic-gate return (PO_FAIL);
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate }
8850Sstevel@tonic-gate
8860Sstevel@tonic-gate switch (value->pv_class) {
8870Sstevel@tonic-gate case POC_UINT:
8880Sstevel@tonic-gate (void) pool_value_get_uint64(value, &ures);
8890Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%llu",
8900Sstevel@tonic-gate (u_longlong_t)ures);
8910Sstevel@tonic-gate break;
8920Sstevel@tonic-gate case POC_INT:
8930Sstevel@tonic-gate (void) pool_value_get_int64(value, &ires);
8940Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%lld",
8950Sstevel@tonic-gate (longlong_t)ires);
8960Sstevel@tonic-gate break;
8970Sstevel@tonic-gate case POC_DOUBLE:
8980Sstevel@tonic-gate (void) pool_value_get_double(value, &dres);
8990Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%f", dres);
9000Sstevel@tonic-gate break;
9010Sstevel@tonic-gate case POC_BOOL:
9020Sstevel@tonic-gate (void) pool_value_get_bool(value, &bres);
9030Sstevel@tonic-gate if (bres == PO_FALSE)
9040Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf),
9050Sstevel@tonic-gate "false");
9060Sstevel@tonic-gate else
9070Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf),
9080Sstevel@tonic-gate "true");
9090Sstevel@tonic-gate break;
9100Sstevel@tonic-gate case POC_STRING:
9110Sstevel@tonic-gate (void) pool_value_get_string(value, &sres);
9120Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%s", sres);
9130Sstevel@tonic-gate break;
9140Sstevel@tonic-gate case POC_INVAL:
9150Sstevel@tonic-gate default:
9160Sstevel@tonic-gate break;
9170Sstevel@tonic-gate }
9180Sstevel@tonic-gate xmlNodeSetContent(element, buf);
9190Sstevel@tonic-gate xmlXPathFreeObject(path);
9200Sstevel@tonic-gate xmlXPathFreeContext(ctx);
9210Sstevel@tonic-gate return (PO_SUCCESS);
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate /*
9250Sstevel@tonic-gate * Return a NULL terminated array of pool_value_t which represents all
9260Sstevel@tonic-gate * of the properties stored for an element
9270Sstevel@tonic-gate *
9280Sstevel@tonic-gate * Return NULL on failure. It is the caller's responsibility to free
9290Sstevel@tonic-gate * the returned array of values.
9300Sstevel@tonic-gate */
9310Sstevel@tonic-gate pool_value_t **
pool_xml_get_properties(const pool_elem_t * pe,uint_t * nprops)9320Sstevel@tonic-gate pool_xml_get_properties(const pool_elem_t *pe, uint_t *nprops)
9330Sstevel@tonic-gate {
9340Sstevel@tonic-gate pool_value_t **result;
9350Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe;
9360Sstevel@tonic-gate int i, j;
9370Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(pe);
9380Sstevel@tonic-gate xmlElementPtr elemDTD;
9390Sstevel@tonic-gate xmlAttributePtr attr;
9400Sstevel@tonic-gate xmlXPathContextPtr ctx;
9410Sstevel@tonic-gate xmlXPathObjectPtr path;
9420Sstevel@tonic-gate char_buf_t *cb = NULL;
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate *nprops = 0;
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate elemDTD = xmlGetDtdElementDesc(pxe->pxe_node->doc->extSubset,
9470Sstevel@tonic-gate pxe->pxe_node->name);
9480Sstevel@tonic-gate for (attr = elemDTD->attributes; attr != NULL; attr = attr->nexth) {
9490Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_a_dtype) != 0 ||
9500Sstevel@tonic-gate strcmp((const char *)attr->name, c_type) != 0)
9510Sstevel@tonic-gate (*nprops)++;
9520Sstevel@tonic-gate }
9530Sstevel@tonic-gate if ((ctx = xmlXPathNewContext(
9540Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc)) == NULL) {
9550Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
9560Sstevel@tonic-gate return (NULL);
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate ctx->node = pxe->pxe_node;
9590Sstevel@tonic-gate path = xmlXPathEval(BAD_CAST "property", ctx);
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate if (path != NULL && path->type == XPATH_NODESET &&
9620Sstevel@tonic-gate path->nodesetval != NULL)
9630Sstevel@tonic-gate (*nprops) += path->nodesetval->nodeNr;
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate if ((result = calloc(*nprops + 1, sizeof (pool_value_t *))) == NULL) {
9660Sstevel@tonic-gate xmlXPathFreeObject(path);
9670Sstevel@tonic-gate xmlXPathFreeContext(ctx);
9680Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
9690Sstevel@tonic-gate return (NULL);
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
9720Sstevel@tonic-gate xmlXPathFreeObject(path);
9730Sstevel@tonic-gate xmlXPathFreeContext(ctx);
9740Sstevel@tonic-gate free(result);
9750Sstevel@tonic-gate return (NULL);
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate /*
9780Sstevel@tonic-gate * Now store our attributes and properties in result
9790Sstevel@tonic-gate */
9800Sstevel@tonic-gate for (i = 0, attr = elemDTD->attributes; attr != NULL;
9810Sstevel@tonic-gate attr = attr->nexth, i++) {
9820Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_a_dtype) == 0 ||
9830Sstevel@tonic-gate strcmp((const char *)attr->name, c_type) == 0) {
9840Sstevel@tonic-gate i--;
9850Sstevel@tonic-gate continue;
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate result[i] = pool_value_alloc();
9880Sstevel@tonic-gate if (pool_xml_get_attr(pxe->pxe_node,
9890Sstevel@tonic-gate BAD_CAST attr->name, result[i]) == POC_INVAL) {
9900Sstevel@tonic-gate xmlXPathFreeObject(path);
9910Sstevel@tonic-gate xmlXPathFreeContext(ctx);
9920Sstevel@tonic-gate while (i-- >= 0)
9930Sstevel@tonic-gate pool_value_free(result[i]);
9940Sstevel@tonic-gate free(result);
9950Sstevel@tonic-gate free_char_buf(cb);
9960Sstevel@tonic-gate return (NULL);
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_type) != 0) {
9990Sstevel@tonic-gate if (set_char_buf(cb, "%s.%s",
10000Sstevel@tonic-gate pool_elem_class_string(pe), attr->name) !=
10010Sstevel@tonic-gate PO_SUCCESS) {
10020Sstevel@tonic-gate xmlXPathFreeObject(path);
10030Sstevel@tonic-gate xmlXPathFreeContext(ctx);
10040Sstevel@tonic-gate while (i-- >= 0)
10050Sstevel@tonic-gate pool_value_free(result[i]);
10060Sstevel@tonic-gate free(result);
10070Sstevel@tonic-gate free_char_buf(cb);
10080Sstevel@tonic-gate return (NULL);
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate if (pool_value_set_name(result[i], cb->cb_buf) !=
10110Sstevel@tonic-gate PO_SUCCESS) {
10120Sstevel@tonic-gate xmlXPathFreeObject(path);
10130Sstevel@tonic-gate xmlXPathFreeContext(ctx);
10140Sstevel@tonic-gate while (i-- >= 0)
10150Sstevel@tonic-gate pool_value_free(result[i]);
10160Sstevel@tonic-gate free(result);
10170Sstevel@tonic-gate free_char_buf(cb);
10180Sstevel@tonic-gate return (NULL);
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate } else {
10210Sstevel@tonic-gate if (pool_value_set_name(result[i],
10220Sstevel@tonic-gate (const char *)attr->name) != PO_SUCCESS) {
10230Sstevel@tonic-gate xmlXPathFreeObject(path);
10240Sstevel@tonic-gate xmlXPathFreeContext(ctx);
10250Sstevel@tonic-gate while (i-- >= 0)
10260Sstevel@tonic-gate pool_value_free(result[i]);
10270Sstevel@tonic-gate free(result);
10280Sstevel@tonic-gate free_char_buf(cb);
10290Sstevel@tonic-gate return (NULL);
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate }
10320Sstevel@tonic-gate }
10330Sstevel@tonic-gate free_char_buf(cb);
10340Sstevel@tonic-gate for (j = 0; j < path->nodesetval->nodeNr; j++, i++) {
10350Sstevel@tonic-gate xmlChar *name = xmlGetProp(path->nodesetval->nodeTab[j],
10360Sstevel@tonic-gate BAD_CAST c_name);
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate result[i] = pool_value_alloc();
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate if (pool_xml_get_prop(pxe->pxe_node, name, result[i]) ==
10410Sstevel@tonic-gate POC_INVAL) {
10420Sstevel@tonic-gate xmlFree(name);
10430Sstevel@tonic-gate xmlXPathFreeObject(path);
10440Sstevel@tonic-gate xmlXPathFreeContext(ctx);
10450Sstevel@tonic-gate while (i-- >= 0)
10460Sstevel@tonic-gate pool_value_free(result[i]);
10470Sstevel@tonic-gate free(result);
10480Sstevel@tonic-gate return (NULL);
10490Sstevel@tonic-gate }
10500Sstevel@tonic-gate if (pool_value_set_name(result[i], (const char *)name) !=
10510Sstevel@tonic-gate PO_SUCCESS) {
10520Sstevel@tonic-gate xmlFree(name);
10530Sstevel@tonic-gate xmlXPathFreeObject(path);
10540Sstevel@tonic-gate xmlXPathFreeContext(ctx);
10550Sstevel@tonic-gate while (i-- >= 0)
10560Sstevel@tonic-gate pool_value_free(result[i]);
10570Sstevel@tonic-gate free(result);
10580Sstevel@tonic-gate return (NULL);
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate xmlFree(name);
10610Sstevel@tonic-gate }
10620Sstevel@tonic-gate xmlXPathFreeObject(path);
10630Sstevel@tonic-gate xmlXPathFreeContext(ctx);
10640Sstevel@tonic-gate return (result);
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate /*
10680Sstevel@tonic-gate * Store a pointer to one of our data types in the _private member of each
10690Sstevel@tonic-gate * XML data node contained within the passed node. Note this function is
10700Sstevel@tonic-gate * recursive and so all sub-nodes are also shadowed. Only shadow the nodes
10710Sstevel@tonic-gate * which we are interested in, i.e. system, pool, res and comp
10720Sstevel@tonic-gate */
10730Sstevel@tonic-gate static int
create_shadow(xmlNodePtr node)10740Sstevel@tonic-gate create_shadow(xmlNodePtr node)
10750Sstevel@tonic-gate {
10760Sstevel@tonic-gate xmlNodePtr sib;
10770Sstevel@tonic-gate int ret = PO_SUCCESS;
10780Sstevel@tonic-gate /* Create a data structure of the appropriate type */
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate if (0 == (xmlStrcmp(node->name,
10810Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_SYSTEM]))) {
10820Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_SYSTEM, PREC_INVALID,
10830Sstevel@tonic-gate PCEC_INVALID);
10840Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name,
10850Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_POOL]))) {
10860Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_POOL, PREC_INVALID,
10870Sstevel@tonic-gate PCEC_INVALID);
10880Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name,
10890Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_RES_COMP]))) {
10900Sstevel@tonic-gate xmlChar *data;
10910Sstevel@tonic-gate pool_resource_elem_class_t res_class;
10920Sstevel@tonic-gate data = xmlGetProp(node, BAD_CAST c_type);
10930Sstevel@tonic-gate
10940Sstevel@tonic-gate res_class = pool_resource_elem_class_from_string((char *)data);
10950Sstevel@tonic-gate xmlFree(data);
10960Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_RES_COMP, res_class,
10970Sstevel@tonic-gate PCEC_INVALID);
10980Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name,
10990Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_RES_AGG]))) {
11000Sstevel@tonic-gate xmlChar *data;
11010Sstevel@tonic-gate pool_resource_elem_class_t res_class;
11020Sstevel@tonic-gate data = xmlGetProp(node, BAD_CAST c_type);
11030Sstevel@tonic-gate
11040Sstevel@tonic-gate res_class = pool_resource_elem_class_from_string((char *)data);
11050Sstevel@tonic-gate xmlFree(data);
11060Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_RES_AGG, res_class,
11070Sstevel@tonic-gate PCEC_INVALID);
11080Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name,
11090Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_COMP]))) {
11100Sstevel@tonic-gate xmlChar *data;
11110Sstevel@tonic-gate pool_component_elem_class_t comp_class;
11120Sstevel@tonic-gate data = xmlGetProp(node, BAD_CAST c_type);
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate comp_class = pool_component_elem_class_from_string(
11150Sstevel@tonic-gate (char *)data);
11160Sstevel@tonic-gate xmlFree(data);
11170Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_COMP, PREC_INVALID,
11180Sstevel@tonic-gate comp_class);
11190Sstevel@tonic-gate }
11200Sstevel@tonic-gate /* Have to shadow all children and all siblings */
11210Sstevel@tonic-gate for (sib = node->children; sib != NULL; sib = sib->next) {
11220Sstevel@tonic-gate if ((ret = create_shadow(sib)) != PO_SUCCESS)
11230Sstevel@tonic-gate break;
11240Sstevel@tonic-gate }
11250Sstevel@tonic-gate return (ret);
11260Sstevel@tonic-gate }
11270Sstevel@tonic-gate
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate /*
11300Sstevel@tonic-gate * XML Data access and navigation APIs
11310Sstevel@tonic-gate */
11320Sstevel@tonic-gate
11330Sstevel@tonic-gate /*
11340Sstevel@tonic-gate * Close the configuration. There are a few steps to closing a configuration:
11350Sstevel@tonic-gate * - Unlock the backing file (if there is one)
11360Sstevel@tonic-gate * - Close the file (if there is one)
11370Sstevel@tonic-gate * - Free the shadow memory }Done in pool_xml_free_doc
11380Sstevel@tonic-gate * - Free the document }
11390Sstevel@tonic-gate * - Free the data provider for this configuration
11400Sstevel@tonic-gate * - Free the configuration location specifier
11410Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
11420Sstevel@tonic-gate */
11430Sstevel@tonic-gate static int
pool_xml_close(pool_conf_t * conf)11440Sstevel@tonic-gate pool_xml_close(pool_conf_t *conf)
11450Sstevel@tonic-gate {
11460Sstevel@tonic-gate pool_xml_connection_t *pxc = (pool_xml_connection_t *)conf->pc_prov;
11470Sstevel@tonic-gate int ret = PO_SUCCESS;
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate if (pxc->pxc_file != NULL) {
11500Sstevel@tonic-gate /* Close (and implicitly) unlock the file */
11510Sstevel@tonic-gate if (fclose(pxc->pxc_file) != 0) {
11520Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
11530Sstevel@tonic-gate ret = PO_FAIL;
11540Sstevel@tonic-gate }
11550Sstevel@tonic-gate pxc->pxc_file = NULL;
11560Sstevel@tonic-gate }
11570Sstevel@tonic-gate /* Close the xml specific parts */
11580Sstevel@tonic-gate (void) pool_xml_free_doc(conf);
11590Sstevel@tonic-gate pool_xml_connection_free((pool_xml_connection_t *)conf->pc_prov);
11600Sstevel@tonic-gate return (ret);
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate
11630Sstevel@tonic-gate /*
11640Sstevel@tonic-gate * Remove the configuration from the backing store. In XML terms delete
11650Sstevel@tonic-gate * the file backing the configuration. You need a copy of the location
11660Sstevel@tonic-gate * since the pool_conf_close function, frees the location.
11670Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
11680Sstevel@tonic-gate */
11690Sstevel@tonic-gate static int
pool_xml_remove(pool_conf_t * conf)11700Sstevel@tonic-gate pool_xml_remove(pool_conf_t *conf)
11710Sstevel@tonic-gate {
11720Sstevel@tonic-gate if (pool_conf_location(conf) != NULL) {
11730Sstevel@tonic-gate /* First unlink the file, to prevent races on open */
11740Sstevel@tonic-gate if (unlink(pool_conf_location(conf)) != 0) {
11750Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
11760Sstevel@tonic-gate return (PO_FAIL);
11770Sstevel@tonic-gate }
11780Sstevel@tonic-gate /* Now close the configuration */
11790Sstevel@tonic-gate (void) pool_conf_close(conf);
11800Sstevel@tonic-gate return (PO_SUCCESS);
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate return (PO_FAIL);
11830Sstevel@tonic-gate }
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate /*
11860Sstevel@tonic-gate * Validate the configuration. There are three levels of validation, loose,
11870Sstevel@tonic-gate * strict and runtime. In this, XML, implementation, loose is mapped to XML
11880Sstevel@tonic-gate * validation, strict implements additional application level validation
11890Sstevel@tonic-gate * checks, e.g. all pools must have unique names, runtime ensures that this
11900Sstevel@tonic-gate * configuration would instantiate on the current system.
11910Sstevel@tonic-gate *
11920Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
11930Sstevel@tonic-gate */
11940Sstevel@tonic-gate static int
pool_xml_validate(const pool_conf_t * conf,pool_valid_level_t level)11950Sstevel@tonic-gate pool_xml_validate(const pool_conf_t *conf, pool_valid_level_t level)
11960Sstevel@tonic-gate {
11970Sstevel@tonic-gate pool_xml_connection_t *pxc = (pool_xml_connection_t *)conf->pc_prov;
11980Sstevel@tonic-gate xmlValidCtxtPtr cvp;
11990Sstevel@tonic-gate
12000Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) {
12010Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
12020Sstevel@tonic-gate return (PO_FAIL);
12030Sstevel@tonic-gate }
12040Sstevel@tonic-gate cvp->error = pool_error_func;
12050Sstevel@tonic-gate cvp->warning = pool_error_func;
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate if (xmlValidateDocument(cvp, pxc->pxc_doc) == 0) {
12080Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
12090Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
12100Sstevel@tonic-gate return (PO_FAIL);
12110Sstevel@tonic-gate }
12120Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
12130Sstevel@tonic-gate
12140Sstevel@tonic-gate if (level >= POV_RUNTIME) {
12150Sstevel@tonic-gate /*
12160Sstevel@tonic-gate * Note: This is resource specific.
12170Sstevel@tonic-gate */
12180Sstevel@tonic-gate return (((pool_validate_resource(conf, "pset", c_min_prop, 0) ==
1219*11411SSurya.Prakki@Sun.COM PO_SUCCESS) &&
1220*11411SSurya.Prakki@Sun.COM (pool_validate_resource(conf, "pset", c_max_prop, 0) ==
1221*11411SSurya.Prakki@Sun.COM PO_SUCCESS)) ? PO_SUCCESS : PO_FAIL);
12220Sstevel@tonic-gate }
12230Sstevel@tonic-gate return (PO_SUCCESS);
12240Sstevel@tonic-gate }
12250Sstevel@tonic-gate
12260Sstevel@tonic-gate /*
12270Sstevel@tonic-gate * Commit the configuration to the backing store. In XML terms this means
12280Sstevel@tonic-gate * write the changes to the backing file. Read the comments below for details
12290Sstevel@tonic-gate * on exactly how this operation is performed.
12300Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
12310Sstevel@tonic-gate */
12320Sstevel@tonic-gate static int
pool_xml_commit(pool_conf_t * conf)12330Sstevel@tonic-gate pool_xml_commit(pool_conf_t *conf)
12340Sstevel@tonic-gate {
12350Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov;
12360Sstevel@tonic-gate xmlOutputBufferPtr buf;
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate /*
12390Sstevel@tonic-gate * Ensure that the configuration file has no contents
12400Sstevel@tonic-gate */
12410Sstevel@tonic-gate if (fseek(prov->pxc_file, 0, SEEK_SET) != 0) {
12420Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
12430Sstevel@tonic-gate return (PO_FAIL);
12440Sstevel@tonic-gate }
12450Sstevel@tonic-gate
12460Sstevel@tonic-gate if (ftruncate(fileno(prov->pxc_file), 0) == -1) {
12470Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
12480Sstevel@tonic-gate return (PO_FAIL);
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate /*
12510Sstevel@tonic-gate * Create an XML output buffer and write out the contents of the
12520Sstevel@tonic-gate * configuration to the file.
12530Sstevel@tonic-gate */
12540Sstevel@tonic-gate if ((buf = xmlOutputBufferCreateFile(prov->pxc_file, NULL)) == NULL) {
12550Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
12560Sstevel@tonic-gate return (PO_FAIL);
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate if (xmlSaveFormatFileTo(buf, prov->pxc_doc, NULL, 1) == -1) {
12600Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
12610Sstevel@tonic-gate return (PO_FAIL);
12620Sstevel@tonic-gate }
12630Sstevel@tonic-gate
12640Sstevel@tonic-gate return (PO_SUCCESS);
12650Sstevel@tonic-gate }
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate /*
12680Sstevel@tonic-gate * Export the configuration in the specified format to the specified location.
12690Sstevel@tonic-gate * The only format implemented now is the native format, which saves the
12700Sstevel@tonic-gate * active configuration to the supplied location.
12710Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
12720Sstevel@tonic-gate */
12730Sstevel@tonic-gate static int
pool_xml_export(const pool_conf_t * conf,const char * location,pool_export_format_t fmt)12740Sstevel@tonic-gate pool_xml_export(const pool_conf_t *conf, const char *location,
12750Sstevel@tonic-gate pool_export_format_t fmt)
12760Sstevel@tonic-gate {
12770Sstevel@tonic-gate int ret;
12780Sstevel@tonic-gate
12790Sstevel@tonic-gate switch (fmt) {
12800Sstevel@tonic-gate case POX_NATIVE:
12810Sstevel@tonic-gate ret = xmlSaveFormatFile(location,
12820Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc,
12830Sstevel@tonic-gate 1);
12840Sstevel@tonic-gate if (ret == -1) {
12850Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
12860Sstevel@tonic-gate return (PO_FAIL);
12870Sstevel@tonic-gate } else
12880Sstevel@tonic-gate return (PO_SUCCESS);
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate default:
12910Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
12920Sstevel@tonic-gate return (PO_FAIL);
12930Sstevel@tonic-gate }
12940Sstevel@tonic-gate }
12950Sstevel@tonic-gate
12960Sstevel@tonic-gate /*
12970Sstevel@tonic-gate * Discard the configuration and restore the configuration to the values
12980Sstevel@tonic-gate * specified in the configuration location.
12990Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
13000Sstevel@tonic-gate */
13010Sstevel@tonic-gate static int
pool_xml_rollback(pool_conf_t * conf)13020Sstevel@tonic-gate pool_xml_rollback(pool_conf_t *conf)
13030Sstevel@tonic-gate {
13040Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov;
13050Sstevel@tonic-gate
13060Sstevel@tonic-gate /* Rollback the file pointer ready for the reparse */
13070Sstevel@tonic-gate if (fseek(prov->pxc_file, 0, SEEK_SET) != 0) {
13080Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
13090Sstevel@tonic-gate return (PO_FAIL);
13100Sstevel@tonic-gate }
13110Sstevel@tonic-gate /* Reparse the document */
13120Sstevel@tonic-gate /* In XML terms this means, discard and reparse the document */
13130Sstevel@tonic-gate (void) pool_xml_free_doc(conf);
13140Sstevel@tonic-gate if (pool_xml_parse_document(conf) == PO_FAIL)
13150Sstevel@tonic-gate return (PO_FAIL);
13160Sstevel@tonic-gate return (PO_SUCCESS);
13170Sstevel@tonic-gate }
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate /*
13200Sstevel@tonic-gate * Allocate a new pool_elem_t in the supplied configuration of the specified
13210Sstevel@tonic-gate * class.
13220Sstevel@tonic-gate * Returns element pointer/NULL
13230Sstevel@tonic-gate */
13240Sstevel@tonic-gate static void
pool_xml_elem_init(pool_conf_t * conf,pool_xml_elem_t * elem,pool_elem_class_t class,pool_resource_elem_class_t res_class,pool_component_elem_class_t comp_class)13250Sstevel@tonic-gate pool_xml_elem_init(pool_conf_t *conf, pool_xml_elem_t *elem,
13260Sstevel@tonic-gate pool_elem_class_t class, pool_resource_elem_class_t res_class,
13270Sstevel@tonic-gate pool_component_elem_class_t comp_class)
13280Sstevel@tonic-gate {
13290Sstevel@tonic-gate pool_elem_t *pe = TO_ELEM(elem);
13300Sstevel@tonic-gate pe->pe_conf = conf;
13310Sstevel@tonic-gate pe->pe_class = class;
13320Sstevel@tonic-gate pe->pe_resource_class = res_class;
13330Sstevel@tonic-gate pe->pe_component_class = comp_class;
13340Sstevel@tonic-gate /* Set up the function pointers for element manipulation */
13350Sstevel@tonic-gate pe->pe_get_prop = pool_xml_get_property;
13360Sstevel@tonic-gate pe->pe_put_prop = pool_xml_put_property;
13370Sstevel@tonic-gate pe->pe_rm_prop = pool_xml_rm_property;
13380Sstevel@tonic-gate pe->pe_get_props = pool_xml_get_properties;
13390Sstevel@tonic-gate pe->pe_remove = pool_xml_elem_remove;
13400Sstevel@tonic-gate pe->pe_get_container = pool_xml_get_container;
13410Sstevel@tonic-gate pe->pe_set_container = pool_xml_set_container;
13420Sstevel@tonic-gate /*
13430Sstevel@tonic-gate * Specific initialisation for different types of element
13440Sstevel@tonic-gate */
13450Sstevel@tonic-gate if (class == PEC_POOL) {
13460Sstevel@tonic-gate pool_xml_pool_t *pp = (pool_xml_pool_t *)elem;
13470Sstevel@tonic-gate pp->pp_associate = pool_xml_pool_associate;
13480Sstevel@tonic-gate pp->pp_dissociate = pool_xml_pool_dissociate;
13490Sstevel@tonic-gate }
13500Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG) {
13510Sstevel@tonic-gate pool_xml_resource_t *pr = (pool_xml_resource_t *)elem;
13520Sstevel@tonic-gate pr->pr_is_system = pool_xml_resource_is_system;
13530Sstevel@tonic-gate pr->pr_can_associate = pool_xml_resource_can_associate;
13540Sstevel@tonic-gate }
13550Sstevel@tonic-gate }
13560Sstevel@tonic-gate
13570Sstevel@tonic-gate /*
13580Sstevel@tonic-gate * "Wrap" a suplied XML node with a pool_elem_t sub-type of the supplied
13590Sstevel@tonic-gate * class.
13600Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
13610Sstevel@tonic-gate */
13620Sstevel@tonic-gate static int
pool_xml_elem_wrap(xmlNodePtr node,pool_elem_class_t class,pool_resource_elem_class_t res_class,pool_component_elem_class_t comp_class)13630Sstevel@tonic-gate pool_xml_elem_wrap(xmlNodePtr node, pool_elem_class_t class,
13640Sstevel@tonic-gate pool_resource_elem_class_t res_class,
13650Sstevel@tonic-gate pool_component_elem_class_t comp_class)
13660Sstevel@tonic-gate {
13670Sstevel@tonic-gate pool_conf_t *conf = node->doc->_private;
13680Sstevel@tonic-gate pool_xml_elem_t *elem;
13690Sstevel@tonic-gate /* Need to do some messing about to support SubTypes */
13700Sstevel@tonic-gate switch (class) {
13710Sstevel@tonic-gate case PEC_SYSTEM:
13720Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_system_t))) == NULL) {
13730Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
13740Sstevel@tonic-gate return (PO_FAIL);
13750Sstevel@tonic-gate }
13760Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_system_t));
13770Sstevel@tonic-gate break;
13780Sstevel@tonic-gate case PEC_POOL:
13790Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_pool_t))) == NULL) {
13800Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
13810Sstevel@tonic-gate return (PO_FAIL);
13820Sstevel@tonic-gate }
13830Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_pool_t));
13840Sstevel@tonic-gate break;
13850Sstevel@tonic-gate case PEC_RES_COMP:
13860Sstevel@tonic-gate case PEC_RES_AGG:
13870Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_resource_t))) == NULL) {
13880Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
13890Sstevel@tonic-gate return (PO_FAIL);
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_resource_t));
13920Sstevel@tonic-gate break;
13930Sstevel@tonic-gate case PEC_COMP:
13940Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_component_t))) == NULL) {
13950Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
13960Sstevel@tonic-gate return (PO_FAIL);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_component_t));
13990Sstevel@tonic-gate break;
14000Sstevel@tonic-gate }
14010Sstevel@tonic-gate pool_xml_elem_init(conf, elem, class, res_class, comp_class);
14020Sstevel@tonic-gate node->_private = elem;
14030Sstevel@tonic-gate elem->pxe_node = node;
14040Sstevel@tonic-gate return (PO_SUCCESS);
14050Sstevel@tonic-gate }
14060Sstevel@tonic-gate
14070Sstevel@tonic-gate /*
14080Sstevel@tonic-gate * Associate a pool to the default resource for the supplied resource
14090Sstevel@tonic-gate * type.
14100Sstevel@tonic-gate */
14110Sstevel@tonic-gate int
pool_assoc_default_resource_type(pool_t * pool,pool_resource_elem_class_t type)14120Sstevel@tonic-gate pool_assoc_default_resource_type(pool_t *pool, pool_resource_elem_class_t type)
14130Sstevel@tonic-gate {
14140Sstevel@tonic-gate pool_value_t *props[] = { NULL, NULL, NULL };
14150Sstevel@tonic-gate uint_t rl_size;
14160Sstevel@tonic-gate pool_resource_t **rsl;
14170Sstevel@tonic-gate pool_conf_t *conf = TO_ELEM(pool)->pe_conf;
14180Sstevel@tonic-gate char_buf_t *cb = NULL;
14190Sstevel@tonic-gate pool_value_t val0 = POOL_VALUE_INITIALIZER;
14200Sstevel@tonic-gate pool_value_t val1 = POOL_VALUE_INITIALIZER;
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate props[0] = &val0;
14230Sstevel@tonic-gate props[1] = &val1;
14240Sstevel@tonic-gate
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate if (pool_value_set_string(props[0], pool_resource_type_string(type)) !=
14270Sstevel@tonic-gate PO_SUCCESS ||
14280Sstevel@tonic-gate pool_value_set_name(props[0], c_type) != PO_SUCCESS) {
14290Sstevel@tonic-gate return (PO_FAIL);
14300Sstevel@tonic-gate }
14310Sstevel@tonic-gate
14320Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
14330Sstevel@tonic-gate return (PO_FAIL);
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate
14360Sstevel@tonic-gate if (set_char_buf(cb, "%s.default",
14370Sstevel@tonic-gate pool_resource_type_string(type)) !=
14380Sstevel@tonic-gate PO_SUCCESS) {
14390Sstevel@tonic-gate free_char_buf(cb);
14400Sstevel@tonic-gate return (PO_FAIL);
14410Sstevel@tonic-gate }
14420Sstevel@tonic-gate if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) {
14430Sstevel@tonic-gate free_char_buf(cb);
14440Sstevel@tonic-gate return (PO_FAIL);
14450Sstevel@tonic-gate }
14460Sstevel@tonic-gate pool_value_set_bool(props[1], PO_TRUE);
14470Sstevel@tonic-gate free_char_buf(cb);
14480Sstevel@tonic-gate
14490Sstevel@tonic-gate if ((rsl = pool_query_resources(conf, &rl_size, props)) == NULL) {
14500Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
14510Sstevel@tonic-gate return (PO_FAIL);
14520Sstevel@tonic-gate }
14530Sstevel@tonic-gate
14540Sstevel@tonic-gate /*
14550Sstevel@tonic-gate * One default resource set per type
14560Sstevel@tonic-gate */
14570Sstevel@tonic-gate if (rl_size != 1) {
14580Sstevel@tonic-gate free(rsl);
14590Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
14600Sstevel@tonic-gate return (PO_FAIL);
14610Sstevel@tonic-gate }
14620Sstevel@tonic-gate if (pool_associate(conf, pool, rsl[0]) < 0) {
14630Sstevel@tonic-gate free(rsl);
14640Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
14650Sstevel@tonic-gate return (PO_FAIL);
14660Sstevel@tonic-gate }
14670Sstevel@tonic-gate free(rsl);
14680Sstevel@tonic-gate return (PO_SUCCESS);
14690Sstevel@tonic-gate }
14700Sstevel@tonic-gate
14710Sstevel@tonic-gate /*
14720Sstevel@tonic-gate * Create an XML node in the supplied configuration with a pool_elem_t
14730Sstevel@tonic-gate * sub-type of the supplied class.
14740Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
14750Sstevel@tonic-gate */
14760Sstevel@tonic-gate static pool_elem_t *
pool_xml_elem_create(pool_conf_t * conf,pool_elem_class_t class,pool_resource_elem_class_t res_class,pool_component_elem_class_t comp_class)14770Sstevel@tonic-gate pool_xml_elem_create(pool_conf_t *conf, pool_elem_class_t class,
14780Sstevel@tonic-gate pool_resource_elem_class_t res_class,
14790Sstevel@tonic-gate pool_component_elem_class_t comp_class)
14800Sstevel@tonic-gate {
14810Sstevel@tonic-gate /* In XML terms, create an element of the appropriate class */
14820Sstevel@tonic-gate pool_xml_elem_t *elem;
14830Sstevel@tonic-gate pool_elem_t *parent;
14840Sstevel@tonic-gate pool_system_t *parent_system;
14850Sstevel@tonic-gate
14860Sstevel@tonic-gate if (class == PEC_INVALID) {
14870Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
14880Sstevel@tonic-gate return (NULL);
14890Sstevel@tonic-gate }
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate /* Now create the XML component and add to it's parent */
14920Sstevel@tonic-gate /*
14930Sstevel@tonic-gate * If we know the class of an element, we know it's parent.
14940Sstevel@tonic-gate * PEC_POOL, the parent must be the system node
14950Sstevel@tonic-gate * PEC_RES, treat as pool.
14960Sstevel@tonic-gate * PEC_COMP, we don't know the parent, leave this up to the
14970Sstevel@tonic-gate * create_comp function.
14980Sstevel@tonic-gate */
14990Sstevel@tonic-gate /* Since we know the subtype we can create and populate the sub-type */
15000Sstevel@tonic-gate switch (class) {
15010Sstevel@tonic-gate case PEC_POOL:
15020Sstevel@tonic-gate if ((parent_system = pool_conf_system(conf)) == NULL) {
15030Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
15040Sstevel@tonic-gate return (NULL);
15050Sstevel@tonic-gate }
15060Sstevel@tonic-gate if ((parent = pool_system_elem(parent_system)) == NULL) {
15070Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
15080Sstevel@tonic-gate return (NULL);
15090Sstevel@tonic-gate }
15100Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_system_t))) == NULL) {
15110Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
15120Sstevel@tonic-gate return (NULL);
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_system_t));
15150Sstevel@tonic-gate if ((elem->pxe_node = node_create_with_id(
15160Sstevel@tonic-gate ((pool_xml_elem_t *)parent)->pxe_node,
15170Sstevel@tonic-gate BAD_CAST element_class_tags[class])) == NULL) {
15180Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
15190Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem);
15200Sstevel@tonic-gate return (NULL);
15210Sstevel@tonic-gate }
15220Sstevel@tonic-gate break;
15230Sstevel@tonic-gate case PEC_RES_COMP:
15240Sstevel@tonic-gate case PEC_RES_AGG:
15250Sstevel@tonic-gate if ((parent_system = pool_conf_system(conf)) == NULL) {
15260Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
15270Sstevel@tonic-gate return (NULL);
15280Sstevel@tonic-gate }
15290Sstevel@tonic-gate if ((parent = pool_system_elem(parent_system)) == NULL) {
15300Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
15310Sstevel@tonic-gate return (NULL);
15320Sstevel@tonic-gate }
15330Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_resource_t))) == NULL) {
15340Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
15350Sstevel@tonic-gate return (NULL);
15360Sstevel@tonic-gate }
15370Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_resource_t));
15380Sstevel@tonic-gate if ((elem->pxe_node = node_create_with_id
15390Sstevel@tonic-gate (((pool_xml_elem_t *)parent)->pxe_node,
1540*11411SSurya.Prakki@Sun.COM BAD_CAST element_class_tags[class])) == NULL) {
15410Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
15420Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem);
15430Sstevel@tonic-gate return (NULL);
15440Sstevel@tonic-gate }
15450Sstevel@tonic-gate break;
15460Sstevel@tonic-gate case PEC_COMP:
15470Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_component_t))) == NULL) {
15480Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
15490Sstevel@tonic-gate return (NULL);
15500Sstevel@tonic-gate }
15510Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_component_t));
15520Sstevel@tonic-gate if ((elem->pxe_node = node_create(NULL,
15530Sstevel@tonic-gate BAD_CAST element_class_tags[class])) == NULL) {
15540Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
15550Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem);
15560Sstevel@tonic-gate return (NULL);
15570Sstevel@tonic-gate }
15580Sstevel@tonic-gate break;
15590Sstevel@tonic-gate default:
15600Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
15610Sstevel@tonic-gate return (NULL);
15620Sstevel@tonic-gate }
15630Sstevel@tonic-gate pool_xml_elem_init(conf, elem, class, res_class, comp_class);
15640Sstevel@tonic-gate elem->pxe_node->_private = elem;
15650Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG ||
15660Sstevel@tonic-gate class == PEC_COMP) {
15670Sstevel@tonic-gate /*
15680Sstevel@tonic-gate * Put the type and an invalid sys_id on the node.
15690Sstevel@tonic-gate */
15700Sstevel@tonic-gate if (xmlSetProp(elem->pxe_node, BAD_CAST c_sys_prop,
15710Sstevel@tonic-gate BAD_CAST POOL_SYSID_BAD_STRING) == NULL) {
15720Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
15730Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem);
15740Sstevel@tonic-gate return (NULL);
15750Sstevel@tonic-gate }
15760Sstevel@tonic-gate if (xmlSetProp(elem->pxe_node, BAD_CAST c_type,
1577*11411SSurya.Prakki@Sun.COM BAD_CAST pool_elem_class_string(
1578*11411SSurya.Prakki@Sun.COM (pool_elem_t *)elem)) == NULL) {
15790Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
15800Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem);
15810Sstevel@tonic-gate return (NULL);
15820Sstevel@tonic-gate }
15830Sstevel@tonic-gate }
15840Sstevel@tonic-gate if (class == PEC_POOL) {
15850Sstevel@tonic-gate /*
15860Sstevel@tonic-gate * Note: This is resource specific.
15870Sstevel@tonic-gate */
15880Sstevel@tonic-gate if (pool_assoc_default_resource_type(pool_elem_pool(
15890Sstevel@tonic-gate (pool_elem_t *)elem), PREC_PSET) == PO_FAIL) {
15900Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem);
15910Sstevel@tonic-gate return (NULL);
15920Sstevel@tonic-gate }
15930Sstevel@tonic-gate }
15940Sstevel@tonic-gate return ((pool_elem_t *)elem);
15950Sstevel@tonic-gate }
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate /*
15980Sstevel@tonic-gate * Allocate a data provider for the supplied configuration and optionally
15990Sstevel@tonic-gate * discover resources.
16000Sstevel@tonic-gate * The data provider is the cross over point from the "abstract" configuration
16010Sstevel@tonic-gate * functions into the data representation specific manipulation routines.
16020Sstevel@tonic-gate * This function sets up all the required pointers to create an XML aware
16030Sstevel@tonic-gate * data provider.
16040Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
16050Sstevel@tonic-gate */
16060Sstevel@tonic-gate int
pool_xml_connection_alloc(pool_conf_t * conf,int oflags)16070Sstevel@tonic-gate pool_xml_connection_alloc(pool_conf_t *conf, int oflags)
16080Sstevel@tonic-gate {
16090Sstevel@tonic-gate pool_xml_connection_t *prov;
16100Sstevel@tonic-gate
16110Sstevel@tonic-gate xml_init();
16120Sstevel@tonic-gate if ((prov = malloc(sizeof (pool_xml_connection_t))) == NULL) {
16130Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
16140Sstevel@tonic-gate return (PO_FAIL);
16150Sstevel@tonic-gate }
16160Sstevel@tonic-gate (void) memset(prov, 0, sizeof (pool_xml_connection_t));
16170Sstevel@tonic-gate /*
16180Sstevel@tonic-gate * Initialise data members
16190Sstevel@tonic-gate */
16200Sstevel@tonic-gate prov->pc_name = strdup("LIBXML 2.4.0");
16210Sstevel@tonic-gate prov->pc_store_type = XML_DATA_STORE;
16220Sstevel@tonic-gate prov->pc_oflags = oflags;
16230Sstevel@tonic-gate /*
16240Sstevel@tonic-gate * Initialise function pointers
16250Sstevel@tonic-gate */
16260Sstevel@tonic-gate prov->pc_close = pool_xml_close;
16270Sstevel@tonic-gate prov->pc_validate = pool_xml_validate;
16280Sstevel@tonic-gate prov->pc_commit = pool_xml_commit;
16290Sstevel@tonic-gate prov->pc_export = pool_xml_export;
16300Sstevel@tonic-gate prov->pc_rollback = pool_xml_rollback;
16310Sstevel@tonic-gate prov->pc_exec_query = pool_xml_exec_query;
16320Sstevel@tonic-gate prov->pc_elem_create = pool_xml_elem_create;
16330Sstevel@tonic-gate prov->pc_remove = pool_xml_remove;
16340Sstevel@tonic-gate prov->pc_res_xfer = pool_xml_res_transfer;
16350Sstevel@tonic-gate prov->pc_res_xxfer = pool_xml_res_xtransfer;
16360Sstevel@tonic-gate /*
16370Sstevel@tonic-gate * End of common initialisation
16380Sstevel@tonic-gate */
16390Sstevel@tonic-gate /*
16400Sstevel@tonic-gate * Associate the provider to it's configuration
16410Sstevel@tonic-gate */
16420Sstevel@tonic-gate conf->pc_prov = (pool_connection_t *)prov;
16430Sstevel@tonic-gate /*
16440Sstevel@tonic-gate * At this point the configuration provider has been initialized,
16450Sstevel@tonic-gate * mark the configuration as valid so that the various routines
16460Sstevel@tonic-gate * which rely on a valid configuration will work correctly.
16470Sstevel@tonic-gate */
16480Sstevel@tonic-gate conf->pc_state = POF_VALID;
16490Sstevel@tonic-gate
16500Sstevel@tonic-gate if ((oflags & PO_CREAT) != 0) {
16510Sstevel@tonic-gate pool_conf_t *dyn;
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate if ((dyn = pool_conf_alloc()) == NULL)
16540Sstevel@tonic-gate return (PO_FAIL);
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate if (pool_conf_open(dyn, pool_dynamic_location(),
16570Sstevel@tonic-gate PO_RDONLY) != PO_SUCCESS) {
16580Sstevel@tonic-gate pool_conf_free(dyn);
16590Sstevel@tonic-gate return (PO_FAIL);
16600Sstevel@tonic-gate }
16610Sstevel@tonic-gate
16620Sstevel@tonic-gate if (pool_conf_export(dyn, conf->pc_location,
16630Sstevel@tonic-gate POX_NATIVE) != PO_SUCCESS) {
16640Sstevel@tonic-gate (void) pool_conf_close(dyn);
16650Sstevel@tonic-gate pool_conf_free(dyn);
16660Sstevel@tonic-gate return (PO_FAIL);
16670Sstevel@tonic-gate }
16680Sstevel@tonic-gate (void) pool_conf_close(dyn);
16690Sstevel@tonic-gate pool_conf_free(dyn);
16700Sstevel@tonic-gate }
16710Sstevel@tonic-gate
16720Sstevel@tonic-gate if (pool_xml_open_file(conf) == PO_FAIL) {
16730Sstevel@tonic-gate (void) pool_xml_close(conf);
16740Sstevel@tonic-gate return (PO_FAIL);
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate return (PO_SUCCESS);
16780Sstevel@tonic-gate }
16790Sstevel@tonic-gate
16800Sstevel@tonic-gate /*
16810Sstevel@tonic-gate * Free the resources for an XML data provider.
16820Sstevel@tonic-gate */
16830Sstevel@tonic-gate static void
pool_xml_connection_free(pool_xml_connection_t * prov)16840Sstevel@tonic-gate pool_xml_connection_free(pool_xml_connection_t *prov)
16850Sstevel@tonic-gate {
16860Sstevel@tonic-gate free((void *)prov->pc_name);
16870Sstevel@tonic-gate free(prov);
16880Sstevel@tonic-gate }
16890Sstevel@tonic-gate
16900Sstevel@tonic-gate /*
16910Sstevel@tonic-gate * Allocate a result set. The Result Set stores the result of an XPath
16920Sstevel@tonic-gate * query along with the parameters used to create the result set (for
16930Sstevel@tonic-gate * debugging purposes).
16940Sstevel@tonic-gate * Returns pool_xml_result_set_t pointer/NULL
16950Sstevel@tonic-gate */
16960Sstevel@tonic-gate static pool_xml_result_set_t *
pool_xml_result_set_alloc(const pool_conf_t * conf)16970Sstevel@tonic-gate pool_xml_result_set_alloc(const pool_conf_t *conf)
16980Sstevel@tonic-gate {
16990Sstevel@tonic-gate pool_xml_result_set_t *rs;
17000Sstevel@tonic-gate
17010Sstevel@tonic-gate if ((rs = malloc(sizeof (pool_xml_result_set_t))) == NULL) {
17020Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
17030Sstevel@tonic-gate return (NULL);
17040Sstevel@tonic-gate }
17050Sstevel@tonic-gate (void) memset(rs, 0, sizeof (pool_xml_result_set_t));
17060Sstevel@tonic-gate rs->prs_conf = conf;
17070Sstevel@tonic-gate rs->prs_index = -1;
17080Sstevel@tonic-gate rs->prs_active = PO_TRUE;
17090Sstevel@tonic-gate /* Fix up the result set accessor functions to the xml specfic ones */
17100Sstevel@tonic-gate rs->prs_next = pool_xml_rs_next;
17110Sstevel@tonic-gate rs->prs_prev = pool_xml_rs_prev;
17120Sstevel@tonic-gate rs->prs_first = pool_xml_rs_first;
17130Sstevel@tonic-gate rs->prs_last = pool_xml_rs_last;
17140Sstevel@tonic-gate rs->prs_get_index = pool_xml_rs_get_index;
17150Sstevel@tonic-gate rs->prs_set_index = pool_xml_rs_set_index;
17160Sstevel@tonic-gate rs->prs_close = pool_xml_rs_close;
17170Sstevel@tonic-gate rs->prs_count = pool_xml_rs_count;
17180Sstevel@tonic-gate return (rs);
17190Sstevel@tonic-gate }
17200Sstevel@tonic-gate
17210Sstevel@tonic-gate /*
17220Sstevel@tonic-gate * Free a result set. Ensure that the resources are all released at this point.
17230Sstevel@tonic-gate */
17240Sstevel@tonic-gate static void
pool_xml_result_set_free(pool_xml_result_set_t * rs)17250Sstevel@tonic-gate pool_xml_result_set_free(pool_xml_result_set_t *rs)
17260Sstevel@tonic-gate {
17270Sstevel@tonic-gate if (rs->pxr_path != NULL)
17280Sstevel@tonic-gate xmlXPathFreeObject(rs->pxr_path);
17290Sstevel@tonic-gate if (rs->pxr_ctx != NULL)
17300Sstevel@tonic-gate xmlXPathFreeContext(rs->pxr_ctx);
17310Sstevel@tonic-gate free(rs);
17320Sstevel@tonic-gate }
17330Sstevel@tonic-gate
17340Sstevel@tonic-gate /*
17350Sstevel@tonic-gate * Transfer size from one resource to another.
17360Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
17370Sstevel@tonic-gate */
17380Sstevel@tonic-gate /* ARGSUSED */
17390Sstevel@tonic-gate int
pool_xml_res_transfer(pool_resource_t * src,pool_resource_t * tgt,uint64_t size)17400Sstevel@tonic-gate pool_xml_res_transfer(pool_resource_t *src, pool_resource_t *tgt, uint64_t size)
17410Sstevel@tonic-gate {
17420Sstevel@tonic-gate return (PO_SUCCESS);
17430Sstevel@tonic-gate }
17440Sstevel@tonic-gate
17450Sstevel@tonic-gate /*
17460Sstevel@tonic-gate * Transfer components rl from one resource to another.
17470Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
17480Sstevel@tonic-gate */
17490Sstevel@tonic-gate /* ARGSUSED */
17500Sstevel@tonic-gate int
pool_xml_res_xtransfer(pool_resource_t * src,pool_resource_t * tgt,pool_component_t ** rl)17510Sstevel@tonic-gate pool_xml_res_xtransfer(pool_resource_t *src, pool_resource_t *tgt,
17520Sstevel@tonic-gate pool_component_t **rl) {
17530Sstevel@tonic-gate int i;
17540Sstevel@tonic-gate
17550Sstevel@tonic-gate /*
17560Sstevel@tonic-gate * Walk the Result Set and move the resource components
17570Sstevel@tonic-gate */
17580Sstevel@tonic-gate for (i = 0; rl[i] != NULL; i++) {
17590Sstevel@tonic-gate if (pool_set_container(TO_ELEM(tgt), TO_ELEM(rl[i])) ==
17600Sstevel@tonic-gate PO_FAIL) {
17610Sstevel@tonic-gate return (PO_FAIL);
17620Sstevel@tonic-gate }
17630Sstevel@tonic-gate }
17640Sstevel@tonic-gate return (PO_SUCCESS);
17650Sstevel@tonic-gate }
17660Sstevel@tonic-gate
17670Sstevel@tonic-gate /*
17680Sstevel@tonic-gate * Return the next element in a result set.
17690Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
17700Sstevel@tonic-gate */
17710Sstevel@tonic-gate static pool_elem_t *
pool_xml_rs_next(pool_result_set_t * set)17720Sstevel@tonic-gate pool_xml_rs_next(pool_result_set_t *set)
17730Sstevel@tonic-gate {
17740Sstevel@tonic-gate pool_elem_t *next;
17750Sstevel@tonic-gate /* Since I know this is an XML result set */
17760Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
17770Sstevel@tonic-gate
17780Sstevel@tonic-gate /* Update the context node */
17790Sstevel@tonic-gate if (xset->prs_index == xset->pxr_path->nodesetval->nodeNr - 1)
17800Sstevel@tonic-gate return (NULL);
17810Sstevel@tonic-gate next =
17820Sstevel@tonic-gate xset->pxr_path->nodesetval->nodeTab[++xset->prs_index]->_private;
17830Sstevel@tonic-gate return (next);
17840Sstevel@tonic-gate }
17850Sstevel@tonic-gate
17860Sstevel@tonic-gate /*
17870Sstevel@tonic-gate * Return the previous element in a result set.
17880Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
17890Sstevel@tonic-gate */
17900Sstevel@tonic-gate static pool_elem_t *
pool_xml_rs_prev(pool_result_set_t * set)17910Sstevel@tonic-gate pool_xml_rs_prev(pool_result_set_t *set)
17920Sstevel@tonic-gate {
17930Sstevel@tonic-gate pool_elem_t *prev;
17940Sstevel@tonic-gate /* Since I know this is an XML result set */
17950Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
17960Sstevel@tonic-gate
17970Sstevel@tonic-gate /* Update the context node */
17980Sstevel@tonic-gate if (xset->prs_index < 0)
17990Sstevel@tonic-gate return (NULL);
18000Sstevel@tonic-gate prev =
18010Sstevel@tonic-gate xset->pxr_path->nodesetval->nodeTab[xset->prs_index--]->_private;
18020Sstevel@tonic-gate return (prev);
18030Sstevel@tonic-gate }
18040Sstevel@tonic-gate
18050Sstevel@tonic-gate /*
18060Sstevel@tonic-gate * Sets the current index in a result set.
18070Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
18080Sstevel@tonic-gate */
18090Sstevel@tonic-gate static int
pool_xml_rs_set_index(pool_result_set_t * set,int index)18100Sstevel@tonic-gate pool_xml_rs_set_index(pool_result_set_t *set, int index)
18110Sstevel@tonic-gate {
18120Sstevel@tonic-gate /* Since I know this is an XML result set */
18130Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
18140Sstevel@tonic-gate
18150Sstevel@tonic-gate if (index < 0 || index >= xset->pxr_path->nodesetval->nodeNr) {
18160Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
18170Sstevel@tonic-gate return (PO_FAIL);
18180Sstevel@tonic-gate }
18190Sstevel@tonic-gate xset->prs_index = index;
18200Sstevel@tonic-gate return (PO_SUCCESS);
18210Sstevel@tonic-gate }
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate /*
18240Sstevel@tonic-gate * Return the current index in a result set.
18250Sstevel@tonic-gate * Returns current index
18260Sstevel@tonic-gate */
18270Sstevel@tonic-gate static int
pool_xml_rs_get_index(pool_result_set_t * set)18280Sstevel@tonic-gate pool_xml_rs_get_index(pool_result_set_t *set)
18290Sstevel@tonic-gate {
18300Sstevel@tonic-gate /* Since I know this is an XML result set */
18310Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
18320Sstevel@tonic-gate
18330Sstevel@tonic-gate return (xset->prs_index);
18340Sstevel@tonic-gate }
18350Sstevel@tonic-gate
18360Sstevel@tonic-gate /*
18370Sstevel@tonic-gate * Return the first element in a result set.
18380Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
18390Sstevel@tonic-gate */
18400Sstevel@tonic-gate static pool_elem_t *
pool_xml_rs_first(pool_result_set_t * set)18410Sstevel@tonic-gate pool_xml_rs_first(pool_result_set_t *set)
18420Sstevel@tonic-gate {
18430Sstevel@tonic-gate /* Since I know this is an XML result set */
18440Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
18450Sstevel@tonic-gate
18460Sstevel@tonic-gate /* Update the context node */
18470Sstevel@tonic-gate return (xset->pxr_path->nodesetval->nodeTab[0]->_private);
18480Sstevel@tonic-gate }
18490Sstevel@tonic-gate
18500Sstevel@tonic-gate /*
18510Sstevel@tonic-gate * Return the last element in a result set.
18520Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
18530Sstevel@tonic-gate */
18540Sstevel@tonic-gate static pool_elem_t *
pool_xml_rs_last(pool_result_set_t * set)18550Sstevel@tonic-gate pool_xml_rs_last(pool_result_set_t *set)
18560Sstevel@tonic-gate {
18570Sstevel@tonic-gate /* Since I know this is an XML result set */
18580Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
18590Sstevel@tonic-gate
18600Sstevel@tonic-gate /* Update the context node */
18610Sstevel@tonic-gate return (xset->pxr_path->nodesetval->
18620Sstevel@tonic-gate nodeTab[xset->pxr_path->nodesetval->nodeNr-1]->_private);
18630Sstevel@tonic-gate }
18640Sstevel@tonic-gate
18650Sstevel@tonic-gate /*
18660Sstevel@tonic-gate * Return the number of results in a result set.
18670Sstevel@tonic-gate * Returns result count
18680Sstevel@tonic-gate */
18690Sstevel@tonic-gate static int
pool_xml_rs_count(pool_result_set_t * set)18700Sstevel@tonic-gate pool_xml_rs_count(pool_result_set_t *set)
18710Sstevel@tonic-gate {
18720Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
18730Sstevel@tonic-gate
18740Sstevel@tonic-gate return (xset->pxr_path->nodesetval->nodeNr);
18750Sstevel@tonic-gate }
18760Sstevel@tonic-gate
18770Sstevel@tonic-gate
18780Sstevel@tonic-gate /*
18790Sstevel@tonic-gate * Close a result set. Remove this result set from the list of results and
18800Sstevel@tonic-gate * free the resources
18810Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
18820Sstevel@tonic-gate */
18830Sstevel@tonic-gate static int
pool_xml_rs_close(pool_result_set_t * set)18840Sstevel@tonic-gate pool_xml_rs_close(pool_result_set_t *set)
18850Sstevel@tonic-gate {
18860Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set;
18870Sstevel@tonic-gate
18880Sstevel@tonic-gate pool_xml_result_set_free(xset);
18890Sstevel@tonic-gate return (PO_SUCCESS);
18900Sstevel@tonic-gate }
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate /*
18930Sstevel@tonic-gate * Set the container for a node.
18940Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
18950Sstevel@tonic-gate */
18960Sstevel@tonic-gate static int
pool_xml_set_container(pool_elem_t * pp,pool_elem_t * pc)18970Sstevel@tonic-gate pool_xml_set_container(pool_elem_t *pp, pool_elem_t *pc)
18980Sstevel@tonic-gate {
18990Sstevel@tonic-gate pool_xml_elem_t *pxp;
19000Sstevel@tonic-gate pool_xml_elem_t *pxc;
19010Sstevel@tonic-gate xmlNodePtr parent;
19020Sstevel@tonic-gate
19030Sstevel@tonic-gate pxp = (pool_xml_elem_t *)pp;
19040Sstevel@tonic-gate pxc = (pool_xml_elem_t *)pc;
19050Sstevel@tonic-gate parent = pxc->pxe_node->parent;
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate xmlUnlinkNode(pxc->pxe_node);
19080Sstevel@tonic-gate if (xmlAddChild(pxp->pxe_node, pxc->pxe_node) == NULL) {
1909*11411SSurya.Prakki@Sun.COM /* Try to move back */
1910*11411SSurya.Prakki@Sun.COM (void) xmlAddChild(parent, pxc->pxe_node);
19110Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
19120Sstevel@tonic-gate return (PO_FAIL);
19130Sstevel@tonic-gate }
19140Sstevel@tonic-gate pc->pe_conf = pp->pe_conf;
19150Sstevel@tonic-gate return (PO_SUCCESS);
19160Sstevel@tonic-gate }
19170Sstevel@tonic-gate /*
19180Sstevel@tonic-gate * Get the container for a node.
19190Sstevel@tonic-gate * Returns Container/NULL
19200Sstevel@tonic-gate */
19210Sstevel@tonic-gate static pool_elem_t *
pool_xml_get_container(const pool_elem_t * pc)19220Sstevel@tonic-gate pool_xml_get_container(const pool_elem_t *pc)
19230Sstevel@tonic-gate {
19240Sstevel@tonic-gate pool_xml_elem_t *pxc = (pool_xml_elem_t *)pc;
19250Sstevel@tonic-gate
19260Sstevel@tonic-gate return ((pool_elem_t *)pxc->pxe_node->parent->_private);
19270Sstevel@tonic-gate }
19280Sstevel@tonic-gate
19290Sstevel@tonic-gate /*
19300Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other
19310Sstevel@tonic-gate * resource types.
19320Sstevel@tonic-gate */
19330Sstevel@tonic-gate int
pool_xml_resource_is_system(const pool_resource_t * pr)19340Sstevel@tonic-gate pool_xml_resource_is_system(const pool_resource_t *pr)
19350Sstevel@tonic-gate {
19360Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) {
19370Sstevel@tonic-gate case PREC_PSET:
19380Sstevel@tonic-gate return (PSID_IS_SYSSET(
19390Sstevel@tonic-gate elem_get_sysid(TO_ELEM(pr))));
19400Sstevel@tonic-gate default:
19410Sstevel@tonic-gate return (PO_FALSE);
19420Sstevel@tonic-gate }
19430Sstevel@tonic-gate }
19440Sstevel@tonic-gate
19450Sstevel@tonic-gate /*
19460Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other
19470Sstevel@tonic-gate * resource types.
19480Sstevel@tonic-gate */
19490Sstevel@tonic-gate int
pool_xml_resource_can_associate(const pool_resource_t * pr)19500Sstevel@tonic-gate pool_xml_resource_can_associate(const pool_resource_t *pr)
19510Sstevel@tonic-gate {
19520Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) {
19530Sstevel@tonic-gate case PREC_PSET:
19540Sstevel@tonic-gate return (PO_TRUE);
19550Sstevel@tonic-gate default:
19560Sstevel@tonic-gate return (PO_FALSE);
19570Sstevel@tonic-gate }
19580Sstevel@tonic-gate }
19590Sstevel@tonic-gate
19600Sstevel@tonic-gate /*
19610Sstevel@tonic-gate * Note: This function is resource specific. It must be extended to support
19620Sstevel@tonic-gate * multiple resource types.
19630Sstevel@tonic-gate */
19640Sstevel@tonic-gate int
pool_xml_pool_associate(pool_t * pool,const pool_resource_t * pr)19650Sstevel@tonic-gate pool_xml_pool_associate(pool_t *pool, const pool_resource_t *pr)
19660Sstevel@tonic-gate {
19670Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
19680Sstevel@tonic-gate
19690Sstevel@tonic-gate if (pool_xml_get_property(TO_ELEM(pr),
19700Sstevel@tonic-gate "pset.ref_id", &val) != POC_STRING)
19710Sstevel@tonic-gate return (PO_FAIL);
19720Sstevel@tonic-gate if (pool_xml_put_property(TO_ELEM(pool), "pool.res", &val) !=
19730Sstevel@tonic-gate PO_SUCCESS)
19740Sstevel@tonic-gate return (PO_FAIL);
19750Sstevel@tonic-gate return (PO_SUCCESS);
19760Sstevel@tonic-gate }
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate /*
19790Sstevel@tonic-gate * pool_xml_pool_dissociate() simply finds the default resource for
19800Sstevel@tonic-gate * the type of resource being dissociated and then calls
19810Sstevel@tonic-gate * pool_xml_pool_associate() to associate to the default resource.
19820Sstevel@tonic-gate */
19830Sstevel@tonic-gate int
pool_xml_pool_dissociate(pool_t * pool,const pool_resource_t * pr)19840Sstevel@tonic-gate pool_xml_pool_dissociate(pool_t *pool, const pool_resource_t *pr)
19850Sstevel@tonic-gate {
19860Sstevel@tonic-gate const pool_resource_t *default_res;
19870Sstevel@tonic-gate
19880Sstevel@tonic-gate if ((default_res = get_default_resource(pr)) == NULL)
19890Sstevel@tonic-gate return (PO_FAIL);
19900Sstevel@tonic-gate if (default_res == pr)
19910Sstevel@tonic-gate return (PO_SUCCESS);
19920Sstevel@tonic-gate return (pool_xml_pool_associate(pool, default_res));
19930Sstevel@tonic-gate }
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate /*
19960Sstevel@tonic-gate * pool_xml_open_file() opens a file for a configuration. This establishes
19970Sstevel@tonic-gate * the locks required to ensure data integrity when manipulating a
19980Sstevel@tonic-gate * configuration.
19990Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
20000Sstevel@tonic-gate */
20010Sstevel@tonic-gate static int
pool_xml_open_file(pool_conf_t * conf)20020Sstevel@tonic-gate pool_xml_open_file(pool_conf_t *conf)
20030Sstevel@tonic-gate {
20040Sstevel@tonic-gate struct flock lock;
20050Sstevel@tonic-gate struct stat s;
20060Sstevel@tonic-gate
20070Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov;
20080Sstevel@tonic-gate
20090Sstevel@tonic-gate /*
20100Sstevel@tonic-gate * Always close the pxc_file in case there was a previously failed open
20110Sstevel@tonic-gate */
20120Sstevel@tonic-gate if (prov->pxc_file != NULL) {
20130Sstevel@tonic-gate (void) fclose(prov->pxc_file);
20140Sstevel@tonic-gate prov->pxc_file = NULL;
20150Sstevel@tonic-gate }
20160Sstevel@tonic-gate
20170Sstevel@tonic-gate /*
20180Sstevel@tonic-gate * Check that the DTD required for this operation is present.
20190Sstevel@tonic-gate * If it isn't fail
20200Sstevel@tonic-gate */
20210Sstevel@tonic-gate if (dtd_exists(dtd_location) == PO_FALSE) {
20220Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
20230Sstevel@tonic-gate return (PO_FAIL);
20240Sstevel@tonic-gate }
20250Sstevel@tonic-gate
20260Sstevel@tonic-gate if ((prov->pc_oflags & PO_RDWR) != 0)
20271914Scasper prov->pxc_file = fopen(conf->pc_location, "r+F");
20280Sstevel@tonic-gate else /* Assume opening PO_RDONLY */
20291914Scasper prov->pxc_file = fopen(conf->pc_location, "rF");
20300Sstevel@tonic-gate
20310Sstevel@tonic-gate if (prov->pxc_file == NULL) {
20320Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
20330Sstevel@tonic-gate return (PO_FAIL);
20340Sstevel@tonic-gate }
20350Sstevel@tonic-gate
20360Sstevel@tonic-gate /*
20370Sstevel@tonic-gate * Setup the lock for the file
20380Sstevel@tonic-gate */
20390Sstevel@tonic-gate lock.l_type = (prov->pc_oflags & PO_RDWR) ? F_WRLCK : F_RDLCK;
20400Sstevel@tonic-gate lock.l_whence = SEEK_SET;
20410Sstevel@tonic-gate lock.l_start = 0;
20420Sstevel@tonic-gate lock.l_len = 0;
20430Sstevel@tonic-gate if (fcntl(fileno(prov->pxc_file), F_SETLKW, &lock) == -1) {
20440Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
20450Sstevel@tonic-gate return (PO_FAIL);
20460Sstevel@tonic-gate }
20470Sstevel@tonic-gate /*
20480Sstevel@tonic-gate * Check to see if the document was removed whilst waiting for
20490Sstevel@tonic-gate * the lock. If it was return an error.
20500Sstevel@tonic-gate */
20510Sstevel@tonic-gate if (stat(conf->pc_location, &s) == -1) {
20520Sstevel@tonic-gate (void) fclose(prov->pxc_file);
20530Sstevel@tonic-gate prov->pxc_file = NULL;
20540Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
20550Sstevel@tonic-gate return (PO_FAIL);
20560Sstevel@tonic-gate }
20570Sstevel@tonic-gate /* Parse the document */
20580Sstevel@tonic-gate if (pool_xml_parse_document(conf) != PO_SUCCESS)
20590Sstevel@tonic-gate return (PO_FAIL);
20600Sstevel@tonic-gate return (PO_SUCCESS);
20610Sstevel@tonic-gate }
20620Sstevel@tonic-gate
20630Sstevel@tonic-gate /*
20640Sstevel@tonic-gate * Try to work out if an element contains an attribute of the supplied name.
20650Sstevel@tonic-gate * Search the internal subset first and then the external subset.
20660Sstevel@tonic-gate * Return PO_TRUE if there is an attribute of that name declared for that
20670Sstevel@tonic-gate * element.
20680Sstevel@tonic-gate */
20690Sstevel@tonic-gate int
pool_is_xml_attr(xmlDocPtr doc,const char * elem,const char * attr)20700Sstevel@tonic-gate pool_is_xml_attr(xmlDocPtr doc, const char *elem, const char *attr)
20710Sstevel@tonic-gate {
20720Sstevel@tonic-gate xmlDtdPtr internal = xmlGetIntSubset(doc);
20730Sstevel@tonic-gate xmlDtdPtr external = doc->extSubset;
20740Sstevel@tonic-gate
20750Sstevel@tonic-gate if (xmlGetDtdAttrDesc(internal, BAD_CAST elem, BAD_CAST attr) == NULL)
20760Sstevel@tonic-gate if (xmlGetDtdAttrDesc(external,
20770Sstevel@tonic-gate BAD_CAST elem, BAD_CAST attr) == NULL)
20780Sstevel@tonic-gate return (PO_FALSE);
20790Sstevel@tonic-gate return (PO_TRUE);
20800Sstevel@tonic-gate }
20810Sstevel@tonic-gate
20820Sstevel@tonic-gate /*
20830Sstevel@tonic-gate * Execute the specified query using XPath. This complex function relies on
20840Sstevel@tonic-gate * a couple of helpers to build up an XPath query, pool_build_xpath_buf in
20850Sstevel@tonic-gate * particular.
20860Sstevel@tonic-gate * conf - the pool configuration being manipulated
20870Sstevel@tonic-gate * src - the root of the search, if NULL that means whole document
20880Sstevel@tonic-gate * src_attr - if supplied means an IDREF(S) search on this attribute
20890Sstevel@tonic-gate * classes - target classes
20900Sstevel@tonic-gate * props - target properties
20910Sstevel@tonic-gate * Returns pool_result_set_t pointer/NULL
20920Sstevel@tonic-gate */
20930Sstevel@tonic-gate pool_result_set_t *
pool_xml_exec_query(const pool_conf_t * conf,const pool_elem_t * src,const char * src_attr,pool_elem_class_t classes,pool_value_t ** props)20940Sstevel@tonic-gate pool_xml_exec_query(const pool_conf_t *conf, const pool_elem_t *src,
20950Sstevel@tonic-gate const char *src_attr, pool_elem_class_t classes, pool_value_t **props)
20960Sstevel@tonic-gate {
20970Sstevel@tonic-gate char *buf = NULL;
20980Sstevel@tonic-gate char_buf_t *cb = NULL;
20990Sstevel@tonic-gate pool_xml_result_set_t *rs;
21000Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)src;
21010Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov;
21020Sstevel@tonic-gate
21030Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
21040Sstevel@tonic-gate return (NULL);
21050Sstevel@tonic-gate
21060Sstevel@tonic-gate /*
21070Sstevel@tonic-gate * Prior to building up the complex XPath query, check to see if
21080Sstevel@tonic-gate * src_attr is an IDREF(S). If it is use the IDREF(S) information
21090Sstevel@tonic-gate * to generate the query rather than the other data
21100Sstevel@tonic-gate */
21110Sstevel@tonic-gate if (src_attr != NULL) {
21120Sstevel@tonic-gate char *tok;
21130Sstevel@tonic-gate char *lasts;
21140Sstevel@tonic-gate char *or = "";
21150Sstevel@tonic-gate xmlChar *id;
21160Sstevel@tonic-gate
21170Sstevel@tonic-gate /*
21180Sstevel@tonic-gate * Check the arguments for consistency
21190Sstevel@tonic-gate */
21200Sstevel@tonic-gate if (pool_is_xml_attr(prov->pxc_doc,
21210Sstevel@tonic-gate element_class_tags[src->pe_class], src_attr) != PO_TRUE) {
21220Sstevel@tonic-gate free_char_buf(cb);
21230Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
21240Sstevel@tonic-gate return (NULL);
21250Sstevel@tonic-gate }
21260Sstevel@tonic-gate
21270Sstevel@tonic-gate if ((id = xmlGetProp(pxe->pxe_node, BAD_CAST src_attr))
21280Sstevel@tonic-gate == NULL) {
21290Sstevel@tonic-gate free_char_buf(cb);
21300Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
21310Sstevel@tonic-gate return (NULL);
21320Sstevel@tonic-gate }
21330Sstevel@tonic-gate for (tok = strtok_r((char *)id, " ", &lasts);
21340Sstevel@tonic-gate tok != NULL; tok = strtok_r(NULL, " ", &lasts)) {
21350Sstevel@tonic-gate (void) append_char_buf(cb, "%s//*[@ref_id=\"%s\"]",
21360Sstevel@tonic-gate or, tok);
21370Sstevel@tonic-gate or = " | ";
21380Sstevel@tonic-gate if ((classes & PEC_QRY_SYSTEM) != 0) {
21390Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_SYSTEM,
21400Sstevel@tonic-gate props, cb, PO_TRUE) == PO_FAIL) {
21410Sstevel@tonic-gate free_char_buf(cb);
21420Sstevel@tonic-gate return (NULL);
21430Sstevel@tonic-gate }
21440Sstevel@tonic-gate }
21450Sstevel@tonic-gate if ((classes & PEC_QRY_POOL) != 0) {
21460Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_POOL,
21470Sstevel@tonic-gate props, cb, PO_TRUE) == PO_FAIL) {
21480Sstevel@tonic-gate free_char_buf(cb);
21490Sstevel@tonic-gate return (NULL);
21500Sstevel@tonic-gate }
21510Sstevel@tonic-gate }
21520Sstevel@tonic-gate if ((classes & PEC_QRY_RES_COMP) != 0) {
21530Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src,
21540Sstevel@tonic-gate PEC_RES_COMP, props, cb, PO_TRUE)
21550Sstevel@tonic-gate == PO_FAIL) {
21560Sstevel@tonic-gate free_char_buf(cb);
21570Sstevel@tonic-gate return (NULL);
21580Sstevel@tonic-gate }
21590Sstevel@tonic-gate } else if ((classes & PEC_QRY_RES_AGG) != 0) {
21600Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src,
21610Sstevel@tonic-gate PEC_RES_AGG, props, cb, PO_TRUE)
21620Sstevel@tonic-gate == PO_FAIL) {
21630Sstevel@tonic-gate free_char_buf(cb);
21640Sstevel@tonic-gate return (NULL);
21650Sstevel@tonic-gate }
21660Sstevel@tonic-gate }
21670Sstevel@tonic-gate }
21680Sstevel@tonic-gate xmlFree(id);
21690Sstevel@tonic-gate } else {
21700Sstevel@tonic-gate /*
21710Sstevel@tonic-gate * Build up an XPath query using the supplied parameters.
21720Sstevel@tonic-gate * The basic logic is to:
21730Sstevel@tonic-gate * - Identify which classes are the targets of the query
21740Sstevel@tonic-gate * - For each class work out if the props are attributes or not
21750Sstevel@tonic-gate * - Build up a piece of XPath for each class
21760Sstevel@tonic-gate * - Combine the results into one large XPath query.
21770Sstevel@tonic-gate * - Execute the query.
21780Sstevel@tonic-gate */
21790Sstevel@tonic-gate if ((classes & PEC_QRY_SYSTEM) != 0) {
21800Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_SYSTEM, props,
21810Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) {
21820Sstevel@tonic-gate free_char_buf(cb);
21830Sstevel@tonic-gate return (NULL);
21840Sstevel@tonic-gate }
21850Sstevel@tonic-gate }
21860Sstevel@tonic-gate if ((classes & PEC_QRY_POOL) != 0) {
21870Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_POOL, props,
21880Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) {
21890Sstevel@tonic-gate free_char_buf(cb);
21900Sstevel@tonic-gate return (NULL);
21910Sstevel@tonic-gate }
21920Sstevel@tonic-gate }
21930Sstevel@tonic-gate if ((classes & PEC_QRY_RES_COMP) != 0) {
21940Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_RES_COMP, props,
21950Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) {
21960Sstevel@tonic-gate free_char_buf(cb);
21970Sstevel@tonic-gate return (NULL);
21980Sstevel@tonic-gate }
21990Sstevel@tonic-gate }
22000Sstevel@tonic-gate if ((classes & PEC_QRY_RES_AGG) != 0) {
22010Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_RES_AGG, props,
22020Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) {
22030Sstevel@tonic-gate free_char_buf(cb);
22040Sstevel@tonic-gate return (NULL);
22050Sstevel@tonic-gate }
22060Sstevel@tonic-gate }
22070Sstevel@tonic-gate if ((classes & PEC_QRY_COMP) != 0) {
22080Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_COMP, props,
22090Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) {
22100Sstevel@tonic-gate free_char_buf(cb);
22110Sstevel@tonic-gate return (NULL);
22120Sstevel@tonic-gate }
22130Sstevel@tonic-gate }
22140Sstevel@tonic-gate }
22150Sstevel@tonic-gate buf = strdup(cb->cb_buf);
22160Sstevel@tonic-gate free_char_buf(cb);
22170Sstevel@tonic-gate /*
22180Sstevel@tonic-gate * Have a buffer at this point, that we can use
22190Sstevel@tonic-gate */
22200Sstevel@tonic-gate if ((rs = pool_xml_result_set_alloc(conf)) == NULL) {
22210Sstevel@tonic-gate free(buf);
22220Sstevel@tonic-gate return (NULL);
22230Sstevel@tonic-gate }
22240Sstevel@tonic-gate /*
22250Sstevel@tonic-gate * Set up the XPath Query
22260Sstevel@tonic-gate */
22270Sstevel@tonic-gate if ((rs->pxr_ctx = xmlXPathNewContext(
22280Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc)) == NULL) {
22290Sstevel@tonic-gate free(buf);
22300Sstevel@tonic-gate (void) pool_xml_rs_close((pool_result_set_t *)rs);
22310Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
22320Sstevel@tonic-gate return (NULL);
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate if (src == NULL)
22350Sstevel@tonic-gate rs->pxr_ctx->node = xmlDocGetRootElement
22360Sstevel@tonic-gate (((pool_xml_connection_t *)conf->pc_prov)->pxc_doc);
22370Sstevel@tonic-gate else
22380Sstevel@tonic-gate rs->pxr_ctx->node = pxe->pxe_node;
22390Sstevel@tonic-gate /*
22400Sstevel@tonic-gate * Select
22410Sstevel@tonic-gate */
22420Sstevel@tonic-gate rs->pxr_path = xmlXPathEval(BAD_CAST buf, rs->pxr_ctx);
22430Sstevel@tonic-gate free(buf);
22440Sstevel@tonic-gate /*
22450Sstevel@tonic-gate * Generate the result set and wrap the results as pool_elem_t
22460Sstevel@tonic-gate */
22471042Sgarypen if (rs->pxr_path->nodesetval->nodeNr == 0)
22481042Sgarypen pool_seterror(POE_INVALID_SEARCH);
22490Sstevel@tonic-gate return ((pool_result_set_t *)rs);
22500Sstevel@tonic-gate }
22510Sstevel@tonic-gate
22520Sstevel@tonic-gate /*
22530Sstevel@tonic-gate * Build an XPath query buffer. This is complex and a little fragile, but
22540Sstevel@tonic-gate * I'm trying to accomplish something complex with as little code as possible.
22550Sstevel@tonic-gate * I wait the implementation of XMLQuery with baited breath...
22560Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
22570Sstevel@tonic-gate */
22580Sstevel@tonic-gate static int
pool_build_xpath_buf(pool_xml_connection_t * prov,const pool_elem_t * src,pool_elem_class_t class,pool_value_t * props[],char_buf_t * cb,int is_ref)22590Sstevel@tonic-gate pool_build_xpath_buf(pool_xml_connection_t *prov, const pool_elem_t *src,
22600Sstevel@tonic-gate pool_elem_class_t class, pool_value_t *props[], char_buf_t *cb, int is_ref)
22610Sstevel@tonic-gate {
22620Sstevel@tonic-gate int i;
22630Sstevel@tonic-gate const char *ATTR_FMTS[] = {
22640Sstevel@tonic-gate "[ @%s=\"%llu\" ]", /* POC_UINT */
22650Sstevel@tonic-gate "[ @%s=\"%lld\" ]", /* POC_INT */
22660Sstevel@tonic-gate "[ @%s=\"%f\" ]", /* POC_DOUBLE */
22670Sstevel@tonic-gate "[ @%s=\"%s\" ]", /* POC_BOOL */
22680Sstevel@tonic-gate "[ @%s=\"%s\" ]", /* POC_STRING */
22690Sstevel@tonic-gate };
22700Sstevel@tonic-gate const char *PROP_FMTS[] = {
22710Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%llu\"] ]", /* POC_UINT */
22720Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%lld\"] ]", /* POC_INT */
22730Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%f\"] ]", /* POC_DOUBLE */
22740Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%s\"] ]", /* POC_BOOL */
22750Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%s\"] ]" /* POC_STRING */
22760Sstevel@tonic-gate };
22770Sstevel@tonic-gate const char **fmts;
22780Sstevel@tonic-gate int nprop;
22790Sstevel@tonic-gate const char *last_prop_name = NULL;
22800Sstevel@tonic-gate char *type_prefix = NULL;
22810Sstevel@tonic-gate int has_type = PO_FALSE;
22820Sstevel@tonic-gate
22830Sstevel@tonic-gate if (is_ref == PO_FALSE) {
22840Sstevel@tonic-gate if (cb->cb_buf != NULL && strlen(cb->cb_buf) > 0)
22850Sstevel@tonic-gate (void) append_char_buf(cb, " |");
22860Sstevel@tonic-gate if (src != NULL)
22870Sstevel@tonic-gate (void) append_char_buf(cb, " ./");
22880Sstevel@tonic-gate else
22890Sstevel@tonic-gate (void) append_char_buf(cb, "//");
22900Sstevel@tonic-gate (void) append_char_buf(cb, element_class_tags[class]);
22910Sstevel@tonic-gate }
22920Sstevel@tonic-gate if (props == NULL || props[0] == NULL)
22930Sstevel@tonic-gate return (PO_SUCCESS);
22940Sstevel@tonic-gate for (nprop = 0; props[nprop] != NULL; nprop++)
22950Sstevel@tonic-gate /* Count properties */;
22960Sstevel@tonic-gate /*
22970Sstevel@tonic-gate * Sort the attributes and properties by name.
22980Sstevel@tonic-gate */
22990Sstevel@tonic-gate qsort(props, nprop, sizeof (pool_value_t *), prop_sort);
23000Sstevel@tonic-gate for (i = 0; i < nprop; i++) {
23010Sstevel@tonic-gate int is_attr = 0;
23020Sstevel@tonic-gate const char *prefix;
23030Sstevel@tonic-gate const char *prop_name;
23040Sstevel@tonic-gate uint64_t uval;
23050Sstevel@tonic-gate int64_t ival;
23060Sstevel@tonic-gate double dval;
23070Sstevel@tonic-gate uchar_t bval;
23080Sstevel@tonic-gate const char *sval;
23090Sstevel@tonic-gate pool_value_class_t pvc;
23100Sstevel@tonic-gate
23110Sstevel@tonic-gate prop_name = pool_value_get_name(props[i]);
23120Sstevel@tonic-gate if ((prefix = is_a_known_prefix(class, prop_name)) != NULL) {
23130Sstevel@tonic-gate const char *attr_name;
23140Sstevel@tonic-gate /*
23150Sstevel@tonic-gate * Possibly an attribute. Strip off the prefix.
23160Sstevel@tonic-gate */
23170Sstevel@tonic-gate if (strcmp(prop_name, c_type) == 0) {
23180Sstevel@tonic-gate has_type = PO_TRUE;
23190Sstevel@tonic-gate attr_name = prop_name;
23200Sstevel@tonic-gate } else
23210Sstevel@tonic-gate attr_name = prop_name + strlen(prefix) + 1;
23220Sstevel@tonic-gate if (pool_is_xml_attr(prov->pxc_doc,
23230Sstevel@tonic-gate element_class_tags[class], attr_name)) {
23240Sstevel@tonic-gate is_attr = 1;
23250Sstevel@tonic-gate prop_name = attr_name;
23260Sstevel@tonic-gate if (class == PEC_RES_COMP ||
23270Sstevel@tonic-gate class == PEC_RES_AGG ||
2328*11411SSurya.Prakki@Sun.COM class == PEC_COMP) {
23290Sstevel@tonic-gate if (type_prefix != NULL)
23300Sstevel@tonic-gate free(type_prefix);
23310Sstevel@tonic-gate type_prefix = strdup(prefix);
23320Sstevel@tonic-gate }
23330Sstevel@tonic-gate }
23340Sstevel@tonic-gate }
23350Sstevel@tonic-gate if (is_attr) {
23360Sstevel@tonic-gate fmts = ATTR_FMTS;
23370Sstevel@tonic-gate } else {
23380Sstevel@tonic-gate fmts = PROP_FMTS;
23390Sstevel@tonic-gate }
23400Sstevel@tonic-gate /*
23410Sstevel@tonic-gate * Add attributes/properties to the search buffer
23420Sstevel@tonic-gate */
23430Sstevel@tonic-gate switch ((pvc = pool_value_get_type(props[i]))) {
23440Sstevel@tonic-gate case POC_UINT:
23450Sstevel@tonic-gate (void) pool_value_get_uint64(props[i], &uval);
23460Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, uval)
23470Sstevel@tonic-gate == PO_FAIL) {
23480Sstevel@tonic-gate free(type_prefix);
23490Sstevel@tonic-gate return (PO_FAIL);
23500Sstevel@tonic-gate }
23510Sstevel@tonic-gate break;
23520Sstevel@tonic-gate case POC_INT:
23530Sstevel@tonic-gate (void) pool_value_get_int64(props[i], &ival);
23540Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, ival)
23550Sstevel@tonic-gate == PO_FAIL) {
23560Sstevel@tonic-gate free(type_prefix);
23570Sstevel@tonic-gate return (PO_FAIL);
23580Sstevel@tonic-gate }
23590Sstevel@tonic-gate break;
23600Sstevel@tonic-gate case POC_DOUBLE:
23610Sstevel@tonic-gate (void) pool_value_get_double(props[i], &dval);
23620Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, dval)
23630Sstevel@tonic-gate == PO_FAIL) {
23640Sstevel@tonic-gate free(type_prefix);
23650Sstevel@tonic-gate return (PO_FAIL);
23660Sstevel@tonic-gate }
23670Sstevel@tonic-gate break;
23680Sstevel@tonic-gate case POC_BOOL:
23690Sstevel@tonic-gate (void) pool_value_get_bool(props[i], &bval);
23700Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name,
23710Sstevel@tonic-gate bval ? "true" : "false") == PO_FAIL) {
23720Sstevel@tonic-gate free(type_prefix);
23730Sstevel@tonic-gate return (PO_FAIL);
23740Sstevel@tonic-gate }
23750Sstevel@tonic-gate break;
23760Sstevel@tonic-gate case POC_STRING:
23770Sstevel@tonic-gate (void) pool_value_get_string(props[i], &sval);
23780Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, sval)
23790Sstevel@tonic-gate == PO_FAIL) {
23800Sstevel@tonic-gate free(type_prefix);
23810Sstevel@tonic-gate return (PO_FAIL);
23820Sstevel@tonic-gate }
23830Sstevel@tonic-gate break;
23840Sstevel@tonic-gate default:
23850Sstevel@tonic-gate free(type_prefix);
23861042Sgarypen pool_seterror(POE_INVALID_SEARCH);
23870Sstevel@tonic-gate return (PO_FAIL);
23880Sstevel@tonic-gate }
23890Sstevel@tonic-gate if (last_prop_name != NULL) {
23900Sstevel@tonic-gate const char *suffix1, *suffix2;
23910Sstevel@tonic-gate /*
23920Sstevel@tonic-gate * Extra fiddling for namespaces
23930Sstevel@tonic-gate */
23940Sstevel@tonic-gate suffix1 = strrchr(prop_name, '.');
23950Sstevel@tonic-gate suffix2 = strrchr(last_prop_name, '.');
23960Sstevel@tonic-gate
23970Sstevel@tonic-gate if (suffix1 != NULL || suffix2 != NULL) {
23980Sstevel@tonic-gate if (suffix1 == NULL)
23990Sstevel@tonic-gate suffix1 = prop_name;
24000Sstevel@tonic-gate else
24010Sstevel@tonic-gate suffix1++;
24020Sstevel@tonic-gate if (suffix2 == NULL)
24030Sstevel@tonic-gate suffix2 = last_prop_name;
24040Sstevel@tonic-gate else
24050Sstevel@tonic-gate suffix2++;
24060Sstevel@tonic-gate } else {
24070Sstevel@tonic-gate suffix1 = prop_name;
24080Sstevel@tonic-gate suffix2 = last_prop_name;
24090Sstevel@tonic-gate }
24100Sstevel@tonic-gate if (strcmp(suffix1, suffix2) == 0) {
24110Sstevel@tonic-gate char *where = strrchr(cb->cb_buf, '[');
24120Sstevel@tonic-gate if (is_attr != PO_TRUE) {
24130Sstevel@tonic-gate /* repeat */
2414*11411SSurya.Prakki@Sun.COM while (*--where != '[')
2415*11411SSurya.Prakki@Sun.COM ;
2416*11411SSurya.Prakki@Sun.COM while (*--where != '[')
2417*11411SSurya.Prakki@Sun.COM ;
24180Sstevel@tonic-gate }
24190Sstevel@tonic-gate *(where - 1) = 'o';
24200Sstevel@tonic-gate *where = 'r';
24210Sstevel@tonic-gate }
24220Sstevel@tonic-gate }
24230Sstevel@tonic-gate last_prop_name = prop_name;
24240Sstevel@tonic-gate }
24250Sstevel@tonic-gate if (has_type == PO_FALSE) {
24260Sstevel@tonic-gate if (type_prefix) {
24270Sstevel@tonic-gate if (append_char_buf(cb, ATTR_FMTS[POC_STRING],
24280Sstevel@tonic-gate c_type, type_prefix) == PO_FAIL) {
24290Sstevel@tonic-gate free(type_prefix);
24300Sstevel@tonic-gate return (PO_FAIL);
24310Sstevel@tonic-gate }
24320Sstevel@tonic-gate }
24330Sstevel@tonic-gate }
24340Sstevel@tonic-gate free(type_prefix);
24350Sstevel@tonic-gate return (PO_SUCCESS);
24360Sstevel@tonic-gate }
24370Sstevel@tonic-gate
24380Sstevel@tonic-gate /*
24390Sstevel@tonic-gate * Utility routine for use by quicksort. Assumes that the supplied data
24400Sstevel@tonic-gate * are pool values and compares the names of the two pool values.
24410Sstevel@tonic-gate * Returns an integer greater than, equal to, or less than 0.
24420Sstevel@tonic-gate */
24430Sstevel@tonic-gate static int
prop_sort(const void * a,const void * b)24440Sstevel@tonic-gate prop_sort(const void *a, const void *b)
24450Sstevel@tonic-gate {
24460Sstevel@tonic-gate pool_value_t **prop_a = (pool_value_t **)a;
24470Sstevel@tonic-gate pool_value_t **prop_b = (pool_value_t **)b;
24480Sstevel@tonic-gate const char *str_a;
24490Sstevel@tonic-gate const char *str_b;
24500Sstevel@tonic-gate const char *suffix1, *suffix2;
24510Sstevel@tonic-gate
24520Sstevel@tonic-gate str_a = pool_value_get_name(*prop_a);
24530Sstevel@tonic-gate str_b = pool_value_get_name(*prop_b);
24540Sstevel@tonic-gate /*
24550Sstevel@tonic-gate * Extra fiddling for namespaces
24560Sstevel@tonic-gate */
24570Sstevel@tonic-gate suffix1 = strrchr(str_a, '.');
24580Sstevel@tonic-gate suffix2 = strrchr(str_b, '.');
24590Sstevel@tonic-gate
24600Sstevel@tonic-gate if (suffix1 != NULL || suffix2 != NULL) {
24610Sstevel@tonic-gate if (suffix1 == NULL)
24620Sstevel@tonic-gate suffix1 = str_a;
24630Sstevel@tonic-gate else
24640Sstevel@tonic-gate suffix1++;
24650Sstevel@tonic-gate if (suffix2 == NULL)
24660Sstevel@tonic-gate suffix2 = str_b;
24670Sstevel@tonic-gate else
24680Sstevel@tonic-gate suffix2++;
24690Sstevel@tonic-gate } else {
24700Sstevel@tonic-gate suffix1 = str_a;
24710Sstevel@tonic-gate suffix2 = str_b;
24720Sstevel@tonic-gate }
24730Sstevel@tonic-gate return (strcmp(suffix1, suffix2));
24740Sstevel@tonic-gate }
24750Sstevel@tonic-gate
24760Sstevel@tonic-gate /*
24770Sstevel@tonic-gate * Order the elements by (ref_id)
24780Sstevel@tonic-gate */
24790Sstevel@tonic-gate
24800Sstevel@tonic-gate /*
24810Sstevel@tonic-gate * Returns PO_TRUE/PO_FALSE to indicate whether the supplied path exists on the
24820Sstevel@tonic-gate * system. It is assumed that the supplied path is in URL format and represents
24830Sstevel@tonic-gate * a file and so file:// is stripped from the start of the search.
24840Sstevel@tonic-gate */
24850Sstevel@tonic-gate static int
dtd_exists(const char * path)24860Sstevel@tonic-gate dtd_exists(const char *path)
24870Sstevel@tonic-gate {
24880Sstevel@tonic-gate struct stat buf;
24890Sstevel@tonic-gate
24900Sstevel@tonic-gate if (strstr(path, "file://") != path)
24910Sstevel@tonic-gate return (PO_FALSE);
24920Sstevel@tonic-gate
24930Sstevel@tonic-gate if (path[7] == 0)
24940Sstevel@tonic-gate return (PO_FALSE);
24950Sstevel@tonic-gate
24960Sstevel@tonic-gate if (stat(&path[7], &buf) == 0)
24970Sstevel@tonic-gate return (PO_TRUE);
24980Sstevel@tonic-gate return (PO_FALSE);
24990Sstevel@tonic-gate }
25000Sstevel@tonic-gate
25010Sstevel@tonic-gate /*
25020Sstevel@tonic-gate * Build the dtype structures to accelerate data type lookup operations. The
25030Sstevel@tonic-gate * purpose is to avoid expensive XML manipulations on data which will not
25040Sstevel@tonic-gate * change over the life of a library invocation. It is designed to be invoked
25050Sstevel@tonic-gate * once from the library init function.
25060Sstevel@tonic-gate */
25070Sstevel@tonic-gate static void
build_dtype_accelerator(void)25080Sstevel@tonic-gate build_dtype_accelerator(void)
25090Sstevel@tonic-gate {
25100Sstevel@tonic-gate xmlDtdPtr dtd;
25110Sstevel@tonic-gate const xmlChar *elem_list[ELEM_TYPE_COUNT] = {
25120Sstevel@tonic-gate BAD_CAST "res_comp",
25130Sstevel@tonic-gate BAD_CAST "res_agg",
25140Sstevel@tonic-gate BAD_CAST "comp",
25150Sstevel@tonic-gate BAD_CAST "pool",
25160Sstevel@tonic-gate BAD_CAST "property",
25170Sstevel@tonic-gate BAD_CAST "system" };
25180Sstevel@tonic-gate int i;
25190Sstevel@tonic-gate
25200Sstevel@tonic-gate if (_libpool_xml_initialised == PO_TRUE)
25210Sstevel@tonic-gate return;
25220Sstevel@tonic-gate
25230Sstevel@tonic-gate /* Load up the d-type data for each element */
25240Sstevel@tonic-gate /*
25250Sstevel@tonic-gate * Store data type information in nested lists
25260Sstevel@tonic-gate * Top level list contains attribute declaration pointers which
25270Sstevel@tonic-gate * can be used to match with supplied nodes.
25280Sstevel@tonic-gate * Second level list contains attribute type information for each
25290Sstevel@tonic-gate * element declaration
25300Sstevel@tonic-gate */
25310Sstevel@tonic-gate /*
25320Sstevel@tonic-gate * Unfortunately, there's no easy way to get a list of all DTD
25330Sstevel@tonic-gate * element descriptions as there is no libxml API to do this (they
25340Sstevel@tonic-gate * are stored in a hash, which I guess is why). Explicitly seek
25350Sstevel@tonic-gate * for descriptions for elements that are known to hold an a-dtype
25360Sstevel@tonic-gate * attribute and build accelerators for those elements.
25370Sstevel@tonic-gate * If the DTD changes, the library may have to change as well now,
25380Sstevel@tonic-gate * since this code makes explicit assumptions about which elements
25390Sstevel@tonic-gate * contain a-dtype information.
25400Sstevel@tonic-gate */
25410Sstevel@tonic-gate
25420Sstevel@tonic-gate if ((dtd = xmlParseDTD(BAD_CAST "-//Sun Microsystems Inc//DTD Resource"
25430Sstevel@tonic-gate " Management All//EN", BAD_CAST dtd_location)) == NULL)
25440Sstevel@tonic-gate return;
25450Sstevel@tonic-gate for (i = 0; i < ELEM_TYPE_COUNT; i++) {
25460Sstevel@tonic-gate xmlElementPtr elem;
25470Sstevel@tonic-gate xmlAttributePtr attr;
25480Sstevel@tonic-gate
25490Sstevel@tonic-gate if ((elem = xmlGetDtdElementDesc(dtd, elem_list[i])) == NULL)
25500Sstevel@tonic-gate return;
25510Sstevel@tonic-gate elem_tbl[i].ett_elem = xmlStrdup(elem->name);
25520Sstevel@tonic-gate /* Walk the list of attributes looking for a-dtype */
25530Sstevel@tonic-gate for (attr = elem->attributes; attr != NULL;
25540Sstevel@tonic-gate attr = attr->nexth) {
25550Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_a_dtype) == 0) {
25560Sstevel@tonic-gate /*
25570Sstevel@tonic-gate * Allocate a dtype_tbl_t
25580Sstevel@tonic-gate */
25590Sstevel@tonic-gate elem_tbl[i].ett_dtype =
25600Sstevel@tonic-gate build_dtype_tbl(attr->defaultValue);
25610Sstevel@tonic-gate /* This could have returned NULL */
25620Sstevel@tonic-gate }
25630Sstevel@tonic-gate }
25640Sstevel@tonic-gate }
25650Sstevel@tonic-gate xmlFreeDtd(dtd);
25660Sstevel@tonic-gate }
25670Sstevel@tonic-gate
25680Sstevel@tonic-gate /*
25690Sstevel@tonic-gate * build_dtype_tbl() parses the supplied data and returns an array (max size
25700Sstevel@tonic-gate * of 10, increase if required) of dtype_tbl_t structures holding data type
25710Sstevel@tonic-gate * information for an element. The supplied data is assumed to be in "a-dtype"
25720Sstevel@tonic-gate * format. The dtype_tbl_t array is NULL terminated, which is why space for
25730Sstevel@tonic-gate * 11 members is allocated.
25740Sstevel@tonic-gate */
25750Sstevel@tonic-gate static dtype_tbl_t
build_dtype_tbl(const xmlChar * rawdata)25760Sstevel@tonic-gate (*build_dtype_tbl(const xmlChar *rawdata))[]
25770Sstevel@tonic-gate {
25780Sstevel@tonic-gate char *tok;
25790Sstevel@tonic-gate char *lasts;
25800Sstevel@tonic-gate dtype_tbl_t (*tbl)[];
25810Sstevel@tonic-gate int j = 0;
25820Sstevel@tonic-gate xmlChar *data;
25830Sstevel@tonic-gate const int max_attr = 11; /* Not more than 10 types per element */
25840Sstevel@tonic-gate
25850Sstevel@tonic-gate /*
25860Sstevel@tonic-gate * Parse the supplied data, assumed to be in a-dtype format, and
25870Sstevel@tonic-gate * generate a lookup table which is indexed by the name and contains
25880Sstevel@tonic-gate * the data type
25890Sstevel@tonic-gate */
25900Sstevel@tonic-gate if (rawdata == NULL)
25910Sstevel@tonic-gate return (NULL);
25920Sstevel@tonic-gate if ((data = xmlStrdup(rawdata)) == NULL)
25930Sstevel@tonic-gate return (NULL);
25940Sstevel@tonic-gate if ((tbl = calloc(max_attr, sizeof (dtype_tbl_t))) == NULL) {
25950Sstevel@tonic-gate xmlFree(data);
25960Sstevel@tonic-gate return (NULL);
25970Sstevel@tonic-gate }
25980Sstevel@tonic-gate for (tok = strtok_r((char *)data, " ", &lasts); tok != NULL;
25990Sstevel@tonic-gate tok = strtok_r(NULL, " ", &lasts)) {
26000Sstevel@tonic-gate int i;
26010Sstevel@tonic-gate (*tbl)[j].dt_name = xmlStrdup(BAD_CAST tok);
26020Sstevel@tonic-gate if ((tok = strtok_r(NULL, " ", &lasts)) == NULL) {
26030Sstevel@tonic-gate int k = j;
26040Sstevel@tonic-gate for (j = 0; j < k; j++)
26050Sstevel@tonic-gate free((*tbl)[j].dt_name);
26060Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
26070Sstevel@tonic-gate xmlFree(data);
26080Sstevel@tonic-gate free(tbl);
26090Sstevel@tonic-gate return (NULL);
26100Sstevel@tonic-gate }
26110Sstevel@tonic-gate for (i = 0; i < (sizeof (data_type_tags) /
26120Sstevel@tonic-gate sizeof (data_type_tags[0])); i++) {
26130Sstevel@tonic-gate if (strcmp(tok, data_type_tags[i]) == 0)
26140Sstevel@tonic-gate (*tbl)[j++].dt_type = i;
26150Sstevel@tonic-gate }
26160Sstevel@tonic-gate if (j == max_attr) { /* too many attributes, bail out */
26170Sstevel@tonic-gate for (j = 0; j < max_attr; j++)
26180Sstevel@tonic-gate free((*tbl)[j].dt_name);
26190Sstevel@tonic-gate free(tbl);
26200Sstevel@tonic-gate xmlFree(data);
26210Sstevel@tonic-gate return (NULL);
26220Sstevel@tonic-gate }
26230Sstevel@tonic-gate }
26240Sstevel@tonic-gate (*tbl)[j].dt_name = NULL; /* Terminate the table */
26250Sstevel@tonic-gate xmlFree(data);
26260Sstevel@tonic-gate return (tbl);
26270Sstevel@tonic-gate }
26280Sstevel@tonic-gate
26290Sstevel@tonic-gate /*
26300Sstevel@tonic-gate * get_fast_dtype() finds the data type for a supplied attribute name on a
26310Sstevel@tonic-gate * supplied node. This is called get_fast_dtype() because it uses the cached
26320Sstevel@tonic-gate * data type information created at library initialisation.
26330Sstevel@tonic-gate */
26340Sstevel@tonic-gate static int
get_fast_dtype(xmlNodePtr node,xmlChar * name)26350Sstevel@tonic-gate get_fast_dtype(xmlNodePtr node, xmlChar *name)
26360Sstevel@tonic-gate {
26370Sstevel@tonic-gate int i;
26380Sstevel@tonic-gate xmlElementPtr elem;
26390Sstevel@tonic-gate
26400Sstevel@tonic-gate if ((elem = xmlGetDtdElementDesc(node->doc->extSubset, node->name))
26410Sstevel@tonic-gate == NULL) {
26420Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
26430Sstevel@tonic-gate return (POC_INVAL);
26440Sstevel@tonic-gate }
26450Sstevel@tonic-gate
26460Sstevel@tonic-gate for (i = 0; i < ELEM_TYPE_COUNT; i++) {
26470Sstevel@tonic-gate if (xmlStrcmp(elem_tbl[i].ett_elem, elem->name) == 0) {
26480Sstevel@tonic-gate dtype_tbl_t (*tbl)[] = elem_tbl[i].ett_dtype;
26490Sstevel@tonic-gate int j = 0;
26500Sstevel@tonic-gate
26510Sstevel@tonic-gate if (tbl == NULL)
26520Sstevel@tonic-gate break;
26530Sstevel@tonic-gate for (j = 0; (*tbl)[j].dt_name != NULL; j++)
26540Sstevel@tonic-gate if (xmlStrcmp(name, (*tbl)[j].dt_name) == 0)
26550Sstevel@tonic-gate return ((*tbl)[j].dt_type); /* found */
26560Sstevel@tonic-gate break; /* if we didn't find it in the elem, break */
26570Sstevel@tonic-gate }
26580Sstevel@tonic-gate }
26590Sstevel@tonic-gate /* If we can't find it, say it's a string */
26600Sstevel@tonic-gate return (POC_STRING);
26610Sstevel@tonic-gate }
26620Sstevel@tonic-gate
26630Sstevel@tonic-gate /*
26640Sstevel@tonic-gate * pool_xml_parse_document() parses the file associated with a supplied
26650Sstevel@tonic-gate * configuration to regenerate the runtime representation. The supplied
26660Sstevel@tonic-gate * configuration must reference an already opened file and this is used
26670Sstevel@tonic-gate * to generate the XML representation via the configuration provider's
26680Sstevel@tonic-gate * pxc_doc member.
26690Sstevel@tonic-gate * size must be >=4 in order for "content encoding detection" to work.
26700Sstevel@tonic-gate */
26710Sstevel@tonic-gate static int
pool_xml_parse_document(pool_conf_t * conf)26720Sstevel@tonic-gate pool_xml_parse_document(pool_conf_t *conf)
26730Sstevel@tonic-gate {
26740Sstevel@tonic-gate int res;
26750Sstevel@tonic-gate char chars[PAGE_READ_SIZE];
26760Sstevel@tonic-gate struct stat f_stat;
26770Sstevel@tonic-gate xmlParserCtxtPtr ctxt;
26780Sstevel@tonic-gate size_t size;
26790Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov;
26800Sstevel@tonic-gate xmlNodePtr root;
26810Sstevel@tonic-gate pool_resource_t **rsl;
26820Sstevel@tonic-gate uint_t nelem;
26830Sstevel@tonic-gate int i;
26840Sstevel@tonic-gate
26850Sstevel@tonic-gate if (fstat(fileno(prov->pxc_file), &f_stat) == -1) {
26860Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
26870Sstevel@tonic-gate return (PO_FAIL);
26880Sstevel@tonic-gate }
26890Sstevel@tonic-gate
26900Sstevel@tonic-gate if (f_stat.st_size == 0) {
26910Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
26920Sstevel@tonic-gate return (PO_FAIL);
26930Sstevel@tonic-gate } else
26940Sstevel@tonic-gate size = f_stat.st_size < 4 ? 4 : PAGE_READ_SIZE;
26950Sstevel@tonic-gate
26960Sstevel@tonic-gate res = fread(chars, 1, size, prov->pxc_file);
26970Sstevel@tonic-gate
26980Sstevel@tonic-gate if (res >= 4) {
26990Sstevel@tonic-gate xmlValidCtxtPtr cvp;
27000Sstevel@tonic-gate
27010Sstevel@tonic-gate if ((ctxt = xmlCreatePushParserCtxt(NULL, NULL,
27020Sstevel@tonic-gate chars, res, conf->pc_location)) == NULL) {
27030Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27040Sstevel@tonic-gate return (PO_FAIL);
27050Sstevel@tonic-gate }
27060Sstevel@tonic-gate
27070Sstevel@tonic-gate while ((res = fread(chars, 1, size, prov->pxc_file)) > 0) {
27080Sstevel@tonic-gate if (xmlParseChunk(ctxt, chars, res, 0) != 0) {
27090Sstevel@tonic-gate xmlFreeParserCtxt(ctxt);
27100Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27110Sstevel@tonic-gate return (PO_FAIL);
27120Sstevel@tonic-gate }
27130Sstevel@tonic-gate }
27140Sstevel@tonic-gate if (xmlParseChunk(ctxt, chars, 0, 1) != 0) {
27150Sstevel@tonic-gate xmlFreeParserCtxt(ctxt);
27160Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27170Sstevel@tonic-gate return (PO_FAIL);
27180Sstevel@tonic-gate }
27190Sstevel@tonic-gate
27200Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) {
27210Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27220Sstevel@tonic-gate return (PO_FAIL);
27230Sstevel@tonic-gate }
27240Sstevel@tonic-gate cvp->error = pool_error_func;
27250Sstevel@tonic-gate cvp->warning = pool_error_func;
27260Sstevel@tonic-gate
27270Sstevel@tonic-gate if (xmlValidateDocument(cvp, ctxt->myDoc) == 0) {
27280Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
27290Sstevel@tonic-gate xmlFreeParserCtxt(ctxt);
27300Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27310Sstevel@tonic-gate return (PO_FAIL);
27320Sstevel@tonic-gate }
27330Sstevel@tonic-gate prov->pxc_doc = ctxt->myDoc;
27340Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
27350Sstevel@tonic-gate xmlFreeParserCtxt(ctxt);
27360Sstevel@tonic-gate }
27370Sstevel@tonic-gate if (prov->pxc_doc == NULL) {
27380Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27390Sstevel@tonic-gate return (PO_FAIL);
27400Sstevel@tonic-gate }
27410Sstevel@tonic-gate prov->pxc_doc->_private = conf;
27420Sstevel@tonic-gate
27430Sstevel@tonic-gate /* Get the root element */
27440Sstevel@tonic-gate if ((root = xmlDocGetRootElement(prov->pxc_doc)) == NULL) {
27450Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27460Sstevel@tonic-gate return (PO_FAIL);
27470Sstevel@tonic-gate }
27480Sstevel@tonic-gate /*
27490Sstevel@tonic-gate * Ensure that the parsed tree has been contained within
27500Sstevel@tonic-gate * our shadow tree.
27510Sstevel@tonic-gate */
27520Sstevel@tonic-gate if (create_shadow(root) != PO_SUCCESS) {
27530Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
27540Sstevel@tonic-gate return (PO_FAIL);
27550Sstevel@tonic-gate }
27560Sstevel@tonic-gate
27570Sstevel@tonic-gate if (pool_xml_validate(conf, POV_STRICT) != PO_SUCCESS) {
27580Sstevel@tonic-gate return (PO_FAIL);
27590Sstevel@tonic-gate }
27600Sstevel@tonic-gate /*
27610Sstevel@tonic-gate * For backwards compatibility with S9, make sure that all
27620Sstevel@tonic-gate * resources have a size and that it is correct.
27630Sstevel@tonic-gate */
27640Sstevel@tonic-gate if ((rsl = pool_query_resources(conf, &nelem, NULL)) != NULL) {
27650Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
27660Sstevel@tonic-gate for (i = 0; i < nelem; i++) {
27670Sstevel@tonic-gate if (pool_get_ns_property(TO_ELEM(rsl[i]), c_size_prop,
27680Sstevel@tonic-gate &val) != POC_UINT) {
27690Sstevel@tonic-gate pool_component_t **cs;
27700Sstevel@tonic-gate uint_t size;
27710Sstevel@tonic-gate if ((cs = pool_query_resource_components(conf,
27720Sstevel@tonic-gate rsl[i], &size, NULL)) != NULL) {
27730Sstevel@tonic-gate free(cs);
27740Sstevel@tonic-gate pool_value_set_uint64(&val, size);
27750Sstevel@tonic-gate } else
27760Sstevel@tonic-gate pool_value_set_uint64(&val, 0);
27770Sstevel@tonic-gate if (pool_put_any_ns_property(TO_ELEM(rsl[i]),
27780Sstevel@tonic-gate c_size_prop, &val) != PO_SUCCESS) {
27790Sstevel@tonic-gate free(rsl);
27800Sstevel@tonic-gate return (PO_FAIL);
27810Sstevel@tonic-gate }
27820Sstevel@tonic-gate }
27830Sstevel@tonic-gate }
27840Sstevel@tonic-gate free(rsl);
27850Sstevel@tonic-gate }
27860Sstevel@tonic-gate return (PO_SUCCESS);
27870Sstevel@tonic-gate }
2788