1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <errno.h> 30*0Sstevel@tonic-gate #include <fcntl.h> 31*0Sstevel@tonic-gate #include <limits.h> 32*0Sstevel@tonic-gate #include <stdlib.h> 33*0Sstevel@tonic-gate #include <stdio.h> 34*0Sstevel@tonic-gate #include <string.h> 35*0Sstevel@tonic-gate #include <thread.h> 36*0Sstevel@tonic-gate #include <time.h> 37*0Sstevel@tonic-gate #include <unistd.h> 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #include <sys/mman.h> 40*0Sstevel@tonic-gate #include <sys/stat.h> 41*0Sstevel@tonic-gate #include <sys/time.h> 42*0Sstevel@tonic-gate #include <sys/types.h> 43*0Sstevel@tonic-gate #include <sys/utsname.h> 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #include <libxml/debugXML.h> 46*0Sstevel@tonic-gate #include <libxml/parser.h> 47*0Sstevel@tonic-gate #include <libxml/tree.h> 48*0Sstevel@tonic-gate #include <libxml/xmlerror.h> 49*0Sstevel@tonic-gate #include <libxml/xpath.h> 50*0Sstevel@tonic-gate #include <libxml/xmlmemory.h> 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate #include <pool.h> 53*0Sstevel@tonic-gate #include "pool_internal.h" 54*0Sstevel@tonic-gate #include "pool_impl.h" 55*0Sstevel@tonic-gate #include "pool_xml_impl.h" 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate /* 58*0Sstevel@tonic-gate * libpool XML Manipulation Routines 59*0Sstevel@tonic-gate * 60*0Sstevel@tonic-gate * pool_xml.c implements the XML manipulation routines used by the libpool 61*0Sstevel@tonic-gate * XML datastore. The functions are grouped into the following logical areas 62*0Sstevel@tonic-gate * - Result Sets 63*0Sstevel@tonic-gate * The XPath API is used to search the XML document represented by a 64*0Sstevel@tonic-gate * configuration. The results of XPath queries are represented through 65*0Sstevel@tonic-gate * pool_result_set_t structures as part of the abstraction of the datastore 66*0Sstevel@tonic-gate * representation. (see pool.c comment for more details) 67*0Sstevel@tonic-gate * 68*0Sstevel@tonic-gate * - Property Manipulation 69*0Sstevel@tonic-gate * Validated XML (XML associated with a DTD) does not allow the introduction 70*0Sstevel@tonic-gate * of attributes which are not recognised by the DTD. This is a limitation 71*0Sstevel@tonic-gate * since we want to allow libpool to associate an arbitrary number of 72*0Sstevel@tonic-gate * properties with an element. The property manipulation code overcomes this 73*0Sstevel@tonic-gate * limitation by allowing property sub-elements to be created and manipulated 74*0Sstevel@tonic-gate * through a single API so that they are indistinguishable from attributes 75*0Sstevel@tonic-gate * to the libpool user. 76*0Sstevel@tonic-gate * 77*0Sstevel@tonic-gate * - XML Element/Attribute Manipulation 78*0Sstevel@tonic-gate * These routines manipulate XML elements and attributes and are the routines 79*0Sstevel@tonic-gate * which interact most directly with libxml. 80*0Sstevel@tonic-gate * 81*0Sstevel@tonic-gate * - File Processing/IO 82*0Sstevel@tonic-gate * Since libpool must present its data in a consistent fashion, we have to 83*0Sstevel@tonic-gate * implement file locking above libxml. These routines allow us to lock files 84*0Sstevel@tonic-gate * during processing and maintain data integrity between processes. Note 85*0Sstevel@tonic-gate * that locks are at the process scope and are advisory (see fcntl). 86*0Sstevel@tonic-gate * 87*0Sstevel@tonic-gate * - Utilities 88*0Sstevel@tonic-gate * Sundry utility functions that aren't easily categorised. 89*0Sstevel@tonic-gate */ 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate #define MAX_PROP_SIZE 1024 /* Size of property buffer */ 92*0Sstevel@tonic-gate /* 93*0Sstevel@tonic-gate * The PAGE_READ_SIZE value is used to determine the size of the input buffer 94*0Sstevel@tonic-gate * used to parse XML files. 95*0Sstevel@tonic-gate */ 96*0Sstevel@tonic-gate #define PAGE_READ_SIZE 8192 97*0Sstevel@tonic-gate #define ELEM_TYPE_COUNT 6 /* Count of Element types */ 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate typedef struct dtype_tbl 100*0Sstevel@tonic-gate { 101*0Sstevel@tonic-gate xmlChar *dt_name; 102*0Sstevel@tonic-gate int dt_type; 103*0Sstevel@tonic-gate } dtype_tbl_t; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate typedef struct elem_type_tbl 106*0Sstevel@tonic-gate { 107*0Sstevel@tonic-gate xmlChar *ett_elem; 108*0Sstevel@tonic-gate dtype_tbl_t (*ett_dtype)[]; 109*0Sstevel@tonic-gate } elem_type_tbl_t; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate extern int xmlDoValidityCheckingDefaultValue; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* 114*0Sstevel@tonic-gate * The _xml_lock is used to lock the state of libpool during 115*0Sstevel@tonic-gate * xml initialisation operations. 116*0Sstevel@tonic-gate */ 117*0Sstevel@tonic-gate static mutex_t _xml_lock; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate const char *element_class_tags[] = { 120*0Sstevel@tonic-gate "any", 121*0Sstevel@tonic-gate "system", 122*0Sstevel@tonic-gate "pool", 123*0Sstevel@tonic-gate "res_comp", 124*0Sstevel@tonic-gate "res_agg", 125*0Sstevel@tonic-gate "comp", 126*0Sstevel@tonic-gate NULL 127*0Sstevel@tonic-gate }; 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate static const char *data_type_tags[] = { 130*0Sstevel@tonic-gate "uint", 131*0Sstevel@tonic-gate "int", 132*0Sstevel@tonic-gate "float", 133*0Sstevel@tonic-gate "boolean", 134*0Sstevel@tonic-gate "string" 135*0Sstevel@tonic-gate }; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate const char *dtd_location = "file:///usr/share/lib/xml/dtd/rm_pool.dtd.1"; 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate static elem_type_tbl_t elem_tbl[ELEM_TYPE_COUNT] = {0}; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate /* libpool initialisation indicator */ 142*0Sstevel@tonic-gate static int _libpool_xml_initialised = PO_FALSE; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate /* 145*0Sstevel@tonic-gate * Utility functions 146*0Sstevel@tonic-gate */ 147*0Sstevel@tonic-gate /* 148*0Sstevel@tonic-gate * Those functions which are not static are shared with pool_kernel.c 149*0Sstevel@tonic-gate * They provide the required XML support for exporting a kernel 150*0Sstevel@tonic-gate * configuration as an XML document. 151*0Sstevel@tonic-gate */ 152*0Sstevel@tonic-gate void xml_init(void); 153*0Sstevel@tonic-gate static int create_shadow(xmlNodePtr node); 154*0Sstevel@tonic-gate static int pool_xml_free_doc(pool_conf_t *conf); 155*0Sstevel@tonic-gate static int prop_sort(const void *a, const void *b); 156*0Sstevel@tonic-gate static int dtd_exists(const char *path); 157*0Sstevel@tonic-gate static void build_dtype_accelerator(void); 158*0Sstevel@tonic-gate static dtype_tbl_t (*build_dtype_tbl(const xmlChar *rawdata))[]; 159*0Sstevel@tonic-gate static int get_fast_dtype(xmlNodePtr node, xmlChar *name); 160*0Sstevel@tonic-gate static int pool_assoc_default_resource_type(pool_t *, 161*0Sstevel@tonic-gate pool_resource_elem_class_t); 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* 164*0Sstevel@tonic-gate * XML Data access and navigation APIs 165*0Sstevel@tonic-gate */ 166*0Sstevel@tonic-gate static int pool_build_xpath_buf(pool_xml_connection_t *, const pool_elem_t *, 167*0Sstevel@tonic-gate pool_elem_class_t, pool_value_t **, char_buf_t *, int); 168*0Sstevel@tonic-gate /* 169*0Sstevel@tonic-gate * SHARED WITH pool_kernel.c for XML export support 170*0Sstevel@tonic-gate */ 171*0Sstevel@tonic-gate xmlNodePtr node_create(xmlNodePtr parent, const xmlChar *name); 172*0Sstevel@tonic-gate static xmlNodePtr node_create_with_id(xmlNodePtr parent, const xmlChar *name); 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* Configuration */ 175*0Sstevel@tonic-gate static int pool_xml_close(pool_conf_t *); 176*0Sstevel@tonic-gate static int pool_xml_validate(const pool_conf_t *, pool_valid_level_t); 177*0Sstevel@tonic-gate static int pool_xml_commit(pool_conf_t *conf); 178*0Sstevel@tonic-gate static int pool_xml_export(const pool_conf_t *conf, const char *location, 179*0Sstevel@tonic-gate pool_export_format_t fmt); 180*0Sstevel@tonic-gate static int pool_xml_rollback(pool_conf_t *conf); 181*0Sstevel@tonic-gate static pool_result_set_t *pool_xml_exec_query(const pool_conf_t *conf, 182*0Sstevel@tonic-gate const pool_elem_t *src, const char *src_attr, 183*0Sstevel@tonic-gate pool_elem_class_t classes, pool_value_t **props); 184*0Sstevel@tonic-gate static int pool_xml_remove(pool_conf_t *conf); 185*0Sstevel@tonic-gate static int pool_xml_res_transfer(pool_resource_t *, pool_resource_t *, 186*0Sstevel@tonic-gate uint64_t); 187*0Sstevel@tonic-gate static int pool_xml_res_xtransfer(pool_resource_t *, pool_resource_t *, 188*0Sstevel@tonic-gate pool_component_t **); 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate /* Connections */ 191*0Sstevel@tonic-gate static void pool_xml_connection_free(pool_xml_connection_t *prov); 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate /* Result Sets */ 194*0Sstevel@tonic-gate static pool_xml_result_set_t *pool_xml_result_set_alloc(const pool_conf_t *); 195*0Sstevel@tonic-gate static void pool_xml_result_set_free(pool_xml_result_set_t *rs); 196*0Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_next(pool_result_set_t *set); 197*0Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_prev(pool_result_set_t *set); 198*0Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_first(pool_result_set_t *set); 199*0Sstevel@tonic-gate static pool_elem_t *pool_xml_rs_last(pool_result_set_t *set); 200*0Sstevel@tonic-gate static int pool_xml_rs_set_index(pool_result_set_t *set, int index); 201*0Sstevel@tonic-gate static int pool_xml_rs_get_index(pool_result_set_t *set); 202*0Sstevel@tonic-gate static int pool_xml_rs_count(pool_result_set_t *set); 203*0Sstevel@tonic-gate static int pool_xml_rs_close(pool_result_set_t *set); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate /* Element (and sub-type) */ 206*0Sstevel@tonic-gate static void pool_xml_elem_init(pool_conf_t *conf, pool_xml_elem_t *elem, 207*0Sstevel@tonic-gate pool_elem_class_t, pool_resource_elem_class_t, pool_component_elem_class_t); 208*0Sstevel@tonic-gate static int pool_xml_elem_wrap(xmlNodePtr node, pool_elem_class_t class, 209*0Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t); 210*0Sstevel@tonic-gate static pool_elem_t *pool_xml_elem_create(pool_conf_t *, pool_elem_class_t, 211*0Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t); 212*0Sstevel@tonic-gate static int pool_xml_elem_remove(pool_elem_t *pe); 213*0Sstevel@tonic-gate static int pool_xml_set_container(pool_elem_t *, pool_elem_t *); 214*0Sstevel@tonic-gate static pool_elem_t *pool_xml_get_container(const pool_elem_t *); 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate /* 217*0Sstevel@tonic-gate * Pool element specific 218*0Sstevel@tonic-gate */ 219*0Sstevel@tonic-gate static int pool_xml_pool_associate(pool_t *, const pool_resource_t *); 220*0Sstevel@tonic-gate static int pool_xml_pool_dissociate(pool_t *, const pool_resource_t *); 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate /* 223*0Sstevel@tonic-gate * Resource elements specific 224*0Sstevel@tonic-gate */ 225*0Sstevel@tonic-gate static int pool_xml_resource_is_system(const pool_resource_t *); 226*0Sstevel@tonic-gate static int pool_xml_resource_can_associate(const pool_resource_t *); 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate /* Properties */ 229*0Sstevel@tonic-gate static pool_value_class_t pool_xml_get_property(const pool_elem_t *, 230*0Sstevel@tonic-gate const char *, pool_value_t *); 231*0Sstevel@tonic-gate static int pool_xml_put_property(pool_elem_t *, const char *, 232*0Sstevel@tonic-gate const pool_value_t *); 233*0Sstevel@tonic-gate static int pool_xml_rm_property(pool_elem_t *, const char *); 234*0Sstevel@tonic-gate static xmlNodePtr property_create(xmlNodePtr, const char *, 235*0Sstevel@tonic-gate pool_value_class_t); 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate /* Internal Attribute/Property manipulation */ 238*0Sstevel@tonic-gate static int pool_is_xml_attr(xmlDocPtr, const char *, const char *); 239*0Sstevel@tonic-gate static pool_value_class_t pool_xml_get_attr(xmlNodePtr node, xmlChar *name, 240*0Sstevel@tonic-gate pool_value_t *value); 241*0Sstevel@tonic-gate int pool_xml_set_attr(xmlNodePtr node, xmlChar *name, 242*0Sstevel@tonic-gate const pool_value_t *value); 243*0Sstevel@tonic-gate static pool_value_class_t pool_xml_get_prop(xmlNodePtr node, xmlChar *name, 244*0Sstevel@tonic-gate pool_value_t *value); 245*0Sstevel@tonic-gate int pool_xml_set_prop(xmlNodePtr node, xmlChar *name, 246*0Sstevel@tonic-gate const pool_value_t *value); 247*0Sstevel@tonic-gate static pool_value_t **pool_xml_get_properties(const pool_elem_t *, uint_t *); 248*0Sstevel@tonic-gate /* XML Error handling */ 249*0Sstevel@tonic-gate void pool_error_func(void *ctx, const char *msg, ...); 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* XML File Input Processing */ 252*0Sstevel@tonic-gate static int pool_xml_open_file(pool_conf_t *conf); 253*0Sstevel@tonic-gate static int pool_xml_parse_document(pool_conf_t *); 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate /* 256*0Sstevel@tonic-gate * Initialise this module 257*0Sstevel@tonic-gate */ 258*0Sstevel@tonic-gate void 259*0Sstevel@tonic-gate xml_init() 260*0Sstevel@tonic-gate { 261*0Sstevel@tonic-gate (void) mutex_lock(&_xml_lock); 262*0Sstevel@tonic-gate if (_libpool_xml_initialised == PO_TRUE) { 263*0Sstevel@tonic-gate (void) mutex_unlock(&_xml_lock); 264*0Sstevel@tonic-gate return; 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate xmlInitParser(); 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * DTD validation, with line numbers. 270*0Sstevel@tonic-gate */ 271*0Sstevel@tonic-gate xmlLineNumbersDefault(1); 272*0Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 273*0Sstevel@tonic-gate xmlDoValidityCheckingDefaultValue = 1; 274*0Sstevel@tonic-gate /* Try to improve indentation and readability */ 275*0Sstevel@tonic-gate xmlKeepBlanksDefault(0); 276*0Sstevel@tonic-gate /* Send all XML errors to our debug handler */ 277*0Sstevel@tonic-gate xmlSetGenericErrorFunc(NULL, pool_error_func); 278*0Sstevel@tonic-gate /* Load up DTD element a-dtype data to improve performance */ 279*0Sstevel@tonic-gate build_dtype_accelerator(); 280*0Sstevel@tonic-gate _libpool_xml_initialised = PO_TRUE; 281*0Sstevel@tonic-gate (void) mutex_unlock(&_xml_lock); 282*0Sstevel@tonic-gate } 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate /* 285*0Sstevel@tonic-gate * Get the next ID for this configuration 286*0Sstevel@tonic-gate */ 287*0Sstevel@tonic-gate static int 288*0Sstevel@tonic-gate get_unique_id(xmlNodePtr node, char *id) 289*0Sstevel@tonic-gate { 290*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 291*0Sstevel@tonic-gate uint64_t nid = 0; 292*0Sstevel@tonic-gate if (node->doc->_private) { 293*0Sstevel@tonic-gate if (pool_get_ns_property( 294*0Sstevel@tonic-gate pool_conf_to_elem((pool_conf_t *)node->doc->_private), 295*0Sstevel@tonic-gate "_next_id", &val) == POC_UINT) 296*0Sstevel@tonic-gate (void) pool_value_get_uint64(&val, &nid); 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate if (snprintf(id, KEY_BUFFER_SIZE, "id_%llx", nid) > KEY_BUFFER_SIZE) { 299*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 300*0Sstevel@tonic-gate return (PO_FAIL); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate pool_value_set_uint64(&val, ++nid); 303*0Sstevel@tonic-gate return (pool_put_ns_property( 304*0Sstevel@tonic-gate pool_conf_to_elem((pool_conf_t *)node->doc->_private), "_next_id", 305*0Sstevel@tonic-gate &val)); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate /* Document building functions */ 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate /* 311*0Sstevel@tonic-gate * node_create() creates a child node of type name of the supplied parent in 312*0Sstevel@tonic-gate * the supplied document. If the parent or document is NULL, create the node 313*0Sstevel@tonic-gate * but do not associate it with a parent or document. 314*0Sstevel@tonic-gate */ 315*0Sstevel@tonic-gate xmlNodePtr 316*0Sstevel@tonic-gate node_create(xmlNodePtr parent, const xmlChar *name) 317*0Sstevel@tonic-gate { 318*0Sstevel@tonic-gate xmlNodePtr node; 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate if (parent == NULL) 321*0Sstevel@tonic-gate node = xmlNewNode(NULL, name); 322*0Sstevel@tonic-gate else 323*0Sstevel@tonic-gate node = xmlNewChild(parent, NULL, name, NULL); 324*0Sstevel@tonic-gate return (node); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate /* 328*0Sstevel@tonic-gate * node_create_with_id() creates a child node of type name of the supplied 329*0Sstevel@tonic-gate * parent with the ref_id generated by get_unique_id(). Actual node creation 330*0Sstevel@tonic-gate * is performed by node_create() and this function just sets the ref_id 331*0Sstevel@tonic-gate * property to the value of the id. 332*0Sstevel@tonic-gate */ 333*0Sstevel@tonic-gate static xmlNodePtr 334*0Sstevel@tonic-gate node_create_with_id(xmlNodePtr parent, const xmlChar *name) 335*0Sstevel@tonic-gate { 336*0Sstevel@tonic-gate char id[KEY_BUFFER_SIZE]; /* Must be big enough for key below */ 337*0Sstevel@tonic-gate xmlNodePtr node = node_create(parent, name); 338*0Sstevel@tonic-gate if (node != NULL) { 339*0Sstevel@tonic-gate if (get_unique_id(node, id) != PO_SUCCESS) { 340*0Sstevel@tonic-gate xmlUnlinkNode(node); 341*0Sstevel@tonic-gate xmlFreeNode(node); /* recurses all children */ 342*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 343*0Sstevel@tonic-gate return (NULL); 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate if (xmlSetProp(node, BAD_CAST c_ref_id, BAD_CAST id) == NULL) { 346*0Sstevel@tonic-gate xmlUnlinkNode(node); 347*0Sstevel@tonic-gate xmlFreeNode(node); /* recurses all children */ 348*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 349*0Sstevel@tonic-gate return (NULL); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate return (node); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* Supporting Data Conversion Routines */ 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate /* XML Parser Utility Functions */ 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate /* 360*0Sstevel@tonic-gate * Handler for XML Errors. Called by libxml at libxml Error. 361*0Sstevel@tonic-gate */ 362*0Sstevel@tonic-gate /*ARGSUSED*/ 363*0Sstevel@tonic-gate void 364*0Sstevel@tonic-gate pool_error_func(void *ctx, const char *msg, ...) 365*0Sstevel@tonic-gate { 366*0Sstevel@tonic-gate va_list ap; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate va_start(ap, msg); 369*0Sstevel@tonic-gate do_dprintf(msg, ap); 370*0Sstevel@tonic-gate va_end(ap); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * Free the shadowed elements from within the supplied document and then 375*0Sstevel@tonic-gate * free the document. This function should always be called when freeing 376*0Sstevel@tonic-gate * a pool document to ensure that all "shadow" resources are reclaimed. 377*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 378*0Sstevel@tonic-gate */ 379*0Sstevel@tonic-gate static int 380*0Sstevel@tonic-gate pool_xml_free_doc(pool_conf_t *conf) 381*0Sstevel@tonic-gate { 382*0Sstevel@tonic-gate /* Only do any of this if there is a document */ 383*0Sstevel@tonic-gate if (((pool_xml_connection_t *)conf->pc_prov)->pxc_doc != NULL) { 384*0Sstevel@tonic-gate pool_elem_t *pe; 385*0Sstevel@tonic-gate pool_result_set_t *rs; 386*0Sstevel@tonic-gate /* Delete all the "shadowed" children of the doc */ 387*0Sstevel@tonic-gate rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_ANY, NULL); 388*0Sstevel@tonic-gate if (rs == NULL) { 389*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 390*0Sstevel@tonic-gate return (PO_FAIL); 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) { 393*0Sstevel@tonic-gate /* 394*0Sstevel@tonic-gate * Work out the element type and free the elem 395*0Sstevel@tonic-gate */ 396*0Sstevel@tonic-gate free(pe); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate (void) pool_rs_close(rs); 399*0Sstevel@tonic-gate xmlFreeDoc(((pool_xml_connection_t *)conf->pc_prov)->pxc_doc); 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc = NULL; 402*0Sstevel@tonic-gate return (PO_SUCCESS); 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* 406*0Sstevel@tonic-gate * Remove an element from the document. Note that only three types of elements 407*0Sstevel@tonic-gate * can be removed, res, comp and pools. comp are moved around to the 408*0Sstevel@tonic-gate * default res when a res is deleted. 409*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 410*0Sstevel@tonic-gate */ 411*0Sstevel@tonic-gate static int 412*0Sstevel@tonic-gate pool_xml_elem_remove(pool_elem_t *pe) 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* 417*0Sstevel@tonic-gate * You can only destroy three elements: pools, resources and 418*0Sstevel@tonic-gate * components. 419*0Sstevel@tonic-gate */ 420*0Sstevel@tonic-gate switch (pe->pe_class) { 421*0Sstevel@tonic-gate case PEC_POOL: 422*0Sstevel@tonic-gate case PEC_RES_COMP: 423*0Sstevel@tonic-gate case PEC_RES_AGG: 424*0Sstevel@tonic-gate case PEC_COMP: 425*0Sstevel@tonic-gate if (pxe->pxe_node) { 426*0Sstevel@tonic-gate xmlUnlinkNode(pxe->pxe_node); 427*0Sstevel@tonic-gate xmlFreeNode(pxe->pxe_node); /* recurses all children */ 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate free(pxe); 430*0Sstevel@tonic-gate break; 431*0Sstevel@tonic-gate default: 432*0Sstevel@tonic-gate break; 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate return (PO_SUCCESS); 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate /* 438*0Sstevel@tonic-gate * Create a property element. 439*0Sstevel@tonic-gate */ 440*0Sstevel@tonic-gate static xmlNodePtr 441*0Sstevel@tonic-gate property_create(xmlNodePtr parent, const char *name, pool_value_class_t type) 442*0Sstevel@tonic-gate { 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate xmlNodePtr element; 445*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate if ((element = node_create(parent, BAD_CAST "property")) == NULL) { 448*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 449*0Sstevel@tonic-gate return (NULL); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate if (pool_value_set_string(&val, name) != PO_SUCCESS) { 452*0Sstevel@tonic-gate xmlFree(element); 453*0Sstevel@tonic-gate return (NULL); 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate (void) pool_xml_set_attr(element, BAD_CAST c_name, &val); 456*0Sstevel@tonic-gate if (pool_value_set_string(&val, data_type_tags[type]) != PO_SUCCESS) { 457*0Sstevel@tonic-gate xmlFree(element); 458*0Sstevel@tonic-gate return (NULL); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate (void) pool_xml_set_attr(element, BAD_CAST c_type, &val); 461*0Sstevel@tonic-gate return (element); 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate /* 465*0Sstevel@tonic-gate * External clients need to be able to put/get properties and this is the 466*0Sstevel@tonic-gate * way to do it. 467*0Sstevel@tonic-gate * This function is an interceptor, since it will *always* try to manipulate 468*0Sstevel@tonic-gate * an attribute first. If the attribute doesn't exist, then it will treat 469*0Sstevel@tonic-gate * the request as a property request. 470*0Sstevel@tonic-gate */ 471*0Sstevel@tonic-gate static pool_value_class_t 472*0Sstevel@tonic-gate pool_xml_get_property(const pool_elem_t *pe, const char *name, 473*0Sstevel@tonic-gate pool_value_t *val) 474*0Sstevel@tonic-gate { 475*0Sstevel@tonic-gate pool_value_class_t type; 476*0Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe; 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate /* 479*0Sstevel@tonic-gate * "type" is a special attribute which is not visible ever outside of 480*0Sstevel@tonic-gate * libpool. Use the specific type accessor function. 481*0Sstevel@tonic-gate */ 482*0Sstevel@tonic-gate if (strcmp(name, c_type) == 0) { 483*0Sstevel@tonic-gate return (pool_xml_get_attr(pxe->pxe_node, BAD_CAST name, 484*0Sstevel@tonic-gate val)); 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate if (is_ns_property(pe, name) != NULL) { /* in ns */ 487*0Sstevel@tonic-gate if ((type = pool_xml_get_attr(pxe->pxe_node, 488*0Sstevel@tonic-gate BAD_CAST property_name_minus_ns(pe, name), val)) 489*0Sstevel@tonic-gate == POC_INVAL) 490*0Sstevel@tonic-gate return (pool_xml_get_prop(pxe->pxe_node, BAD_CAST name, 491*0Sstevel@tonic-gate val)); 492*0Sstevel@tonic-gate } else 493*0Sstevel@tonic-gate return (pool_xml_get_prop(pxe->pxe_node, BAD_CAST name, val)); 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate return (type); 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate /* 499*0Sstevel@tonic-gate * Put a property on an element. Check if the property is an attribute, 500*0Sstevel@tonic-gate * if it is update that value. If not add a property element. 501*0Sstevel@tonic-gate * 502*0Sstevel@tonic-gate * There are three possible conditions here: 503*0Sstevel@tonic-gate * - the name is a ns 504*0Sstevel@tonic-gate * - the name is an attribute 505*0Sstevel@tonic-gate * - the name isn't an attribute 506*0Sstevel@tonic-gate * - the name is not a ns 507*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 508*0Sstevel@tonic-gate */ 509*0Sstevel@tonic-gate static int 510*0Sstevel@tonic-gate pool_xml_put_property(pool_elem_t *pe, const char *name, 511*0Sstevel@tonic-gate const pool_value_t *val) 512*0Sstevel@tonic-gate { 513*0Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe; 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate /* 516*0Sstevel@tonic-gate * "type" is a special attribute which is not visible ever outside of 517*0Sstevel@tonic-gate * libpool. Use the specific type accessor function. 518*0Sstevel@tonic-gate */ 519*0Sstevel@tonic-gate if (strcmp(name, c_type) == 0) { 520*0Sstevel@tonic-gate return (pool_xml_set_attr(pxe->pxe_node, BAD_CAST name, 521*0Sstevel@tonic-gate val)); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate if (is_ns_property(pe, name) != NULL) { /* in ns */ 524*0Sstevel@tonic-gate if (pool_xml_set_attr(pxe->pxe_node, 525*0Sstevel@tonic-gate BAD_CAST property_name_minus_ns(pe, name), val) == PO_FAIL) 526*0Sstevel@tonic-gate return (pool_xml_set_prop(pxe->pxe_node, BAD_CAST name, 527*0Sstevel@tonic-gate val)); 528*0Sstevel@tonic-gate } else 529*0Sstevel@tonic-gate return (pool_xml_set_prop(pxe->pxe_node, BAD_CAST name, val)); 530*0Sstevel@tonic-gate return (PO_SUCCESS); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate /* 534*0Sstevel@tonic-gate * Remove a property from an element. Check if the property is an attribute, 535*0Sstevel@tonic-gate * if it is fail. Otherwise remove the property subelement. 536*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 537*0Sstevel@tonic-gate */ 538*0Sstevel@tonic-gate static int 539*0Sstevel@tonic-gate pool_xml_rm_property(pool_elem_t *pe, const char *name) 540*0Sstevel@tonic-gate { 541*0Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe; 542*0Sstevel@tonic-gate xmlXPathContextPtr ctx; 543*0Sstevel@tonic-gate xmlXPathObjectPtr path; 544*0Sstevel@tonic-gate char buf[MAX_PROP_SIZE]; 545*0Sstevel@tonic-gate int ret; 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate if (xmlHasProp(pxe->pxe_node, BAD_CAST name) != NULL) { 548*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 549*0Sstevel@tonic-gate return (PO_FAIL); 550*0Sstevel@tonic-gate } 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* use xpath to find the node with the appropriate value for name */ 553*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "property[@name=\"%s\"]", name); 554*0Sstevel@tonic-gate if ((ctx = xmlXPathNewContext(pxe->pxe_node->doc)) == NULL) { 555*0Sstevel@tonic-gate pool_seterror(POE_PUTPROP); 556*0Sstevel@tonic-gate return (PO_FAIL); 557*0Sstevel@tonic-gate } 558*0Sstevel@tonic-gate ctx->node = pxe->pxe_node; 559*0Sstevel@tonic-gate path = xmlXPathEval(BAD_CAST buf, ctx); 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate if (path && (path->type == XPATH_NODESET) && 562*0Sstevel@tonic-gate (path->nodesetval->nodeNr == 1)) { 563*0Sstevel@tonic-gate xmlUnlinkNode(path->nodesetval->nodeTab[0]); 564*0Sstevel@tonic-gate xmlFreeNode(path->nodesetval->nodeTab[0]); 565*0Sstevel@tonic-gate ret = PO_SUCCESS; 566*0Sstevel@tonic-gate } else { 567*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 568*0Sstevel@tonic-gate ret = PO_FAIL; 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate xmlXPathFreeObject(path); 571*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 572*0Sstevel@tonic-gate return (ret); 573*0Sstevel@tonic-gate } 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate /* 576*0Sstevel@tonic-gate * Get the data type for an attribute name from the element node. The data 577*0Sstevel@tonic-gate * type is returned and the value of the attribute updates the supplied value 578*0Sstevel@tonic-gate * pointer. 579*0Sstevel@tonic-gate */ 580*0Sstevel@tonic-gate static pool_value_class_t 581*0Sstevel@tonic-gate pool_xml_get_attr(xmlNodePtr node, xmlChar *name, pool_value_t *value) 582*0Sstevel@tonic-gate { 583*0Sstevel@tonic-gate pool_value_class_t data_type; 584*0Sstevel@tonic-gate xmlChar *data; 585*0Sstevel@tonic-gate uint64_t uval; 586*0Sstevel@tonic-gate int64_t ival; 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate if (xmlHasProp(node, name) == NULL && pool_is_xml_attr(node->doc, 589*0Sstevel@tonic-gate (const char *) node->name, (const char *) name) == PO_FALSE) { 590*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 591*0Sstevel@tonic-gate return (POC_INVAL); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate if (xmlHasProp(node, BAD_CAST c_a_dtype) == NULL) { 594*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 595*0Sstevel@tonic-gate return (POC_INVAL); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate data = xmlGetProp(node, name); 598*0Sstevel@tonic-gate data_type = get_fast_dtype(node, name); 599*0Sstevel@tonic-gate if (data_type != POC_STRING && data == NULL) { 600*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 601*0Sstevel@tonic-gate return (POC_INVAL); 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate switch (data_type) { 604*0Sstevel@tonic-gate case POC_UINT: 605*0Sstevel@tonic-gate errno = 0; 606*0Sstevel@tonic-gate uval = strtoull((char *)data, NULL, 0); 607*0Sstevel@tonic-gate if (errno != 0) { 608*0Sstevel@tonic-gate data_type = POC_INVAL; 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate else 611*0Sstevel@tonic-gate pool_value_set_uint64(value, uval); 612*0Sstevel@tonic-gate break; 613*0Sstevel@tonic-gate case POC_INT: 614*0Sstevel@tonic-gate errno = 0; 615*0Sstevel@tonic-gate ival = strtoll((char *)data, NULL, 0); 616*0Sstevel@tonic-gate if (errno != 0) { 617*0Sstevel@tonic-gate data_type = POC_INVAL; 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate else 620*0Sstevel@tonic-gate pool_value_set_int64(value, ival); 621*0Sstevel@tonic-gate break; 622*0Sstevel@tonic-gate case POC_DOUBLE: 623*0Sstevel@tonic-gate pool_value_set_double(value, atof((const char *)data)); 624*0Sstevel@tonic-gate break; 625*0Sstevel@tonic-gate case POC_BOOL: 626*0Sstevel@tonic-gate if (strcmp((const char *)data, "true") == 0) 627*0Sstevel@tonic-gate pool_value_set_bool(value, PO_TRUE); 628*0Sstevel@tonic-gate else 629*0Sstevel@tonic-gate pool_value_set_bool(value, PO_FALSE); 630*0Sstevel@tonic-gate break; 631*0Sstevel@tonic-gate case POC_STRING: 632*0Sstevel@tonic-gate if (pool_value_set_string(value, data ? 633*0Sstevel@tonic-gate (const char *)data : "") != PO_SUCCESS) { 634*0Sstevel@tonic-gate xmlFree(data); 635*0Sstevel@tonic-gate return (POC_INVAL); 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate break; 638*0Sstevel@tonic-gate case POC_INVAL: 639*0Sstevel@tonic-gate default: 640*0Sstevel@tonic-gate break; 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate xmlFree(data); 643*0Sstevel@tonic-gate return (data_type); 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate /* 647*0Sstevel@tonic-gate * Set the data type for an attribute name from the element node. The 648*0Sstevel@tonic-gate * supplied value is used to update the designated name using the data 649*0Sstevel@tonic-gate * type supplied. 650*0Sstevel@tonic-gate */ 651*0Sstevel@tonic-gate int 652*0Sstevel@tonic-gate pool_xml_set_attr(xmlNodePtr node, xmlChar *name, const pool_value_t *value) 653*0Sstevel@tonic-gate { 654*0Sstevel@tonic-gate xmlChar buf[MAX_PROP_SIZE] = {0}; 655*0Sstevel@tonic-gate uint64_t ures; 656*0Sstevel@tonic-gate int64_t ires; 657*0Sstevel@tonic-gate uchar_t bres; 658*0Sstevel@tonic-gate double dres; 659*0Sstevel@tonic-gate const char *sres; 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate pool_value_class_t data_type; 662*0Sstevel@tonic-gate 663*0Sstevel@tonic-gate if (xmlHasProp(node, name) == NULL && pool_is_xml_attr(node->doc, 664*0Sstevel@tonic-gate (const char *) node->name, (const char *) name) == PO_FALSE) { 665*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 666*0Sstevel@tonic-gate return (PO_FAIL); 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate if (xmlHasProp(node, BAD_CAST c_a_dtype) == NULL) { 670*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 671*0Sstevel@tonic-gate return (PO_FAIL); 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate data_type = get_fast_dtype(node, name); 674*0Sstevel@tonic-gate if (data_type != value->pv_class) { 675*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 676*0Sstevel@tonic-gate return (PO_FAIL); 677*0Sstevel@tonic-gate } 678*0Sstevel@tonic-gate switch (value->pv_class) { 679*0Sstevel@tonic-gate case POC_UINT: 680*0Sstevel@tonic-gate (void) pool_value_get_uint64(value, &ures); 681*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%llu", 682*0Sstevel@tonic-gate (u_longlong_t)ures); 683*0Sstevel@tonic-gate break; 684*0Sstevel@tonic-gate case POC_INT: 685*0Sstevel@tonic-gate (void) pool_value_get_int64(value, &ires); 686*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%lld", 687*0Sstevel@tonic-gate (longlong_t)ires); 688*0Sstevel@tonic-gate break; 689*0Sstevel@tonic-gate case POC_DOUBLE: 690*0Sstevel@tonic-gate (void) pool_value_get_double(value, &dres); 691*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%f", dres); 692*0Sstevel@tonic-gate break; 693*0Sstevel@tonic-gate case POC_BOOL: 694*0Sstevel@tonic-gate (void) pool_value_get_bool(value, &bres); 695*0Sstevel@tonic-gate if (bres == PO_FALSE) 696*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), 697*0Sstevel@tonic-gate "false"); 698*0Sstevel@tonic-gate else 699*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), 700*0Sstevel@tonic-gate "true"); 701*0Sstevel@tonic-gate break; 702*0Sstevel@tonic-gate case POC_STRING: 703*0Sstevel@tonic-gate (void) pool_value_get_string(value, &sres); 704*0Sstevel@tonic-gate if (sres != NULL) 705*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%s", 706*0Sstevel@tonic-gate sres); 707*0Sstevel@tonic-gate break; 708*0Sstevel@tonic-gate case POC_INVAL: 709*0Sstevel@tonic-gate default: 710*0Sstevel@tonic-gate break; 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate if (xmlSetProp(node, name, buf) == NULL) { 713*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 714*0Sstevel@tonic-gate return (PO_FAIL); 715*0Sstevel@tonic-gate } 716*0Sstevel@tonic-gate return (PO_SUCCESS); 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate /* 720*0Sstevel@tonic-gate * Get the data type for a property name from the element node. The data 721*0Sstevel@tonic-gate * type is returned and the value of the property updates the supplied value 722*0Sstevel@tonic-gate * pointer. The user is responsible for freeing the memory associated with 723*0Sstevel@tonic-gate * a string. 724*0Sstevel@tonic-gate */ 725*0Sstevel@tonic-gate static pool_value_class_t 726*0Sstevel@tonic-gate pool_xml_get_prop(xmlNodePtr node, xmlChar *name, pool_value_t *value) 727*0Sstevel@tonic-gate { 728*0Sstevel@tonic-gate pool_value_class_t data_type; 729*0Sstevel@tonic-gate xmlChar *data, *node_data; 730*0Sstevel@tonic-gate xmlXPathContextPtr ctx; 731*0Sstevel@tonic-gate xmlXPathObjectPtr path; 732*0Sstevel@tonic-gate char buf[MAX_PROP_SIZE]; 733*0Sstevel@tonic-gate int64_t uval; 734*0Sstevel@tonic-gate int64_t ival; 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate /* use xpath to find the node with the appropriate value for name */ 737*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "property[@name=\"%s\"]", name); 738*0Sstevel@tonic-gate if ((ctx = xmlXPathNewContext(node->doc)) == NULL) { 739*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 740*0Sstevel@tonic-gate return (POC_INVAL); 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate ctx->node = node; 743*0Sstevel@tonic-gate path = xmlXPathEval(BAD_CAST buf, ctx); 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate if (path && (path->type == XPATH_NODESET) && 746*0Sstevel@tonic-gate (path->nodesetval->nodeNr == 1)) { 747*0Sstevel@tonic-gate int i; 748*0Sstevel@tonic-gate if (xmlHasProp(path->nodesetval->nodeTab[0], 749*0Sstevel@tonic-gate BAD_CAST c_type) == NULL) { 750*0Sstevel@tonic-gate xmlXPathFreeObject(path); 751*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 752*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 753*0Sstevel@tonic-gate return (POC_INVAL); 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate /* type is a string representation of the type */ 756*0Sstevel@tonic-gate data = xmlGetProp(path->nodesetval->nodeTab[0], 757*0Sstevel@tonic-gate BAD_CAST c_type); 758*0Sstevel@tonic-gate node_data = xmlNodeGetContent(path->nodesetval->nodeTab[0]); 759*0Sstevel@tonic-gate data_type = POC_INVAL; 760*0Sstevel@tonic-gate for (i = 0; i < (sizeof (data_type_tags) / 761*0Sstevel@tonic-gate sizeof (data_type_tags[0])); i++) { 762*0Sstevel@tonic-gate if (strcmp((char *)data, data_type_tags[i]) == 0) { 763*0Sstevel@tonic-gate data_type = i; 764*0Sstevel@tonic-gate break; 765*0Sstevel@tonic-gate } 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate switch (data_type) { 768*0Sstevel@tonic-gate case POC_UINT: 769*0Sstevel@tonic-gate errno = 0; 770*0Sstevel@tonic-gate uval = strtoull((char *)node_data, NULL, 0); 771*0Sstevel@tonic-gate if (errno != 0) 772*0Sstevel@tonic-gate data_type = POC_INVAL; 773*0Sstevel@tonic-gate else 774*0Sstevel@tonic-gate pool_value_set_uint64(value, uval); 775*0Sstevel@tonic-gate break; 776*0Sstevel@tonic-gate case POC_INT: 777*0Sstevel@tonic-gate errno = 0; 778*0Sstevel@tonic-gate ival = strtoll((char *)node_data, NULL, 0); 779*0Sstevel@tonic-gate if (errno != 0) 780*0Sstevel@tonic-gate data_type = POC_INVAL; 781*0Sstevel@tonic-gate else 782*0Sstevel@tonic-gate pool_value_set_int64(value, ival); 783*0Sstevel@tonic-gate break; 784*0Sstevel@tonic-gate case POC_DOUBLE: 785*0Sstevel@tonic-gate pool_value_set_double(value, 786*0Sstevel@tonic-gate atof((const char *)node_data)); 787*0Sstevel@tonic-gate break; 788*0Sstevel@tonic-gate case POC_BOOL: 789*0Sstevel@tonic-gate if (strcmp((const char *)node_data, "true") 790*0Sstevel@tonic-gate == 0) 791*0Sstevel@tonic-gate pool_value_set_bool(value, PO_TRUE); 792*0Sstevel@tonic-gate else 793*0Sstevel@tonic-gate pool_value_set_bool(value, PO_FALSE); 794*0Sstevel@tonic-gate break; 795*0Sstevel@tonic-gate case POC_STRING: 796*0Sstevel@tonic-gate if (pool_value_set_string(value, 797*0Sstevel@tonic-gate (const char *)node_data) != PO_SUCCESS) { 798*0Sstevel@tonic-gate data_type = POC_INVAL; 799*0Sstevel@tonic-gate break; 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate break; 802*0Sstevel@tonic-gate case POC_INVAL: 803*0Sstevel@tonic-gate default: 804*0Sstevel@tonic-gate break; 805*0Sstevel@tonic-gate } 806*0Sstevel@tonic-gate xmlFree(data); 807*0Sstevel@tonic-gate xmlFree(node_data); 808*0Sstevel@tonic-gate xmlXPathFreeObject(path); 809*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 810*0Sstevel@tonic-gate return (data_type); 811*0Sstevel@tonic-gate } else { /* No property exists, clean up and return */ 812*0Sstevel@tonic-gate xmlXPathFreeObject(path); 813*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 814*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 815*0Sstevel@tonic-gate return (POC_INVAL); 816*0Sstevel@tonic-gate } 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate /* 820*0Sstevel@tonic-gate * Set the data type for a property name from the element node. The 821*0Sstevel@tonic-gate * supplied value is used to update the designated name using the data 822*0Sstevel@tonic-gate * type supplied. 823*0Sstevel@tonic-gate */ 824*0Sstevel@tonic-gate int 825*0Sstevel@tonic-gate pool_xml_set_prop(xmlNodePtr node, xmlChar *name, const pool_value_t *value) 826*0Sstevel@tonic-gate { 827*0Sstevel@tonic-gate /* First check if we have a property with this name (and type???). */ 828*0Sstevel@tonic-gate xmlXPathContextPtr ctx; 829*0Sstevel@tonic-gate xmlXPathObjectPtr path; 830*0Sstevel@tonic-gate xmlChar buf[MAX_PROP_SIZE]; 831*0Sstevel@tonic-gate xmlNodePtr element; 832*0Sstevel@tonic-gate uint64_t ures; 833*0Sstevel@tonic-gate int64_t ires; 834*0Sstevel@tonic-gate uchar_t bres; 835*0Sstevel@tonic-gate double dres; 836*0Sstevel@tonic-gate const char *sres; 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate /* use xpath to find the node with the appropriate value for name */ 839*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "property[@name=\"%s\"]", 840*0Sstevel@tonic-gate name); 841*0Sstevel@tonic-gate if ((ctx = xmlXPathNewContext(node->doc)) == NULL) { 842*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 843*0Sstevel@tonic-gate return (PO_FAIL); 844*0Sstevel@tonic-gate } 845*0Sstevel@tonic-gate ctx->node = node; 846*0Sstevel@tonic-gate path = xmlXPathEval(buf, ctx); 847*0Sstevel@tonic-gate if (path == NULL || path->type != XPATH_NODESET) { 848*0Sstevel@tonic-gate xmlXPathFreeObject(path); 849*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 850*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 851*0Sstevel@tonic-gate return (PO_FAIL); 852*0Sstevel@tonic-gate } else { 853*0Sstevel@tonic-gate if (path->nodesetval->nodeNr == 0) 854*0Sstevel@tonic-gate element = property_create 855*0Sstevel@tonic-gate (node, (const char *)name, value->pv_class); 856*0Sstevel@tonic-gate else if (path->nodesetval->nodeNr == 1) { 857*0Sstevel@tonic-gate int i; 858*0Sstevel@tonic-gate xmlChar *data; 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate element = path->nodesetval->nodeTab[0]; 861*0Sstevel@tonic-gate if (xmlHasProp(element, BAD_CAST c_type) == NULL) { 862*0Sstevel@tonic-gate xmlXPathFreeObject(path); 863*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 864*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 865*0Sstevel@tonic-gate return (PO_FAIL); 866*0Sstevel@tonic-gate } 867*0Sstevel@tonic-gate data = xmlGetProp(element, BAD_CAST c_type); 868*0Sstevel@tonic-gate for (i = 0; i < (sizeof (data_type_tags) / 869*0Sstevel@tonic-gate sizeof (data_type_tags[0])); i++) 870*0Sstevel@tonic-gate if (strcmp((char *)data, data_type_tags[i]) 871*0Sstevel@tonic-gate == 0) { 872*0Sstevel@tonic-gate break; 873*0Sstevel@tonic-gate } 874*0Sstevel@tonic-gate xmlFree(data); 875*0Sstevel@tonic-gate if (value->pv_class != i) { 876*0Sstevel@tonic-gate xmlXPathFreeObject(path); 877*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 878*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 879*0Sstevel@tonic-gate return (PO_FAIL); 880*0Sstevel@tonic-gate } 881*0Sstevel@tonic-gate } else { 882*0Sstevel@tonic-gate xmlXPathFreeObject(path); 883*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 884*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 885*0Sstevel@tonic-gate return (PO_FAIL); 886*0Sstevel@tonic-gate } 887*0Sstevel@tonic-gate } 888*0Sstevel@tonic-gate 889*0Sstevel@tonic-gate switch (value->pv_class) { 890*0Sstevel@tonic-gate case POC_UINT: 891*0Sstevel@tonic-gate (void) pool_value_get_uint64(value, &ures); 892*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%llu", 893*0Sstevel@tonic-gate (u_longlong_t)ures); 894*0Sstevel@tonic-gate break; 895*0Sstevel@tonic-gate case POC_INT: 896*0Sstevel@tonic-gate (void) pool_value_get_int64(value, &ires); 897*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%lld", 898*0Sstevel@tonic-gate (longlong_t)ires); 899*0Sstevel@tonic-gate break; 900*0Sstevel@tonic-gate case POC_DOUBLE: 901*0Sstevel@tonic-gate (void) pool_value_get_double(value, &dres); 902*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%f", dres); 903*0Sstevel@tonic-gate break; 904*0Sstevel@tonic-gate case POC_BOOL: 905*0Sstevel@tonic-gate (void) pool_value_get_bool(value, &bres); 906*0Sstevel@tonic-gate if (bres == PO_FALSE) 907*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), 908*0Sstevel@tonic-gate "false"); 909*0Sstevel@tonic-gate else 910*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), 911*0Sstevel@tonic-gate "true"); 912*0Sstevel@tonic-gate break; 913*0Sstevel@tonic-gate case POC_STRING: 914*0Sstevel@tonic-gate (void) pool_value_get_string(value, &sres); 915*0Sstevel@tonic-gate (void) snprintf((char *)buf, sizeof (buf), "%s", sres); 916*0Sstevel@tonic-gate break; 917*0Sstevel@tonic-gate case POC_INVAL: 918*0Sstevel@tonic-gate default: 919*0Sstevel@tonic-gate break; 920*0Sstevel@tonic-gate } 921*0Sstevel@tonic-gate xmlNodeSetContent(element, buf); 922*0Sstevel@tonic-gate xmlXPathFreeObject(path); 923*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 924*0Sstevel@tonic-gate return (PO_SUCCESS); 925*0Sstevel@tonic-gate } 926*0Sstevel@tonic-gate 927*0Sstevel@tonic-gate /* 928*0Sstevel@tonic-gate * Return a NULL terminated array of pool_value_t which represents all 929*0Sstevel@tonic-gate * of the properties stored for an element 930*0Sstevel@tonic-gate * 931*0Sstevel@tonic-gate * Return NULL on failure. It is the caller's responsibility to free 932*0Sstevel@tonic-gate * the returned array of values. 933*0Sstevel@tonic-gate */ 934*0Sstevel@tonic-gate pool_value_t ** 935*0Sstevel@tonic-gate pool_xml_get_properties(const pool_elem_t *pe, uint_t *nprops) 936*0Sstevel@tonic-gate { 937*0Sstevel@tonic-gate pool_value_t **result; 938*0Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)pe; 939*0Sstevel@tonic-gate int i, j; 940*0Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(pe); 941*0Sstevel@tonic-gate xmlElementPtr elemDTD; 942*0Sstevel@tonic-gate xmlAttributePtr attr; 943*0Sstevel@tonic-gate xmlXPathContextPtr ctx; 944*0Sstevel@tonic-gate xmlXPathObjectPtr path; 945*0Sstevel@tonic-gate char_buf_t *cb = NULL; 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate *nprops = 0; 948*0Sstevel@tonic-gate 949*0Sstevel@tonic-gate elemDTD = xmlGetDtdElementDesc(pxe->pxe_node->doc->extSubset, 950*0Sstevel@tonic-gate pxe->pxe_node->name); 951*0Sstevel@tonic-gate for (attr = elemDTD->attributes; attr != NULL; attr = attr->nexth) { 952*0Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_a_dtype) != 0 || 953*0Sstevel@tonic-gate strcmp((const char *)attr->name, c_type) != 0) 954*0Sstevel@tonic-gate (*nprops)++; 955*0Sstevel@tonic-gate } 956*0Sstevel@tonic-gate if ((ctx = xmlXPathNewContext( 957*0Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc)) == NULL) { 958*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 959*0Sstevel@tonic-gate return (NULL); 960*0Sstevel@tonic-gate } 961*0Sstevel@tonic-gate ctx->node = pxe->pxe_node; 962*0Sstevel@tonic-gate path = xmlXPathEval(BAD_CAST "property", ctx); 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate if (path != NULL && path->type == XPATH_NODESET && 965*0Sstevel@tonic-gate path->nodesetval != NULL) 966*0Sstevel@tonic-gate (*nprops) += path->nodesetval->nodeNr; 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gate if ((result = calloc(*nprops + 1, sizeof (pool_value_t *))) == NULL) { 969*0Sstevel@tonic-gate xmlXPathFreeObject(path); 970*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 971*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 972*0Sstevel@tonic-gate return (NULL); 973*0Sstevel@tonic-gate } 974*0Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 975*0Sstevel@tonic-gate xmlXPathFreeObject(path); 976*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 977*0Sstevel@tonic-gate free(result); 978*0Sstevel@tonic-gate return (NULL); 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate /* 981*0Sstevel@tonic-gate * Now store our attributes and properties in result 982*0Sstevel@tonic-gate */ 983*0Sstevel@tonic-gate for (i = 0, attr = elemDTD->attributes; attr != NULL; 984*0Sstevel@tonic-gate attr = attr->nexth, i++) { 985*0Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_a_dtype) == 0 || 986*0Sstevel@tonic-gate strcmp((const char *)attr->name, c_type) == 0) { 987*0Sstevel@tonic-gate i--; 988*0Sstevel@tonic-gate continue; 989*0Sstevel@tonic-gate } 990*0Sstevel@tonic-gate result[i] = pool_value_alloc(); 991*0Sstevel@tonic-gate if (pool_xml_get_attr(pxe->pxe_node, 992*0Sstevel@tonic-gate BAD_CAST attr->name, result[i]) == POC_INVAL) { 993*0Sstevel@tonic-gate xmlXPathFreeObject(path); 994*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 995*0Sstevel@tonic-gate while (i-- >= 0) 996*0Sstevel@tonic-gate pool_value_free(result[i]); 997*0Sstevel@tonic-gate free(result); 998*0Sstevel@tonic-gate free_char_buf(cb); 999*0Sstevel@tonic-gate return (NULL); 1000*0Sstevel@tonic-gate } 1001*0Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_type) != 0) { 1002*0Sstevel@tonic-gate if (set_char_buf(cb, "%s.%s", 1003*0Sstevel@tonic-gate pool_elem_class_string(pe), attr->name) != 1004*0Sstevel@tonic-gate PO_SUCCESS) { 1005*0Sstevel@tonic-gate xmlXPathFreeObject(path); 1006*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 1007*0Sstevel@tonic-gate while (i-- >= 0) 1008*0Sstevel@tonic-gate pool_value_free(result[i]); 1009*0Sstevel@tonic-gate free(result); 1010*0Sstevel@tonic-gate free_char_buf(cb); 1011*0Sstevel@tonic-gate return (NULL); 1012*0Sstevel@tonic-gate } 1013*0Sstevel@tonic-gate if (pool_value_set_name(result[i], cb->cb_buf) != 1014*0Sstevel@tonic-gate PO_SUCCESS) { 1015*0Sstevel@tonic-gate xmlXPathFreeObject(path); 1016*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 1017*0Sstevel@tonic-gate while (i-- >= 0) 1018*0Sstevel@tonic-gate pool_value_free(result[i]); 1019*0Sstevel@tonic-gate free(result); 1020*0Sstevel@tonic-gate free_char_buf(cb); 1021*0Sstevel@tonic-gate return (NULL); 1022*0Sstevel@tonic-gate } 1023*0Sstevel@tonic-gate } else { 1024*0Sstevel@tonic-gate if (pool_value_set_name(result[i], 1025*0Sstevel@tonic-gate (const char *)attr->name) != PO_SUCCESS) { 1026*0Sstevel@tonic-gate xmlXPathFreeObject(path); 1027*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 1028*0Sstevel@tonic-gate while (i-- >= 0) 1029*0Sstevel@tonic-gate pool_value_free(result[i]); 1030*0Sstevel@tonic-gate free(result); 1031*0Sstevel@tonic-gate free_char_buf(cb); 1032*0Sstevel@tonic-gate return (NULL); 1033*0Sstevel@tonic-gate } 1034*0Sstevel@tonic-gate } 1035*0Sstevel@tonic-gate } 1036*0Sstevel@tonic-gate free_char_buf(cb); 1037*0Sstevel@tonic-gate for (j = 0; j < path->nodesetval->nodeNr; j++, i++) { 1038*0Sstevel@tonic-gate xmlChar *name = xmlGetProp(path->nodesetval->nodeTab[j], 1039*0Sstevel@tonic-gate BAD_CAST c_name); 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate result[i] = pool_value_alloc(); 1042*0Sstevel@tonic-gate 1043*0Sstevel@tonic-gate if (pool_xml_get_prop(pxe->pxe_node, name, result[i]) == 1044*0Sstevel@tonic-gate POC_INVAL) { 1045*0Sstevel@tonic-gate xmlFree(name); 1046*0Sstevel@tonic-gate xmlXPathFreeObject(path); 1047*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 1048*0Sstevel@tonic-gate while (i-- >= 0) 1049*0Sstevel@tonic-gate pool_value_free(result[i]); 1050*0Sstevel@tonic-gate free(result); 1051*0Sstevel@tonic-gate return (NULL); 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate if (pool_value_set_name(result[i], (const char *)name) != 1054*0Sstevel@tonic-gate PO_SUCCESS) { 1055*0Sstevel@tonic-gate xmlFree(name); 1056*0Sstevel@tonic-gate xmlXPathFreeObject(path); 1057*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 1058*0Sstevel@tonic-gate while (i-- >= 0) 1059*0Sstevel@tonic-gate pool_value_free(result[i]); 1060*0Sstevel@tonic-gate free(result); 1061*0Sstevel@tonic-gate return (NULL); 1062*0Sstevel@tonic-gate } 1063*0Sstevel@tonic-gate xmlFree(name); 1064*0Sstevel@tonic-gate } 1065*0Sstevel@tonic-gate xmlXPathFreeObject(path); 1066*0Sstevel@tonic-gate xmlXPathFreeContext(ctx); 1067*0Sstevel@tonic-gate return (result); 1068*0Sstevel@tonic-gate } 1069*0Sstevel@tonic-gate 1070*0Sstevel@tonic-gate /* 1071*0Sstevel@tonic-gate * Store a pointer to one of our data types in the _private member of each 1072*0Sstevel@tonic-gate * XML data node contained within the passed node. Note this function is 1073*0Sstevel@tonic-gate * recursive and so all sub-nodes are also shadowed. Only shadow the nodes 1074*0Sstevel@tonic-gate * which we are interested in, i.e. system, pool, res and comp 1075*0Sstevel@tonic-gate */ 1076*0Sstevel@tonic-gate static int 1077*0Sstevel@tonic-gate create_shadow(xmlNodePtr node) 1078*0Sstevel@tonic-gate { 1079*0Sstevel@tonic-gate xmlNodePtr sib; 1080*0Sstevel@tonic-gate int ret = PO_SUCCESS; 1081*0Sstevel@tonic-gate /* Create a data structure of the appropriate type */ 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate if (0 == (xmlStrcmp(node->name, 1084*0Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_SYSTEM]))) { 1085*0Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_SYSTEM, PREC_INVALID, 1086*0Sstevel@tonic-gate PCEC_INVALID); 1087*0Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name, 1088*0Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_POOL]))) { 1089*0Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_POOL, PREC_INVALID, 1090*0Sstevel@tonic-gate PCEC_INVALID); 1091*0Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name, 1092*0Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_RES_COMP]))) { 1093*0Sstevel@tonic-gate xmlChar *data; 1094*0Sstevel@tonic-gate pool_resource_elem_class_t res_class; 1095*0Sstevel@tonic-gate data = xmlGetProp(node, BAD_CAST c_type); 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate res_class = pool_resource_elem_class_from_string((char *)data); 1098*0Sstevel@tonic-gate xmlFree(data); 1099*0Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_RES_COMP, res_class, 1100*0Sstevel@tonic-gate PCEC_INVALID); 1101*0Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name, 1102*0Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_RES_AGG]))) { 1103*0Sstevel@tonic-gate xmlChar *data; 1104*0Sstevel@tonic-gate pool_resource_elem_class_t res_class; 1105*0Sstevel@tonic-gate data = xmlGetProp(node, BAD_CAST c_type); 1106*0Sstevel@tonic-gate 1107*0Sstevel@tonic-gate res_class = pool_resource_elem_class_from_string((char *)data); 1108*0Sstevel@tonic-gate xmlFree(data); 1109*0Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_RES_AGG, res_class, 1110*0Sstevel@tonic-gate PCEC_INVALID); 1111*0Sstevel@tonic-gate } else if (0 == (xmlStrcmp(node->name, 1112*0Sstevel@tonic-gate BAD_CAST element_class_tags[PEC_COMP]))) { 1113*0Sstevel@tonic-gate xmlChar *data; 1114*0Sstevel@tonic-gate pool_component_elem_class_t comp_class; 1115*0Sstevel@tonic-gate data = xmlGetProp(node, BAD_CAST c_type); 1116*0Sstevel@tonic-gate 1117*0Sstevel@tonic-gate comp_class = pool_component_elem_class_from_string( 1118*0Sstevel@tonic-gate (char *)data); 1119*0Sstevel@tonic-gate xmlFree(data); 1120*0Sstevel@tonic-gate ret = pool_xml_elem_wrap(node, PEC_COMP, PREC_INVALID, 1121*0Sstevel@tonic-gate comp_class); 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate /* Have to shadow all children and all siblings */ 1124*0Sstevel@tonic-gate for (sib = node->children; sib != NULL; sib = sib->next) { 1125*0Sstevel@tonic-gate if ((ret = create_shadow(sib)) != PO_SUCCESS) 1126*0Sstevel@tonic-gate break; 1127*0Sstevel@tonic-gate } 1128*0Sstevel@tonic-gate return (ret); 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate 1132*0Sstevel@tonic-gate /* 1133*0Sstevel@tonic-gate * XML Data access and navigation APIs 1134*0Sstevel@tonic-gate */ 1135*0Sstevel@tonic-gate 1136*0Sstevel@tonic-gate /* 1137*0Sstevel@tonic-gate * Close the configuration. There are a few steps to closing a configuration: 1138*0Sstevel@tonic-gate * - Unlock the backing file (if there is one) 1139*0Sstevel@tonic-gate * - Close the file (if there is one) 1140*0Sstevel@tonic-gate * - Free the shadow memory }Done in pool_xml_free_doc 1141*0Sstevel@tonic-gate * - Free the document } 1142*0Sstevel@tonic-gate * - Free the data provider for this configuration 1143*0Sstevel@tonic-gate * - Free the configuration location specifier 1144*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1145*0Sstevel@tonic-gate */ 1146*0Sstevel@tonic-gate static int 1147*0Sstevel@tonic-gate pool_xml_close(pool_conf_t *conf) 1148*0Sstevel@tonic-gate { 1149*0Sstevel@tonic-gate pool_xml_connection_t *pxc = (pool_xml_connection_t *)conf->pc_prov; 1150*0Sstevel@tonic-gate int ret = PO_SUCCESS; 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate if (pxc->pxc_file != NULL) { 1153*0Sstevel@tonic-gate /* Close (and implicitly) unlock the file */ 1154*0Sstevel@tonic-gate if (fclose(pxc->pxc_file) != 0) { 1155*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1156*0Sstevel@tonic-gate ret = PO_FAIL; 1157*0Sstevel@tonic-gate } 1158*0Sstevel@tonic-gate pxc->pxc_file = NULL; 1159*0Sstevel@tonic-gate } 1160*0Sstevel@tonic-gate /* Close the xml specific parts */ 1161*0Sstevel@tonic-gate (void) pool_xml_free_doc(conf); 1162*0Sstevel@tonic-gate pool_xml_connection_free((pool_xml_connection_t *)conf->pc_prov); 1163*0Sstevel@tonic-gate return (ret); 1164*0Sstevel@tonic-gate } 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate /* 1167*0Sstevel@tonic-gate * Remove the configuration from the backing store. In XML terms delete 1168*0Sstevel@tonic-gate * the file backing the configuration. You need a copy of the location 1169*0Sstevel@tonic-gate * since the pool_conf_close function, frees the location. 1170*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1171*0Sstevel@tonic-gate */ 1172*0Sstevel@tonic-gate static int 1173*0Sstevel@tonic-gate pool_xml_remove(pool_conf_t *conf) 1174*0Sstevel@tonic-gate { 1175*0Sstevel@tonic-gate if (pool_conf_location(conf) != NULL) { 1176*0Sstevel@tonic-gate /* First unlink the file, to prevent races on open */ 1177*0Sstevel@tonic-gate if (unlink(pool_conf_location(conf)) != 0) { 1178*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1179*0Sstevel@tonic-gate return (PO_FAIL); 1180*0Sstevel@tonic-gate } 1181*0Sstevel@tonic-gate /* Now close the configuration */ 1182*0Sstevel@tonic-gate (void) pool_conf_close(conf); 1183*0Sstevel@tonic-gate return (PO_SUCCESS); 1184*0Sstevel@tonic-gate } 1185*0Sstevel@tonic-gate return (PO_FAIL); 1186*0Sstevel@tonic-gate } 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate /* 1189*0Sstevel@tonic-gate * Validate the configuration. There are three levels of validation, loose, 1190*0Sstevel@tonic-gate * strict and runtime. In this, XML, implementation, loose is mapped to XML 1191*0Sstevel@tonic-gate * validation, strict implements additional application level validation 1192*0Sstevel@tonic-gate * checks, e.g. all pools must have unique names, runtime ensures that this 1193*0Sstevel@tonic-gate * configuration would instantiate on the current system. 1194*0Sstevel@tonic-gate * 1195*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1196*0Sstevel@tonic-gate */ 1197*0Sstevel@tonic-gate static int 1198*0Sstevel@tonic-gate pool_xml_validate(const pool_conf_t *conf, pool_valid_level_t level) 1199*0Sstevel@tonic-gate { 1200*0Sstevel@tonic-gate pool_xml_connection_t *pxc = (pool_xml_connection_t *)conf->pc_prov; 1201*0Sstevel@tonic-gate xmlValidCtxtPtr cvp; 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) { 1204*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1205*0Sstevel@tonic-gate return (PO_FAIL); 1206*0Sstevel@tonic-gate } 1207*0Sstevel@tonic-gate cvp->error = pool_error_func; 1208*0Sstevel@tonic-gate cvp->warning = pool_error_func; 1209*0Sstevel@tonic-gate 1210*0Sstevel@tonic-gate if (xmlValidateDocument(cvp, pxc->pxc_doc) == 0) { 1211*0Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 1212*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1213*0Sstevel@tonic-gate return (PO_FAIL); 1214*0Sstevel@tonic-gate } 1215*0Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate if (level >= POV_RUNTIME) { 1218*0Sstevel@tonic-gate /* 1219*0Sstevel@tonic-gate * Note: This is resource specific. 1220*0Sstevel@tonic-gate */ 1221*0Sstevel@tonic-gate return (((pool_validate_resource(conf, "pset", c_min_prop, 0) == 1222*0Sstevel@tonic-gate PO_SUCCESS) && 1223*0Sstevel@tonic-gate (pool_validate_resource(conf, "pset", c_max_prop, 0) == 1224*0Sstevel@tonic-gate PO_SUCCESS)) ? PO_SUCCESS : PO_FAIL); 1225*0Sstevel@tonic-gate } 1226*0Sstevel@tonic-gate return (PO_SUCCESS); 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate 1229*0Sstevel@tonic-gate /* 1230*0Sstevel@tonic-gate * Commit the configuration to the backing store. In XML terms this means 1231*0Sstevel@tonic-gate * write the changes to the backing file. Read the comments below for details 1232*0Sstevel@tonic-gate * on exactly how this operation is performed. 1233*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1234*0Sstevel@tonic-gate */ 1235*0Sstevel@tonic-gate static int 1236*0Sstevel@tonic-gate pool_xml_commit(pool_conf_t *conf) 1237*0Sstevel@tonic-gate { 1238*0Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov; 1239*0Sstevel@tonic-gate xmlOutputBufferPtr buf; 1240*0Sstevel@tonic-gate 1241*0Sstevel@tonic-gate /* 1242*0Sstevel@tonic-gate * Ensure that the configuration file has no contents 1243*0Sstevel@tonic-gate */ 1244*0Sstevel@tonic-gate if (fseek(prov->pxc_file, 0, SEEK_SET) != 0) { 1245*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1246*0Sstevel@tonic-gate return (PO_FAIL); 1247*0Sstevel@tonic-gate } 1248*0Sstevel@tonic-gate 1249*0Sstevel@tonic-gate if (ftruncate(fileno(prov->pxc_file), 0) == -1) { 1250*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1251*0Sstevel@tonic-gate return (PO_FAIL); 1252*0Sstevel@tonic-gate } 1253*0Sstevel@tonic-gate /* 1254*0Sstevel@tonic-gate * Create an XML output buffer and write out the contents of the 1255*0Sstevel@tonic-gate * configuration to the file. 1256*0Sstevel@tonic-gate */ 1257*0Sstevel@tonic-gate if ((buf = xmlOutputBufferCreateFile(prov->pxc_file, NULL)) == NULL) { 1258*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1259*0Sstevel@tonic-gate return (PO_FAIL); 1260*0Sstevel@tonic-gate } 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate if (xmlSaveFormatFileTo(buf, prov->pxc_doc, NULL, 1) == -1) { 1263*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1264*0Sstevel@tonic-gate return (PO_FAIL); 1265*0Sstevel@tonic-gate } 1266*0Sstevel@tonic-gate 1267*0Sstevel@tonic-gate return (PO_SUCCESS); 1268*0Sstevel@tonic-gate } 1269*0Sstevel@tonic-gate 1270*0Sstevel@tonic-gate /* 1271*0Sstevel@tonic-gate * Export the configuration in the specified format to the specified location. 1272*0Sstevel@tonic-gate * The only format implemented now is the native format, which saves the 1273*0Sstevel@tonic-gate * active configuration to the supplied location. 1274*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1275*0Sstevel@tonic-gate */ 1276*0Sstevel@tonic-gate static int 1277*0Sstevel@tonic-gate pool_xml_export(const pool_conf_t *conf, const char *location, 1278*0Sstevel@tonic-gate pool_export_format_t fmt) 1279*0Sstevel@tonic-gate { 1280*0Sstevel@tonic-gate int ret; 1281*0Sstevel@tonic-gate 1282*0Sstevel@tonic-gate switch (fmt) { 1283*0Sstevel@tonic-gate case POX_NATIVE: 1284*0Sstevel@tonic-gate ret = xmlSaveFormatFile(location, 1285*0Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc, 1286*0Sstevel@tonic-gate 1); 1287*0Sstevel@tonic-gate if (ret == -1) { 1288*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1289*0Sstevel@tonic-gate return (PO_FAIL); 1290*0Sstevel@tonic-gate } else 1291*0Sstevel@tonic-gate return (PO_SUCCESS); 1292*0Sstevel@tonic-gate 1293*0Sstevel@tonic-gate default: 1294*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1295*0Sstevel@tonic-gate return (PO_FAIL); 1296*0Sstevel@tonic-gate } 1297*0Sstevel@tonic-gate } 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate /* 1300*0Sstevel@tonic-gate * Discard the configuration and restore the configuration to the values 1301*0Sstevel@tonic-gate * specified in the configuration location. 1302*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1303*0Sstevel@tonic-gate */ 1304*0Sstevel@tonic-gate static int 1305*0Sstevel@tonic-gate pool_xml_rollback(pool_conf_t *conf) 1306*0Sstevel@tonic-gate { 1307*0Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov; 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate /* Rollback the file pointer ready for the reparse */ 1310*0Sstevel@tonic-gate if (fseek(prov->pxc_file, 0, SEEK_SET) != 0) { 1311*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1312*0Sstevel@tonic-gate return (PO_FAIL); 1313*0Sstevel@tonic-gate } 1314*0Sstevel@tonic-gate /* Reparse the document */ 1315*0Sstevel@tonic-gate /* In XML terms this means, discard and reparse the document */ 1316*0Sstevel@tonic-gate (void) pool_xml_free_doc(conf); 1317*0Sstevel@tonic-gate if (pool_xml_parse_document(conf) == PO_FAIL) 1318*0Sstevel@tonic-gate return (PO_FAIL); 1319*0Sstevel@tonic-gate return (PO_SUCCESS); 1320*0Sstevel@tonic-gate } 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate /* 1323*0Sstevel@tonic-gate * Allocate a new pool_elem_t in the supplied configuration of the specified 1324*0Sstevel@tonic-gate * class. 1325*0Sstevel@tonic-gate * Returns element pointer/NULL 1326*0Sstevel@tonic-gate */ 1327*0Sstevel@tonic-gate static void 1328*0Sstevel@tonic-gate pool_xml_elem_init(pool_conf_t *conf, pool_xml_elem_t *elem, 1329*0Sstevel@tonic-gate pool_elem_class_t class, pool_resource_elem_class_t res_class, 1330*0Sstevel@tonic-gate pool_component_elem_class_t comp_class) 1331*0Sstevel@tonic-gate { 1332*0Sstevel@tonic-gate pool_elem_t *pe = TO_ELEM(elem); 1333*0Sstevel@tonic-gate pe->pe_conf = conf; 1334*0Sstevel@tonic-gate pe->pe_class = class; 1335*0Sstevel@tonic-gate pe->pe_resource_class = res_class; 1336*0Sstevel@tonic-gate pe->pe_component_class = comp_class; 1337*0Sstevel@tonic-gate /* Set up the function pointers for element manipulation */ 1338*0Sstevel@tonic-gate pe->pe_get_prop = pool_xml_get_property; 1339*0Sstevel@tonic-gate pe->pe_put_prop = pool_xml_put_property; 1340*0Sstevel@tonic-gate pe->pe_rm_prop = pool_xml_rm_property; 1341*0Sstevel@tonic-gate pe->pe_get_props = pool_xml_get_properties; 1342*0Sstevel@tonic-gate pe->pe_remove = pool_xml_elem_remove; 1343*0Sstevel@tonic-gate pe->pe_get_container = pool_xml_get_container; 1344*0Sstevel@tonic-gate pe->pe_set_container = pool_xml_set_container; 1345*0Sstevel@tonic-gate /* 1346*0Sstevel@tonic-gate * Specific initialisation for different types of element 1347*0Sstevel@tonic-gate */ 1348*0Sstevel@tonic-gate if (class == PEC_POOL) { 1349*0Sstevel@tonic-gate pool_xml_pool_t *pp = (pool_xml_pool_t *)elem; 1350*0Sstevel@tonic-gate pp->pp_associate = pool_xml_pool_associate; 1351*0Sstevel@tonic-gate pp->pp_dissociate = pool_xml_pool_dissociate; 1352*0Sstevel@tonic-gate } 1353*0Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG) { 1354*0Sstevel@tonic-gate pool_xml_resource_t *pr = (pool_xml_resource_t *)elem; 1355*0Sstevel@tonic-gate pr->pr_is_system = pool_xml_resource_is_system; 1356*0Sstevel@tonic-gate pr->pr_can_associate = pool_xml_resource_can_associate; 1357*0Sstevel@tonic-gate } 1358*0Sstevel@tonic-gate } 1359*0Sstevel@tonic-gate 1360*0Sstevel@tonic-gate /* 1361*0Sstevel@tonic-gate * "Wrap" a suplied XML node with a pool_elem_t sub-type of the supplied 1362*0Sstevel@tonic-gate * class. 1363*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1364*0Sstevel@tonic-gate */ 1365*0Sstevel@tonic-gate static int 1366*0Sstevel@tonic-gate pool_xml_elem_wrap(xmlNodePtr node, pool_elem_class_t class, 1367*0Sstevel@tonic-gate pool_resource_elem_class_t res_class, 1368*0Sstevel@tonic-gate pool_component_elem_class_t comp_class) 1369*0Sstevel@tonic-gate { 1370*0Sstevel@tonic-gate pool_conf_t *conf = node->doc->_private; 1371*0Sstevel@tonic-gate pool_xml_elem_t *elem; 1372*0Sstevel@tonic-gate /* Need to do some messing about to support SubTypes */ 1373*0Sstevel@tonic-gate switch (class) { 1374*0Sstevel@tonic-gate case PEC_SYSTEM: 1375*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_system_t))) == NULL) { 1376*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1377*0Sstevel@tonic-gate return (PO_FAIL); 1378*0Sstevel@tonic-gate } 1379*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_system_t)); 1380*0Sstevel@tonic-gate break; 1381*0Sstevel@tonic-gate case PEC_POOL: 1382*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_pool_t))) == NULL) { 1383*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1384*0Sstevel@tonic-gate return (PO_FAIL); 1385*0Sstevel@tonic-gate } 1386*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_pool_t)); 1387*0Sstevel@tonic-gate break; 1388*0Sstevel@tonic-gate case PEC_RES_COMP: 1389*0Sstevel@tonic-gate case PEC_RES_AGG: 1390*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_resource_t))) == NULL) { 1391*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1392*0Sstevel@tonic-gate return (PO_FAIL); 1393*0Sstevel@tonic-gate } 1394*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_resource_t)); 1395*0Sstevel@tonic-gate break; 1396*0Sstevel@tonic-gate case PEC_COMP: 1397*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_component_t))) == NULL) { 1398*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1399*0Sstevel@tonic-gate return (PO_FAIL); 1400*0Sstevel@tonic-gate } 1401*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_component_t)); 1402*0Sstevel@tonic-gate break; 1403*0Sstevel@tonic-gate } 1404*0Sstevel@tonic-gate pool_xml_elem_init(conf, elem, class, res_class, comp_class); 1405*0Sstevel@tonic-gate node->_private = elem; 1406*0Sstevel@tonic-gate elem->pxe_node = node; 1407*0Sstevel@tonic-gate return (PO_SUCCESS); 1408*0Sstevel@tonic-gate } 1409*0Sstevel@tonic-gate 1410*0Sstevel@tonic-gate /* 1411*0Sstevel@tonic-gate * Associate a pool to the default resource for the supplied resource 1412*0Sstevel@tonic-gate * type. 1413*0Sstevel@tonic-gate */ 1414*0Sstevel@tonic-gate int 1415*0Sstevel@tonic-gate pool_assoc_default_resource_type(pool_t *pool, pool_resource_elem_class_t type) 1416*0Sstevel@tonic-gate { 1417*0Sstevel@tonic-gate pool_value_t *props[] = { NULL, NULL, NULL }; 1418*0Sstevel@tonic-gate uint_t rl_size; 1419*0Sstevel@tonic-gate pool_resource_t **rsl; 1420*0Sstevel@tonic-gate pool_conf_t *conf = TO_ELEM(pool)->pe_conf; 1421*0Sstevel@tonic-gate char_buf_t *cb = NULL; 1422*0Sstevel@tonic-gate pool_value_t val0 = POOL_VALUE_INITIALIZER; 1423*0Sstevel@tonic-gate pool_value_t val1 = POOL_VALUE_INITIALIZER; 1424*0Sstevel@tonic-gate 1425*0Sstevel@tonic-gate props[0] = &val0; 1426*0Sstevel@tonic-gate props[1] = &val1; 1427*0Sstevel@tonic-gate 1428*0Sstevel@tonic-gate 1429*0Sstevel@tonic-gate if (pool_value_set_string(props[0], pool_resource_type_string(type)) != 1430*0Sstevel@tonic-gate PO_SUCCESS || 1431*0Sstevel@tonic-gate pool_value_set_name(props[0], c_type) != PO_SUCCESS) { 1432*0Sstevel@tonic-gate return (PO_FAIL); 1433*0Sstevel@tonic-gate } 1434*0Sstevel@tonic-gate 1435*0Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 1436*0Sstevel@tonic-gate return (PO_FAIL); 1437*0Sstevel@tonic-gate } 1438*0Sstevel@tonic-gate 1439*0Sstevel@tonic-gate if (set_char_buf(cb, "%s.default", 1440*0Sstevel@tonic-gate pool_resource_type_string(type)) != 1441*0Sstevel@tonic-gate PO_SUCCESS) { 1442*0Sstevel@tonic-gate free_char_buf(cb); 1443*0Sstevel@tonic-gate return (PO_FAIL); 1444*0Sstevel@tonic-gate } 1445*0Sstevel@tonic-gate if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) { 1446*0Sstevel@tonic-gate free_char_buf(cb); 1447*0Sstevel@tonic-gate return (PO_FAIL); 1448*0Sstevel@tonic-gate } 1449*0Sstevel@tonic-gate pool_value_set_bool(props[1], PO_TRUE); 1450*0Sstevel@tonic-gate free_char_buf(cb); 1451*0Sstevel@tonic-gate 1452*0Sstevel@tonic-gate if ((rsl = pool_query_resources(conf, &rl_size, props)) == NULL) { 1453*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1454*0Sstevel@tonic-gate return (PO_FAIL); 1455*0Sstevel@tonic-gate } 1456*0Sstevel@tonic-gate 1457*0Sstevel@tonic-gate /* 1458*0Sstevel@tonic-gate * One default resource set per type 1459*0Sstevel@tonic-gate */ 1460*0Sstevel@tonic-gate if (rl_size != 1) { 1461*0Sstevel@tonic-gate free(rsl); 1462*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1463*0Sstevel@tonic-gate return (PO_FAIL); 1464*0Sstevel@tonic-gate } 1465*0Sstevel@tonic-gate if (pool_associate(conf, pool, rsl[0]) < 0) { 1466*0Sstevel@tonic-gate free(rsl); 1467*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1468*0Sstevel@tonic-gate return (PO_FAIL); 1469*0Sstevel@tonic-gate } 1470*0Sstevel@tonic-gate free(rsl); 1471*0Sstevel@tonic-gate return (PO_SUCCESS); 1472*0Sstevel@tonic-gate } 1473*0Sstevel@tonic-gate 1474*0Sstevel@tonic-gate /* 1475*0Sstevel@tonic-gate * Create an XML node in the supplied configuration with a pool_elem_t 1476*0Sstevel@tonic-gate * sub-type of the supplied class. 1477*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 1478*0Sstevel@tonic-gate */ 1479*0Sstevel@tonic-gate static pool_elem_t * 1480*0Sstevel@tonic-gate pool_xml_elem_create(pool_conf_t *conf, pool_elem_class_t class, 1481*0Sstevel@tonic-gate pool_resource_elem_class_t res_class, 1482*0Sstevel@tonic-gate pool_component_elem_class_t comp_class) 1483*0Sstevel@tonic-gate { 1484*0Sstevel@tonic-gate /* In XML terms, create an element of the appropriate class */ 1485*0Sstevel@tonic-gate pool_xml_elem_t *elem; 1486*0Sstevel@tonic-gate pool_elem_t *parent; 1487*0Sstevel@tonic-gate pool_system_t *parent_system; 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gate if (class == PEC_INVALID) { 1490*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1491*0Sstevel@tonic-gate return (NULL); 1492*0Sstevel@tonic-gate } 1493*0Sstevel@tonic-gate 1494*0Sstevel@tonic-gate /* Now create the XML component and add to it's parent */ 1495*0Sstevel@tonic-gate /* 1496*0Sstevel@tonic-gate * If we know the class of an element, we know it's parent. 1497*0Sstevel@tonic-gate * PEC_POOL, the parent must be the system node 1498*0Sstevel@tonic-gate * PEC_RES, treat as pool. 1499*0Sstevel@tonic-gate * PEC_COMP, we don't know the parent, leave this up to the 1500*0Sstevel@tonic-gate * create_comp function. 1501*0Sstevel@tonic-gate */ 1502*0Sstevel@tonic-gate /* Since we know the subtype we can create and populate the sub-type */ 1503*0Sstevel@tonic-gate switch (class) { 1504*0Sstevel@tonic-gate case PEC_POOL: 1505*0Sstevel@tonic-gate if ((parent_system = pool_conf_system(conf)) == NULL) { 1506*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1507*0Sstevel@tonic-gate return (NULL); 1508*0Sstevel@tonic-gate } 1509*0Sstevel@tonic-gate if ((parent = pool_system_elem(parent_system)) == NULL) { 1510*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1511*0Sstevel@tonic-gate return (NULL); 1512*0Sstevel@tonic-gate } 1513*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_system_t))) == NULL) { 1514*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1515*0Sstevel@tonic-gate return (NULL); 1516*0Sstevel@tonic-gate } 1517*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_system_t)); 1518*0Sstevel@tonic-gate if ((elem->pxe_node = node_create_with_id( 1519*0Sstevel@tonic-gate ((pool_xml_elem_t *)parent)->pxe_node, 1520*0Sstevel@tonic-gate BAD_CAST element_class_tags[class])) == NULL) { 1521*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1522*0Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem); 1523*0Sstevel@tonic-gate return (NULL); 1524*0Sstevel@tonic-gate } 1525*0Sstevel@tonic-gate break; 1526*0Sstevel@tonic-gate case PEC_RES_COMP: 1527*0Sstevel@tonic-gate case PEC_RES_AGG: 1528*0Sstevel@tonic-gate if ((parent_system = pool_conf_system(conf)) == NULL) { 1529*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1530*0Sstevel@tonic-gate return (NULL); 1531*0Sstevel@tonic-gate } 1532*0Sstevel@tonic-gate if ((parent = pool_system_elem(parent_system)) == NULL) { 1533*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1534*0Sstevel@tonic-gate return (NULL); 1535*0Sstevel@tonic-gate } 1536*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_resource_t))) == NULL) { 1537*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1538*0Sstevel@tonic-gate return (NULL); 1539*0Sstevel@tonic-gate } 1540*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_resource_t)); 1541*0Sstevel@tonic-gate if ((elem->pxe_node = node_create_with_id 1542*0Sstevel@tonic-gate (((pool_xml_elem_t *)parent)->pxe_node, 1543*0Sstevel@tonic-gate BAD_CAST element_class_tags[class])) == NULL) { 1544*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1545*0Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem); 1546*0Sstevel@tonic-gate return (NULL); 1547*0Sstevel@tonic-gate } 1548*0Sstevel@tonic-gate break; 1549*0Sstevel@tonic-gate case PEC_COMP: 1550*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_xml_component_t))) == NULL) { 1551*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1552*0Sstevel@tonic-gate return (NULL); 1553*0Sstevel@tonic-gate } 1554*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_xml_component_t)); 1555*0Sstevel@tonic-gate if ((elem->pxe_node = node_create(NULL, 1556*0Sstevel@tonic-gate BAD_CAST element_class_tags[class])) == NULL) { 1557*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1558*0Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem); 1559*0Sstevel@tonic-gate return (NULL); 1560*0Sstevel@tonic-gate } 1561*0Sstevel@tonic-gate break; 1562*0Sstevel@tonic-gate default: 1563*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1564*0Sstevel@tonic-gate return (NULL); 1565*0Sstevel@tonic-gate } 1566*0Sstevel@tonic-gate pool_xml_elem_init(conf, elem, class, res_class, comp_class); 1567*0Sstevel@tonic-gate elem->pxe_node->_private = elem; 1568*0Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG || 1569*0Sstevel@tonic-gate class == PEC_COMP) { 1570*0Sstevel@tonic-gate /* 1571*0Sstevel@tonic-gate * Put the type and an invalid sys_id on the node. 1572*0Sstevel@tonic-gate */ 1573*0Sstevel@tonic-gate if (xmlSetProp(elem->pxe_node, BAD_CAST c_sys_prop, 1574*0Sstevel@tonic-gate BAD_CAST POOL_SYSID_BAD_STRING) == NULL) { 1575*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1576*0Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem); 1577*0Sstevel@tonic-gate return (NULL); 1578*0Sstevel@tonic-gate } 1579*0Sstevel@tonic-gate if (xmlSetProp(elem->pxe_node, BAD_CAST c_type, 1580*0Sstevel@tonic-gate BAD_CAST pool_elem_class_string( 1581*0Sstevel@tonic-gate (pool_elem_t *)elem)) == NULL) { 1582*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1583*0Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem); 1584*0Sstevel@tonic-gate return (NULL); 1585*0Sstevel@tonic-gate } 1586*0Sstevel@tonic-gate } 1587*0Sstevel@tonic-gate if (class == PEC_POOL) { 1588*0Sstevel@tonic-gate /* 1589*0Sstevel@tonic-gate * Note: This is resource specific. 1590*0Sstevel@tonic-gate */ 1591*0Sstevel@tonic-gate if (pool_assoc_default_resource_type(pool_elem_pool( 1592*0Sstevel@tonic-gate (pool_elem_t *)elem), PREC_PSET) == PO_FAIL) { 1593*0Sstevel@tonic-gate (void) pool_xml_elem_remove((pool_elem_t *)elem); 1594*0Sstevel@tonic-gate return (NULL); 1595*0Sstevel@tonic-gate } 1596*0Sstevel@tonic-gate } 1597*0Sstevel@tonic-gate return ((pool_elem_t *)elem); 1598*0Sstevel@tonic-gate } 1599*0Sstevel@tonic-gate 1600*0Sstevel@tonic-gate /* 1601*0Sstevel@tonic-gate * Allocate a data provider for the supplied configuration and optionally 1602*0Sstevel@tonic-gate * discover resources. 1603*0Sstevel@tonic-gate * The data provider is the cross over point from the "abstract" configuration 1604*0Sstevel@tonic-gate * functions into the data representation specific manipulation routines. 1605*0Sstevel@tonic-gate * This function sets up all the required pointers to create an XML aware 1606*0Sstevel@tonic-gate * data provider. 1607*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1608*0Sstevel@tonic-gate */ 1609*0Sstevel@tonic-gate int 1610*0Sstevel@tonic-gate pool_xml_connection_alloc(pool_conf_t *conf, int oflags) 1611*0Sstevel@tonic-gate { 1612*0Sstevel@tonic-gate pool_xml_connection_t *prov; 1613*0Sstevel@tonic-gate 1614*0Sstevel@tonic-gate xml_init(); 1615*0Sstevel@tonic-gate if ((prov = malloc(sizeof (pool_xml_connection_t))) == NULL) { 1616*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1617*0Sstevel@tonic-gate return (PO_FAIL); 1618*0Sstevel@tonic-gate } 1619*0Sstevel@tonic-gate (void) memset(prov, 0, sizeof (pool_xml_connection_t)); 1620*0Sstevel@tonic-gate /* 1621*0Sstevel@tonic-gate * Initialise data members 1622*0Sstevel@tonic-gate */ 1623*0Sstevel@tonic-gate prov->pc_name = strdup("LIBXML 2.4.0"); 1624*0Sstevel@tonic-gate prov->pc_store_type = XML_DATA_STORE; 1625*0Sstevel@tonic-gate prov->pc_oflags = oflags; 1626*0Sstevel@tonic-gate /* 1627*0Sstevel@tonic-gate * Initialise function pointers 1628*0Sstevel@tonic-gate */ 1629*0Sstevel@tonic-gate prov->pc_close = pool_xml_close; 1630*0Sstevel@tonic-gate prov->pc_validate = pool_xml_validate; 1631*0Sstevel@tonic-gate prov->pc_commit = pool_xml_commit; 1632*0Sstevel@tonic-gate prov->pc_export = pool_xml_export; 1633*0Sstevel@tonic-gate prov->pc_rollback = pool_xml_rollback; 1634*0Sstevel@tonic-gate prov->pc_exec_query = pool_xml_exec_query; 1635*0Sstevel@tonic-gate prov->pc_elem_create = pool_xml_elem_create; 1636*0Sstevel@tonic-gate prov->pc_remove = pool_xml_remove; 1637*0Sstevel@tonic-gate prov->pc_res_xfer = pool_xml_res_transfer; 1638*0Sstevel@tonic-gate prov->pc_res_xxfer = pool_xml_res_xtransfer; 1639*0Sstevel@tonic-gate /* 1640*0Sstevel@tonic-gate * End of common initialisation 1641*0Sstevel@tonic-gate */ 1642*0Sstevel@tonic-gate /* 1643*0Sstevel@tonic-gate * Associate the provider to it's configuration 1644*0Sstevel@tonic-gate */ 1645*0Sstevel@tonic-gate conf->pc_prov = (pool_connection_t *)prov; 1646*0Sstevel@tonic-gate /* 1647*0Sstevel@tonic-gate * At this point the configuration provider has been initialized, 1648*0Sstevel@tonic-gate * mark the configuration as valid so that the various routines 1649*0Sstevel@tonic-gate * which rely on a valid configuration will work correctly. 1650*0Sstevel@tonic-gate */ 1651*0Sstevel@tonic-gate conf->pc_state = POF_VALID; 1652*0Sstevel@tonic-gate 1653*0Sstevel@tonic-gate if ((oflags & PO_CREAT) != 0) { 1654*0Sstevel@tonic-gate pool_conf_t *dyn; 1655*0Sstevel@tonic-gate 1656*0Sstevel@tonic-gate if ((dyn = pool_conf_alloc()) == NULL) 1657*0Sstevel@tonic-gate return (PO_FAIL); 1658*0Sstevel@tonic-gate 1659*0Sstevel@tonic-gate if (pool_conf_open(dyn, pool_dynamic_location(), 1660*0Sstevel@tonic-gate PO_RDONLY) != PO_SUCCESS) { 1661*0Sstevel@tonic-gate pool_conf_free(dyn); 1662*0Sstevel@tonic-gate return (PO_FAIL); 1663*0Sstevel@tonic-gate } 1664*0Sstevel@tonic-gate 1665*0Sstevel@tonic-gate if (pool_conf_export(dyn, conf->pc_location, 1666*0Sstevel@tonic-gate POX_NATIVE) != PO_SUCCESS) { 1667*0Sstevel@tonic-gate (void) pool_conf_close(dyn); 1668*0Sstevel@tonic-gate pool_conf_free(dyn); 1669*0Sstevel@tonic-gate return (PO_FAIL); 1670*0Sstevel@tonic-gate } 1671*0Sstevel@tonic-gate (void) pool_conf_close(dyn); 1672*0Sstevel@tonic-gate pool_conf_free(dyn); 1673*0Sstevel@tonic-gate } 1674*0Sstevel@tonic-gate 1675*0Sstevel@tonic-gate if (pool_xml_open_file(conf) == PO_FAIL) { 1676*0Sstevel@tonic-gate (void) pool_xml_close(conf); 1677*0Sstevel@tonic-gate return (PO_FAIL); 1678*0Sstevel@tonic-gate } 1679*0Sstevel@tonic-gate 1680*0Sstevel@tonic-gate return (PO_SUCCESS); 1681*0Sstevel@tonic-gate } 1682*0Sstevel@tonic-gate 1683*0Sstevel@tonic-gate /* 1684*0Sstevel@tonic-gate * Free the resources for an XML data provider. 1685*0Sstevel@tonic-gate */ 1686*0Sstevel@tonic-gate static void 1687*0Sstevel@tonic-gate pool_xml_connection_free(pool_xml_connection_t *prov) 1688*0Sstevel@tonic-gate { 1689*0Sstevel@tonic-gate free((void *)prov->pc_name); 1690*0Sstevel@tonic-gate free(prov); 1691*0Sstevel@tonic-gate } 1692*0Sstevel@tonic-gate 1693*0Sstevel@tonic-gate /* 1694*0Sstevel@tonic-gate * Allocate a result set. The Result Set stores the result of an XPath 1695*0Sstevel@tonic-gate * query along with the parameters used to create the result set (for 1696*0Sstevel@tonic-gate * debugging purposes). 1697*0Sstevel@tonic-gate * Returns pool_xml_result_set_t pointer/NULL 1698*0Sstevel@tonic-gate */ 1699*0Sstevel@tonic-gate static pool_xml_result_set_t * 1700*0Sstevel@tonic-gate pool_xml_result_set_alloc(const pool_conf_t *conf) 1701*0Sstevel@tonic-gate { 1702*0Sstevel@tonic-gate pool_xml_result_set_t *rs; 1703*0Sstevel@tonic-gate 1704*0Sstevel@tonic-gate if ((rs = malloc(sizeof (pool_xml_result_set_t))) == NULL) { 1705*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1706*0Sstevel@tonic-gate return (NULL); 1707*0Sstevel@tonic-gate } 1708*0Sstevel@tonic-gate (void) memset(rs, 0, sizeof (pool_xml_result_set_t)); 1709*0Sstevel@tonic-gate rs->prs_conf = conf; 1710*0Sstevel@tonic-gate rs->prs_index = -1; 1711*0Sstevel@tonic-gate rs->prs_active = PO_TRUE; 1712*0Sstevel@tonic-gate /* Fix up the result set accessor functions to the xml specfic ones */ 1713*0Sstevel@tonic-gate rs->prs_next = pool_xml_rs_next; 1714*0Sstevel@tonic-gate rs->prs_prev = pool_xml_rs_prev; 1715*0Sstevel@tonic-gate rs->prs_first = pool_xml_rs_first; 1716*0Sstevel@tonic-gate rs->prs_last = pool_xml_rs_last; 1717*0Sstevel@tonic-gate rs->prs_get_index = pool_xml_rs_get_index; 1718*0Sstevel@tonic-gate rs->prs_set_index = pool_xml_rs_set_index; 1719*0Sstevel@tonic-gate rs->prs_close = pool_xml_rs_close; 1720*0Sstevel@tonic-gate rs->prs_count = pool_xml_rs_count; 1721*0Sstevel@tonic-gate return (rs); 1722*0Sstevel@tonic-gate } 1723*0Sstevel@tonic-gate 1724*0Sstevel@tonic-gate /* 1725*0Sstevel@tonic-gate * Free a result set. Ensure that the resources are all released at this point. 1726*0Sstevel@tonic-gate */ 1727*0Sstevel@tonic-gate static void 1728*0Sstevel@tonic-gate pool_xml_result_set_free(pool_xml_result_set_t *rs) 1729*0Sstevel@tonic-gate { 1730*0Sstevel@tonic-gate if (rs->pxr_path != NULL) 1731*0Sstevel@tonic-gate xmlXPathFreeObject(rs->pxr_path); 1732*0Sstevel@tonic-gate if (rs->pxr_ctx != NULL) 1733*0Sstevel@tonic-gate xmlXPathFreeContext(rs->pxr_ctx); 1734*0Sstevel@tonic-gate free(rs); 1735*0Sstevel@tonic-gate } 1736*0Sstevel@tonic-gate 1737*0Sstevel@tonic-gate /* 1738*0Sstevel@tonic-gate * Transfer size from one resource to another. 1739*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1740*0Sstevel@tonic-gate */ 1741*0Sstevel@tonic-gate /* ARGSUSED */ 1742*0Sstevel@tonic-gate int 1743*0Sstevel@tonic-gate pool_xml_res_transfer(pool_resource_t *src, pool_resource_t *tgt, uint64_t size) 1744*0Sstevel@tonic-gate { 1745*0Sstevel@tonic-gate return (PO_SUCCESS); 1746*0Sstevel@tonic-gate } 1747*0Sstevel@tonic-gate 1748*0Sstevel@tonic-gate /* 1749*0Sstevel@tonic-gate * Transfer components rl from one resource to another. 1750*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1751*0Sstevel@tonic-gate */ 1752*0Sstevel@tonic-gate /* ARGSUSED */ 1753*0Sstevel@tonic-gate int 1754*0Sstevel@tonic-gate pool_xml_res_xtransfer(pool_resource_t *src, pool_resource_t *tgt, 1755*0Sstevel@tonic-gate pool_component_t **rl) { 1756*0Sstevel@tonic-gate int i; 1757*0Sstevel@tonic-gate 1758*0Sstevel@tonic-gate /* 1759*0Sstevel@tonic-gate * Walk the Result Set and move the resource components 1760*0Sstevel@tonic-gate */ 1761*0Sstevel@tonic-gate for (i = 0; rl[i] != NULL; i++) { 1762*0Sstevel@tonic-gate if (pool_set_container(TO_ELEM(tgt), TO_ELEM(rl[i])) == 1763*0Sstevel@tonic-gate PO_FAIL) { 1764*0Sstevel@tonic-gate return (PO_FAIL); 1765*0Sstevel@tonic-gate } 1766*0Sstevel@tonic-gate } 1767*0Sstevel@tonic-gate return (PO_SUCCESS); 1768*0Sstevel@tonic-gate } 1769*0Sstevel@tonic-gate 1770*0Sstevel@tonic-gate /* 1771*0Sstevel@tonic-gate * Return the next element in a result set. 1772*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 1773*0Sstevel@tonic-gate */ 1774*0Sstevel@tonic-gate static pool_elem_t * 1775*0Sstevel@tonic-gate pool_xml_rs_next(pool_result_set_t *set) 1776*0Sstevel@tonic-gate { 1777*0Sstevel@tonic-gate pool_elem_t *next; 1778*0Sstevel@tonic-gate /* Since I know this is an XML result set */ 1779*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1780*0Sstevel@tonic-gate 1781*0Sstevel@tonic-gate /* Update the context node */ 1782*0Sstevel@tonic-gate if (xset->prs_index == xset->pxr_path->nodesetval->nodeNr - 1) 1783*0Sstevel@tonic-gate return (NULL); 1784*0Sstevel@tonic-gate next = 1785*0Sstevel@tonic-gate xset->pxr_path->nodesetval->nodeTab[++xset->prs_index]->_private; 1786*0Sstevel@tonic-gate return (next); 1787*0Sstevel@tonic-gate } 1788*0Sstevel@tonic-gate 1789*0Sstevel@tonic-gate /* 1790*0Sstevel@tonic-gate * Return the previous element in a result set. 1791*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 1792*0Sstevel@tonic-gate */ 1793*0Sstevel@tonic-gate static pool_elem_t * 1794*0Sstevel@tonic-gate pool_xml_rs_prev(pool_result_set_t *set) 1795*0Sstevel@tonic-gate { 1796*0Sstevel@tonic-gate pool_elem_t *prev; 1797*0Sstevel@tonic-gate /* Since I know this is an XML result set */ 1798*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1799*0Sstevel@tonic-gate 1800*0Sstevel@tonic-gate /* Update the context node */ 1801*0Sstevel@tonic-gate if (xset->prs_index < 0) 1802*0Sstevel@tonic-gate return (NULL); 1803*0Sstevel@tonic-gate prev = 1804*0Sstevel@tonic-gate xset->pxr_path->nodesetval->nodeTab[xset->prs_index--]->_private; 1805*0Sstevel@tonic-gate return (prev); 1806*0Sstevel@tonic-gate } 1807*0Sstevel@tonic-gate 1808*0Sstevel@tonic-gate /* 1809*0Sstevel@tonic-gate * Sets the current index in a result set. 1810*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1811*0Sstevel@tonic-gate */ 1812*0Sstevel@tonic-gate static int 1813*0Sstevel@tonic-gate pool_xml_rs_set_index(pool_result_set_t *set, int index) 1814*0Sstevel@tonic-gate { 1815*0Sstevel@tonic-gate /* Since I know this is an XML result set */ 1816*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1817*0Sstevel@tonic-gate 1818*0Sstevel@tonic-gate if (index < 0 || index >= xset->pxr_path->nodesetval->nodeNr) { 1819*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1820*0Sstevel@tonic-gate return (PO_FAIL); 1821*0Sstevel@tonic-gate } 1822*0Sstevel@tonic-gate xset->prs_index = index; 1823*0Sstevel@tonic-gate return (PO_SUCCESS); 1824*0Sstevel@tonic-gate } 1825*0Sstevel@tonic-gate 1826*0Sstevel@tonic-gate /* 1827*0Sstevel@tonic-gate * Return the current index in a result set. 1828*0Sstevel@tonic-gate * Returns current index 1829*0Sstevel@tonic-gate */ 1830*0Sstevel@tonic-gate static int 1831*0Sstevel@tonic-gate pool_xml_rs_get_index(pool_result_set_t *set) 1832*0Sstevel@tonic-gate { 1833*0Sstevel@tonic-gate /* Since I know this is an XML result set */ 1834*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1835*0Sstevel@tonic-gate 1836*0Sstevel@tonic-gate return (xset->prs_index); 1837*0Sstevel@tonic-gate } 1838*0Sstevel@tonic-gate 1839*0Sstevel@tonic-gate /* 1840*0Sstevel@tonic-gate * Return the first element in a result set. 1841*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 1842*0Sstevel@tonic-gate */ 1843*0Sstevel@tonic-gate static pool_elem_t * 1844*0Sstevel@tonic-gate pool_xml_rs_first(pool_result_set_t *set) 1845*0Sstevel@tonic-gate { 1846*0Sstevel@tonic-gate /* Since I know this is an XML result set */ 1847*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1848*0Sstevel@tonic-gate 1849*0Sstevel@tonic-gate /* Update the context node */ 1850*0Sstevel@tonic-gate return (xset->pxr_path->nodesetval->nodeTab[0]->_private); 1851*0Sstevel@tonic-gate } 1852*0Sstevel@tonic-gate 1853*0Sstevel@tonic-gate /* 1854*0Sstevel@tonic-gate * Return the last element in a result set. 1855*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 1856*0Sstevel@tonic-gate */ 1857*0Sstevel@tonic-gate static pool_elem_t * 1858*0Sstevel@tonic-gate pool_xml_rs_last(pool_result_set_t *set) 1859*0Sstevel@tonic-gate { 1860*0Sstevel@tonic-gate /* Since I know this is an XML result set */ 1861*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1862*0Sstevel@tonic-gate 1863*0Sstevel@tonic-gate /* Update the context node */ 1864*0Sstevel@tonic-gate return (xset->pxr_path->nodesetval-> 1865*0Sstevel@tonic-gate nodeTab[xset->pxr_path->nodesetval->nodeNr-1]->_private); 1866*0Sstevel@tonic-gate } 1867*0Sstevel@tonic-gate 1868*0Sstevel@tonic-gate /* 1869*0Sstevel@tonic-gate * Return the number of results in a result set. 1870*0Sstevel@tonic-gate * Returns result count 1871*0Sstevel@tonic-gate */ 1872*0Sstevel@tonic-gate static int 1873*0Sstevel@tonic-gate pool_xml_rs_count(pool_result_set_t *set) 1874*0Sstevel@tonic-gate { 1875*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1876*0Sstevel@tonic-gate 1877*0Sstevel@tonic-gate return (xset->pxr_path->nodesetval->nodeNr); 1878*0Sstevel@tonic-gate } 1879*0Sstevel@tonic-gate 1880*0Sstevel@tonic-gate 1881*0Sstevel@tonic-gate /* 1882*0Sstevel@tonic-gate * Close a result set. Remove this result set from the list of results and 1883*0Sstevel@tonic-gate * free the resources 1884*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1885*0Sstevel@tonic-gate */ 1886*0Sstevel@tonic-gate static int 1887*0Sstevel@tonic-gate pool_xml_rs_close(pool_result_set_t *set) 1888*0Sstevel@tonic-gate { 1889*0Sstevel@tonic-gate pool_xml_result_set_t *xset = (pool_xml_result_set_t *)set; 1890*0Sstevel@tonic-gate 1891*0Sstevel@tonic-gate pool_xml_result_set_free(xset); 1892*0Sstevel@tonic-gate return (PO_SUCCESS); 1893*0Sstevel@tonic-gate } 1894*0Sstevel@tonic-gate 1895*0Sstevel@tonic-gate /* 1896*0Sstevel@tonic-gate * Set the container for a node. 1897*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 1898*0Sstevel@tonic-gate */ 1899*0Sstevel@tonic-gate static int 1900*0Sstevel@tonic-gate pool_xml_set_container(pool_elem_t *pp, pool_elem_t *pc) 1901*0Sstevel@tonic-gate { 1902*0Sstevel@tonic-gate pool_xml_elem_t *pxp; 1903*0Sstevel@tonic-gate pool_xml_elem_t *pxc; 1904*0Sstevel@tonic-gate xmlNodePtr parent; 1905*0Sstevel@tonic-gate 1906*0Sstevel@tonic-gate pxp = (pool_xml_elem_t *)pp; 1907*0Sstevel@tonic-gate pxc = (pool_xml_elem_t *)pc; 1908*0Sstevel@tonic-gate parent = pxc->pxe_node->parent; 1909*0Sstevel@tonic-gate 1910*0Sstevel@tonic-gate xmlUnlinkNode(pxc->pxe_node); 1911*0Sstevel@tonic-gate if (xmlAddChild(pxp->pxe_node, pxc->pxe_node) == NULL) { 1912*0Sstevel@tonic-gate xmlAddChild(parent, pxc->pxe_node); /* Try to move back */ 1913*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1914*0Sstevel@tonic-gate return (PO_FAIL); 1915*0Sstevel@tonic-gate } 1916*0Sstevel@tonic-gate pc->pe_conf = pp->pe_conf; 1917*0Sstevel@tonic-gate return (PO_SUCCESS); 1918*0Sstevel@tonic-gate } 1919*0Sstevel@tonic-gate /* 1920*0Sstevel@tonic-gate * Get the container for a node. 1921*0Sstevel@tonic-gate * Returns Container/NULL 1922*0Sstevel@tonic-gate */ 1923*0Sstevel@tonic-gate static pool_elem_t * 1924*0Sstevel@tonic-gate pool_xml_get_container(const pool_elem_t *pc) 1925*0Sstevel@tonic-gate { 1926*0Sstevel@tonic-gate pool_xml_elem_t *pxc = (pool_xml_elem_t *)pc; 1927*0Sstevel@tonic-gate 1928*0Sstevel@tonic-gate return ((pool_elem_t *)pxc->pxe_node->parent->_private); 1929*0Sstevel@tonic-gate } 1930*0Sstevel@tonic-gate 1931*0Sstevel@tonic-gate /* 1932*0Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other 1933*0Sstevel@tonic-gate * resource types. 1934*0Sstevel@tonic-gate */ 1935*0Sstevel@tonic-gate int 1936*0Sstevel@tonic-gate pool_xml_resource_is_system(const pool_resource_t *pr) 1937*0Sstevel@tonic-gate { 1938*0Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) { 1939*0Sstevel@tonic-gate case PREC_PSET: 1940*0Sstevel@tonic-gate return (PSID_IS_SYSSET( 1941*0Sstevel@tonic-gate elem_get_sysid(TO_ELEM(pr)))); 1942*0Sstevel@tonic-gate default: 1943*0Sstevel@tonic-gate return (PO_FALSE); 1944*0Sstevel@tonic-gate } 1945*0Sstevel@tonic-gate } 1946*0Sstevel@tonic-gate 1947*0Sstevel@tonic-gate /* 1948*0Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other 1949*0Sstevel@tonic-gate * resource types. 1950*0Sstevel@tonic-gate */ 1951*0Sstevel@tonic-gate int 1952*0Sstevel@tonic-gate pool_xml_resource_can_associate(const pool_resource_t *pr) 1953*0Sstevel@tonic-gate { 1954*0Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) { 1955*0Sstevel@tonic-gate case PREC_PSET: 1956*0Sstevel@tonic-gate return (PO_TRUE); 1957*0Sstevel@tonic-gate default: 1958*0Sstevel@tonic-gate return (PO_FALSE); 1959*0Sstevel@tonic-gate } 1960*0Sstevel@tonic-gate } 1961*0Sstevel@tonic-gate 1962*0Sstevel@tonic-gate /* 1963*0Sstevel@tonic-gate * Note: This function is resource specific. It must be extended to support 1964*0Sstevel@tonic-gate * multiple resource types. 1965*0Sstevel@tonic-gate */ 1966*0Sstevel@tonic-gate int 1967*0Sstevel@tonic-gate pool_xml_pool_associate(pool_t *pool, const pool_resource_t *pr) 1968*0Sstevel@tonic-gate { 1969*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 1970*0Sstevel@tonic-gate 1971*0Sstevel@tonic-gate if (pool_xml_get_property(TO_ELEM(pr), 1972*0Sstevel@tonic-gate "pset.ref_id", &val) != POC_STRING) 1973*0Sstevel@tonic-gate return (PO_FAIL); 1974*0Sstevel@tonic-gate if (pool_xml_put_property(TO_ELEM(pool), "pool.res", &val) != 1975*0Sstevel@tonic-gate PO_SUCCESS) 1976*0Sstevel@tonic-gate return (PO_FAIL); 1977*0Sstevel@tonic-gate return (PO_SUCCESS); 1978*0Sstevel@tonic-gate } 1979*0Sstevel@tonic-gate 1980*0Sstevel@tonic-gate /* 1981*0Sstevel@tonic-gate * pool_xml_pool_dissociate() simply finds the default resource for 1982*0Sstevel@tonic-gate * the type of resource being dissociated and then calls 1983*0Sstevel@tonic-gate * pool_xml_pool_associate() to associate to the default resource. 1984*0Sstevel@tonic-gate */ 1985*0Sstevel@tonic-gate int 1986*0Sstevel@tonic-gate pool_xml_pool_dissociate(pool_t *pool, const pool_resource_t *pr) 1987*0Sstevel@tonic-gate { 1988*0Sstevel@tonic-gate const pool_resource_t *default_res; 1989*0Sstevel@tonic-gate 1990*0Sstevel@tonic-gate if ((default_res = get_default_resource(pr)) == NULL) 1991*0Sstevel@tonic-gate return (PO_FAIL); 1992*0Sstevel@tonic-gate if (default_res == pr) 1993*0Sstevel@tonic-gate return (PO_SUCCESS); 1994*0Sstevel@tonic-gate return (pool_xml_pool_associate(pool, default_res)); 1995*0Sstevel@tonic-gate } 1996*0Sstevel@tonic-gate 1997*0Sstevel@tonic-gate /* 1998*0Sstevel@tonic-gate * pool_xml_open_file() opens a file for a configuration. This establishes 1999*0Sstevel@tonic-gate * the locks required to ensure data integrity when manipulating a 2000*0Sstevel@tonic-gate * configuration. 2001*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 2002*0Sstevel@tonic-gate */ 2003*0Sstevel@tonic-gate static int 2004*0Sstevel@tonic-gate pool_xml_open_file(pool_conf_t *conf) 2005*0Sstevel@tonic-gate { 2006*0Sstevel@tonic-gate struct flock lock; 2007*0Sstevel@tonic-gate struct stat s; 2008*0Sstevel@tonic-gate 2009*0Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov; 2010*0Sstevel@tonic-gate 2011*0Sstevel@tonic-gate /* 2012*0Sstevel@tonic-gate * Always close the pxc_file in case there was a previously failed open 2013*0Sstevel@tonic-gate */ 2014*0Sstevel@tonic-gate if (prov->pxc_file != NULL) { 2015*0Sstevel@tonic-gate (void) fclose(prov->pxc_file); 2016*0Sstevel@tonic-gate prov->pxc_file = NULL; 2017*0Sstevel@tonic-gate } 2018*0Sstevel@tonic-gate 2019*0Sstevel@tonic-gate /* 2020*0Sstevel@tonic-gate * Check that the DTD required for this operation is present. 2021*0Sstevel@tonic-gate * If it isn't fail 2022*0Sstevel@tonic-gate */ 2023*0Sstevel@tonic-gate if (dtd_exists(dtd_location) == PO_FALSE) { 2024*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 2025*0Sstevel@tonic-gate return (PO_FAIL); 2026*0Sstevel@tonic-gate } 2027*0Sstevel@tonic-gate 2028*0Sstevel@tonic-gate if ((prov->pc_oflags & PO_RDWR) != 0) 2029*0Sstevel@tonic-gate prov->pxc_file = fopen(conf->pc_location, "r+"); 2030*0Sstevel@tonic-gate else /* Assume opening PO_RDONLY */ 2031*0Sstevel@tonic-gate prov->pxc_file = fopen(conf->pc_location, "r"); 2032*0Sstevel@tonic-gate 2033*0Sstevel@tonic-gate if (prov->pxc_file == NULL) { 2034*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2035*0Sstevel@tonic-gate return (PO_FAIL); 2036*0Sstevel@tonic-gate } 2037*0Sstevel@tonic-gate 2038*0Sstevel@tonic-gate /* 2039*0Sstevel@tonic-gate * Setup the lock for the file 2040*0Sstevel@tonic-gate */ 2041*0Sstevel@tonic-gate lock.l_type = (prov->pc_oflags & PO_RDWR) ? F_WRLCK : F_RDLCK; 2042*0Sstevel@tonic-gate lock.l_whence = SEEK_SET; 2043*0Sstevel@tonic-gate lock.l_start = 0; 2044*0Sstevel@tonic-gate lock.l_len = 0; 2045*0Sstevel@tonic-gate if (fcntl(fileno(prov->pxc_file), F_SETLKW, &lock) == -1) { 2046*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2047*0Sstevel@tonic-gate return (PO_FAIL); 2048*0Sstevel@tonic-gate } 2049*0Sstevel@tonic-gate /* 2050*0Sstevel@tonic-gate * Check to see if the document was removed whilst waiting for 2051*0Sstevel@tonic-gate * the lock. If it was return an error. 2052*0Sstevel@tonic-gate */ 2053*0Sstevel@tonic-gate if (stat(conf->pc_location, &s) == -1) { 2054*0Sstevel@tonic-gate (void) fclose(prov->pxc_file); 2055*0Sstevel@tonic-gate prov->pxc_file = NULL; 2056*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2057*0Sstevel@tonic-gate return (PO_FAIL); 2058*0Sstevel@tonic-gate } 2059*0Sstevel@tonic-gate /* Parse the document */ 2060*0Sstevel@tonic-gate if (pool_xml_parse_document(conf) != PO_SUCCESS) 2061*0Sstevel@tonic-gate return (PO_FAIL); 2062*0Sstevel@tonic-gate return (PO_SUCCESS); 2063*0Sstevel@tonic-gate } 2064*0Sstevel@tonic-gate 2065*0Sstevel@tonic-gate /* 2066*0Sstevel@tonic-gate * Try to work out if an element contains an attribute of the supplied name. 2067*0Sstevel@tonic-gate * Search the internal subset first and then the external subset. 2068*0Sstevel@tonic-gate * Return PO_TRUE if there is an attribute of that name declared for that 2069*0Sstevel@tonic-gate * element. 2070*0Sstevel@tonic-gate */ 2071*0Sstevel@tonic-gate int 2072*0Sstevel@tonic-gate pool_is_xml_attr(xmlDocPtr doc, const char *elem, const char *attr) 2073*0Sstevel@tonic-gate { 2074*0Sstevel@tonic-gate xmlDtdPtr internal = xmlGetIntSubset(doc); 2075*0Sstevel@tonic-gate xmlDtdPtr external = doc->extSubset; 2076*0Sstevel@tonic-gate 2077*0Sstevel@tonic-gate if (xmlGetDtdAttrDesc(internal, BAD_CAST elem, BAD_CAST attr) == NULL) 2078*0Sstevel@tonic-gate if (xmlGetDtdAttrDesc(external, 2079*0Sstevel@tonic-gate BAD_CAST elem, BAD_CAST attr) == NULL) 2080*0Sstevel@tonic-gate return (PO_FALSE); 2081*0Sstevel@tonic-gate return (PO_TRUE); 2082*0Sstevel@tonic-gate } 2083*0Sstevel@tonic-gate 2084*0Sstevel@tonic-gate /* 2085*0Sstevel@tonic-gate * Execute the specified query using XPath. This complex function relies on 2086*0Sstevel@tonic-gate * a couple of helpers to build up an XPath query, pool_build_xpath_buf in 2087*0Sstevel@tonic-gate * particular. 2088*0Sstevel@tonic-gate * conf - the pool configuration being manipulated 2089*0Sstevel@tonic-gate * src - the root of the search, if NULL that means whole document 2090*0Sstevel@tonic-gate * src_attr - if supplied means an IDREF(S) search on this attribute 2091*0Sstevel@tonic-gate * classes - target classes 2092*0Sstevel@tonic-gate * props - target properties 2093*0Sstevel@tonic-gate * Returns pool_result_set_t pointer/NULL 2094*0Sstevel@tonic-gate */ 2095*0Sstevel@tonic-gate pool_result_set_t * 2096*0Sstevel@tonic-gate pool_xml_exec_query(const pool_conf_t *conf, const pool_elem_t *src, 2097*0Sstevel@tonic-gate const char *src_attr, pool_elem_class_t classes, pool_value_t **props) 2098*0Sstevel@tonic-gate { 2099*0Sstevel@tonic-gate char *buf = NULL; 2100*0Sstevel@tonic-gate char_buf_t *cb = NULL; 2101*0Sstevel@tonic-gate pool_xml_result_set_t *rs; 2102*0Sstevel@tonic-gate pool_xml_elem_t *pxe = (pool_xml_elem_t *)src; 2103*0Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov; 2104*0Sstevel@tonic-gate 2105*0Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) 2106*0Sstevel@tonic-gate return (NULL); 2107*0Sstevel@tonic-gate 2108*0Sstevel@tonic-gate /* 2109*0Sstevel@tonic-gate * Prior to building up the complex XPath query, check to see if 2110*0Sstevel@tonic-gate * src_attr is an IDREF(S). If it is use the IDREF(S) information 2111*0Sstevel@tonic-gate * to generate the query rather than the other data 2112*0Sstevel@tonic-gate */ 2113*0Sstevel@tonic-gate if (src_attr != NULL) { 2114*0Sstevel@tonic-gate char *tok; 2115*0Sstevel@tonic-gate char *lasts; 2116*0Sstevel@tonic-gate char *or = ""; 2117*0Sstevel@tonic-gate xmlChar *id; 2118*0Sstevel@tonic-gate 2119*0Sstevel@tonic-gate /* 2120*0Sstevel@tonic-gate * Check the arguments for consistency 2121*0Sstevel@tonic-gate */ 2122*0Sstevel@tonic-gate if (pool_is_xml_attr(prov->pxc_doc, 2123*0Sstevel@tonic-gate element_class_tags[src->pe_class], src_attr) != PO_TRUE) { 2124*0Sstevel@tonic-gate free_char_buf(cb); 2125*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 2126*0Sstevel@tonic-gate return (NULL); 2127*0Sstevel@tonic-gate } 2128*0Sstevel@tonic-gate 2129*0Sstevel@tonic-gate if ((id = xmlGetProp(pxe->pxe_node, BAD_CAST src_attr)) 2130*0Sstevel@tonic-gate == NULL) { 2131*0Sstevel@tonic-gate free_char_buf(cb); 2132*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 2133*0Sstevel@tonic-gate return (NULL); 2134*0Sstevel@tonic-gate } 2135*0Sstevel@tonic-gate for (tok = strtok_r((char *)id, " ", &lasts); 2136*0Sstevel@tonic-gate tok != NULL; tok = strtok_r(NULL, " ", &lasts)) { 2137*0Sstevel@tonic-gate (void) append_char_buf(cb, "%s//*[@ref_id=\"%s\"]", 2138*0Sstevel@tonic-gate or, tok); 2139*0Sstevel@tonic-gate or = " | "; 2140*0Sstevel@tonic-gate if ((classes & PEC_QRY_SYSTEM) != 0) { 2141*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_SYSTEM, 2142*0Sstevel@tonic-gate props, cb, PO_TRUE) == PO_FAIL) { 2143*0Sstevel@tonic-gate free_char_buf(cb); 2144*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2145*0Sstevel@tonic-gate return (NULL); 2146*0Sstevel@tonic-gate } 2147*0Sstevel@tonic-gate } 2148*0Sstevel@tonic-gate if ((classes & PEC_QRY_POOL) != 0) { 2149*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_POOL, 2150*0Sstevel@tonic-gate props, cb, PO_TRUE) == PO_FAIL) { 2151*0Sstevel@tonic-gate free_char_buf(cb); 2152*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2153*0Sstevel@tonic-gate return (NULL); 2154*0Sstevel@tonic-gate } 2155*0Sstevel@tonic-gate } 2156*0Sstevel@tonic-gate if ((classes & PEC_QRY_RES_COMP) != 0) { 2157*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, 2158*0Sstevel@tonic-gate PEC_RES_COMP, props, cb, PO_TRUE) 2159*0Sstevel@tonic-gate == PO_FAIL) { 2160*0Sstevel@tonic-gate free_char_buf(cb); 2161*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2162*0Sstevel@tonic-gate return (NULL); 2163*0Sstevel@tonic-gate } 2164*0Sstevel@tonic-gate } else if ((classes & PEC_QRY_RES_AGG) != 0) { 2165*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, 2166*0Sstevel@tonic-gate PEC_RES_AGG, props, cb, PO_TRUE) 2167*0Sstevel@tonic-gate == PO_FAIL) { 2168*0Sstevel@tonic-gate free_char_buf(cb); 2169*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2170*0Sstevel@tonic-gate return (NULL); 2171*0Sstevel@tonic-gate } 2172*0Sstevel@tonic-gate } 2173*0Sstevel@tonic-gate } 2174*0Sstevel@tonic-gate xmlFree(id); 2175*0Sstevel@tonic-gate } else { 2176*0Sstevel@tonic-gate /* 2177*0Sstevel@tonic-gate * Build up an XPath query using the supplied parameters. 2178*0Sstevel@tonic-gate * The basic logic is to: 2179*0Sstevel@tonic-gate * - Identify which classes are the targets of the query 2180*0Sstevel@tonic-gate * - For each class work out if the props are attributes or not 2181*0Sstevel@tonic-gate * - Build up a piece of XPath for each class 2182*0Sstevel@tonic-gate * - Combine the results into one large XPath query. 2183*0Sstevel@tonic-gate * - Execute the query. 2184*0Sstevel@tonic-gate */ 2185*0Sstevel@tonic-gate if ((classes & PEC_QRY_SYSTEM) != 0) { 2186*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_SYSTEM, props, 2187*0Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) { 2188*0Sstevel@tonic-gate free_char_buf(cb); 2189*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2190*0Sstevel@tonic-gate return (NULL); 2191*0Sstevel@tonic-gate } 2192*0Sstevel@tonic-gate } 2193*0Sstevel@tonic-gate if ((classes & PEC_QRY_POOL) != 0) { 2194*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_POOL, props, 2195*0Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) { 2196*0Sstevel@tonic-gate free_char_buf(cb); 2197*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2198*0Sstevel@tonic-gate return (NULL); 2199*0Sstevel@tonic-gate } 2200*0Sstevel@tonic-gate } 2201*0Sstevel@tonic-gate if ((classes & PEC_QRY_RES_COMP) != 0) { 2202*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_RES_COMP, props, 2203*0Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) { 2204*0Sstevel@tonic-gate free_char_buf(cb); 2205*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2206*0Sstevel@tonic-gate return (NULL); 2207*0Sstevel@tonic-gate } 2208*0Sstevel@tonic-gate } 2209*0Sstevel@tonic-gate if ((classes & PEC_QRY_RES_AGG) != 0) { 2210*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_RES_AGG, props, 2211*0Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) { 2212*0Sstevel@tonic-gate free_char_buf(cb); 2213*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2214*0Sstevel@tonic-gate return (NULL); 2215*0Sstevel@tonic-gate } 2216*0Sstevel@tonic-gate } 2217*0Sstevel@tonic-gate if ((classes & PEC_QRY_COMP) != 0) { 2218*0Sstevel@tonic-gate if (pool_build_xpath_buf(prov, src, PEC_COMP, props, 2219*0Sstevel@tonic-gate cb, PO_FALSE) == PO_FAIL) { 2220*0Sstevel@tonic-gate free_char_buf(cb); 2221*0Sstevel@tonic-gate pool_seterror(POE_INVALID_SEARCH); 2222*0Sstevel@tonic-gate return (NULL); 2223*0Sstevel@tonic-gate } 2224*0Sstevel@tonic-gate } 2225*0Sstevel@tonic-gate } 2226*0Sstevel@tonic-gate buf = strdup(cb->cb_buf); 2227*0Sstevel@tonic-gate free_char_buf(cb); 2228*0Sstevel@tonic-gate /* 2229*0Sstevel@tonic-gate * Have a buffer at this point, that we can use 2230*0Sstevel@tonic-gate */ 2231*0Sstevel@tonic-gate if ((rs = pool_xml_result_set_alloc(conf)) == NULL) { 2232*0Sstevel@tonic-gate free(buf); 2233*0Sstevel@tonic-gate return (NULL); 2234*0Sstevel@tonic-gate } 2235*0Sstevel@tonic-gate /* 2236*0Sstevel@tonic-gate * Set up the XPath Query 2237*0Sstevel@tonic-gate */ 2238*0Sstevel@tonic-gate if ((rs->pxr_ctx = xmlXPathNewContext( 2239*0Sstevel@tonic-gate ((pool_xml_connection_t *)conf->pc_prov)->pxc_doc)) == NULL) { 2240*0Sstevel@tonic-gate free(buf); 2241*0Sstevel@tonic-gate (void) pool_xml_rs_close((pool_result_set_t *)rs); 2242*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 2243*0Sstevel@tonic-gate return (NULL); 2244*0Sstevel@tonic-gate } 2245*0Sstevel@tonic-gate if (src == NULL) 2246*0Sstevel@tonic-gate rs->pxr_ctx->node = xmlDocGetRootElement 2247*0Sstevel@tonic-gate (((pool_xml_connection_t *)conf->pc_prov)->pxc_doc); 2248*0Sstevel@tonic-gate else 2249*0Sstevel@tonic-gate rs->pxr_ctx->node = pxe->pxe_node; 2250*0Sstevel@tonic-gate /* 2251*0Sstevel@tonic-gate * Select 2252*0Sstevel@tonic-gate */ 2253*0Sstevel@tonic-gate rs->pxr_path = xmlXPathEval(BAD_CAST buf, rs->pxr_ctx); 2254*0Sstevel@tonic-gate free(buf); 2255*0Sstevel@tonic-gate /* 2256*0Sstevel@tonic-gate * Generate the result set and wrap the results as pool_elem_t 2257*0Sstevel@tonic-gate */ 2258*0Sstevel@tonic-gate return ((pool_result_set_t *)rs); 2259*0Sstevel@tonic-gate } 2260*0Sstevel@tonic-gate 2261*0Sstevel@tonic-gate /* 2262*0Sstevel@tonic-gate * Build an XPath query buffer. This is complex and a little fragile, but 2263*0Sstevel@tonic-gate * I'm trying to accomplish something complex with as little code as possible. 2264*0Sstevel@tonic-gate * I wait the implementation of XMLQuery with baited breath... 2265*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 2266*0Sstevel@tonic-gate */ 2267*0Sstevel@tonic-gate static int 2268*0Sstevel@tonic-gate pool_build_xpath_buf(pool_xml_connection_t *prov, const pool_elem_t *src, 2269*0Sstevel@tonic-gate pool_elem_class_t class, pool_value_t *props[], char_buf_t *cb, int is_ref) 2270*0Sstevel@tonic-gate { 2271*0Sstevel@tonic-gate int i; 2272*0Sstevel@tonic-gate const char *ATTR_FMTS[] = { 2273*0Sstevel@tonic-gate "[ @%s=\"%llu\" ]", /* POC_UINT */ 2274*0Sstevel@tonic-gate "[ @%s=\"%lld\" ]", /* POC_INT */ 2275*0Sstevel@tonic-gate "[ @%s=\"%f\" ]", /* POC_DOUBLE */ 2276*0Sstevel@tonic-gate "[ @%s=\"%s\" ]", /* POC_BOOL */ 2277*0Sstevel@tonic-gate "[ @%s=\"%s\" ]", /* POC_STRING */ 2278*0Sstevel@tonic-gate }; 2279*0Sstevel@tonic-gate const char *PROP_FMTS[] = { 2280*0Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%llu\"] ]", /* POC_UINT */ 2281*0Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%lld\"] ]", /* POC_INT */ 2282*0Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%f\"] ]", /* POC_DOUBLE */ 2283*0Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%s\"] ]", /* POC_BOOL */ 2284*0Sstevel@tonic-gate "[ property[@name=\"%s\"][text()=\"%s\"] ]" /* POC_STRING */ 2285*0Sstevel@tonic-gate }; 2286*0Sstevel@tonic-gate const char **fmts; 2287*0Sstevel@tonic-gate int nprop; 2288*0Sstevel@tonic-gate const char *last_prop_name = NULL; 2289*0Sstevel@tonic-gate char *type_prefix = NULL; 2290*0Sstevel@tonic-gate int has_type = PO_FALSE; 2291*0Sstevel@tonic-gate 2292*0Sstevel@tonic-gate if (is_ref == PO_FALSE) { 2293*0Sstevel@tonic-gate if (cb->cb_buf != NULL && strlen(cb->cb_buf) > 0) 2294*0Sstevel@tonic-gate (void) append_char_buf(cb, " |"); 2295*0Sstevel@tonic-gate if (src != NULL) 2296*0Sstevel@tonic-gate (void) append_char_buf(cb, " ./"); 2297*0Sstevel@tonic-gate else 2298*0Sstevel@tonic-gate (void) append_char_buf(cb, "//"); 2299*0Sstevel@tonic-gate (void) append_char_buf(cb, element_class_tags[class]); 2300*0Sstevel@tonic-gate } 2301*0Sstevel@tonic-gate if (props == NULL || props[0] == NULL) 2302*0Sstevel@tonic-gate return (PO_SUCCESS); 2303*0Sstevel@tonic-gate for (nprop = 0; props[nprop] != NULL; nprop++) 2304*0Sstevel@tonic-gate /* Count properties */; 2305*0Sstevel@tonic-gate /* 2306*0Sstevel@tonic-gate * Sort the attributes and properties by name. 2307*0Sstevel@tonic-gate */ 2308*0Sstevel@tonic-gate qsort(props, nprop, sizeof (pool_value_t *), prop_sort); 2309*0Sstevel@tonic-gate for (i = 0; i < nprop; i++) { 2310*0Sstevel@tonic-gate int is_attr = 0; 2311*0Sstevel@tonic-gate const char *prefix; 2312*0Sstevel@tonic-gate const char *prop_name; 2313*0Sstevel@tonic-gate uint64_t uval; 2314*0Sstevel@tonic-gate int64_t ival; 2315*0Sstevel@tonic-gate double dval; 2316*0Sstevel@tonic-gate uchar_t bval; 2317*0Sstevel@tonic-gate const char *sval; 2318*0Sstevel@tonic-gate pool_value_class_t pvc; 2319*0Sstevel@tonic-gate 2320*0Sstevel@tonic-gate prop_name = pool_value_get_name(props[i]); 2321*0Sstevel@tonic-gate if ((prefix = is_a_known_prefix(class, prop_name)) != NULL) { 2322*0Sstevel@tonic-gate const char *attr_name; 2323*0Sstevel@tonic-gate /* 2324*0Sstevel@tonic-gate * Possibly an attribute. Strip off the prefix. 2325*0Sstevel@tonic-gate */ 2326*0Sstevel@tonic-gate if (strcmp(prop_name, c_type) == 0) { 2327*0Sstevel@tonic-gate has_type = PO_TRUE; 2328*0Sstevel@tonic-gate attr_name = prop_name; 2329*0Sstevel@tonic-gate } else 2330*0Sstevel@tonic-gate attr_name = prop_name + strlen(prefix) + 1; 2331*0Sstevel@tonic-gate if (pool_is_xml_attr(prov->pxc_doc, 2332*0Sstevel@tonic-gate element_class_tags[class], attr_name)) { 2333*0Sstevel@tonic-gate is_attr = 1; 2334*0Sstevel@tonic-gate prop_name = attr_name; 2335*0Sstevel@tonic-gate if (class == PEC_RES_COMP || 2336*0Sstevel@tonic-gate class == PEC_RES_AGG || 2337*0Sstevel@tonic-gate class == PEC_COMP) { 2338*0Sstevel@tonic-gate if (type_prefix != NULL) 2339*0Sstevel@tonic-gate free(type_prefix); 2340*0Sstevel@tonic-gate type_prefix = strdup(prefix); 2341*0Sstevel@tonic-gate } 2342*0Sstevel@tonic-gate } 2343*0Sstevel@tonic-gate } 2344*0Sstevel@tonic-gate if (is_attr) { 2345*0Sstevel@tonic-gate fmts = ATTR_FMTS; 2346*0Sstevel@tonic-gate } else { 2347*0Sstevel@tonic-gate fmts = PROP_FMTS; 2348*0Sstevel@tonic-gate } 2349*0Sstevel@tonic-gate /* 2350*0Sstevel@tonic-gate * Add attributes/properties to the search buffer 2351*0Sstevel@tonic-gate */ 2352*0Sstevel@tonic-gate switch ((pvc = pool_value_get_type(props[i]))) { 2353*0Sstevel@tonic-gate case POC_UINT: 2354*0Sstevel@tonic-gate (void) pool_value_get_uint64(props[i], &uval); 2355*0Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, uval) 2356*0Sstevel@tonic-gate == PO_FAIL) { 2357*0Sstevel@tonic-gate free(type_prefix); 2358*0Sstevel@tonic-gate return (PO_FAIL); 2359*0Sstevel@tonic-gate } 2360*0Sstevel@tonic-gate break; 2361*0Sstevel@tonic-gate case POC_INT: 2362*0Sstevel@tonic-gate (void) pool_value_get_int64(props[i], &ival); 2363*0Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, ival) 2364*0Sstevel@tonic-gate == PO_FAIL) { 2365*0Sstevel@tonic-gate free(type_prefix); 2366*0Sstevel@tonic-gate return (PO_FAIL); 2367*0Sstevel@tonic-gate } 2368*0Sstevel@tonic-gate break; 2369*0Sstevel@tonic-gate case POC_DOUBLE: 2370*0Sstevel@tonic-gate (void) pool_value_get_double(props[i], &dval); 2371*0Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, dval) 2372*0Sstevel@tonic-gate == PO_FAIL) { 2373*0Sstevel@tonic-gate free(type_prefix); 2374*0Sstevel@tonic-gate return (PO_FAIL); 2375*0Sstevel@tonic-gate } 2376*0Sstevel@tonic-gate break; 2377*0Sstevel@tonic-gate case POC_BOOL: 2378*0Sstevel@tonic-gate (void) pool_value_get_bool(props[i], &bval); 2379*0Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, 2380*0Sstevel@tonic-gate bval ? "true" : "false") == PO_FAIL) { 2381*0Sstevel@tonic-gate free(type_prefix); 2382*0Sstevel@tonic-gate return (PO_FAIL); 2383*0Sstevel@tonic-gate } 2384*0Sstevel@tonic-gate break; 2385*0Sstevel@tonic-gate case POC_STRING: 2386*0Sstevel@tonic-gate (void) pool_value_get_string(props[i], &sval); 2387*0Sstevel@tonic-gate if (append_char_buf(cb, fmts[pvc], prop_name, sval) 2388*0Sstevel@tonic-gate == PO_FAIL) { 2389*0Sstevel@tonic-gate free(type_prefix); 2390*0Sstevel@tonic-gate return (PO_FAIL); 2391*0Sstevel@tonic-gate } 2392*0Sstevel@tonic-gate break; 2393*0Sstevel@tonic-gate default: 2394*0Sstevel@tonic-gate free(type_prefix); 2395*0Sstevel@tonic-gate return (PO_FAIL); 2396*0Sstevel@tonic-gate } 2397*0Sstevel@tonic-gate if (last_prop_name != NULL) { 2398*0Sstevel@tonic-gate const char *suffix1, *suffix2; 2399*0Sstevel@tonic-gate /* 2400*0Sstevel@tonic-gate * Extra fiddling for namespaces 2401*0Sstevel@tonic-gate */ 2402*0Sstevel@tonic-gate suffix1 = strrchr(prop_name, '.'); 2403*0Sstevel@tonic-gate suffix2 = strrchr(last_prop_name, '.'); 2404*0Sstevel@tonic-gate 2405*0Sstevel@tonic-gate if (suffix1 != NULL || suffix2 != NULL) { 2406*0Sstevel@tonic-gate if (suffix1 == NULL) 2407*0Sstevel@tonic-gate suffix1 = prop_name; 2408*0Sstevel@tonic-gate else 2409*0Sstevel@tonic-gate suffix1++; 2410*0Sstevel@tonic-gate if (suffix2 == NULL) 2411*0Sstevel@tonic-gate suffix2 = last_prop_name; 2412*0Sstevel@tonic-gate else 2413*0Sstevel@tonic-gate suffix2++; 2414*0Sstevel@tonic-gate } else { 2415*0Sstevel@tonic-gate suffix1 = prop_name; 2416*0Sstevel@tonic-gate suffix2 = last_prop_name; 2417*0Sstevel@tonic-gate } 2418*0Sstevel@tonic-gate if (strcmp(suffix1, suffix2) == 0) { 2419*0Sstevel@tonic-gate char *where = strrchr(cb->cb_buf, '['); 2420*0Sstevel@tonic-gate if (is_attr != PO_TRUE) { 2421*0Sstevel@tonic-gate /* repeat */ 2422*0Sstevel@tonic-gate while (*--where != '['); 2423*0Sstevel@tonic-gate while (*--where != '['); 2424*0Sstevel@tonic-gate } 2425*0Sstevel@tonic-gate *(where - 1) = 'o'; 2426*0Sstevel@tonic-gate *where = 'r'; 2427*0Sstevel@tonic-gate } 2428*0Sstevel@tonic-gate } 2429*0Sstevel@tonic-gate last_prop_name = prop_name; 2430*0Sstevel@tonic-gate } 2431*0Sstevel@tonic-gate if (has_type == PO_FALSE) { 2432*0Sstevel@tonic-gate if (type_prefix) { 2433*0Sstevel@tonic-gate if (append_char_buf(cb, ATTR_FMTS[POC_STRING], 2434*0Sstevel@tonic-gate c_type, type_prefix) == PO_FAIL) { 2435*0Sstevel@tonic-gate free(type_prefix); 2436*0Sstevel@tonic-gate return (PO_FAIL); 2437*0Sstevel@tonic-gate } 2438*0Sstevel@tonic-gate } 2439*0Sstevel@tonic-gate } 2440*0Sstevel@tonic-gate free(type_prefix); 2441*0Sstevel@tonic-gate return (PO_SUCCESS); 2442*0Sstevel@tonic-gate } 2443*0Sstevel@tonic-gate 2444*0Sstevel@tonic-gate /* 2445*0Sstevel@tonic-gate * Utility routine for use by quicksort. Assumes that the supplied data 2446*0Sstevel@tonic-gate * are pool values and compares the names of the two pool values. 2447*0Sstevel@tonic-gate * Returns an integer greater than, equal to, or less than 0. 2448*0Sstevel@tonic-gate */ 2449*0Sstevel@tonic-gate static int 2450*0Sstevel@tonic-gate prop_sort(const void *a, const void *b) 2451*0Sstevel@tonic-gate { 2452*0Sstevel@tonic-gate pool_value_t **prop_a = (pool_value_t **)a; 2453*0Sstevel@tonic-gate pool_value_t **prop_b = (pool_value_t **)b; 2454*0Sstevel@tonic-gate const char *str_a; 2455*0Sstevel@tonic-gate const char *str_b; 2456*0Sstevel@tonic-gate const char *suffix1, *suffix2; 2457*0Sstevel@tonic-gate 2458*0Sstevel@tonic-gate str_a = pool_value_get_name(*prop_a); 2459*0Sstevel@tonic-gate str_b = pool_value_get_name(*prop_b); 2460*0Sstevel@tonic-gate /* 2461*0Sstevel@tonic-gate * Extra fiddling for namespaces 2462*0Sstevel@tonic-gate */ 2463*0Sstevel@tonic-gate suffix1 = strrchr(str_a, '.'); 2464*0Sstevel@tonic-gate suffix2 = strrchr(str_b, '.'); 2465*0Sstevel@tonic-gate 2466*0Sstevel@tonic-gate if (suffix1 != NULL || suffix2 != NULL) { 2467*0Sstevel@tonic-gate if (suffix1 == NULL) 2468*0Sstevel@tonic-gate suffix1 = str_a; 2469*0Sstevel@tonic-gate else 2470*0Sstevel@tonic-gate suffix1++; 2471*0Sstevel@tonic-gate if (suffix2 == NULL) 2472*0Sstevel@tonic-gate suffix2 = str_b; 2473*0Sstevel@tonic-gate else 2474*0Sstevel@tonic-gate suffix2++; 2475*0Sstevel@tonic-gate } else { 2476*0Sstevel@tonic-gate suffix1 = str_a; 2477*0Sstevel@tonic-gate suffix2 = str_b; 2478*0Sstevel@tonic-gate } 2479*0Sstevel@tonic-gate return (strcmp(suffix1, suffix2)); 2480*0Sstevel@tonic-gate } 2481*0Sstevel@tonic-gate 2482*0Sstevel@tonic-gate /* 2483*0Sstevel@tonic-gate * Order the elements by (ref_id) 2484*0Sstevel@tonic-gate */ 2485*0Sstevel@tonic-gate 2486*0Sstevel@tonic-gate /* 2487*0Sstevel@tonic-gate * Returns PO_TRUE/PO_FALSE to indicate whether the supplied path exists on the 2488*0Sstevel@tonic-gate * system. It is assumed that the supplied path is in URL format and represents 2489*0Sstevel@tonic-gate * a file and so file:// is stripped from the start of the search. 2490*0Sstevel@tonic-gate */ 2491*0Sstevel@tonic-gate static int 2492*0Sstevel@tonic-gate dtd_exists(const char *path) 2493*0Sstevel@tonic-gate { 2494*0Sstevel@tonic-gate struct stat buf; 2495*0Sstevel@tonic-gate 2496*0Sstevel@tonic-gate if (strstr(path, "file://") != path) 2497*0Sstevel@tonic-gate return (PO_FALSE); 2498*0Sstevel@tonic-gate 2499*0Sstevel@tonic-gate if (path[7] == 0) 2500*0Sstevel@tonic-gate return (PO_FALSE); 2501*0Sstevel@tonic-gate 2502*0Sstevel@tonic-gate if (stat(&path[7], &buf) == 0) 2503*0Sstevel@tonic-gate return (PO_TRUE); 2504*0Sstevel@tonic-gate return (PO_FALSE); 2505*0Sstevel@tonic-gate } 2506*0Sstevel@tonic-gate 2507*0Sstevel@tonic-gate /* 2508*0Sstevel@tonic-gate * Build the dtype structures to accelerate data type lookup operations. The 2509*0Sstevel@tonic-gate * purpose is to avoid expensive XML manipulations on data which will not 2510*0Sstevel@tonic-gate * change over the life of a library invocation. It is designed to be invoked 2511*0Sstevel@tonic-gate * once from the library init function. 2512*0Sstevel@tonic-gate */ 2513*0Sstevel@tonic-gate static void 2514*0Sstevel@tonic-gate build_dtype_accelerator(void) 2515*0Sstevel@tonic-gate { 2516*0Sstevel@tonic-gate xmlDtdPtr dtd; 2517*0Sstevel@tonic-gate const xmlChar *elem_list[ELEM_TYPE_COUNT] = { 2518*0Sstevel@tonic-gate BAD_CAST "res_comp", 2519*0Sstevel@tonic-gate BAD_CAST "res_agg", 2520*0Sstevel@tonic-gate BAD_CAST "comp", 2521*0Sstevel@tonic-gate BAD_CAST "pool", 2522*0Sstevel@tonic-gate BAD_CAST "property", 2523*0Sstevel@tonic-gate BAD_CAST "system" }; 2524*0Sstevel@tonic-gate int i; 2525*0Sstevel@tonic-gate 2526*0Sstevel@tonic-gate if (_libpool_xml_initialised == PO_TRUE) 2527*0Sstevel@tonic-gate return; 2528*0Sstevel@tonic-gate 2529*0Sstevel@tonic-gate /* Load up the d-type data for each element */ 2530*0Sstevel@tonic-gate /* 2531*0Sstevel@tonic-gate * Store data type information in nested lists 2532*0Sstevel@tonic-gate * Top level list contains attribute declaration pointers which 2533*0Sstevel@tonic-gate * can be used to match with supplied nodes. 2534*0Sstevel@tonic-gate * Second level list contains attribute type information for each 2535*0Sstevel@tonic-gate * element declaration 2536*0Sstevel@tonic-gate */ 2537*0Sstevel@tonic-gate /* 2538*0Sstevel@tonic-gate * Unfortunately, there's no easy way to get a list of all DTD 2539*0Sstevel@tonic-gate * element descriptions as there is no libxml API to do this (they 2540*0Sstevel@tonic-gate * are stored in a hash, which I guess is why). Explicitly seek 2541*0Sstevel@tonic-gate * for descriptions for elements that are known to hold an a-dtype 2542*0Sstevel@tonic-gate * attribute and build accelerators for those elements. 2543*0Sstevel@tonic-gate * If the DTD changes, the library may have to change as well now, 2544*0Sstevel@tonic-gate * since this code makes explicit assumptions about which elements 2545*0Sstevel@tonic-gate * contain a-dtype information. 2546*0Sstevel@tonic-gate */ 2547*0Sstevel@tonic-gate 2548*0Sstevel@tonic-gate if ((dtd = xmlParseDTD(BAD_CAST "-//Sun Microsystems Inc//DTD Resource" 2549*0Sstevel@tonic-gate " Management All//EN", BAD_CAST dtd_location)) == NULL) 2550*0Sstevel@tonic-gate return; 2551*0Sstevel@tonic-gate for (i = 0; i < ELEM_TYPE_COUNT; i++) { 2552*0Sstevel@tonic-gate xmlElementPtr elem; 2553*0Sstevel@tonic-gate xmlAttributePtr attr; 2554*0Sstevel@tonic-gate 2555*0Sstevel@tonic-gate if ((elem = xmlGetDtdElementDesc(dtd, elem_list[i])) == NULL) 2556*0Sstevel@tonic-gate return; 2557*0Sstevel@tonic-gate elem_tbl[i].ett_elem = xmlStrdup(elem->name); 2558*0Sstevel@tonic-gate /* Walk the list of attributes looking for a-dtype */ 2559*0Sstevel@tonic-gate for (attr = elem->attributes; attr != NULL; 2560*0Sstevel@tonic-gate attr = attr->nexth) { 2561*0Sstevel@tonic-gate if (strcmp((const char *)attr->name, c_a_dtype) == 0) { 2562*0Sstevel@tonic-gate /* 2563*0Sstevel@tonic-gate * Allocate a dtype_tbl_t 2564*0Sstevel@tonic-gate */ 2565*0Sstevel@tonic-gate elem_tbl[i].ett_dtype = 2566*0Sstevel@tonic-gate build_dtype_tbl(attr->defaultValue); 2567*0Sstevel@tonic-gate /* This could have returned NULL */ 2568*0Sstevel@tonic-gate } 2569*0Sstevel@tonic-gate } 2570*0Sstevel@tonic-gate } 2571*0Sstevel@tonic-gate xmlFreeDtd(dtd); 2572*0Sstevel@tonic-gate } 2573*0Sstevel@tonic-gate 2574*0Sstevel@tonic-gate /* 2575*0Sstevel@tonic-gate * build_dtype_tbl() parses the supplied data and returns an array (max size 2576*0Sstevel@tonic-gate * of 10, increase if required) of dtype_tbl_t structures holding data type 2577*0Sstevel@tonic-gate * information for an element. The supplied data is assumed to be in "a-dtype" 2578*0Sstevel@tonic-gate * format. The dtype_tbl_t array is NULL terminated, which is why space for 2579*0Sstevel@tonic-gate * 11 members is allocated. 2580*0Sstevel@tonic-gate */ 2581*0Sstevel@tonic-gate static dtype_tbl_t 2582*0Sstevel@tonic-gate (*build_dtype_tbl(const xmlChar *rawdata))[] 2583*0Sstevel@tonic-gate { 2584*0Sstevel@tonic-gate char *tok; 2585*0Sstevel@tonic-gate char *lasts; 2586*0Sstevel@tonic-gate dtype_tbl_t (*tbl)[]; 2587*0Sstevel@tonic-gate int j = 0; 2588*0Sstevel@tonic-gate xmlChar *data; 2589*0Sstevel@tonic-gate const int max_attr = 11; /* Not more than 10 types per element */ 2590*0Sstevel@tonic-gate 2591*0Sstevel@tonic-gate /* 2592*0Sstevel@tonic-gate * Parse the supplied data, assumed to be in a-dtype format, and 2593*0Sstevel@tonic-gate * generate a lookup table which is indexed by the name and contains 2594*0Sstevel@tonic-gate * the data type 2595*0Sstevel@tonic-gate */ 2596*0Sstevel@tonic-gate if (rawdata == NULL) 2597*0Sstevel@tonic-gate return (NULL); 2598*0Sstevel@tonic-gate if ((data = xmlStrdup(rawdata)) == NULL) 2599*0Sstevel@tonic-gate return (NULL); 2600*0Sstevel@tonic-gate if ((tbl = calloc(max_attr, sizeof (dtype_tbl_t))) == NULL) { 2601*0Sstevel@tonic-gate xmlFree(data); 2602*0Sstevel@tonic-gate return (NULL); 2603*0Sstevel@tonic-gate } 2604*0Sstevel@tonic-gate for (tok = strtok_r((char *)data, " ", &lasts); tok != NULL; 2605*0Sstevel@tonic-gate tok = strtok_r(NULL, " ", &lasts)) { 2606*0Sstevel@tonic-gate int i; 2607*0Sstevel@tonic-gate (*tbl)[j].dt_name = xmlStrdup(BAD_CAST tok); 2608*0Sstevel@tonic-gate if ((tok = strtok_r(NULL, " ", &lasts)) == NULL) { 2609*0Sstevel@tonic-gate int k = j; 2610*0Sstevel@tonic-gate for (j = 0; j < k; j++) 2611*0Sstevel@tonic-gate free((*tbl)[j].dt_name); 2612*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 2613*0Sstevel@tonic-gate xmlFree(data); 2614*0Sstevel@tonic-gate free(tbl); 2615*0Sstevel@tonic-gate return (NULL); 2616*0Sstevel@tonic-gate } 2617*0Sstevel@tonic-gate for (i = 0; i < (sizeof (data_type_tags) / 2618*0Sstevel@tonic-gate sizeof (data_type_tags[0])); i++) { 2619*0Sstevel@tonic-gate if (strcmp(tok, data_type_tags[i]) == 0) 2620*0Sstevel@tonic-gate (*tbl)[j++].dt_type = i; 2621*0Sstevel@tonic-gate } 2622*0Sstevel@tonic-gate if (j == max_attr) { /* too many attributes, bail out */ 2623*0Sstevel@tonic-gate for (j = 0; j < max_attr; j++) 2624*0Sstevel@tonic-gate free((*tbl)[j].dt_name); 2625*0Sstevel@tonic-gate free(tbl); 2626*0Sstevel@tonic-gate xmlFree(data); 2627*0Sstevel@tonic-gate return (NULL); 2628*0Sstevel@tonic-gate } 2629*0Sstevel@tonic-gate } 2630*0Sstevel@tonic-gate (*tbl)[j].dt_name = NULL; /* Terminate the table */ 2631*0Sstevel@tonic-gate xmlFree(data); 2632*0Sstevel@tonic-gate return (tbl); 2633*0Sstevel@tonic-gate } 2634*0Sstevel@tonic-gate 2635*0Sstevel@tonic-gate /* 2636*0Sstevel@tonic-gate * get_fast_dtype() finds the data type for a supplied attribute name on a 2637*0Sstevel@tonic-gate * supplied node. This is called get_fast_dtype() because it uses the cached 2638*0Sstevel@tonic-gate * data type information created at library initialisation. 2639*0Sstevel@tonic-gate */ 2640*0Sstevel@tonic-gate static int 2641*0Sstevel@tonic-gate get_fast_dtype(xmlNodePtr node, xmlChar *name) 2642*0Sstevel@tonic-gate { 2643*0Sstevel@tonic-gate int i; 2644*0Sstevel@tonic-gate xmlElementPtr elem; 2645*0Sstevel@tonic-gate 2646*0Sstevel@tonic-gate if ((elem = xmlGetDtdElementDesc(node->doc->extSubset, node->name)) 2647*0Sstevel@tonic-gate == NULL) { 2648*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 2649*0Sstevel@tonic-gate return (POC_INVAL); 2650*0Sstevel@tonic-gate } 2651*0Sstevel@tonic-gate 2652*0Sstevel@tonic-gate for (i = 0; i < ELEM_TYPE_COUNT; i++) { 2653*0Sstevel@tonic-gate if (xmlStrcmp(elem_tbl[i].ett_elem, elem->name) == 0) { 2654*0Sstevel@tonic-gate dtype_tbl_t (*tbl)[] = elem_tbl[i].ett_dtype; 2655*0Sstevel@tonic-gate int j = 0; 2656*0Sstevel@tonic-gate 2657*0Sstevel@tonic-gate if (tbl == NULL) 2658*0Sstevel@tonic-gate break; 2659*0Sstevel@tonic-gate for (j = 0; (*tbl)[j].dt_name != NULL; j++) 2660*0Sstevel@tonic-gate if (xmlStrcmp(name, (*tbl)[j].dt_name) == 0) 2661*0Sstevel@tonic-gate return ((*tbl)[j].dt_type); /* found */ 2662*0Sstevel@tonic-gate break; /* if we didn't find it in the elem, break */ 2663*0Sstevel@tonic-gate } 2664*0Sstevel@tonic-gate } 2665*0Sstevel@tonic-gate /* If we can't find it, say it's a string */ 2666*0Sstevel@tonic-gate return (POC_STRING); 2667*0Sstevel@tonic-gate } 2668*0Sstevel@tonic-gate 2669*0Sstevel@tonic-gate /* 2670*0Sstevel@tonic-gate * pool_xml_parse_document() parses the file associated with a supplied 2671*0Sstevel@tonic-gate * configuration to regenerate the runtime representation. The supplied 2672*0Sstevel@tonic-gate * configuration must reference an already opened file and this is used 2673*0Sstevel@tonic-gate * to generate the XML representation via the configuration provider's 2674*0Sstevel@tonic-gate * pxc_doc member. 2675*0Sstevel@tonic-gate * size must be >=4 in order for "content encoding detection" to work. 2676*0Sstevel@tonic-gate */ 2677*0Sstevel@tonic-gate static int 2678*0Sstevel@tonic-gate pool_xml_parse_document(pool_conf_t *conf) 2679*0Sstevel@tonic-gate { 2680*0Sstevel@tonic-gate int res; 2681*0Sstevel@tonic-gate char chars[PAGE_READ_SIZE]; 2682*0Sstevel@tonic-gate struct stat f_stat; 2683*0Sstevel@tonic-gate xmlParserCtxtPtr ctxt; 2684*0Sstevel@tonic-gate size_t size; 2685*0Sstevel@tonic-gate pool_xml_connection_t *prov = (pool_xml_connection_t *)conf->pc_prov; 2686*0Sstevel@tonic-gate xmlNodePtr root; 2687*0Sstevel@tonic-gate pool_resource_t **rsl; 2688*0Sstevel@tonic-gate uint_t nelem; 2689*0Sstevel@tonic-gate int i; 2690*0Sstevel@tonic-gate 2691*0Sstevel@tonic-gate if (fstat(fileno(prov->pxc_file), &f_stat) == -1) { 2692*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2693*0Sstevel@tonic-gate return (PO_FAIL); 2694*0Sstevel@tonic-gate } 2695*0Sstevel@tonic-gate 2696*0Sstevel@tonic-gate if (f_stat.st_size == 0) { 2697*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2698*0Sstevel@tonic-gate return (PO_FAIL); 2699*0Sstevel@tonic-gate } else 2700*0Sstevel@tonic-gate size = f_stat.st_size < 4 ? 4 : PAGE_READ_SIZE; 2701*0Sstevel@tonic-gate 2702*0Sstevel@tonic-gate res = fread(chars, 1, size, prov->pxc_file); 2703*0Sstevel@tonic-gate 2704*0Sstevel@tonic-gate if (res >= 4) { 2705*0Sstevel@tonic-gate xmlValidCtxtPtr cvp; 2706*0Sstevel@tonic-gate 2707*0Sstevel@tonic-gate if ((ctxt = xmlCreatePushParserCtxt(NULL, NULL, 2708*0Sstevel@tonic-gate chars, res, conf->pc_location)) == NULL) { 2709*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2710*0Sstevel@tonic-gate return (PO_FAIL); 2711*0Sstevel@tonic-gate } 2712*0Sstevel@tonic-gate 2713*0Sstevel@tonic-gate while ((res = fread(chars, 1, size, prov->pxc_file)) > 0) { 2714*0Sstevel@tonic-gate if (xmlParseChunk(ctxt, chars, res, 0) != 0) { 2715*0Sstevel@tonic-gate xmlFreeParserCtxt(ctxt); 2716*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2717*0Sstevel@tonic-gate return (PO_FAIL); 2718*0Sstevel@tonic-gate } 2719*0Sstevel@tonic-gate } 2720*0Sstevel@tonic-gate if (xmlParseChunk(ctxt, chars, 0, 1) != 0) { 2721*0Sstevel@tonic-gate xmlFreeParserCtxt(ctxt); 2722*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2723*0Sstevel@tonic-gate return (PO_FAIL); 2724*0Sstevel@tonic-gate } 2725*0Sstevel@tonic-gate 2726*0Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) { 2727*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2728*0Sstevel@tonic-gate return (PO_FAIL); 2729*0Sstevel@tonic-gate } 2730*0Sstevel@tonic-gate cvp->error = pool_error_func; 2731*0Sstevel@tonic-gate cvp->warning = pool_error_func; 2732*0Sstevel@tonic-gate 2733*0Sstevel@tonic-gate if (xmlValidateDocument(cvp, ctxt->myDoc) == 0) { 2734*0Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 2735*0Sstevel@tonic-gate xmlFreeParserCtxt(ctxt); 2736*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2737*0Sstevel@tonic-gate return (PO_FAIL); 2738*0Sstevel@tonic-gate } 2739*0Sstevel@tonic-gate prov->pxc_doc = ctxt->myDoc; 2740*0Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 2741*0Sstevel@tonic-gate xmlFreeParserCtxt(ctxt); 2742*0Sstevel@tonic-gate } 2743*0Sstevel@tonic-gate if (prov->pxc_doc == NULL) { 2744*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2745*0Sstevel@tonic-gate return (PO_FAIL); 2746*0Sstevel@tonic-gate } 2747*0Sstevel@tonic-gate prov->pxc_doc->_private = conf; 2748*0Sstevel@tonic-gate 2749*0Sstevel@tonic-gate /* Get the root element */ 2750*0Sstevel@tonic-gate if ((root = xmlDocGetRootElement(prov->pxc_doc)) == NULL) { 2751*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2752*0Sstevel@tonic-gate return (PO_FAIL); 2753*0Sstevel@tonic-gate } 2754*0Sstevel@tonic-gate /* 2755*0Sstevel@tonic-gate * Ensure that the parsed tree has been contained within 2756*0Sstevel@tonic-gate * our shadow tree. 2757*0Sstevel@tonic-gate */ 2758*0Sstevel@tonic-gate if (create_shadow(root) != PO_SUCCESS) { 2759*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 2760*0Sstevel@tonic-gate return (PO_FAIL); 2761*0Sstevel@tonic-gate } 2762*0Sstevel@tonic-gate 2763*0Sstevel@tonic-gate if (pool_xml_validate(conf, POV_STRICT) != PO_SUCCESS) { 2764*0Sstevel@tonic-gate return (PO_FAIL); 2765*0Sstevel@tonic-gate } 2766*0Sstevel@tonic-gate /* 2767*0Sstevel@tonic-gate * For backwards compatibility with S9, make sure that all 2768*0Sstevel@tonic-gate * resources have a size and that it is correct. 2769*0Sstevel@tonic-gate */ 2770*0Sstevel@tonic-gate if ((rsl = pool_query_resources(conf, &nelem, NULL)) != NULL) { 2771*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 2772*0Sstevel@tonic-gate for (i = 0; i < nelem; i++) { 2773*0Sstevel@tonic-gate if (pool_get_ns_property(TO_ELEM(rsl[i]), c_size_prop, 2774*0Sstevel@tonic-gate &val) != POC_UINT) { 2775*0Sstevel@tonic-gate pool_component_t **cs; 2776*0Sstevel@tonic-gate uint_t size; 2777*0Sstevel@tonic-gate if ((cs = pool_query_resource_components(conf, 2778*0Sstevel@tonic-gate rsl[i], &size, NULL)) != NULL) { 2779*0Sstevel@tonic-gate free(cs); 2780*0Sstevel@tonic-gate pool_value_set_uint64(&val, size); 2781*0Sstevel@tonic-gate } else 2782*0Sstevel@tonic-gate pool_value_set_uint64(&val, 0); 2783*0Sstevel@tonic-gate if (pool_put_any_ns_property(TO_ELEM(rsl[i]), 2784*0Sstevel@tonic-gate c_size_prop, &val) != PO_SUCCESS) { 2785*0Sstevel@tonic-gate free(rsl); 2786*0Sstevel@tonic-gate return (PO_FAIL); 2787*0Sstevel@tonic-gate } 2788*0Sstevel@tonic-gate } 2789*0Sstevel@tonic-gate } 2790*0Sstevel@tonic-gate free(rsl); 2791*0Sstevel@tonic-gate } 2792*0Sstevel@tonic-gate return (PO_SUCCESS); 2793*0Sstevel@tonic-gate } 2794