1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This module implements the PTree interface and the PICL to PTree calls 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * Note: 35*7c478bd9Sstevel@tonic-gate * PICL Node and Property Handles Table: 36*7c478bd9Sstevel@tonic-gate * A node or property in PICL tree has two handles: a ptree handle, which is 37*7c478bd9Sstevel@tonic-gate * used by plug-ins and the libpicltree interface, and a picl handle 38*7c478bd9Sstevel@tonic-gate * which is used by clients and the libpicl interface. 39*7c478bd9Sstevel@tonic-gate * The mapping of ptree handles to the internal PICL object (picl_obj_t) is 40*7c478bd9Sstevel@tonic-gate * kept in a ptree hash table (ptreetbl), and the mapping of a picl handle 41*7c478bd9Sstevel@tonic-gate * to its ptree handle is kept in the picl hash table (picltbl). 42*7c478bd9Sstevel@tonic-gate * The reader/writer lock, ptree_rwlock, is held when reading or modifying ptree 43*7c478bd9Sstevel@tonic-gate * hash table (ptreetbl) and/or the PICL tree structure (nodes and linkages 44*7c478bd9Sstevel@tonic-gate * between them). The reader/writer lock, picltbl_rwlock, is held when reading 45*7c478bd9Sstevel@tonic-gate * or modifying picl hash table (picltbl). 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * The mutex, ptreehdl_lock, is used to control allocation of ptree handles. 48*7c478bd9Sstevel@tonic-gate * The mutex, piclhdl_lock, is used to control allocation of picl handles. 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * The mutex, ptree_refresh_mutex, and the condition, ptree_refresh_cond, 51*7c478bd9Sstevel@tonic-gate * are used to synchronize PICL refreshes (ptree_refresh) and to wait/signal 52*7c478bd9Sstevel@tonic-gate * change in PICL tree structure. 53*7c478bd9Sstevel@tonic-gate * 54*7c478bd9Sstevel@tonic-gate * The counter, picl_hdl_hi, is the hi water mark for allocated picl handles. 55*7c478bd9Sstevel@tonic-gate * The counter, ptree_hdl_hi, is the hi water mark for allocated ptree handles. 56*7c478bd9Sstevel@tonic-gate * A stale handle error is returned for handle values below the hi water 57*7c478bd9Sstevel@tonic-gate * mark, and invalid handles are returned for handle values above the hi water 58*7c478bd9Sstevel@tonic-gate * mark or when the process id field of the handle does not match. 59*7c478bd9Sstevel@tonic-gate * 60*7c478bd9Sstevel@tonic-gate * Locking Scheme: 61*7c478bd9Sstevel@tonic-gate * The structure of the PICL tree is controlled by the ptree_rwlock. The 62*7c478bd9Sstevel@tonic-gate * properties of a node are controlled by individual node locks. The 63*7c478bd9Sstevel@tonic-gate * piclize-ing or unpiclize-ing of a node is controlled by picltbl_rwlock. 64*7c478bd9Sstevel@tonic-gate * 65*7c478bd9Sstevel@tonic-gate * Two-Phase Locking scheme: lock acquire phase and lock release phase. 66*7c478bd9Sstevel@tonic-gate * 67*7c478bd9Sstevel@tonic-gate * Lock Ordering: 68*7c478bd9Sstevel@tonic-gate * The ptree_rwlock and node locks are always acquired in the following order: 69*7c478bd9Sstevel@tonic-gate * lock ptree_rwlock 70*7c478bd9Sstevel@tonic-gate * lock node 71*7c478bd9Sstevel@tonic-gate * 72*7c478bd9Sstevel@tonic-gate * Lock Strategy: 73*7c478bd9Sstevel@tonic-gate * There are three locks: 74*7c478bd9Sstevel@tonic-gate * ptree_rwlock: a reader lock is obtained to do ptree hash table 75*7c478bd9Sstevel@tonic-gate * lookups and traverse tree. A writer lock is obtained 76*7c478bd9Sstevel@tonic-gate * when creating or destroying nodes from the ptree, 77*7c478bd9Sstevel@tonic-gate * or when modifying node linkages: parent, peer, child. 78*7c478bd9Sstevel@tonic-gate * picltbl_rwlock: a reader lock is obtained for picl hash table lookups. 79*7c478bd9Sstevel@tonic-gate * A writer lock is obtained when piclize-ing or 80*7c478bd9Sstevel@tonic-gate * unpiclize-ing nodes or properties. 81*7c478bd9Sstevel@tonic-gate * node_lock: This is a reader/writer lock for properties of a node. 82*7c478bd9Sstevel@tonic-gate * A reader lock is obtained before reading property 83*7c478bd9Sstevel@tonic-gate * values. A writer lock is obtained when adding or 84*7c478bd9Sstevel@tonic-gate * removing properties and when modifying a property value. 85*7c478bd9Sstevel@tonic-gate * 86*7c478bd9Sstevel@tonic-gate * Never hold more than one node lock at a time. 87*7c478bd9Sstevel@tonic-gate * 88*7c478bd9Sstevel@tonic-gate * Event Locking: 89*7c478bd9Sstevel@tonic-gate * There are two locks: 90*7c478bd9Sstevel@tonic-gate * evtq_lock: this lock protects the event queue. It is obtained 91*7c478bd9Sstevel@tonic-gate * to queue events that are posted and to unqueue 92*7c478bd9Sstevel@tonic-gate * events to be dispatched. 93*7c478bd9Sstevel@tonic-gate * evtq_cv: condition variable is protected by evtq_lock. It is 94*7c478bd9Sstevel@tonic-gate * used by the ptree event thread to wait for events 95*7c478bd9Sstevel@tonic-gate * until eventqp is not NULL. 96*7c478bd9Sstevel@tonic-gate * evtq_empty: condition variable protected by evtq_lock. It is 97*7c478bd9Sstevel@tonic-gate * used to signal when the eventq becomes empty. The 98*7c478bd9Sstevel@tonic-gate * reinitialization process waits on this condition. 99*7c478bd9Sstevel@tonic-gate * evthandler_lock: this protects the event handler list. It is obtained 100*7c478bd9Sstevel@tonic-gate * to add event handlers on registration and to remove 101*7c478bd9Sstevel@tonic-gate * event handlers on unregistration. 102*7c478bd9Sstevel@tonic-gate * (handler)->cv: condition variable per handler protected by 103*7c478bd9Sstevel@tonic-gate * evthandler_lock. It is used to wait until the 104*7c478bd9Sstevel@tonic-gate * event handler completes execution (execflg == 0) 105*7c478bd9Sstevel@tonic-gate * before unregistering the handler. 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate #include <stdio.h> 109*7c478bd9Sstevel@tonic-gate #include <string.h> 110*7c478bd9Sstevel@tonic-gate #include <strings.h> 111*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 112*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 113*7c478bd9Sstevel@tonic-gate #include <alloca.h> 114*7c478bd9Sstevel@tonic-gate #include <assert.h> 115*7c478bd9Sstevel@tonic-gate #include <errno.h> 116*7c478bd9Sstevel@tonic-gate #include <unistd.h> 117*7c478bd9Sstevel@tonic-gate #include <limits.h> 118*7c478bd9Sstevel@tonic-gate #include <libintl.h> 119*7c478bd9Sstevel@tonic-gate #include <syslog.h> 120*7c478bd9Sstevel@tonic-gate #include <pthread.h> 121*7c478bd9Sstevel@tonic-gate #include <synch.h> 122*7c478bd9Sstevel@tonic-gate #include <setjmp.h> 123*7c478bd9Sstevel@tonic-gate #include <signal.h> 124*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 125*7c478bd9Sstevel@tonic-gate #include <dirent.h> 126*7c478bd9Sstevel@tonic-gate #include <door.h> 127*7c478bd9Sstevel@tonic-gate #include <time.h> 128*7c478bd9Sstevel@tonic-gate #include <inttypes.h> 129*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 130*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 131*7c478bd9Sstevel@tonic-gate #include <picl.h> 132*7c478bd9Sstevel@tonic-gate #include <picltree.h> 133*7c478bd9Sstevel@tonic-gate #include "picldefs.h" 134*7c478bd9Sstevel@tonic-gate #include "ptree_impl.h" 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate #define SO_VERS ".so.1" 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate static hash_t picltbl; /* client handles to picl obj */ 139*7c478bd9Sstevel@tonic-gate static hash_t ptreetbl; /* ptree handles to picl obj */ 140*7c478bd9Sstevel@tonic-gate static pthread_mutex_t ptreehdl_lock; 141*7c478bd9Sstevel@tonic-gate static pthread_mutex_t piclhdl_lock; 142*7c478bd9Sstevel@tonic-gate static pthread_mutex_t ptree_refresh_mutex; 143*7c478bd9Sstevel@tonic-gate static rwlock_t picltbl_rwlock; /* PICL handle table lock */ 144*7c478bd9Sstevel@tonic-gate static rwlock_t ptree_rwlock; /* PICL tree lock */ 145*7c478bd9Sstevel@tonic-gate static pthread_cond_t ptree_refresh_cond = PTHREAD_COND_INITIALIZER; 146*7c478bd9Sstevel@tonic-gate static uint32_t ptree_hdl_hi = 1; 147*7c478bd9Sstevel@tonic-gate static uint32_t picl_hdl_hi = 1; 148*7c478bd9Sstevel@tonic-gate static picl_obj_t *picl_root_obj = NULL; 149*7c478bd9Sstevel@tonic-gate static picl_nodehdl_t ptree_root_hdl = PICL_INVALID_PICLHDL; 150*7c478bd9Sstevel@tonic-gate static int ptree_generation = 0; 151*7c478bd9Sstevel@tonic-gate static pid_t picld_pid; 152*7c478bd9Sstevel@tonic-gate static door_cred_t picld_cred; 153*7c478bd9Sstevel@tonic-gate static int qempty_wait; /* evtq_empty condition waiter flag */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate static picld_plugin_reg_list_t *plugin_reg_list = NULL; 156*7c478bd9Sstevel@tonic-gate static picld_plugin_desc_t *plugin_desc; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate static eventq_t *eventqp; /* PICL events queue */ 159*7c478bd9Sstevel@tonic-gate static pthread_mutex_t evtq_lock = PTHREAD_MUTEX_INITIALIZER; 160*7c478bd9Sstevel@tonic-gate static pthread_cond_t evtq_cv = PTHREAD_COND_INITIALIZER; 161*7c478bd9Sstevel@tonic-gate static pthread_cond_t evtq_empty = PTHREAD_COND_INITIALIZER; 162*7c478bd9Sstevel@tonic-gate static evt_handler_t *evt_handlers; /* Event handler list */ 163*7c478bd9Sstevel@tonic-gate static pthread_mutex_t evthandler_lock = PTHREAD_MUTEX_INITIALIZER; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * PICL daemon verbose level 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate int verbose_level; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * Event handler free functions 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate static void 175*7c478bd9Sstevel@tonic-gate free_handler(evt_handler_t *evhp) 176*7c478bd9Sstevel@tonic-gate { 177*7c478bd9Sstevel@tonic-gate if (evhp->ename) 178*7c478bd9Sstevel@tonic-gate free(evhp->ename); 179*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evhp->cv); 180*7c478bd9Sstevel@tonic-gate (void) pthread_cond_destroy(&evhp->cv); 181*7c478bd9Sstevel@tonic-gate free(evhp); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * queue_event to events queue 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate static void 189*7c478bd9Sstevel@tonic-gate queue_event(eventq_t *evt) 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate eventq_t *tmpp; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate evt->next = NULL; 194*7c478bd9Sstevel@tonic-gate if (eventqp == NULL) 195*7c478bd9Sstevel@tonic-gate eventqp = evt; 196*7c478bd9Sstevel@tonic-gate else { 197*7c478bd9Sstevel@tonic-gate tmpp = eventqp; 198*7c478bd9Sstevel@tonic-gate while (tmpp->next != NULL) 199*7c478bd9Sstevel@tonic-gate tmpp = tmpp->next; 200*7c478bd9Sstevel@tonic-gate tmpp->next = evt; 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * unqueue_event from the specified eventq 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate static eventq_t * 208*7c478bd9Sstevel@tonic-gate unqueue_event(eventq_t **qp) 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate eventq_t *evtp; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate evtp = *qp; 213*7c478bd9Sstevel@tonic-gate if (evtp != NULL) 214*7c478bd9Sstevel@tonic-gate *qp = evtp->next; 215*7c478bd9Sstevel@tonic-gate return (evtp); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * register an event handler by adding it to the list 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate int 222*7c478bd9Sstevel@tonic-gate ptree_register_handler(const char *ename, 223*7c478bd9Sstevel@tonic-gate void (*evt_handler)(const char *ename, const void *earg, size_t size, 224*7c478bd9Sstevel@tonic-gate void *cookie), void *cookie) 225*7c478bd9Sstevel@tonic-gate { 226*7c478bd9Sstevel@tonic-gate evt_handler_t *ent; 227*7c478bd9Sstevel@tonic-gate evt_handler_t *iter; 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate if (ename == NULL) 230*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate /* 233*7c478bd9Sstevel@tonic-gate * Initialize event handler entry 234*7c478bd9Sstevel@tonic-gate */ 235*7c478bd9Sstevel@tonic-gate ent = malloc(sizeof (*ent)); 236*7c478bd9Sstevel@tonic-gate if (ent == NULL) 237*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 238*7c478bd9Sstevel@tonic-gate ent->ename = strdup(ename); 239*7c478bd9Sstevel@tonic-gate if (ent->ename == NULL) { 240*7c478bd9Sstevel@tonic-gate free(ent); 241*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate ent->cookie = cookie; 244*7c478bd9Sstevel@tonic-gate ent->evt_handler = evt_handler; 245*7c478bd9Sstevel@tonic-gate ent->execflg = 0; 246*7c478bd9Sstevel@tonic-gate ent->wakeupflg = 0; 247*7c478bd9Sstevel@tonic-gate (void) pthread_cond_init(&ent->cv, NULL); 248*7c478bd9Sstevel@tonic-gate ent->next = NULL; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* 251*7c478bd9Sstevel@tonic-gate * add handler to the handler list 252*7c478bd9Sstevel@tonic-gate */ 253*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 254*7c478bd9Sstevel@tonic-gate if (evt_handlers == NULL) { 255*7c478bd9Sstevel@tonic-gate evt_handlers = ent; 256*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 257*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate iter = evt_handlers; 260*7c478bd9Sstevel@tonic-gate while (iter->next != NULL) 261*7c478bd9Sstevel@tonic-gate iter = iter->next; 262*7c478bd9Sstevel@tonic-gate iter->next = ent; 263*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * unregister handler 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate void 272*7c478bd9Sstevel@tonic-gate ptree_unregister_handler(const char *ename, 273*7c478bd9Sstevel@tonic-gate void (*evt_handler)(const char *ename, const void *earg, size_t size, 274*7c478bd9Sstevel@tonic-gate void *cookie), void *cookie) 275*7c478bd9Sstevel@tonic-gate { 276*7c478bd9Sstevel@tonic-gate evt_handler_t *evhdlrp, **evhdlrpp; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if (ename == NULL) 279*7c478bd9Sstevel@tonic-gate return; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * unlink handler from handler list 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate retry: 287*7c478bd9Sstevel@tonic-gate for (evhdlrpp = &evt_handlers; (evhdlrp = *evhdlrpp) != NULL; 288*7c478bd9Sstevel@tonic-gate evhdlrpp = &evhdlrp->next) { 289*7c478bd9Sstevel@tonic-gate if ((evhdlrp->cookie != cookie) || 290*7c478bd9Sstevel@tonic-gate (strcmp(evhdlrp->ename, ename) != 0) || 291*7c478bd9Sstevel@tonic-gate (evhdlrp->evt_handler != evt_handler)) 292*7c478bd9Sstevel@tonic-gate continue; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate /* 295*7c478bd9Sstevel@tonic-gate * If the handler is in execution, release the lock 296*7c478bd9Sstevel@tonic-gate * and wait for it to complete and retry. 297*7c478bd9Sstevel@tonic-gate */ 298*7c478bd9Sstevel@tonic-gate if (evhdlrp->execflg) { 299*7c478bd9Sstevel@tonic-gate evhdlrp->wakeupflg = 1; 300*7c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&evhdlrp->cv, 301*7c478bd9Sstevel@tonic-gate &evthandler_lock); 302*7c478bd9Sstevel@tonic-gate goto retry; 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate /* 306*7c478bd9Sstevel@tonic-gate * Unlink this handler from the linked list 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate *evhdlrpp = evhdlrp->next; 309*7c478bd9Sstevel@tonic-gate free_handler(evhdlrp); 310*7c478bd9Sstevel@tonic-gate break; 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * Call all registered handlers for the event 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate static void 320*7c478bd9Sstevel@tonic-gate call_event_handlers(eventq_t *ev) 321*7c478bd9Sstevel@tonic-gate { 322*7c478bd9Sstevel@tonic-gate evt_handler_t *iter; 323*7c478bd9Sstevel@tonic-gate void (*evhandler)(const char *, const void *, size_t, void *); 324*7c478bd9Sstevel@tonic-gate void (*completion_handler)(char *ename, void *earg, size_t size); 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 327*7c478bd9Sstevel@tonic-gate iter = evt_handlers; 328*7c478bd9Sstevel@tonic-gate while (iter != NULL) { 329*7c478bd9Sstevel@tonic-gate if (strcmp(iter->ename, ev->ename) == 0) { 330*7c478bd9Sstevel@tonic-gate evhandler = iter->evt_handler; 331*7c478bd9Sstevel@tonic-gate iter->execflg = 1; 332*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 333*7c478bd9Sstevel@tonic-gate if (evhandler) { 334*7c478bd9Sstevel@tonic-gate dbg_print(2, "ptree_evthr: Invoking evthdlr:%p" 335*7c478bd9Sstevel@tonic-gate " ename:%s\n", evhandler, ev->ename); 336*7c478bd9Sstevel@tonic-gate (*evhandler)(ev->ename, ev->earg, ev->size, 337*7c478bd9Sstevel@tonic-gate iter->cookie); 338*7c478bd9Sstevel@tonic-gate dbg_print(2, "ptree_evthr: done evthdlr:%p " 339*7c478bd9Sstevel@tonic-gate "ename:%s\n", evhandler, ev->ename); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 342*7c478bd9Sstevel@tonic-gate iter->execflg = 0; 343*7c478bd9Sstevel@tonic-gate if (iter->wakeupflg) { 344*7c478bd9Sstevel@tonic-gate iter->wakeupflg = 0; 345*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&iter->cv); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate iter = iter->next; 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 351*7c478bd9Sstevel@tonic-gate if ((completion_handler = ev->completion_handler) != NULL) { 352*7c478bd9Sstevel@tonic-gate dbg_print(2, 353*7c478bd9Sstevel@tonic-gate "ptree_evthr: Invoking completion hdlr:%p ename:%s\n", 354*7c478bd9Sstevel@tonic-gate completion_handler, ev->ename); 355*7c478bd9Sstevel@tonic-gate (*completion_handler)((char *)ev->ename, (void *)ev->earg, 356*7c478bd9Sstevel@tonic-gate ev->size); 357*7c478bd9Sstevel@tonic-gate dbg_print(2, "ptree_evthr: done completion hdlr:%p ename:%s\n", 358*7c478bd9Sstevel@tonic-gate completion_handler, ev->ename); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptree_refresh_mutex); 361*7c478bd9Sstevel@tonic-gate ++ptree_generation; 362*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&ptree_refresh_cond); 363*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * This function is called by a plug-in to post an event 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate int 370*7c478bd9Sstevel@tonic-gate ptree_post_event(const char *ename, const void *earg, size_t size, 371*7c478bd9Sstevel@tonic-gate void (*completion_handler)(char *ename, void *earg, size_t size)) 372*7c478bd9Sstevel@tonic-gate { 373*7c478bd9Sstevel@tonic-gate eventq_t *evt; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate if (ename == NULL) 376*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate evt = malloc(sizeof (*evt)); 379*7c478bd9Sstevel@tonic-gate if (evt == NULL) 380*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 381*7c478bd9Sstevel@tonic-gate evt->ename = ename; 382*7c478bd9Sstevel@tonic-gate evt->earg = earg; 383*7c478bd9Sstevel@tonic-gate evt->size = size; 384*7c478bd9Sstevel@tonic-gate evt->completion_handler = completion_handler; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 387*7c478bd9Sstevel@tonic-gate queue_event(evt); 388*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evtq_cv); 389*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 390*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * PICLTREE event thread 395*7c478bd9Sstevel@tonic-gate */ 396*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 397*7c478bd9Sstevel@tonic-gate static void * 398*7c478bd9Sstevel@tonic-gate ptree_event_thread(void *argp) 399*7c478bd9Sstevel@tonic-gate { 400*7c478bd9Sstevel@tonic-gate eventq_t *evt; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate for (;;) { 403*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 404*7c478bd9Sstevel@tonic-gate while (eventqp == NULL) { 405*7c478bd9Sstevel@tonic-gate /* 406*7c478bd9Sstevel@tonic-gate * Signal empty queue 407*7c478bd9Sstevel@tonic-gate */ 408*7c478bd9Sstevel@tonic-gate if (qempty_wait) 409*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evtq_empty); 410*7c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&evtq_cv, &evtq_lock); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate if ((evt = unqueue_event(&eventqp)) != NULL) { 413*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 414*7c478bd9Sstevel@tonic-gate call_event_handlers(evt); 415*7c478bd9Sstevel@tonic-gate free(evt); 416*7c478bd9Sstevel@tonic-gate } else 417*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 420*7c478bd9Sstevel@tonic-gate return (NULL); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate /* 425*7c478bd9Sstevel@tonic-gate * Create a new element 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate static hash_elem_t * 428*7c478bd9Sstevel@tonic-gate hash_newobj(uint32_t hdl_val, void *obj_val) 429*7c478bd9Sstevel@tonic-gate { 430*7c478bd9Sstevel@tonic-gate hash_elem_t *n; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate n = malloc(sizeof (*n)); 433*7c478bd9Sstevel@tonic-gate if (n == NULL) 434*7c478bd9Sstevel@tonic-gate return (NULL); 435*7c478bd9Sstevel@tonic-gate n->hdl = hdl_val; 436*7c478bd9Sstevel@tonic-gate n->hash_obj = obj_val; 437*7c478bd9Sstevel@tonic-gate n->next = NULL; 438*7c478bd9Sstevel@tonic-gate return (n); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate static hash_elem_t * 442*7c478bd9Sstevel@tonic-gate hash_newhdl(uint32_t picl_hdl, uint32_t ptreeh) 443*7c478bd9Sstevel@tonic-gate { 444*7c478bd9Sstevel@tonic-gate hash_elem_t *n; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate n = malloc(sizeof (*n)); 447*7c478bd9Sstevel@tonic-gate if (n == NULL) 448*7c478bd9Sstevel@tonic-gate return (NULL); 449*7c478bd9Sstevel@tonic-gate n->hdl = picl_hdl; 450*7c478bd9Sstevel@tonic-gate n->hash_hdl = ptreeh; 451*7c478bd9Sstevel@tonic-gate n->next = NULL; 452*7c478bd9Sstevel@tonic-gate return (n); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate /* 456*7c478bd9Sstevel@tonic-gate * Initialize a hash table by setting all entries to NULL 457*7c478bd9Sstevel@tonic-gate */ 458*7c478bd9Sstevel@tonic-gate static int 459*7c478bd9Sstevel@tonic-gate hash_init(hash_t *htbl) 460*7c478bd9Sstevel@tonic-gate { 461*7c478bd9Sstevel@tonic-gate int i; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate htbl->hash_size = HASH_TBL_SIZE; 464*7c478bd9Sstevel@tonic-gate htbl->tbl = malloc(sizeof (hash_elem_t *) * HASH_TBL_SIZE); 465*7c478bd9Sstevel@tonic-gate if (htbl->tbl == NULL) 466*7c478bd9Sstevel@tonic-gate return (-1); 467*7c478bd9Sstevel@tonic-gate for (i = 0; i < htbl->hash_size; ++i) 468*7c478bd9Sstevel@tonic-gate htbl->tbl[i] = NULL; 469*7c478bd9Sstevel@tonic-gate return (0); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate /* 473*7c478bd9Sstevel@tonic-gate * Lock free function to add an entry in the hash table 474*7c478bd9Sstevel@tonic-gate */ 475*7c478bd9Sstevel@tonic-gate static int 476*7c478bd9Sstevel@tonic-gate hash_add_newobj(hash_t *htbl, picl_hdl_t hdl, void *pobj) 477*7c478bd9Sstevel@tonic-gate { 478*7c478bd9Sstevel@tonic-gate int indx; 479*7c478bd9Sstevel@tonic-gate hash_elem_t *n; 480*7c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate n = hash_newobj(hash_val, pobj); 483*7c478bd9Sstevel@tonic-gate if (n == NULL) 484*7c478bd9Sstevel@tonic-gate return (-1); 485*7c478bd9Sstevel@tonic-gate indx = HASH_INDEX(htbl->hash_size, hash_val); 486*7c478bd9Sstevel@tonic-gate n->next = htbl->tbl[indx]; 487*7c478bd9Sstevel@tonic-gate htbl->tbl[indx] = n; 488*7c478bd9Sstevel@tonic-gate return (0); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate static int 492*7c478bd9Sstevel@tonic-gate hash_add_newhdl(hash_t *htbl, picl_hdl_t piclh, picl_hdl_t ptreeh) 493*7c478bd9Sstevel@tonic-gate { 494*7c478bd9Sstevel@tonic-gate int indx; 495*7c478bd9Sstevel@tonic-gate hash_elem_t *n; 496*7c478bd9Sstevel@tonic-gate uint32_t picl_val = HASH_VAL(piclh); 497*7c478bd9Sstevel@tonic-gate uint32_t ptree_val = HASH_VAL(ptreeh); 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate n = hash_newhdl(picl_val, ptree_val); 500*7c478bd9Sstevel@tonic-gate if (n == NULL) 501*7c478bd9Sstevel@tonic-gate return (-1); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate indx = HASH_INDEX(htbl->hash_size, picl_val); 504*7c478bd9Sstevel@tonic-gate n->next = htbl->tbl[indx]; 505*7c478bd9Sstevel@tonic-gate htbl->tbl[indx] = n; 506*7c478bd9Sstevel@tonic-gate return (0); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate /* 510*7c478bd9Sstevel@tonic-gate * Lock free function to remove the handle from the hash table 511*7c478bd9Sstevel@tonic-gate * Returns -1 if element not found, 0 if successful 512*7c478bd9Sstevel@tonic-gate */ 513*7c478bd9Sstevel@tonic-gate static int 514*7c478bd9Sstevel@tonic-gate hash_remove(hash_t *htbl, picl_hdl_t hdl) 515*7c478bd9Sstevel@tonic-gate { 516*7c478bd9Sstevel@tonic-gate hash_elem_t *nxt; 517*7c478bd9Sstevel@tonic-gate hash_elem_t *cur; 518*7c478bd9Sstevel@tonic-gate int i; 519*7c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate i = HASH_INDEX(htbl->hash_size, hash_val); 522*7c478bd9Sstevel@tonic-gate if (htbl->tbl[i] == NULL) 523*7c478bd9Sstevel@tonic-gate return (-1); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate cur = htbl->tbl[i]; 526*7c478bd9Sstevel@tonic-gate if (cur->hdl == hash_val) { 527*7c478bd9Sstevel@tonic-gate htbl->tbl[i] = cur->next; 528*7c478bd9Sstevel@tonic-gate free(cur); 529*7c478bd9Sstevel@tonic-gate return (0); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate nxt = cur->next; 532*7c478bd9Sstevel@tonic-gate while (nxt != NULL) { 533*7c478bd9Sstevel@tonic-gate if (nxt->hdl == hash_val) { 534*7c478bd9Sstevel@tonic-gate cur->next = nxt->next; 535*7c478bd9Sstevel@tonic-gate free(nxt); 536*7c478bd9Sstevel@tonic-gate return (0); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate cur = nxt; 539*7c478bd9Sstevel@tonic-gate nxt = nxt->next; 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate return (-1); 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate /* 545*7c478bd9Sstevel@tonic-gate * Lock free function to lookup the hash table for a given handle 546*7c478bd9Sstevel@tonic-gate * Returns NULL if not found 547*7c478bd9Sstevel@tonic-gate */ 548*7c478bd9Sstevel@tonic-gate static void * 549*7c478bd9Sstevel@tonic-gate hash_lookup_obj(hash_t *htbl, picl_hdl_t hdl) 550*7c478bd9Sstevel@tonic-gate { 551*7c478bd9Sstevel@tonic-gate hash_elem_t *tmp; 552*7c478bd9Sstevel@tonic-gate int i; 553*7c478bd9Sstevel@tonic-gate uint32_t hash_val; 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate hash_val = HASH_VAL(hdl); 556*7c478bd9Sstevel@tonic-gate i = HASH_INDEX(htbl->hash_size, hash_val); 557*7c478bd9Sstevel@tonic-gate tmp = htbl->tbl[i]; 558*7c478bd9Sstevel@tonic-gate while (tmp != NULL) { 559*7c478bd9Sstevel@tonic-gate if (tmp->hdl == hash_val) 560*7c478bd9Sstevel@tonic-gate return (tmp->hash_obj); 561*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate return (NULL); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate static picl_hdl_t 567*7c478bd9Sstevel@tonic-gate hash_lookup_hdl(hash_t *htbl, picl_hdl_t hdl) 568*7c478bd9Sstevel@tonic-gate { 569*7c478bd9Sstevel@tonic-gate hash_elem_t *tmp; 570*7c478bd9Sstevel@tonic-gate int i; 571*7c478bd9Sstevel@tonic-gate uint32_t hash_val; 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate hash_val = HASH_VAL(hdl); 574*7c478bd9Sstevel@tonic-gate i = HASH_INDEX(htbl->hash_size, hash_val); 575*7c478bd9Sstevel@tonic-gate tmp = htbl->tbl[i]; 576*7c478bd9Sstevel@tonic-gate while (tmp != NULL) { 577*7c478bd9Sstevel@tonic-gate if (tmp->hdl == hash_val) 578*7c478bd9Sstevel@tonic-gate return (MAKE_HANDLE(picld_pid, tmp->hash_hdl)); 579*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate return (PICL_INVALID_PICLHDL); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate /* 585*7c478bd9Sstevel@tonic-gate * Is the PICL handle stale or invalid handle? 586*7c478bd9Sstevel@tonic-gate */ 587*7c478bd9Sstevel@tonic-gate static int 588*7c478bd9Sstevel@tonic-gate picl_hdl_error(picl_hdl_t hdl) 589*7c478bd9Sstevel@tonic-gate { 590*7c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 591*7c478bd9Sstevel@tonic-gate pid_t pid = GET_PID(hdl); 592*7c478bd9Sstevel@tonic-gate int err; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&piclhdl_lock); 595*7c478bd9Sstevel@tonic-gate err = PICL_STALEHANDLE; 596*7c478bd9Sstevel@tonic-gate if ((pid != picld_pid) || (hash_val >= picl_hdl_hi) || 597*7c478bd9Sstevel@tonic-gate (hash_val == NULL)) 598*7c478bd9Sstevel@tonic-gate err = PICL_INVALIDHANDLE; 599*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&piclhdl_lock); 600*7c478bd9Sstevel@tonic-gate return (err); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate /* 604*7c478bd9Sstevel@tonic-gate * Is the Ptree handle stale or invalid handle? 605*7c478bd9Sstevel@tonic-gate */ 606*7c478bd9Sstevel@tonic-gate static int 607*7c478bd9Sstevel@tonic-gate ptree_hdl_error(picl_hdl_t hdl) 608*7c478bd9Sstevel@tonic-gate { 609*7c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 610*7c478bd9Sstevel@tonic-gate pid_t pid = GET_PID(hdl); 611*7c478bd9Sstevel@tonic-gate int err; 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptreehdl_lock); 614*7c478bd9Sstevel@tonic-gate err = PICL_STALEHANDLE; 615*7c478bd9Sstevel@tonic-gate if ((pid != picld_pid) || (hash_val >= ptree_hdl_hi) || 616*7c478bd9Sstevel@tonic-gate (hash_val == NULL)) 617*7c478bd9Sstevel@tonic-gate err = PICL_INVALIDHANDLE; 618*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptreehdl_lock); 619*7c478bd9Sstevel@tonic-gate return (err); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate /* 623*7c478bd9Sstevel@tonic-gate * For a PICL handle, return the PTree handle and the PICL object 624*7c478bd9Sstevel@tonic-gate * Locks and releases the PICL table. 625*7c478bd9Sstevel@tonic-gate */ 626*7c478bd9Sstevel@tonic-gate int 627*7c478bd9Sstevel@tonic-gate cvt_picl2ptree(picl_hdl_t hdl, picl_hdl_t *ptree_hdl) 628*7c478bd9Sstevel@tonic-gate { 629*7c478bd9Sstevel@tonic-gate picl_hdl_t tmph; 630*7c478bd9Sstevel@tonic-gate int err; 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&picltbl_rwlock); /* lock picl */ 633*7c478bd9Sstevel@tonic-gate tmph = hash_lookup_hdl(&picltbl, hdl); 634*7c478bd9Sstevel@tonic-gate if (tmph == PICL_INVALID_PICLHDL) { 635*7c478bd9Sstevel@tonic-gate err = picl_hdl_error(hdl); 636*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); /* unlock picl */ 637*7c478bd9Sstevel@tonic-gate return (err); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate *ptree_hdl = tmph; 640*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); /* unlock picl */ 641*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate /* 645*7c478bd9Sstevel@tonic-gate * Allocate a ptree handle 646*7c478bd9Sstevel@tonic-gate */ 647*7c478bd9Sstevel@tonic-gate static picl_hdl_t 648*7c478bd9Sstevel@tonic-gate alloc_ptreehdl(void) 649*7c478bd9Sstevel@tonic-gate { 650*7c478bd9Sstevel@tonic-gate picl_hdl_t hdl; 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptreehdl_lock); /* lock ptreehdl */ 653*7c478bd9Sstevel@tonic-gate hdl = MAKE_HANDLE(picld_pid, ptree_hdl_hi); 654*7c478bd9Sstevel@tonic-gate ++ptree_hdl_hi; 655*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptreehdl_lock); /* unlock ptreehdl */ 656*7c478bd9Sstevel@tonic-gate return (hdl); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate /* 660*7c478bd9Sstevel@tonic-gate * Allocate a picl handle 661*7c478bd9Sstevel@tonic-gate * A PICL handle is ptree_hdl value with 1 in MSB of handle value. 662*7c478bd9Sstevel@tonic-gate * If a ptree handle already has 1 in MSB, then it cannot be piclized 663*7c478bd9Sstevel@tonic-gate * and the daemon must be restarted. 664*7c478bd9Sstevel@tonic-gate */ 665*7c478bd9Sstevel@tonic-gate static picl_hdl_t 666*7c478bd9Sstevel@tonic-gate alloc_piclhdl(void) 667*7c478bd9Sstevel@tonic-gate { 668*7c478bd9Sstevel@tonic-gate picl_hdl_t hdl; 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&piclhdl_lock); /* lock piclhdl */ 671*7c478bd9Sstevel@tonic-gate hdl = MAKE_HANDLE(picld_pid, picl_hdl_hi); 672*7c478bd9Sstevel@tonic-gate ++picl_hdl_hi; 673*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&piclhdl_lock); /* unlock piclhdl */ 674*7c478bd9Sstevel@tonic-gate return (hdl); 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate /* 678*7c478bd9Sstevel@tonic-gate * Allocate and add handle to PTree hash table 679*7c478bd9Sstevel@tonic-gate */ 680*7c478bd9Sstevel@tonic-gate static void 681*7c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(picl_obj_t *pobj) 682*7c478bd9Sstevel@tonic-gate { 683*7c478bd9Sstevel@tonic-gate pobj->ptree_hdl = alloc_ptreehdl(); 684*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); 685*7c478bd9Sstevel@tonic-gate (void) hash_add_newobj(&ptreetbl, pobj->ptree_hdl, pobj); 686*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate * Lock a picl node object 691*7c478bd9Sstevel@tonic-gate */ 692*7c478bd9Sstevel@tonic-gate static int 693*7c478bd9Sstevel@tonic-gate lock_obj(int rw, picl_obj_t *nodep) 694*7c478bd9Sstevel@tonic-gate { 695*7c478bd9Sstevel@tonic-gate if (rw == RDLOCK_NODE) 696*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&nodep->node_lock); 697*7c478bd9Sstevel@tonic-gate else if (rw == WRLOCK_NODE) 698*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&nodep->node_lock); 699*7c478bd9Sstevel@tonic-gate else 700*7c478bd9Sstevel@tonic-gate return (-1); 701*7c478bd9Sstevel@tonic-gate return (0); 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate /* 705*7c478bd9Sstevel@tonic-gate * Release the picl node object. 706*7c478bd9Sstevel@tonic-gate * This function may be called with a NULL object pointer. 707*7c478bd9Sstevel@tonic-gate */ 708*7c478bd9Sstevel@tonic-gate static void 709*7c478bd9Sstevel@tonic-gate unlock_node(picl_obj_t *nodep) 710*7c478bd9Sstevel@tonic-gate { 711*7c478bd9Sstevel@tonic-gate if (nodep == NULL) 712*7c478bd9Sstevel@tonic-gate return; 713*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&nodep->node_lock); 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate /* 717*7c478bd9Sstevel@tonic-gate * This function locks the node of a property and returns the node object 718*7c478bd9Sstevel@tonic-gate * and the property object. 719*7c478bd9Sstevel@tonic-gate */ 720*7c478bd9Sstevel@tonic-gate static int 721*7c478bd9Sstevel@tonic-gate lookup_and_lock_propnode(int rw, picl_prophdl_t proph, picl_obj_t **nodep, 722*7c478bd9Sstevel@tonic-gate picl_obj_t **propp) 723*7c478bd9Sstevel@tonic-gate { 724*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 725*7c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, proph); 728*7c478bd9Sstevel@tonic-gate if (pobj == NULL) 729*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(proph)); 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate /* 732*7c478bd9Sstevel@tonic-gate * Get the property's or table entry's node object 733*7c478bd9Sstevel@tonic-gate */ 734*7c478bd9Sstevel@tonic-gate nobj = NULL; 735*7c478bd9Sstevel@tonic-gate if (pobj->obj_type == PICL_OBJ_PROP) 736*7c478bd9Sstevel@tonic-gate nobj = pobj->prop_node; 737*7c478bd9Sstevel@tonic-gate else if (pobj->obj_type == (PICL_OBJ_PROP|PICL_OBJ_TABLEENTRY)) 738*7c478bd9Sstevel@tonic-gate nobj = pobj->prop_table->prop_node; 739*7c478bd9Sstevel@tonic-gate else { 740*7c478bd9Sstevel@tonic-gate *propp = pobj; /* return the prop */ 741*7c478bd9Sstevel@tonic-gate return (PICL_NOTPROP); 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate if (nobj && (lock_obj(rw, nobj) < 0)) /* Lock node */ 745*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate *nodep = nobj; 748*7c478bd9Sstevel@tonic-gate *propp = pobj; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * This function locks the node of a table and returns the node object 755*7c478bd9Sstevel@tonic-gate * and the table object. 756*7c478bd9Sstevel@tonic-gate */ 757*7c478bd9Sstevel@tonic-gate static int 758*7c478bd9Sstevel@tonic-gate lookup_and_lock_tablenode(int rw, picl_prophdl_t tblh, picl_obj_t **nodep, 759*7c478bd9Sstevel@tonic-gate picl_obj_t **tblobj) 760*7c478bd9Sstevel@tonic-gate { 761*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 762*7c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, tblh); 765*7c478bd9Sstevel@tonic-gate if (pobj == NULL) 766*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(tblh)); 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate /* 769*7c478bd9Sstevel@tonic-gate * Get the property's or table entry's node object 770*7c478bd9Sstevel@tonic-gate */ 771*7c478bd9Sstevel@tonic-gate nobj = NULL; 772*7c478bd9Sstevel@tonic-gate if (pobj->obj_type != PICL_OBJ_TABLE) 773*7c478bd9Sstevel@tonic-gate return (PICL_NOTTABLE); 774*7c478bd9Sstevel@tonic-gate nobj = pobj->prop_node; 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate if (nobj && (lock_obj(rw, nobj) < 0)) /* Lock node */ 777*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate *nodep = nobj; 780*7c478bd9Sstevel@tonic-gate *tblobj = pobj; 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate /* 786*7c478bd9Sstevel@tonic-gate * This locks the node of a table or a table entry and returns the 787*7c478bd9Sstevel@tonic-gate * node object and the table or table entry object 788*7c478bd9Sstevel@tonic-gate */ 789*7c478bd9Sstevel@tonic-gate static int 790*7c478bd9Sstevel@tonic-gate lookup_and_lock_tableprop_node(int rw, picl_prophdl_t tblproph, 791*7c478bd9Sstevel@tonic-gate picl_obj_t **nodep, picl_obj_t **tblpropp) 792*7c478bd9Sstevel@tonic-gate { 793*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 794*7c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, tblproph); 797*7c478bd9Sstevel@tonic-gate if (pobj == NULL) 798*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(tblproph)); 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* 801*7c478bd9Sstevel@tonic-gate * Get the property's or table entry's node object 802*7c478bd9Sstevel@tonic-gate */ 803*7c478bd9Sstevel@tonic-gate nobj = NULL; 804*7c478bd9Sstevel@tonic-gate if ((pobj->obj_type != PICL_OBJ_TABLE) && /* not a table */ 805*7c478bd9Sstevel@tonic-gate !(pobj->obj_type & PICL_OBJ_TABLEENTRY)) /* or an entry */ 806*7c478bd9Sstevel@tonic-gate return (PICL_NOTTABLE); 807*7c478bd9Sstevel@tonic-gate if (pobj->obj_type == PICL_OBJ_TABLE) 808*7c478bd9Sstevel@tonic-gate nobj = pobj->prop_node; 809*7c478bd9Sstevel@tonic-gate else 810*7c478bd9Sstevel@tonic-gate nobj = pobj->prop_table->prop_node; 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate if (nobj && (lock_obj(rw, nobj) < 0)) /* Lock node */ 813*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate *tblpropp = pobj; 816*7c478bd9Sstevel@tonic-gate *nodep = nobj; 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * Lock the node corresponding to the given handle and return its object 823*7c478bd9Sstevel@tonic-gate */ 824*7c478bd9Sstevel@tonic-gate static int 825*7c478bd9Sstevel@tonic-gate lookup_and_lock_node(int rw, picl_nodehdl_t nodeh, picl_obj_t **nodep) 826*7c478bd9Sstevel@tonic-gate { 827*7c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate nobj = hash_lookup_obj(&ptreetbl, nodeh); 830*7c478bd9Sstevel@tonic-gate if (nobj == NULL) 831*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(nodeh)); 832*7c478bd9Sstevel@tonic-gate else if (nobj->obj_type != PICL_OBJ_NODE) 833*7c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 834*7c478bd9Sstevel@tonic-gate if (lock_obj(rw, nobj) < 0) /* Lock node */ 835*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 836*7c478bd9Sstevel@tonic-gate *nodep = nobj; 837*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate /* 841*7c478bd9Sstevel@tonic-gate * Is the property name a restricted property name? 842*7c478bd9Sstevel@tonic-gate */ 843*7c478bd9Sstevel@tonic-gate static int 844*7c478bd9Sstevel@tonic-gate picl_restricted(const char *name) 845*7c478bd9Sstevel@tonic-gate { 846*7c478bd9Sstevel@tonic-gate if (strcmp(name, PICL_PROP_CLASSNAME) == 0) 847*7c478bd9Sstevel@tonic-gate return (0); /* not restricted */ 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate if ((name[0] == '_') && (strchr(&name[1], '_') == NULL)) 850*7c478bd9Sstevel@tonic-gate return (1); 851*7c478bd9Sstevel@tonic-gate return (0); 852*7c478bd9Sstevel@tonic-gate } 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate /* 855*7c478bd9Sstevel@tonic-gate * Check the value size with the property size 856*7c478bd9Sstevel@tonic-gate * Return PICL_INVALIDARG if the size does not match exactly for strongly 857*7c478bd9Sstevel@tonic-gate * typed properties. 858*7c478bd9Sstevel@tonic-gate * For charstring reads allow sizes that match the value size 859*7c478bd9Sstevel@tonic-gate * For bytearray return PICL_VALUETOOBIG 860*7c478bd9Sstevel@tonic-gate * if the size is greater than the buffer size. 861*7c478bd9Sstevel@tonic-gate */ 862*7c478bd9Sstevel@tonic-gate static int 863*7c478bd9Sstevel@tonic-gate check_propsize(int op, picl_obj_t *propp, size_t sz) 864*7c478bd9Sstevel@tonic-gate { 865*7c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) { 866*7c478bd9Sstevel@tonic-gate if (sz != propp->prop_size) 867*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 868*7c478bd9Sstevel@tonic-gate else 869*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate /* 873*7c478bd9Sstevel@tonic-gate * check size for non-volatile properties 874*7c478bd9Sstevel@tonic-gate */ 875*7c478bd9Sstevel@tonic-gate switch (propp->prop_type) { 876*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 877*7c478bd9Sstevel@tonic-gate if ((op == PROP_READ) && 878*7c478bd9Sstevel@tonic-gate (strlen(propp->prop_val) >= sz)) 879*7c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 880*7c478bd9Sstevel@tonic-gate if ((op == PROP_WRITE) && (sz > propp->prop_size)) 881*7c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 882*7c478bd9Sstevel@tonic-gate break; 883*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_BYTEARRAY: 884*7c478bd9Sstevel@tonic-gate if (op == PROP_WRITE) { 885*7c478bd9Sstevel@tonic-gate if (sz > propp->prop_size) 886*7c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 887*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); /* allow small writes */ 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate /* fall through for reads */ 890*7c478bd9Sstevel@tonic-gate default: 891*7c478bd9Sstevel@tonic-gate if (propp->prop_size != sz) 892*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 893*7c478bd9Sstevel@tonic-gate break; 894*7c478bd9Sstevel@tonic-gate } 895*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate void 899*7c478bd9Sstevel@tonic-gate cvt_ptree2picl(picl_hdl_t *handlep) 900*7c478bd9Sstevel@tonic-gate { 901*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); 904*7c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, *handlep); 905*7c478bd9Sstevel@tonic-gate if (pobj == NULL) 906*7c478bd9Sstevel@tonic-gate *handlep = PICL_INVALID_PICLHDL; 907*7c478bd9Sstevel@tonic-gate else 908*7c478bd9Sstevel@tonic-gate (void) memcpy(handlep, &pobj->picl_hdl, sizeof (*handlep)); 909*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 910*7c478bd9Sstevel@tonic-gate } 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate /* 913*7c478bd9Sstevel@tonic-gate * The caller of the piclize() set of functions is assumed to hold 914*7c478bd9Sstevel@tonic-gate * the ptree_rwlock(). 915*7c478bd9Sstevel@tonic-gate */ 916*7c478bd9Sstevel@tonic-gate static void 917*7c478bd9Sstevel@tonic-gate piclize_obj(picl_obj_t *pobj) 918*7c478bd9Sstevel@tonic-gate { 919*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&picltbl_rwlock); 920*7c478bd9Sstevel@tonic-gate pobj->picl_hdl = alloc_piclhdl(); 921*7c478bd9Sstevel@tonic-gate (void) hash_add_newhdl(&picltbl, pobj->picl_hdl, pobj->ptree_hdl); 922*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate static void 926*7c478bd9Sstevel@tonic-gate piclize_table(picl_obj_t *tbl_obj) 927*7c478bd9Sstevel@tonic-gate { 928*7c478bd9Sstevel@tonic-gate picl_obj_t *rowp; 929*7c478bd9Sstevel@tonic-gate picl_obj_t *colp; 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate for (rowp = tbl_obj->next_row; rowp != NULL; rowp = rowp->next_col) 932*7c478bd9Sstevel@tonic-gate for (colp = rowp; colp != NULL; colp = colp->next_row) 933*7c478bd9Sstevel@tonic-gate piclize_obj(colp); 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate static void 937*7c478bd9Sstevel@tonic-gate piclize_prop(picl_obj_t *propp) 938*7c478bd9Sstevel@tonic-gate { 939*7c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 940*7c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate piclize_obj(propp); 943*7c478bd9Sstevel@tonic-gate if (!(propp->prop_mode & PICL_VOLATILE) && 944*7c478bd9Sstevel@tonic-gate (propp->prop_type == PICL_PTYPE_TABLE)) { 945*7c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)propp->prop_val; 946*7c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 947*7c478bd9Sstevel@tonic-gate if (tbl_obj == NULL) 948*7c478bd9Sstevel@tonic-gate return; 949*7c478bd9Sstevel@tonic-gate piclize_obj(tbl_obj); 950*7c478bd9Sstevel@tonic-gate piclize_table(tbl_obj); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate /* 955*7c478bd9Sstevel@tonic-gate * Function to create PICL handles for a subtree and add them to 956*7c478bd9Sstevel@tonic-gate * the table 957*7c478bd9Sstevel@tonic-gate */ 958*7c478bd9Sstevel@tonic-gate static void 959*7c478bd9Sstevel@tonic-gate piclize_node(picl_obj_t *nodep) 960*7c478bd9Sstevel@tonic-gate { 961*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 962*7c478bd9Sstevel@tonic-gate picl_obj_t *chdp; 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate piclize_obj(nodep); 965*7c478bd9Sstevel@tonic-gate propp = nodep->first_prop; 966*7c478bd9Sstevel@tonic-gate while (propp != NULL) { 967*7c478bd9Sstevel@tonic-gate piclize_prop(propp); 968*7c478bd9Sstevel@tonic-gate propp = propp->next_prop; 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate /* go through the children */ 972*7c478bd9Sstevel@tonic-gate for (chdp = nodep->child_node; chdp != NULL; chdp = chdp->sibling_node) 973*7c478bd9Sstevel@tonic-gate piclize_node(chdp); 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate /* 977*7c478bd9Sstevel@tonic-gate * Function to remove PICL handles 978*7c478bd9Sstevel@tonic-gate */ 979*7c478bd9Sstevel@tonic-gate static void 980*7c478bd9Sstevel@tonic-gate unpiclize_obj(picl_obj_t *pobj) 981*7c478bd9Sstevel@tonic-gate { 982*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&picltbl_rwlock); 983*7c478bd9Sstevel@tonic-gate (void) hash_remove(&picltbl, pobj->picl_hdl); 984*7c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 985*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate static void 989*7c478bd9Sstevel@tonic-gate unpiclize_table(picl_obj_t *tbl_obj) 990*7c478bd9Sstevel@tonic-gate { 991*7c478bd9Sstevel@tonic-gate picl_obj_t *rowp; 992*7c478bd9Sstevel@tonic-gate picl_obj_t *colp; 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate for (rowp = tbl_obj->next_row; rowp != NULL; rowp = rowp->next_col) 995*7c478bd9Sstevel@tonic-gate for (colp = rowp; colp != NULL; colp = colp->next_row) 996*7c478bd9Sstevel@tonic-gate unpiclize_obj(colp); 997*7c478bd9Sstevel@tonic-gate unpiclize_obj(tbl_obj); 998*7c478bd9Sstevel@tonic-gate } 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate static void 1001*7c478bd9Sstevel@tonic-gate unpiclize_prop(picl_obj_t *propp) 1002*7c478bd9Sstevel@tonic-gate { 1003*7c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 1004*7c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate if (!IS_PICLIZED(propp)) 1007*7c478bd9Sstevel@tonic-gate return; 1008*7c478bd9Sstevel@tonic-gate unpiclize_obj(propp); 1009*7c478bd9Sstevel@tonic-gate if (!(propp->prop_mode & PICL_VOLATILE) && 1010*7c478bd9Sstevel@tonic-gate (propp->prop_type == PICL_PTYPE_TABLE)) { 1011*7c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)propp->prop_val; 1012*7c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 1013*7c478bd9Sstevel@tonic-gate unpiclize_table(tbl_obj); 1014*7c478bd9Sstevel@tonic-gate } 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate /* 1018*7c478bd9Sstevel@tonic-gate * Function to remove PICL handles for a subtree and its 1019*7c478bd9Sstevel@tonic-gate * properties 1020*7c478bd9Sstevel@tonic-gate */ 1021*7c478bd9Sstevel@tonic-gate static void 1022*7c478bd9Sstevel@tonic-gate unpiclize_node(picl_obj_t *nodep) 1023*7c478bd9Sstevel@tonic-gate { 1024*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1025*7c478bd9Sstevel@tonic-gate picl_obj_t *chdp; 1026*7c478bd9Sstevel@tonic-gate 1027*7c478bd9Sstevel@tonic-gate 1028*7c478bd9Sstevel@tonic-gate if (!IS_PICLIZED(nodep)) 1029*7c478bd9Sstevel@tonic-gate return; 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate unpiclize_obj(nodep); 1032*7c478bd9Sstevel@tonic-gate propp = nodep->first_prop; 1033*7c478bd9Sstevel@tonic-gate while (propp != NULL) { 1034*7c478bd9Sstevel@tonic-gate unpiclize_prop(propp); 1035*7c478bd9Sstevel@tonic-gate propp = propp->next_prop; 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate /* go through the children */ 1039*7c478bd9Sstevel@tonic-gate for (chdp = nodep->child_node; chdp != NULL; chdp = chdp->sibling_node) 1040*7c478bd9Sstevel@tonic-gate unpiclize_node(chdp); 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate /* 1045*7c478bd9Sstevel@tonic-gate * The caller holds the lock on the ptree_lock when calling this. 1046*7c478bd9Sstevel@tonic-gate * If ret is not NULL then this function returns the referenced object. 1047*7c478bd9Sstevel@tonic-gate */ 1048*7c478bd9Sstevel@tonic-gate static int 1049*7c478bd9Sstevel@tonic-gate lookup_verify_ref_prop(picl_obj_t *propp, picl_obj_t **ret) 1050*7c478bd9Sstevel@tonic-gate { 1051*7c478bd9Sstevel@tonic-gate picl_nodehdl_t refh; 1052*7c478bd9Sstevel@tonic-gate picl_obj_t *refobj; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate refh = *(picl_nodehdl_t *)propp->prop_val; 1055*7c478bd9Sstevel@tonic-gate refobj = hash_lookup_obj(&ptreetbl, refh); 1056*7c478bd9Sstevel@tonic-gate if (refobj == NULL) 1057*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(refh)); 1058*7c478bd9Sstevel@tonic-gate else if (refobj->obj_type != PICL_OBJ_NODE) 1059*7c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 1060*7c478bd9Sstevel@tonic-gate if (ret) 1061*7c478bd9Sstevel@tonic-gate *ret = refobj; 1062*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate /* 1066*7c478bd9Sstevel@tonic-gate * The caller holds the lock on ptree_lock when calling this. 1067*7c478bd9Sstevel@tonic-gate * If ret is not NULL, then this function returns the table object 1068*7c478bd9Sstevel@tonic-gate */ 1069*7c478bd9Sstevel@tonic-gate static int 1070*7c478bd9Sstevel@tonic-gate lookup_verify_table_prop(picl_obj_t *propp, picl_obj_t **ret) 1071*7c478bd9Sstevel@tonic-gate { 1072*7c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 1073*7c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)propp->prop_val; 1076*7c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 1077*7c478bd9Sstevel@tonic-gate if (tbl_obj == NULL) 1078*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(tblh)); 1079*7c478bd9Sstevel@tonic-gate else if (!(tbl_obj->obj_type & PICL_OBJ_TABLE)) 1080*7c478bd9Sstevel@tonic-gate return (PICL_NOTTABLE); 1081*7c478bd9Sstevel@tonic-gate if (ret) 1082*7c478bd9Sstevel@tonic-gate *ret = tbl_obj; 1083*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate static int 1087*7c478bd9Sstevel@tonic-gate lookup_verify_prop_handle(picl_prophdl_t proph, picl_obj_t **ret) 1088*7c478bd9Sstevel@tonic-gate { 1089*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate propp = hash_lookup_obj(&ptreetbl, proph); 1092*7c478bd9Sstevel@tonic-gate if (propp == NULL) 1093*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(proph)); 1094*7c478bd9Sstevel@tonic-gate else if (!(propp->obj_type & PICL_OBJ_PROP)) 1095*7c478bd9Sstevel@tonic-gate return (PICL_NOTPROP); 1096*7c478bd9Sstevel@tonic-gate if (ret) 1097*7c478bd9Sstevel@tonic-gate *ret = propp; 1098*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate static int 1102*7c478bd9Sstevel@tonic-gate lookup_verify_node_handle(picl_nodehdl_t nodeh, picl_obj_t **ret) 1103*7c478bd9Sstevel@tonic-gate { 1104*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate nodep = hash_lookup_obj(&ptreetbl, nodeh); 1107*7c478bd9Sstevel@tonic-gate if (nodep == NULL) 1108*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(nodeh)); 1109*7c478bd9Sstevel@tonic-gate else if (nodep->obj_type != PICL_OBJ_NODE) 1110*7c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 1111*7c478bd9Sstevel@tonic-gate if (ret) 1112*7c478bd9Sstevel@tonic-gate *ret = nodep; 1113*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate static int 1117*7c478bd9Sstevel@tonic-gate lookup_prop_by_name(picl_obj_t *nodep, const char *pname, picl_obj_t **ret) 1118*7c478bd9Sstevel@tonic-gate { 1119*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_PARENT) == 0) { 1122*7c478bd9Sstevel@tonic-gate if (nodep->parent_node == NULL) 1123*7c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 1124*7c478bd9Sstevel@tonic-gate else 1125*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_CHILD) == 0) { 1128*7c478bd9Sstevel@tonic-gate if (nodep->child_node == NULL) 1129*7c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 1130*7c478bd9Sstevel@tonic-gate else 1131*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_PEER) == 0) { 1134*7c478bd9Sstevel@tonic-gate if (nodep->sibling_node == NULL) 1135*7c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 1136*7c478bd9Sstevel@tonic-gate else 1137*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate propp = nodep->first_prop; 1141*7c478bd9Sstevel@tonic-gate while (propp != NULL) { 1142*7c478bd9Sstevel@tonic-gate if (strcmp(propp->prop_name, pname) == 0) { 1143*7c478bd9Sstevel@tonic-gate if (ret) 1144*7c478bd9Sstevel@tonic-gate *ret = propp; 1145*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate propp = propp->next_prop; 1148*7c478bd9Sstevel@tonic-gate } 1149*7c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate /* 1153*7c478bd9Sstevel@tonic-gate * This function locks the ptree, verifies that the handle is a reference 1154*7c478bd9Sstevel@tonic-gate * to a node of specified class name, releases the lock 1155*7c478bd9Sstevel@tonic-gate */ 1156*7c478bd9Sstevel@tonic-gate static int 1157*7c478bd9Sstevel@tonic-gate check_ref_handle(picl_nodehdl_t refh, char *clname) 1158*7c478bd9Sstevel@tonic-gate { 1159*7c478bd9Sstevel@tonic-gate picl_obj_t *refobj; 1160*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1161*7c478bd9Sstevel@tonic-gate int err; 1162*7c478bd9Sstevel@tonic-gate 1163*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* Lock ptree */ 1164*7c478bd9Sstevel@tonic-gate refobj = hash_lookup_obj(&ptreetbl, refh); 1165*7c478bd9Sstevel@tonic-gate if ((refobj == NULL) || !(refobj->obj_type & PICL_OBJ_NODE)) { 1166*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1167*7c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 1168*7c478bd9Sstevel@tonic-gate } 1169*7c478bd9Sstevel@tonic-gate 1170*7c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(refobj, PICL_PROP_CLASSNAME, &propp); 1171*7c478bd9Sstevel@tonic-gate if ((err != PICL_SUCCESS) || (propp->prop_val == NULL) || 1172*7c478bd9Sstevel@tonic-gate (strcmp(propp->prop_val, clname) != 0)) 1173*7c478bd9Sstevel@tonic-gate err = PICL_INVREFERENCE; 1174*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1175*7c478bd9Sstevel@tonic-gate return (err); 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate static int 1179*7c478bd9Sstevel@tonic-gate check_table_handle(picl_prophdl_t tblh) 1180*7c478bd9Sstevel@tonic-gate { 1181*7c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 1182*7c478bd9Sstevel@tonic-gate int err; 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); 1185*7c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 1186*7c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 1187*7c478bd9Sstevel@tonic-gate if ((tbl_obj == NULL) || !(tbl_obj->obj_type & PICL_OBJ_TABLE)) 1188*7c478bd9Sstevel@tonic-gate err = PICL_NOTTABLE; 1189*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1190*7c478bd9Sstevel@tonic-gate return (err); 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate /* 1194*7c478bd9Sstevel@tonic-gate * PICLTree Interface routines for plug-in modules 1195*7c478bd9Sstevel@tonic-gate */ 1196*7c478bd9Sstevel@tonic-gate int 1197*7c478bd9Sstevel@tonic-gate ptree_get_root(picl_nodehdl_t *rooth) 1198*7c478bd9Sstevel@tonic-gate { 1199*7c478bd9Sstevel@tonic-gate *rooth = ptree_root_hdl; 1200*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1201*7c478bd9Sstevel@tonic-gate } 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate /* 1204*7c478bd9Sstevel@tonic-gate * Lock free create a property object 1205*7c478bd9Sstevel@tonic-gate */ 1206*7c478bd9Sstevel@tonic-gate static int 1207*7c478bd9Sstevel@tonic-gate create_propobj(const ptree_propinfo_t *pinfo, const void *valbuf, 1208*7c478bd9Sstevel@tonic-gate picl_obj_t **pobjp) 1209*7c478bd9Sstevel@tonic-gate { 1210*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate if (pinfo->version != PTREE_PROPINFO_VERSION_1) 1213*7c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE) && 1216*7c478bd9Sstevel@tonic-gate (pinfo->piclinfo.type != PICL_PTYPE_VOID) && 1217*7c478bd9Sstevel@tonic-gate (valbuf == NULL)) 1218*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate pobj = malloc(sizeof (picl_obj_t)); 1221*7c478bd9Sstevel@tonic-gate if (pobj == NULL) 1222*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate pobj->obj_type = PICL_OBJ_PROP; 1225*7c478bd9Sstevel@tonic-gate pobj->pinfo_ver = pinfo->version; 1226*7c478bd9Sstevel@tonic-gate pobj->prop_type = pinfo->piclinfo.type; 1227*7c478bd9Sstevel@tonic-gate pobj->prop_mode = pinfo->piclinfo.accessmode; 1228*7c478bd9Sstevel@tonic-gate pobj->prop_size = pinfo->piclinfo.size; 1229*7c478bd9Sstevel@tonic-gate (void) strcpy(pobj->prop_name, pinfo->piclinfo.name); 1230*7c478bd9Sstevel@tonic-gate pobj->read_func = pinfo->read; 1231*7c478bd9Sstevel@tonic-gate pobj->write_func = pinfo->write; 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate pobj->prop_val = NULL; 1234*7c478bd9Sstevel@tonic-gate if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE)) { 1235*7c478bd9Sstevel@tonic-gate pobj->prop_val = malloc(pinfo->piclinfo.size); 1236*7c478bd9Sstevel@tonic-gate if (pobj->prop_val == NULL) { 1237*7c478bd9Sstevel@tonic-gate free(pobj); 1238*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 1239*7c478bd9Sstevel@tonic-gate } 1240*7c478bd9Sstevel@tonic-gate if (pobj->prop_type == PICL_PTYPE_CHARSTRING) 1241*7c478bd9Sstevel@tonic-gate (void) strlcpy(pobj->prop_val, valbuf, 1242*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.size); 1243*7c478bd9Sstevel@tonic-gate else 1244*7c478bd9Sstevel@tonic-gate (void) memcpy(pobj->prop_val, valbuf, 1245*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.size); 1246*7c478bd9Sstevel@tonic-gate } 1247*7c478bd9Sstevel@tonic-gate pobj->prop_node = NULL; 1248*7c478bd9Sstevel@tonic-gate pobj->ptree_hdl = PICL_INVALID_PICLHDL; 1249*7c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 1250*7c478bd9Sstevel@tonic-gate pobj->next_prop = NULL; 1251*7c478bd9Sstevel@tonic-gate pobj->next_row = NULL; 1252*7c478bd9Sstevel@tonic-gate pobj->next_col = NULL; 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate *pobjp = pobj; 1255*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1256*7c478bd9Sstevel@tonic-gate } 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate /* 1259*7c478bd9Sstevel@tonic-gate * Check for valid arguments, create a property object, 1260*7c478bd9Sstevel@tonic-gate * Lock ptree_rwlock, add the new property handle, release the lock 1261*7c478bd9Sstevel@tonic-gate * For reference properties and table properties, the handles are verified 1262*7c478bd9Sstevel@tonic-gate * before creating the property. 1263*7c478bd9Sstevel@tonic-gate */ 1264*7c478bd9Sstevel@tonic-gate int 1265*7c478bd9Sstevel@tonic-gate ptree_create_prop(const ptree_propinfo_t *pinfo, const void *valbuf, 1266*7c478bd9Sstevel@tonic-gate picl_prophdl_t *proph) 1267*7c478bd9Sstevel@tonic-gate { 1268*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 1269*7c478bd9Sstevel@tonic-gate picl_nodehdl_t refh; 1270*7c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 1271*7c478bd9Sstevel@tonic-gate int err; 1272*7c478bd9Sstevel@tonic-gate char *ptr; 1273*7c478bd9Sstevel@tonic-gate int refflag; 1274*7c478bd9Sstevel@tonic-gate char classname[PICL_PROPNAMELEN_MAX]; 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate if (pinfo == NULL) 1277*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 1278*7c478bd9Sstevel@tonic-gate if (pinfo->version != PTREE_PROPINFO_VERSION_1) 1279*7c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 1280*7c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.size >= PICL_PROPSIZE_MAX) 1281*7c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 1282*7c478bd9Sstevel@tonic-gate if (picl_restricted(pinfo->piclinfo.name)) 1283*7c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate refflag = 0; 1286*7c478bd9Sstevel@tonic-gate if ((pinfo->piclinfo.name[0] == '_') && 1287*7c478bd9Sstevel@tonic-gate (strchr(&pinfo->piclinfo.name[1], '_') != NULL)) 1288*7c478bd9Sstevel@tonic-gate refflag = 1; 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.type == PICL_PTYPE_REFERENCE) { 1291*7c478bd9Sstevel@tonic-gate if (refflag == 0) 1292*7c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 1293*7c478bd9Sstevel@tonic-gate /* 1294*7c478bd9Sstevel@tonic-gate * check valid reference handle for non-volatiles 1295*7c478bd9Sstevel@tonic-gate */ 1296*7c478bd9Sstevel@tonic-gate if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE)) { 1297*7c478bd9Sstevel@tonic-gate if (valbuf == NULL) 1298*7c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 1299*7c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.size != sizeof (picl_nodehdl_t)) 1300*7c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 1301*7c478bd9Sstevel@tonic-gate (void) strcpy(classname, pinfo->piclinfo.name); 1302*7c478bd9Sstevel@tonic-gate ptr = strchr(&classname[1], '_'); 1303*7c478bd9Sstevel@tonic-gate *ptr = '\0'; 1304*7c478bd9Sstevel@tonic-gate refh = *(picl_hdl_t *)valbuf; 1305*7c478bd9Sstevel@tonic-gate err = check_ref_handle(refh, &classname[1]); 1306*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 1307*7c478bd9Sstevel@tonic-gate return (err); 1308*7c478bd9Sstevel@tonic-gate } 1309*7c478bd9Sstevel@tonic-gate } else if (refflag == 1) 1310*7c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 1311*7c478bd9Sstevel@tonic-gate else if ((pinfo->piclinfo.type == PICL_PTYPE_TABLE) && 1312*7c478bd9Sstevel@tonic-gate (!(pinfo->piclinfo.accessmode & PICL_VOLATILE))) { 1313*7c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.size != sizeof (picl_prophdl_t)) 1314*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 1315*7c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)valbuf; 1316*7c478bd9Sstevel@tonic-gate err = check_table_handle(tblh); 1317*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 1318*7c478bd9Sstevel@tonic-gate return (err); 1319*7c478bd9Sstevel@tonic-gate } else if ((strcmp(pinfo->piclinfo.name, PICL_PROP_CLASSNAME) == 0) && 1320*7c478bd9Sstevel@tonic-gate ((pinfo->piclinfo.type != PICL_PTYPE_CHARSTRING) || 1321*7c478bd9Sstevel@tonic-gate (strlen(valbuf) >= PICL_CLASSNAMELEN_MAX))) 1322*7c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 1323*7c478bd9Sstevel@tonic-gate else if ((strcmp(pinfo->piclinfo.name, PICL_PROP_NAME) == 0) && 1324*7c478bd9Sstevel@tonic-gate (pinfo->piclinfo.type != PICL_PTYPE_CHARSTRING)) 1325*7c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 1326*7c478bd9Sstevel@tonic-gate /* 1327*7c478bd9Sstevel@tonic-gate * No locks held when you get here 1328*7c478bd9Sstevel@tonic-gate */ 1329*7c478bd9Sstevel@tonic-gate err = create_propobj(pinfo, valbuf, &pobj); 1330*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 1331*7c478bd9Sstevel@tonic-gate return (err); 1332*7c478bd9Sstevel@tonic-gate 1333*7c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(pobj); 1334*7c478bd9Sstevel@tonic-gate *proph = pobj->ptree_hdl; 1335*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1336*7c478bd9Sstevel@tonic-gate } 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate /* 1339*7c478bd9Sstevel@tonic-gate * Lock free routine to destroy table entries 1340*7c478bd9Sstevel@tonic-gate * This function removes the destroyed handles from the hash table 1341*7c478bd9Sstevel@tonic-gate * Uses lock free routines: hash_lookup() and hash_remove() 1342*7c478bd9Sstevel@tonic-gate */ 1343*7c478bd9Sstevel@tonic-gate static void 1344*7c478bd9Sstevel@tonic-gate destroy_table(picl_obj_t *pobj) 1345*7c478bd9Sstevel@tonic-gate { 1346*7c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 1347*7c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 1348*7c478bd9Sstevel@tonic-gate picl_obj_t *rowp; 1349*7c478bd9Sstevel@tonic-gate picl_obj_t *colp; 1350*7c478bd9Sstevel@tonic-gate picl_obj_t *freep; 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)pobj->prop_val; 1353*7c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 1354*7c478bd9Sstevel@tonic-gate if (tbl_obj == NULL) 1355*7c478bd9Sstevel@tonic-gate return; 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate assert(tbl_obj->obj_type & PICL_OBJ_TABLE); 1358*7c478bd9Sstevel@tonic-gate 1359*7c478bd9Sstevel@tonic-gate /* Delete all entries */ 1360*7c478bd9Sstevel@tonic-gate rowp = tbl_obj->next_row; 1361*7c478bd9Sstevel@tonic-gate while (rowp != NULL) { 1362*7c478bd9Sstevel@tonic-gate colp = rowp; 1363*7c478bd9Sstevel@tonic-gate rowp = rowp->next_col; 1364*7c478bd9Sstevel@tonic-gate while (colp != NULL) { 1365*7c478bd9Sstevel@tonic-gate freep = colp; 1366*7c478bd9Sstevel@tonic-gate colp = colp->next_row; 1367*7c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, freep->ptree_hdl); 1368*7c478bd9Sstevel@tonic-gate if (freep->prop_val) 1369*7c478bd9Sstevel@tonic-gate free(freep->prop_val); 1370*7c478bd9Sstevel@tonic-gate free(freep); 1371*7c478bd9Sstevel@tonic-gate } 1372*7c478bd9Sstevel@tonic-gate } 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, tbl_obj->ptree_hdl); 1375*7c478bd9Sstevel@tonic-gate free(tbl_obj); 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate 1379*7c478bd9Sstevel@tonic-gate /* 1380*7c478bd9Sstevel@tonic-gate * Lock free function that frees up a property object and removes the 1381*7c478bd9Sstevel@tonic-gate * handles from Ptree table 1382*7c478bd9Sstevel@tonic-gate */ 1383*7c478bd9Sstevel@tonic-gate static void 1384*7c478bd9Sstevel@tonic-gate destroy_propobj(picl_obj_t *propp) 1385*7c478bd9Sstevel@tonic-gate { 1386*7c478bd9Sstevel@tonic-gate if (propp->prop_type == PICL_PTYPE_TABLE) 1387*7c478bd9Sstevel@tonic-gate destroy_table(propp); 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, propp->ptree_hdl); 1390*7c478bd9Sstevel@tonic-gate if (propp->prop_val) 1391*7c478bd9Sstevel@tonic-gate free(propp->prop_val); 1392*7c478bd9Sstevel@tonic-gate free(propp); 1393*7c478bd9Sstevel@tonic-gate } 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate /* 1396*7c478bd9Sstevel@tonic-gate * This function destroys a previously deleted property. 1397*7c478bd9Sstevel@tonic-gate * A deleted property does not have an associated node. 1398*7c478bd9Sstevel@tonic-gate * All memory allocated for this property are freed 1399*7c478bd9Sstevel@tonic-gate */ 1400*7c478bd9Sstevel@tonic-gate int 1401*7c478bd9Sstevel@tonic-gate ptree_destroy_prop(picl_prophdl_t proph) 1402*7c478bd9Sstevel@tonic-gate { 1403*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1404*7c478bd9Sstevel@tonic-gate 1405*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* Exclusive Lock ptree */ 1406*7c478bd9Sstevel@tonic-gate 1407*7c478bd9Sstevel@tonic-gate propp = hash_lookup_obj(&ptreetbl, proph); 1408*7c478bd9Sstevel@tonic-gate if (propp == NULL) { 1409*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 1410*7c478bd9Sstevel@tonic-gate return (ptree_hdl_error(proph)); 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate /* Is the prop still attached to a node? */ 1414*7c478bd9Sstevel@tonic-gate if (propp->prop_node != NULL) { 1415*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 1416*7c478bd9Sstevel@tonic-gate return (PICL_CANTDESTROY); 1417*7c478bd9Sstevel@tonic-gate } 1418*7c478bd9Sstevel@tonic-gate 1419*7c478bd9Sstevel@tonic-gate destroy_propobj(propp); 1420*7c478bd9Sstevel@tonic-gate 1421*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 1422*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1423*7c478bd9Sstevel@tonic-gate } 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate /* 1426*7c478bd9Sstevel@tonic-gate * This function adds a property to the property list of a node and adds 1427*7c478bd9Sstevel@tonic-gate * it to the PICL table if the node has a PICL handle. 1428*7c478bd9Sstevel@tonic-gate * This function locks the picl_rwlock and ptree_rwlock. 1429*7c478bd9Sstevel@tonic-gate */ 1430*7c478bd9Sstevel@tonic-gate int 1431*7c478bd9Sstevel@tonic-gate ptree_add_prop(picl_nodehdl_t nodeh, picl_prophdl_t proph) 1432*7c478bd9Sstevel@tonic-gate { 1433*7c478bd9Sstevel@tonic-gate int err; 1434*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1435*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1436*7c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 1437*7c478bd9Sstevel@tonic-gate picl_obj_t *refobj; 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* RDLock ptree */ 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate /* 1442*7c478bd9Sstevel@tonic-gate * Verify property handle 1443*7c478bd9Sstevel@tonic-gate */ 1444*7c478bd9Sstevel@tonic-gate err = lookup_verify_prop_handle(proph, &propp); 1445*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1446*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 1447*7c478bd9Sstevel@tonic-gate return (err); 1448*7c478bd9Sstevel@tonic-gate } 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate if (propp->prop_node != NULL) { 1451*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1452*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 1453*7c478bd9Sstevel@tonic-gate } 1454*7c478bd9Sstevel@tonic-gate 1455*7c478bd9Sstevel@tonic-gate nodep = NULL; 1456*7c478bd9Sstevel@tonic-gate /* 1457*7c478bd9Sstevel@tonic-gate * Exclusive Lock the node's properties 1458*7c478bd9Sstevel@tonic-gate */ 1459*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(WRLOCK_NODE, nodeh, &nodep); 1460*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1461*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 1462*7c478bd9Sstevel@tonic-gate return (err); 1463*7c478bd9Sstevel@tonic-gate } 1464*7c478bd9Sstevel@tonic-gate 1465*7c478bd9Sstevel@tonic-gate /* 1466*7c478bd9Sstevel@tonic-gate * check if prop already exists 1467*7c478bd9Sstevel@tonic-gate */ 1468*7c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, propp->prop_name, NULL); 1469*7c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 1470*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 1471*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 1472*7c478bd9Sstevel@tonic-gate return (PICL_PROPEXISTS); 1473*7c478bd9Sstevel@tonic-gate } 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate /* 1476*7c478bd9Sstevel@tonic-gate * Verify property's value 1477*7c478bd9Sstevel@tonic-gate */ 1478*7c478bd9Sstevel@tonic-gate tbl_obj = NULL; 1479*7c478bd9Sstevel@tonic-gate switch (propp->prop_type) { 1480*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_TABLE: 1481*7c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) 1482*7c478bd9Sstevel@tonic-gate break; 1483*7c478bd9Sstevel@tonic-gate err = lookup_verify_table_prop(propp, &tbl_obj); 1484*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1485*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 1486*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1487*7c478bd9Sstevel@tonic-gate return (err); 1488*7c478bd9Sstevel@tonic-gate } 1489*7c478bd9Sstevel@tonic-gate tbl_obj->prop_node = nodep; /* set table's nodep */ 1490*7c478bd9Sstevel@tonic-gate tbl_obj->table_prop = propp; /* set table prop */ 1491*7c478bd9Sstevel@tonic-gate break; 1492*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_REFERENCE: 1493*7c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) 1494*7c478bd9Sstevel@tonic-gate break; 1495*7c478bd9Sstevel@tonic-gate err = lookup_verify_ref_prop(propp, &refobj); 1496*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1497*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 1498*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1499*7c478bd9Sstevel@tonic-gate return (err); 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate if (IS_PICLIZED(nodep) && !IS_PICLIZED(refobj)) { 1502*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 1503*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1504*7c478bd9Sstevel@tonic-gate return (err); 1505*7c478bd9Sstevel@tonic-gate } 1506*7c478bd9Sstevel@tonic-gate break; 1507*7c478bd9Sstevel@tonic-gate default: 1508*7c478bd9Sstevel@tonic-gate break; 1509*7c478bd9Sstevel@tonic-gate } 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate if (IS_PICLIZED(nodep)) 1512*7c478bd9Sstevel@tonic-gate piclize_prop(propp); 1513*7c478bd9Sstevel@tonic-gate /* 1514*7c478bd9Sstevel@tonic-gate * Add prop to beginning of list 1515*7c478bd9Sstevel@tonic-gate */ 1516*7c478bd9Sstevel@tonic-gate propp->prop_node = nodep; /* set prop's nodep */ 1517*7c478bd9Sstevel@tonic-gate propp->next_prop = nodep->first_prop; 1518*7c478bd9Sstevel@tonic-gate nodep->first_prop = propp; 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 1521*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 1522*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1523*7c478bd9Sstevel@tonic-gate } 1524*7c478bd9Sstevel@tonic-gate 1525*7c478bd9Sstevel@tonic-gate /* 1526*7c478bd9Sstevel@tonic-gate * Lock free function that unlinks a property from its node 1527*7c478bd9Sstevel@tonic-gate */ 1528*7c478bd9Sstevel@tonic-gate static int 1529*7c478bd9Sstevel@tonic-gate unlink_prop(picl_obj_t *nodep, picl_obj_t *propp) 1530*7c478bd9Sstevel@tonic-gate { 1531*7c478bd9Sstevel@tonic-gate picl_obj_t *iterp; 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate iterp = nodep->first_prop; 1534*7c478bd9Sstevel@tonic-gate if (iterp == propp) { /* first property */ 1535*7c478bd9Sstevel@tonic-gate nodep->first_prop = iterp->next_prop; 1536*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1537*7c478bd9Sstevel@tonic-gate } 1538*7c478bd9Sstevel@tonic-gate while ((iterp != NULL) && (iterp->next_prop != propp)) 1539*7c478bd9Sstevel@tonic-gate iterp = iterp->next_prop; 1540*7c478bd9Sstevel@tonic-gate if (iterp == NULL) 1541*7c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 1542*7c478bd9Sstevel@tonic-gate iterp->next_prop = propp->next_prop; 1543*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1544*7c478bd9Sstevel@tonic-gate } 1545*7c478bd9Sstevel@tonic-gate 1546*7c478bd9Sstevel@tonic-gate /* 1547*7c478bd9Sstevel@tonic-gate * This function deletes the specified property from the property list 1548*7c478bd9Sstevel@tonic-gate * of its node and removes the handle from PICL table, if the node 1549*7c478bd9Sstevel@tonic-gate * was piclized. 1550*7c478bd9Sstevel@tonic-gate */ 1551*7c478bd9Sstevel@tonic-gate int 1552*7c478bd9Sstevel@tonic-gate ptree_delete_prop(picl_prophdl_t proph) 1553*7c478bd9Sstevel@tonic-gate { 1554*7c478bd9Sstevel@tonic-gate int err; 1555*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1556*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 1559*7c478bd9Sstevel@tonic-gate /* 1560*7c478bd9Sstevel@tonic-gate * Lookup the property's node and lock it if there is one 1561*7c478bd9Sstevel@tonic-gate * return the objects for the property and the node 1562*7c478bd9Sstevel@tonic-gate */ 1563*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 1564*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(WRLOCK_NODE, proph, &nodep, &propp); 1565*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1566*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1567*7c478bd9Sstevel@tonic-gate return (err); 1568*7c478bd9Sstevel@tonic-gate } else if (nodep == NULL) { 1569*7c478bd9Sstevel@tonic-gate /* Nothing to do - already deleted! */ 1570*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1571*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1572*7c478bd9Sstevel@tonic-gate } 1573*7c478bd9Sstevel@tonic-gate 1574*7c478bd9Sstevel@tonic-gate if (propp->obj_type & PICL_OBJ_TABLEENTRY) { 1575*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 1576*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1577*7c478bd9Sstevel@tonic-gate return (PICL_NOTPROP); 1578*7c478bd9Sstevel@tonic-gate } 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate err = unlink_prop(nodep, propp); 1581*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1582*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 1583*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1584*7c478bd9Sstevel@tonic-gate return (err); 1585*7c478bd9Sstevel@tonic-gate } 1586*7c478bd9Sstevel@tonic-gate 1587*7c478bd9Sstevel@tonic-gate propp->prop_node = NULL; /* reset prop's nodep */ 1588*7c478bd9Sstevel@tonic-gate propp->next_prop = NULL; 1589*7c478bd9Sstevel@tonic-gate 1590*7c478bd9Sstevel@tonic-gate unpiclize_prop(propp); 1591*7c478bd9Sstevel@tonic-gate 1592*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 1593*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1594*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate 1597*7c478bd9Sstevel@tonic-gate /* 1598*7c478bd9Sstevel@tonic-gate * Create a table object and return its handle 1599*7c478bd9Sstevel@tonic-gate */ 1600*7c478bd9Sstevel@tonic-gate int 1601*7c478bd9Sstevel@tonic-gate ptree_create_table(picl_prophdl_t *tblh) 1602*7c478bd9Sstevel@tonic-gate { 1603*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 1604*7c478bd9Sstevel@tonic-gate 1605*7c478bd9Sstevel@tonic-gate pobj = malloc(sizeof (picl_obj_t)); 1606*7c478bd9Sstevel@tonic-gate if (pobj == NULL) 1607*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 1608*7c478bd9Sstevel@tonic-gate pobj->obj_type = PICL_OBJ_TABLE; 1609*7c478bd9Sstevel@tonic-gate pobj->prop_val = NULL; 1610*7c478bd9Sstevel@tonic-gate pobj->prop_node = NULL; 1611*7c478bd9Sstevel@tonic-gate pobj->ptree_hdl = PICL_INVALID_PICLHDL; 1612*7c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 1613*7c478bd9Sstevel@tonic-gate pobj->table_prop = NULL; 1614*7c478bd9Sstevel@tonic-gate pobj->next_row = NULL; 1615*7c478bd9Sstevel@tonic-gate pobj->next_col = NULL; 1616*7c478bd9Sstevel@tonic-gate 1617*7c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(pobj); 1618*7c478bd9Sstevel@tonic-gate *tblh = pobj->ptree_hdl; 1619*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1620*7c478bd9Sstevel@tonic-gate } 1621*7c478bd9Sstevel@tonic-gate 1622*7c478bd9Sstevel@tonic-gate /* 1623*7c478bd9Sstevel@tonic-gate * Add the properties in <props> array as a row in the table 1624*7c478bd9Sstevel@tonic-gate * Add PICL handles if the table has a valid PICL handle 1625*7c478bd9Sstevel@tonic-gate */ 1626*7c478bd9Sstevel@tonic-gate int 1627*7c478bd9Sstevel@tonic-gate ptree_add_row_to_table(picl_prophdl_t tblh, int nprops, 1628*7c478bd9Sstevel@tonic-gate const picl_prophdl_t *props) 1629*7c478bd9Sstevel@tonic-gate { 1630*7c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 1631*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1632*7c478bd9Sstevel@tonic-gate picl_obj_t *lastrow; 1633*7c478bd9Sstevel@tonic-gate picl_obj_t **newrow; 1634*7c478bd9Sstevel@tonic-gate int i; 1635*7c478bd9Sstevel@tonic-gate int err; 1636*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 1637*7c478bd9Sstevel@tonic-gate int picl_it; 1638*7c478bd9Sstevel@tonic-gate 1639*7c478bd9Sstevel@tonic-gate if (nprops < 1) 1640*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 1641*7c478bd9Sstevel@tonic-gate 1642*7c478bd9Sstevel@tonic-gate newrow = malloc(sizeof (picl_obj_t *) * nprops); 1643*7c478bd9Sstevel@tonic-gate if (newrow == NULL) 1644*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* Lock ptree */ 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_tablenode(WRLOCK_NODE, tblh, &nodep, &tbl_obj); 1649*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1650*7c478bd9Sstevel@tonic-gate free(newrow); 1651*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 1652*7c478bd9Sstevel@tonic-gate return (err); 1653*7c478bd9Sstevel@tonic-gate } 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate /* 1656*7c478bd9Sstevel@tonic-gate * make sure all are either props or table handles 1657*7c478bd9Sstevel@tonic-gate */ 1658*7c478bd9Sstevel@tonic-gate for (i = 0; i < nprops; ++i) { 1659*7c478bd9Sstevel@tonic-gate pobj = newrow[i] = hash_lookup_obj(&ptreetbl, props[i]); 1660*7c478bd9Sstevel@tonic-gate if (pobj == NULL) { /* no object */ 1661*7c478bd9Sstevel@tonic-gate err = ptree_hdl_error(props[i]); 1662*7c478bd9Sstevel@tonic-gate break; 1663*7c478bd9Sstevel@tonic-gate } 1664*7c478bd9Sstevel@tonic-gate if ((!(pobj->obj_type & PICL_OBJ_PROP)) && 1665*7c478bd9Sstevel@tonic-gate (!(pobj->obj_type & PICL_OBJ_TABLE))) { 1666*7c478bd9Sstevel@tonic-gate err = PICL_NOTPROP; 1667*7c478bd9Sstevel@tonic-gate break; 1668*7c478bd9Sstevel@tonic-gate } 1669*7c478bd9Sstevel@tonic-gate if (IS_PICLIZED(pobj) || (pobj->prop_table != NULL) || 1670*7c478bd9Sstevel@tonic-gate (pobj->prop_node != NULL)) { 1671*7c478bd9Sstevel@tonic-gate err = PICL_INVALIDARG; 1672*7c478bd9Sstevel@tonic-gate break; 1673*7c478bd9Sstevel@tonic-gate } 1674*7c478bd9Sstevel@tonic-gate 1675*7c478bd9Sstevel@tonic-gate } 1676*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1677*7c478bd9Sstevel@tonic-gate free(newrow); 1678*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 1679*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 1680*7c478bd9Sstevel@tonic-gate return (err); 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate /* 1684*7c478bd9Sstevel@tonic-gate * Mark all props as table entries, set up row linkages 1685*7c478bd9Sstevel@tonic-gate */ 1686*7c478bd9Sstevel@tonic-gate picl_it = 0; 1687*7c478bd9Sstevel@tonic-gate if (IS_PICLIZED(tbl_obj)) 1688*7c478bd9Sstevel@tonic-gate picl_it = 1; 1689*7c478bd9Sstevel@tonic-gate for (i = 0; i < nprops; ++i) { 1690*7c478bd9Sstevel@tonic-gate newrow[i]->obj_type |= PICL_OBJ_TABLEENTRY; 1691*7c478bd9Sstevel@tonic-gate newrow[i]->prop_table = tbl_obj; 1692*7c478bd9Sstevel@tonic-gate newrow[i]->next_prop = NULL; 1693*7c478bd9Sstevel@tonic-gate newrow[i]->next_col = NULL; 1694*7c478bd9Sstevel@tonic-gate if (picl_it) 1695*7c478bd9Sstevel@tonic-gate piclize_obj(newrow[i]); 1696*7c478bd9Sstevel@tonic-gate if (i != nprops - 1) 1697*7c478bd9Sstevel@tonic-gate newrow[i]->next_row = newrow[i+1]; 1698*7c478bd9Sstevel@tonic-gate } 1699*7c478bd9Sstevel@tonic-gate newrow[nprops - 1]->next_row = NULL; 1700*7c478bd9Sstevel@tonic-gate 1701*7c478bd9Sstevel@tonic-gate if (tbl_obj->next_row == NULL) { /* add first row */ 1702*7c478bd9Sstevel@tonic-gate tbl_obj->next_row = newrow[0]; 1703*7c478bd9Sstevel@tonic-gate tbl_obj->next_col = newrow[0]; 1704*7c478bd9Sstevel@tonic-gate } else { 1705*7c478bd9Sstevel@tonic-gate lastrow = tbl_obj->next_row; 1706*7c478bd9Sstevel@tonic-gate while (lastrow->next_col != NULL) 1707*7c478bd9Sstevel@tonic-gate lastrow = lastrow->next_col; 1708*7c478bd9Sstevel@tonic-gate i = 0; 1709*7c478bd9Sstevel@tonic-gate while (lastrow != NULL) { 1710*7c478bd9Sstevel@tonic-gate lastrow->next_col = newrow[i]; 1711*7c478bd9Sstevel@tonic-gate lastrow = lastrow->next_row; 1712*7c478bd9Sstevel@tonic-gate ++i; 1713*7c478bd9Sstevel@tonic-gate } 1714*7c478bd9Sstevel@tonic-gate } 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 1717*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 1718*7c478bd9Sstevel@tonic-gate free(newrow); 1719*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1720*7c478bd9Sstevel@tonic-gate } 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate /* 1723*7c478bd9Sstevel@tonic-gate * This function returns the handle of the next property in the row 1724*7c478bd9Sstevel@tonic-gate */ 1725*7c478bd9Sstevel@tonic-gate int 1726*7c478bd9Sstevel@tonic-gate ptree_get_next_by_row(picl_prophdl_t proph, picl_prophdl_t *nextrowh) 1727*7c478bd9Sstevel@tonic-gate { 1728*7c478bd9Sstevel@tonic-gate int err; 1729*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1730*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 1733*7c478bd9Sstevel@tonic-gate 1734*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 1735*7c478bd9Sstevel@tonic-gate /* 1736*7c478bd9Sstevel@tonic-gate * proph could be a table handle or a table entry handle 1737*7c478bd9Sstevel@tonic-gate * Look it up as a table entry handle first, check error code 1738*7c478bd9Sstevel@tonic-gate * to see if it is a table handle 1739*7c478bd9Sstevel@tonic-gate */ 1740*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_tableprop_node(RDLOCK_NODE, proph, &nodep, 1741*7c478bd9Sstevel@tonic-gate &propp); 1742*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1743*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1744*7c478bd9Sstevel@tonic-gate return (err); 1745*7c478bd9Sstevel@tonic-gate } 1746*7c478bd9Sstevel@tonic-gate 1747*7c478bd9Sstevel@tonic-gate if (propp->next_row) 1748*7c478bd9Sstevel@tonic-gate *nextrowh = propp->next_row->ptree_hdl; 1749*7c478bd9Sstevel@tonic-gate else 1750*7c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 1751*7c478bd9Sstevel@tonic-gate 1752*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 1753*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1754*7c478bd9Sstevel@tonic-gate return (err); 1755*7c478bd9Sstevel@tonic-gate } 1756*7c478bd9Sstevel@tonic-gate 1757*7c478bd9Sstevel@tonic-gate int 1758*7c478bd9Sstevel@tonic-gate ptree_get_next_by_col(picl_prophdl_t proph, picl_prophdl_t *nextcolh) 1759*7c478bd9Sstevel@tonic-gate { 1760*7c478bd9Sstevel@tonic-gate int err; 1761*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 1762*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1763*7c478bd9Sstevel@tonic-gate 1764*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 1765*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 1766*7c478bd9Sstevel@tonic-gate /* 1767*7c478bd9Sstevel@tonic-gate * proph could be a table handle or a table entry handle 1768*7c478bd9Sstevel@tonic-gate * Look it up as a table entry handle first, check error code 1769*7c478bd9Sstevel@tonic-gate * to see if it is a table handle 1770*7c478bd9Sstevel@tonic-gate */ 1771*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_tableprop_node(RDLOCK_NODE, proph, &nodep, 1772*7c478bd9Sstevel@tonic-gate &propp); 1773*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1774*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 1775*7c478bd9Sstevel@tonic-gate return (err); 1776*7c478bd9Sstevel@tonic-gate } 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate if (propp->next_col) 1779*7c478bd9Sstevel@tonic-gate *nextcolh = propp->next_col->ptree_hdl; 1780*7c478bd9Sstevel@tonic-gate else 1781*7c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 1784*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1785*7c478bd9Sstevel@tonic-gate return (err); 1786*7c478bd9Sstevel@tonic-gate } 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate /* 1789*7c478bd9Sstevel@tonic-gate * This function creates node object and adds its handle to the Ptree 1790*7c478bd9Sstevel@tonic-gate */ 1791*7c478bd9Sstevel@tonic-gate int 1792*7c478bd9Sstevel@tonic-gate ptree_create_node(const char *name, const char *clname, picl_nodehdl_t *nodeh) 1793*7c478bd9Sstevel@tonic-gate { 1794*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 1795*7c478bd9Sstevel@tonic-gate ptree_propinfo_t propinfo; 1796*7c478bd9Sstevel@tonic-gate picl_prophdl_t phdl; 1797*7c478bd9Sstevel@tonic-gate picl_prophdl_t cphdl; 1798*7c478bd9Sstevel@tonic-gate int err; 1799*7c478bd9Sstevel@tonic-gate 1800*7c478bd9Sstevel@tonic-gate if ((name == NULL) || (*name == '\0') || 1801*7c478bd9Sstevel@tonic-gate (clname == NULL) || (*clname == '\0')) 1802*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate if ((strlen(name) >= PICL_PROPNAMELEN_MAX) || 1805*7c478bd9Sstevel@tonic-gate (strlen(clname) >= PICL_CLASSNAMELEN_MAX)) 1806*7c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 1807*7c478bd9Sstevel@tonic-gate 1808*7c478bd9Sstevel@tonic-gate /* 1809*7c478bd9Sstevel@tonic-gate * Create the picl object for node 1810*7c478bd9Sstevel@tonic-gate */ 1811*7c478bd9Sstevel@tonic-gate pobj = malloc(sizeof (picl_obj_t)); 1812*7c478bd9Sstevel@tonic-gate if (pobj == NULL) 1813*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 1814*7c478bd9Sstevel@tonic-gate pobj->obj_type = PICL_OBJ_NODE; 1815*7c478bd9Sstevel@tonic-gate pobj->first_prop = NULL; 1816*7c478bd9Sstevel@tonic-gate pobj->ptree_hdl = PICL_INVALID_PICLHDL; 1817*7c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 1818*7c478bd9Sstevel@tonic-gate pobj->parent_node = NULL; 1819*7c478bd9Sstevel@tonic-gate pobj->sibling_node = NULL; 1820*7c478bd9Sstevel@tonic-gate pobj->child_node = NULL; 1821*7c478bd9Sstevel@tonic-gate pobj->node_classname = strdup(clname); 1822*7c478bd9Sstevel@tonic-gate if (pobj->node_classname == NULL) { 1823*7c478bd9Sstevel@tonic-gate free(pobj); 1824*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 1825*7c478bd9Sstevel@tonic-gate } 1826*7c478bd9Sstevel@tonic-gate (void) rwlock_init(&pobj->node_lock, USYNC_THREAD, NULL); 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(pobj); /* commit the node */ 1829*7c478bd9Sstevel@tonic-gate 1830*7c478bd9Sstevel@tonic-gate /* 1831*7c478bd9Sstevel@tonic-gate * create name property 1832*7c478bd9Sstevel@tonic-gate */ 1833*7c478bd9Sstevel@tonic-gate propinfo.version = PTREE_PROPINFO_VERSION_1; 1834*7c478bd9Sstevel@tonic-gate propinfo.piclinfo.type = PICL_PTYPE_CHARSTRING; 1835*7c478bd9Sstevel@tonic-gate propinfo.piclinfo.accessmode = PICL_READ; 1836*7c478bd9Sstevel@tonic-gate propinfo.piclinfo.size = strlen(name) + 1; 1837*7c478bd9Sstevel@tonic-gate (void) strcpy(propinfo.piclinfo.name, PICL_PROP_NAME); 1838*7c478bd9Sstevel@tonic-gate propinfo.read = NULL; 1839*7c478bd9Sstevel@tonic-gate propinfo.write = NULL; 1840*7c478bd9Sstevel@tonic-gate err = ptree_create_prop(&propinfo, (const void *)name, &phdl); 1841*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1842*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 1843*7c478bd9Sstevel@tonic-gate return (err); 1844*7c478bd9Sstevel@tonic-gate } 1845*7c478bd9Sstevel@tonic-gate err = ptree_add_prop(pobj->ptree_hdl, phdl); 1846*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1847*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_prop(phdl); 1848*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 1849*7c478bd9Sstevel@tonic-gate return (err); 1850*7c478bd9Sstevel@tonic-gate } 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate /* 1853*7c478bd9Sstevel@tonic-gate * create picl classname property 1854*7c478bd9Sstevel@tonic-gate */ 1855*7c478bd9Sstevel@tonic-gate propinfo.piclinfo.size = strlen(clname) + 1; 1856*7c478bd9Sstevel@tonic-gate (void) strcpy(propinfo.piclinfo.name, PICL_PROP_CLASSNAME); 1857*7c478bd9Sstevel@tonic-gate propinfo.read = NULL; 1858*7c478bd9Sstevel@tonic-gate propinfo.write = NULL; 1859*7c478bd9Sstevel@tonic-gate err = ptree_create_prop(&propinfo, (const void *)clname, &cphdl); 1860*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1861*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 1862*7c478bd9Sstevel@tonic-gate return (err); 1863*7c478bd9Sstevel@tonic-gate } 1864*7c478bd9Sstevel@tonic-gate err = ptree_add_prop(pobj->ptree_hdl, cphdl); 1865*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1866*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_prop(cphdl); 1867*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 1868*7c478bd9Sstevel@tonic-gate return (err); 1869*7c478bd9Sstevel@tonic-gate } 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate *nodeh = pobj->ptree_hdl; 1872*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1873*7c478bd9Sstevel@tonic-gate } 1874*7c478bd9Sstevel@tonic-gate 1875*7c478bd9Sstevel@tonic-gate /* 1876*7c478bd9Sstevel@tonic-gate * Destroy a node/subtree freeing up space 1877*7c478bd9Sstevel@tonic-gate * Removed destroyed objects' handles from PTree table 1878*7c478bd9Sstevel@tonic-gate */ 1879*7c478bd9Sstevel@tonic-gate static void 1880*7c478bd9Sstevel@tonic-gate destroy_subtree(picl_obj_t *nodep) 1881*7c478bd9Sstevel@tonic-gate { 1882*7c478bd9Sstevel@tonic-gate picl_obj_t *iterp; 1883*7c478bd9Sstevel@tonic-gate picl_obj_t *freep; 1884*7c478bd9Sstevel@tonic-gate picl_obj_t *chdp; 1885*7c478bd9Sstevel@tonic-gate 1886*7c478bd9Sstevel@tonic-gate if (nodep == NULL) 1887*7c478bd9Sstevel@tonic-gate return; 1888*7c478bd9Sstevel@tonic-gate 1889*7c478bd9Sstevel@tonic-gate chdp = nodep->child_node; 1890*7c478bd9Sstevel@tonic-gate while (chdp != NULL) { 1891*7c478bd9Sstevel@tonic-gate freep = chdp; 1892*7c478bd9Sstevel@tonic-gate chdp = chdp->sibling_node; 1893*7c478bd9Sstevel@tonic-gate destroy_subtree(freep); 1894*7c478bd9Sstevel@tonic-gate } 1895*7c478bd9Sstevel@tonic-gate 1896*7c478bd9Sstevel@tonic-gate /* 1897*7c478bd9Sstevel@tonic-gate * Lock the node 1898*7c478bd9Sstevel@tonic-gate */ 1899*7c478bd9Sstevel@tonic-gate (void) lock_obj(WRLOCK_NODE, nodep); 1900*7c478bd9Sstevel@tonic-gate 1901*7c478bd9Sstevel@tonic-gate /* 1902*7c478bd9Sstevel@tonic-gate * destroy all properties associated with this node 1903*7c478bd9Sstevel@tonic-gate */ 1904*7c478bd9Sstevel@tonic-gate iterp = nodep->first_prop; 1905*7c478bd9Sstevel@tonic-gate while (iterp != NULL) { 1906*7c478bd9Sstevel@tonic-gate freep = iterp; 1907*7c478bd9Sstevel@tonic-gate iterp = iterp->next_prop; 1908*7c478bd9Sstevel@tonic-gate destroy_propobj(freep); 1909*7c478bd9Sstevel@tonic-gate } 1910*7c478bd9Sstevel@tonic-gate 1911*7c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, nodep->ptree_hdl); 1912*7c478bd9Sstevel@tonic-gate (void) rwlock_destroy(&nodep->node_lock); 1913*7c478bd9Sstevel@tonic-gate free(nodep->node_classname); 1914*7c478bd9Sstevel@tonic-gate free(nodep); 1915*7c478bd9Sstevel@tonic-gate } 1916*7c478bd9Sstevel@tonic-gate 1917*7c478bd9Sstevel@tonic-gate /* 1918*7c478bd9Sstevel@tonic-gate * This function destroys a previously deleted node/subtree. All the properties 1919*7c478bd9Sstevel@tonic-gate * are freed and removed from the PTree table. 1920*7c478bd9Sstevel@tonic-gate * Only one destroy is in progress at any time. 1921*7c478bd9Sstevel@tonic-gate */ 1922*7c478bd9Sstevel@tonic-gate int 1923*7c478bd9Sstevel@tonic-gate ptree_destroy_node(picl_nodehdl_t nodeh) 1924*7c478bd9Sstevel@tonic-gate { 1925*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1926*7c478bd9Sstevel@tonic-gate picl_obj_t *parp; 1927*7c478bd9Sstevel@tonic-gate picl_obj_t *np; 1928*7c478bd9Sstevel@tonic-gate int err; 1929*7c478bd9Sstevel@tonic-gate 1930*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* exclusive wrlock ptree */ 1931*7c478bd9Sstevel@tonic-gate nodep = NULL; 1932*7c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(nodeh, &nodep); 1933*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1934*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1935*7c478bd9Sstevel@tonic-gate return (err); 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate 1938*7c478bd9Sstevel@tonic-gate /* 1939*7c478bd9Sstevel@tonic-gate * Has this node/subtree been deleted? 1940*7c478bd9Sstevel@tonic-gate */ 1941*7c478bd9Sstevel@tonic-gate if (IS_PICLIZED(nodep)) { 1942*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1943*7c478bd9Sstevel@tonic-gate return (PICL_CANTDESTROY); 1944*7c478bd9Sstevel@tonic-gate } 1945*7c478bd9Sstevel@tonic-gate 1946*7c478bd9Sstevel@tonic-gate /* 1947*7c478bd9Sstevel@tonic-gate * update parent's child list to repair the tree when 1948*7c478bd9Sstevel@tonic-gate * parent is not null 1949*7c478bd9Sstevel@tonic-gate */ 1950*7c478bd9Sstevel@tonic-gate parp = nodep->parent_node; 1951*7c478bd9Sstevel@tonic-gate if (parp == NULL) { /* root */ 1952*7c478bd9Sstevel@tonic-gate destroy_subtree(nodep); 1953*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1954*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1955*7c478bd9Sstevel@tonic-gate } 1956*7c478bd9Sstevel@tonic-gate 1957*7c478bd9Sstevel@tonic-gate np = parp->child_node; 1958*7c478bd9Sstevel@tonic-gate if (np == nodep) { /* first child */ 1959*7c478bd9Sstevel@tonic-gate parp->child_node = nodep->sibling_node; 1960*7c478bd9Sstevel@tonic-gate } else { 1961*7c478bd9Sstevel@tonic-gate while ((np != NULL) && (np->sibling_node != nodep)) 1962*7c478bd9Sstevel@tonic-gate np = np->sibling_node; 1963*7c478bd9Sstevel@tonic-gate if (np != NULL) 1964*7c478bd9Sstevel@tonic-gate np->sibling_node = nodep->sibling_node; 1965*7c478bd9Sstevel@tonic-gate } 1966*7c478bd9Sstevel@tonic-gate 1967*7c478bd9Sstevel@tonic-gate destroy_subtree(nodep); 1968*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1969*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 1970*7c478bd9Sstevel@tonic-gate } 1971*7c478bd9Sstevel@tonic-gate 1972*7c478bd9Sstevel@tonic-gate /* 1973*7c478bd9Sstevel@tonic-gate * This function deletes a node/subtree from the tree and removes the handles 1974*7c478bd9Sstevel@tonic-gate * from PICL table 1975*7c478bd9Sstevel@tonic-gate */ 1976*7c478bd9Sstevel@tonic-gate int 1977*7c478bd9Sstevel@tonic-gate ptree_delete_node(picl_nodehdl_t nodeh) 1978*7c478bd9Sstevel@tonic-gate { 1979*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 1980*7c478bd9Sstevel@tonic-gate picl_obj_t *parp; 1981*7c478bd9Sstevel@tonic-gate picl_obj_t *np; 1982*7c478bd9Sstevel@tonic-gate int err; 1983*7c478bd9Sstevel@tonic-gate 1984*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* exclusive wrlock ptree */ 1985*7c478bd9Sstevel@tonic-gate 1986*7c478bd9Sstevel@tonic-gate nodep = NULL; 1987*7c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(nodeh, &nodep); 1988*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1989*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 1990*7c478bd9Sstevel@tonic-gate return (err); 1991*7c478bd9Sstevel@tonic-gate } 1992*7c478bd9Sstevel@tonic-gate 1993*7c478bd9Sstevel@tonic-gate /* 1994*7c478bd9Sstevel@tonic-gate * unparent it 1995*7c478bd9Sstevel@tonic-gate */ 1996*7c478bd9Sstevel@tonic-gate parp = nodep->parent_node; 1997*7c478bd9Sstevel@tonic-gate if (parp != NULL) { 1998*7c478bd9Sstevel@tonic-gate np = parp->child_node; 1999*7c478bd9Sstevel@tonic-gate if (np == nodep) /* first child */ 2000*7c478bd9Sstevel@tonic-gate parp->child_node = nodep->sibling_node; 2001*7c478bd9Sstevel@tonic-gate else { 2002*7c478bd9Sstevel@tonic-gate while ((np != NULL) && (np->sibling_node != nodep)) 2003*7c478bd9Sstevel@tonic-gate np = np->sibling_node; 2004*7c478bd9Sstevel@tonic-gate if (np != NULL) 2005*7c478bd9Sstevel@tonic-gate np->sibling_node = nodep->sibling_node; 2006*7c478bd9Sstevel@tonic-gate } 2007*7c478bd9Sstevel@tonic-gate } 2008*7c478bd9Sstevel@tonic-gate 2009*7c478bd9Sstevel@tonic-gate nodep->parent_node = NULL; 2010*7c478bd9Sstevel@tonic-gate nodep->sibling_node = NULL; 2011*7c478bd9Sstevel@tonic-gate 2012*7c478bd9Sstevel@tonic-gate unpiclize_node(nodep); 2013*7c478bd9Sstevel@tonic-gate 2014*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2015*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2016*7c478bd9Sstevel@tonic-gate } 2017*7c478bd9Sstevel@tonic-gate 2018*7c478bd9Sstevel@tonic-gate /* 2019*7c478bd9Sstevel@tonic-gate * This function adds a node as a child of another node 2020*7c478bd9Sstevel@tonic-gate */ 2021*7c478bd9Sstevel@tonic-gate int 2022*7c478bd9Sstevel@tonic-gate ptree_add_node(picl_nodehdl_t parh, picl_nodehdl_t chdh) 2023*7c478bd9Sstevel@tonic-gate { 2024*7c478bd9Sstevel@tonic-gate picl_obj_t *pnodep; 2025*7c478bd9Sstevel@tonic-gate picl_obj_t *cnodep; 2026*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2027*7c478bd9Sstevel@tonic-gate int err; 2028*7c478bd9Sstevel@tonic-gate 2029*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* exclusive lock ptree */ 2030*7c478bd9Sstevel@tonic-gate 2031*7c478bd9Sstevel@tonic-gate pnodep = cnodep = NULL; 2032*7c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(parh, &pnodep); 2033*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2034*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2035*7c478bd9Sstevel@tonic-gate return (err); 2036*7c478bd9Sstevel@tonic-gate } 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(chdh, &cnodep); 2039*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2040*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2041*7c478bd9Sstevel@tonic-gate return (err); 2042*7c478bd9Sstevel@tonic-gate } 2043*7c478bd9Sstevel@tonic-gate 2044*7c478bd9Sstevel@tonic-gate /* is chdh already a child? */ 2045*7c478bd9Sstevel@tonic-gate if (cnodep->parent_node != NULL) { 2046*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2047*7c478bd9Sstevel@tonic-gate return (PICL_CANTPARENT); 2048*7c478bd9Sstevel@tonic-gate } 2049*7c478bd9Sstevel@tonic-gate 2050*7c478bd9Sstevel@tonic-gate /* 2051*7c478bd9Sstevel@tonic-gate * append child to children list 2052*7c478bd9Sstevel@tonic-gate */ 2053*7c478bd9Sstevel@tonic-gate cnodep->parent_node = pnodep; 2054*7c478bd9Sstevel@tonic-gate if (pnodep->child_node == NULL) 2055*7c478bd9Sstevel@tonic-gate pnodep->child_node = cnodep; 2056*7c478bd9Sstevel@tonic-gate else { 2057*7c478bd9Sstevel@tonic-gate for (nodep = pnodep->child_node; nodep->sibling_node != NULL; 2058*7c478bd9Sstevel@tonic-gate nodep = nodep->sibling_node) 2059*7c478bd9Sstevel@tonic-gate continue; 2060*7c478bd9Sstevel@tonic-gate nodep->sibling_node = cnodep; 2061*7c478bd9Sstevel@tonic-gate 2062*7c478bd9Sstevel@tonic-gate } 2063*7c478bd9Sstevel@tonic-gate 2064*7c478bd9Sstevel@tonic-gate /* piclize */ 2065*7c478bd9Sstevel@tonic-gate if (IS_PICLIZED(pnodep)) 2066*7c478bd9Sstevel@tonic-gate piclize_node(cnodep); 2067*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2068*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2069*7c478bd9Sstevel@tonic-gate } 2070*7c478bd9Sstevel@tonic-gate 2071*7c478bd9Sstevel@tonic-gate static void 2072*7c478bd9Sstevel@tonic-gate copy_propinfo_ver_1(ptree_propinfo_t *pinfo, picl_obj_t *propp) 2073*7c478bd9Sstevel@tonic-gate { 2074*7c478bd9Sstevel@tonic-gate pinfo->version = propp->pinfo_ver; 2075*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.type = propp->prop_type; 2076*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.accessmode = propp->prop_mode; 2077*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.size = propp->prop_size; 2078*7c478bd9Sstevel@tonic-gate (void) strcpy(pinfo->piclinfo.name, propp->prop_name); 2079*7c478bd9Sstevel@tonic-gate pinfo->read = propp->read_func; 2080*7c478bd9Sstevel@tonic-gate pinfo->write = propp->write_func; 2081*7c478bd9Sstevel@tonic-gate } 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate static void 2084*7c478bd9Sstevel@tonic-gate copy_reserved_propinfo_ver_1(ptree_propinfo_t *pinfo, const char *pname) 2085*7c478bd9Sstevel@tonic-gate { 2086*7c478bd9Sstevel@tonic-gate pinfo->version = PTREE_PROPINFO_VERSION_1; 2087*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.type = PICL_PTYPE_REFERENCE; 2088*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.accessmode = PICL_READ; 2089*7c478bd9Sstevel@tonic-gate pinfo->piclinfo.size = sizeof (picl_nodehdl_t); 2090*7c478bd9Sstevel@tonic-gate (void) strcpy(pinfo->piclinfo.name, pname); 2091*7c478bd9Sstevel@tonic-gate pinfo->read = NULL; 2092*7c478bd9Sstevel@tonic-gate pinfo->write = NULL; 2093*7c478bd9Sstevel@tonic-gate } 2094*7c478bd9Sstevel@tonic-gate 2095*7c478bd9Sstevel@tonic-gate /* 2096*7c478bd9Sstevel@tonic-gate * This function returns the property information to a plug-in 2097*7c478bd9Sstevel@tonic-gate */ 2098*7c478bd9Sstevel@tonic-gate int 2099*7c478bd9Sstevel@tonic-gate ptree_get_propinfo(picl_prophdl_t proph, ptree_propinfo_t *pinfo) 2100*7c478bd9Sstevel@tonic-gate { 2101*7c478bd9Sstevel@tonic-gate int err; 2102*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2103*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2104*7c478bd9Sstevel@tonic-gate 2105*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2106*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 2107*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp); 2108*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2109*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2110*7c478bd9Sstevel@tonic-gate return (err); 2111*7c478bd9Sstevel@tonic-gate } 2112*7c478bd9Sstevel@tonic-gate 2113*7c478bd9Sstevel@tonic-gate if (propp->pinfo_ver == PTREE_PROPINFO_VERSION_1) 2114*7c478bd9Sstevel@tonic-gate copy_propinfo_ver_1(pinfo, propp); 2115*7c478bd9Sstevel@tonic-gate else 2116*7c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 2117*7c478bd9Sstevel@tonic-gate 2118*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2119*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2120*7c478bd9Sstevel@tonic-gate return (err); 2121*7c478bd9Sstevel@tonic-gate } 2122*7c478bd9Sstevel@tonic-gate 2123*7c478bd9Sstevel@tonic-gate /* 2124*7c478bd9Sstevel@tonic-gate * This function returns the property information to a plug-in 2125*7c478bd9Sstevel@tonic-gate */ 2126*7c478bd9Sstevel@tonic-gate int 2127*7c478bd9Sstevel@tonic-gate xptree_get_propinfo_by_name(picl_nodehdl_t nodeh, const char *pname, 2128*7c478bd9Sstevel@tonic-gate ptree_propinfo_t *pinfo) 2129*7c478bd9Sstevel@tonic-gate { 2130*7c478bd9Sstevel@tonic-gate int err; 2131*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2132*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2133*7c478bd9Sstevel@tonic-gate 2134*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2135*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 2136*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep); /* lock node */ 2137*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2138*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2139*7c478bd9Sstevel@tonic-gate return (err); 2140*7c478bd9Sstevel@tonic-gate } 2141*7c478bd9Sstevel@tonic-gate 2142*7c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 2143*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2144*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2145*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2146*7c478bd9Sstevel@tonic-gate return (err); 2147*7c478bd9Sstevel@tonic-gate } 2148*7c478bd9Sstevel@tonic-gate 2149*7c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) 2150*7c478bd9Sstevel@tonic-gate copy_reserved_propinfo_ver_1(pinfo, pname); 2151*7c478bd9Sstevel@tonic-gate else if (propp->pinfo_ver == PTREE_PROPINFO_VERSION_1) 2152*7c478bd9Sstevel@tonic-gate copy_propinfo_ver_1(pinfo, propp); 2153*7c478bd9Sstevel@tonic-gate else 2154*7c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 2155*7c478bd9Sstevel@tonic-gate 2156*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2157*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2158*7c478bd9Sstevel@tonic-gate return (err); 2159*7c478bd9Sstevel@tonic-gate } 2160*7c478bd9Sstevel@tonic-gate 2161*7c478bd9Sstevel@tonic-gate /* 2162*7c478bd9Sstevel@tonic-gate * This function must be called only after a lookup_prop_by_name() returns 2163*7c478bd9Sstevel@tonic-gate * success and only if picl_restricted() returns true. 2164*7c478bd9Sstevel@tonic-gate */ 2165*7c478bd9Sstevel@tonic-gate static int 2166*7c478bd9Sstevel@tonic-gate read_reserved_propval_and_unlock(picl_obj_t *nodep, const char *pname, 2167*7c478bd9Sstevel@tonic-gate void *vbuf, size_t size) 2168*7c478bd9Sstevel@tonic-gate { 2169*7c478bd9Sstevel@tonic-gate void *srcp; 2170*7c478bd9Sstevel@tonic-gate 2171*7c478bd9Sstevel@tonic-gate if (size != sizeof (picl_nodehdl_t)) 2172*7c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 2173*7c478bd9Sstevel@tonic-gate 2174*7c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_PARENT) == 0) 2175*7c478bd9Sstevel@tonic-gate srcp = &nodep->parent_node->ptree_hdl; 2176*7c478bd9Sstevel@tonic-gate else if (strcmp(pname, PICL_PROP_CHILD) == 0) 2177*7c478bd9Sstevel@tonic-gate srcp = &nodep->child_node->ptree_hdl; 2178*7c478bd9Sstevel@tonic-gate else if (strcmp(pname, PICL_PROP_PEER) == 0) 2179*7c478bd9Sstevel@tonic-gate srcp = &nodep->sibling_node->ptree_hdl; 2180*7c478bd9Sstevel@tonic-gate else 2181*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2182*7c478bd9Sstevel@tonic-gate 2183*7c478bd9Sstevel@tonic-gate (void) memcpy(vbuf, srcp, sizeof (picl_nodehdl_t)); 2184*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2185*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2186*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2187*7c478bd9Sstevel@tonic-gate } 2188*7c478bd9Sstevel@tonic-gate 2189*7c478bd9Sstevel@tonic-gate /* 2190*7c478bd9Sstevel@tonic-gate * Returns the property value in the buffer and releases the node and 2191*7c478bd9Sstevel@tonic-gate * ptree locks. 2192*7c478bd9Sstevel@tonic-gate * For volatile properties, this function releases the locks on ptree 2193*7c478bd9Sstevel@tonic-gate * table and the node before calling the plug-in provided access function 2194*7c478bd9Sstevel@tonic-gate */ 2195*7c478bd9Sstevel@tonic-gate static int 2196*7c478bd9Sstevel@tonic-gate read_propval_and_unlock(picl_obj_t *nodep, picl_obj_t *propp, void *vbuf, 2197*7c478bd9Sstevel@tonic-gate door_cred_t cred) 2198*7c478bd9Sstevel@tonic-gate { 2199*7c478bd9Sstevel@tonic-gate int err; 2200*7c478bd9Sstevel@tonic-gate int (*volrd)(ptree_rarg_t *arg, void *buf); 2201*7c478bd9Sstevel@tonic-gate 2202*7c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 2203*7c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) { 2204*7c478bd9Sstevel@tonic-gate ptree_rarg_t rarg; 2205*7c478bd9Sstevel@tonic-gate 2206*7c478bd9Sstevel@tonic-gate if (nodep) 2207*7c478bd9Sstevel@tonic-gate rarg.nodeh = nodep->ptree_hdl; 2208*7c478bd9Sstevel@tonic-gate else 2209*7c478bd9Sstevel@tonic-gate rarg.nodeh = PICL_INVALID_PICLHDL; 2210*7c478bd9Sstevel@tonic-gate rarg.proph = propp->ptree_hdl; 2211*7c478bd9Sstevel@tonic-gate rarg.cred = cred; 2212*7c478bd9Sstevel@tonic-gate volrd = propp->read_func; 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2215*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate if (volrd == NULL) 2218*7c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 2219*7c478bd9Sstevel@tonic-gate else 2220*7c478bd9Sstevel@tonic-gate err = (volrd)(&rarg, vbuf); 2221*7c478bd9Sstevel@tonic-gate return (err); 2222*7c478bd9Sstevel@tonic-gate } else if (propp->prop_type == PICL_PTYPE_CHARSTRING) 2223*7c478bd9Sstevel@tonic-gate (void) strlcpy(vbuf, propp->prop_val, propp->prop_size); 2224*7c478bd9Sstevel@tonic-gate else 2225*7c478bd9Sstevel@tonic-gate (void) memcpy(vbuf, propp->prop_val, propp->prop_size); 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2228*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2229*7c478bd9Sstevel@tonic-gate return (err); 2230*7c478bd9Sstevel@tonic-gate } 2231*7c478bd9Sstevel@tonic-gate 2232*7c478bd9Sstevel@tonic-gate int 2233*7c478bd9Sstevel@tonic-gate xptree_get_propval_with_cred(picl_prophdl_t proph, void *vbuf, size_t size, 2234*7c478bd9Sstevel@tonic-gate door_cred_t cred) 2235*7c478bd9Sstevel@tonic-gate { 2236*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2237*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2238*7c478bd9Sstevel@tonic-gate int err; 2239*7c478bd9Sstevel@tonic-gate 2240*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2241*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 2242*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp); 2243*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2244*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2245*7c478bd9Sstevel@tonic-gate return (err); 2246*7c478bd9Sstevel@tonic-gate } 2247*7c478bd9Sstevel@tonic-gate 2248*7c478bd9Sstevel@tonic-gate err = check_propsize(PROP_READ, propp, size); 2249*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2250*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2251*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2252*7c478bd9Sstevel@tonic-gate return (err); 2253*7c478bd9Sstevel@tonic-gate } 2254*7c478bd9Sstevel@tonic-gate 2255*7c478bd9Sstevel@tonic-gate return (read_propval_and_unlock(nodep, propp, vbuf, cred)); 2256*7c478bd9Sstevel@tonic-gate } 2257*7c478bd9Sstevel@tonic-gate 2258*7c478bd9Sstevel@tonic-gate /* 2259*7c478bd9Sstevel@tonic-gate * This function gets the credentials and calls get_propval_with_cred. 2260*7c478bd9Sstevel@tonic-gate */ 2261*7c478bd9Sstevel@tonic-gate int 2262*7c478bd9Sstevel@tonic-gate ptree_get_propval(picl_prophdl_t proph, void *vbuf, size_t size) 2263*7c478bd9Sstevel@tonic-gate { 2264*7c478bd9Sstevel@tonic-gate return (xptree_get_propval_with_cred(proph, vbuf, size, picld_cred)); 2265*7c478bd9Sstevel@tonic-gate } 2266*7c478bd9Sstevel@tonic-gate 2267*7c478bd9Sstevel@tonic-gate /* 2268*7c478bd9Sstevel@tonic-gate * This function retrieves a property's value by by its name 2269*7c478bd9Sstevel@tonic-gate * For volatile properties, the locks on ptree and node are released 2270*7c478bd9Sstevel@tonic-gate * before calling the plug-in provided access function 2271*7c478bd9Sstevel@tonic-gate */ 2272*7c478bd9Sstevel@tonic-gate int 2273*7c478bd9Sstevel@tonic-gate xptree_get_propval_by_name_with_cred(picl_nodehdl_t nodeh, const char *pname, 2274*7c478bd9Sstevel@tonic-gate void *vbuf, size_t size, door_cred_t cred) 2275*7c478bd9Sstevel@tonic-gate { 2276*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2277*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2278*7c478bd9Sstevel@tonic-gate int err; 2279*7c478bd9Sstevel@tonic-gate 2280*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2281*7c478bd9Sstevel@tonic-gate 2282*7c478bd9Sstevel@tonic-gate nodep = NULL; 2283*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep); /* lock node */ 2284*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2285*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2286*7c478bd9Sstevel@tonic-gate return (err); 2287*7c478bd9Sstevel@tonic-gate } 2288*7c478bd9Sstevel@tonic-gate 2289*7c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 2290*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2291*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2292*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2293*7c478bd9Sstevel@tonic-gate return (err); 2294*7c478bd9Sstevel@tonic-gate } 2295*7c478bd9Sstevel@tonic-gate 2296*7c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) 2297*7c478bd9Sstevel@tonic-gate return (read_reserved_propval_and_unlock(nodep, pname, vbuf, 2298*7c478bd9Sstevel@tonic-gate size)); 2299*7c478bd9Sstevel@tonic-gate 2300*7c478bd9Sstevel@tonic-gate err = check_propsize(PROP_READ, propp, size); 2301*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2302*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2303*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2304*7c478bd9Sstevel@tonic-gate return (err); 2305*7c478bd9Sstevel@tonic-gate } 2306*7c478bd9Sstevel@tonic-gate 2307*7c478bd9Sstevel@tonic-gate return (read_propval_and_unlock(nodep, propp, vbuf, cred)); 2308*7c478bd9Sstevel@tonic-gate } 2309*7c478bd9Sstevel@tonic-gate 2310*7c478bd9Sstevel@tonic-gate /* 2311*7c478bd9Sstevel@tonic-gate * This function is used by plugins to get a value of a property 2312*7c478bd9Sstevel@tonic-gate * looking it up by its name. 2313*7c478bd9Sstevel@tonic-gate */ 2314*7c478bd9Sstevel@tonic-gate int 2315*7c478bd9Sstevel@tonic-gate ptree_get_propval_by_name(picl_nodehdl_t nodeh, const char *pname, void *vbuf, 2316*7c478bd9Sstevel@tonic-gate size_t size) 2317*7c478bd9Sstevel@tonic-gate { 2318*7c478bd9Sstevel@tonic-gate return (xptree_get_propval_by_name_with_cred(nodeh, pname, vbuf, size, 2319*7c478bd9Sstevel@tonic-gate picld_cred)); 2320*7c478bd9Sstevel@tonic-gate } 2321*7c478bd9Sstevel@tonic-gate 2322*7c478bd9Sstevel@tonic-gate /* 2323*7c478bd9Sstevel@tonic-gate * This function updates a property's value. 2324*7c478bd9Sstevel@tonic-gate * For volatile properties, the locks on the node and the ptree table 2325*7c478bd9Sstevel@tonic-gate * are released before calling the plug-in provided access function. 2326*7c478bd9Sstevel@tonic-gate */ 2327*7c478bd9Sstevel@tonic-gate static int 2328*7c478bd9Sstevel@tonic-gate write_propval_and_unlock(picl_obj_t *nodep, picl_obj_t *propp, const void *vbuf, 2329*7c478bd9Sstevel@tonic-gate size_t size, door_cred_t cred) 2330*7c478bd9Sstevel@tonic-gate { 2331*7c478bd9Sstevel@tonic-gate int err; 2332*7c478bd9Sstevel@tonic-gate int (*volwr)(ptree_warg_t *arg, const void *buf); 2333*7c478bd9Sstevel@tonic-gate 2334*7c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 2335*7c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) { 2336*7c478bd9Sstevel@tonic-gate ptree_warg_t warg; 2337*7c478bd9Sstevel@tonic-gate 2338*7c478bd9Sstevel@tonic-gate if (nodep) 2339*7c478bd9Sstevel@tonic-gate warg.nodeh = nodep->ptree_hdl; 2340*7c478bd9Sstevel@tonic-gate else 2341*7c478bd9Sstevel@tonic-gate warg.nodeh = PICL_INVALID_PICLHDL; 2342*7c478bd9Sstevel@tonic-gate warg.proph = propp->ptree_hdl; 2343*7c478bd9Sstevel@tonic-gate warg.cred = cred; 2344*7c478bd9Sstevel@tonic-gate volwr = propp->write_func; 2345*7c478bd9Sstevel@tonic-gate 2346*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2347*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2348*7c478bd9Sstevel@tonic-gate 2349*7c478bd9Sstevel@tonic-gate if (volwr == NULL) 2350*7c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 2351*7c478bd9Sstevel@tonic-gate else 2352*7c478bd9Sstevel@tonic-gate err = (volwr)(&warg, vbuf); 2353*7c478bd9Sstevel@tonic-gate return (err); 2354*7c478bd9Sstevel@tonic-gate } else 2355*7c478bd9Sstevel@tonic-gate (void) memcpy(propp->prop_val, vbuf, size); 2356*7c478bd9Sstevel@tonic-gate 2357*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2358*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2359*7c478bd9Sstevel@tonic-gate return (err); 2360*7c478bd9Sstevel@tonic-gate } 2361*7c478bd9Sstevel@tonic-gate 2362*7c478bd9Sstevel@tonic-gate int 2363*7c478bd9Sstevel@tonic-gate xptree_update_propval_with_cred(picl_prophdl_t proph, const void *vbuf, 2364*7c478bd9Sstevel@tonic-gate size_t size, door_cred_t cred) 2365*7c478bd9Sstevel@tonic-gate { 2366*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2367*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2368*7c478bd9Sstevel@tonic-gate int err; 2369*7c478bd9Sstevel@tonic-gate 2370*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2371*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 2372*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(WRLOCK_NODE, proph, &nodep, &propp); 2373*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2374*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2375*7c478bd9Sstevel@tonic-gate return (err); 2376*7c478bd9Sstevel@tonic-gate } 2377*7c478bd9Sstevel@tonic-gate 2378*7c478bd9Sstevel@tonic-gate err = check_propsize(PROP_WRITE, propp, size); 2379*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2380*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2381*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2382*7c478bd9Sstevel@tonic-gate return (err); 2383*7c478bd9Sstevel@tonic-gate } 2384*7c478bd9Sstevel@tonic-gate 2385*7c478bd9Sstevel@tonic-gate return (write_propval_and_unlock(nodep, propp, vbuf, size, cred)); 2386*7c478bd9Sstevel@tonic-gate } 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate /* 2389*7c478bd9Sstevel@tonic-gate * Ptree function used by plug-ins to update a property's value 2390*7c478bd9Sstevel@tonic-gate * calls update_propval_with_cred(), which releases locks for volatile props 2391*7c478bd9Sstevel@tonic-gate */ 2392*7c478bd9Sstevel@tonic-gate int 2393*7c478bd9Sstevel@tonic-gate ptree_update_propval(picl_prophdl_t proph, const void *vbuf, size_t size) 2394*7c478bd9Sstevel@tonic-gate { 2395*7c478bd9Sstevel@tonic-gate return (xptree_update_propval_with_cred(proph, vbuf, size, picld_cred)); 2396*7c478bd9Sstevel@tonic-gate } 2397*7c478bd9Sstevel@tonic-gate 2398*7c478bd9Sstevel@tonic-gate /* 2399*7c478bd9Sstevel@tonic-gate * This function writes/updates a property's value by looking it up 2400*7c478bd9Sstevel@tonic-gate * by its name. 2401*7c478bd9Sstevel@tonic-gate * For volatile properties this function releases the locks on the 2402*7c478bd9Sstevel@tonic-gate * node and the ptree table. 2403*7c478bd9Sstevel@tonic-gate */ 2404*7c478bd9Sstevel@tonic-gate int 2405*7c478bd9Sstevel@tonic-gate xptree_update_propval_by_name_with_cred(picl_nodehdl_t nodeh, const char *pname, 2406*7c478bd9Sstevel@tonic-gate const void *vbuf, size_t size, door_cred_t cred) 2407*7c478bd9Sstevel@tonic-gate { 2408*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2409*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2410*7c478bd9Sstevel@tonic-gate int err; 2411*7c478bd9Sstevel@tonic-gate 2412*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2413*7c478bd9Sstevel@tonic-gate nodep = NULL; 2414*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(WRLOCK_NODE, nodeh, &nodep); /* lock node */ 2415*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2416*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2417*7c478bd9Sstevel@tonic-gate return (err); 2418*7c478bd9Sstevel@tonic-gate } 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) { 2421*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2422*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2423*7c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 2424*7c478bd9Sstevel@tonic-gate } 2425*7c478bd9Sstevel@tonic-gate 2426*7c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 2427*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2428*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2429*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2430*7c478bd9Sstevel@tonic-gate return (err); 2431*7c478bd9Sstevel@tonic-gate } 2432*7c478bd9Sstevel@tonic-gate 2433*7c478bd9Sstevel@tonic-gate err = check_propsize(PROP_WRITE, propp, size); 2434*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2435*7c478bd9Sstevel@tonic-gate unlock_node(nodep); 2436*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 2437*7c478bd9Sstevel@tonic-gate return (err); 2438*7c478bd9Sstevel@tonic-gate } 2439*7c478bd9Sstevel@tonic-gate 2440*7c478bd9Sstevel@tonic-gate return (write_propval_and_unlock(nodep, propp, vbuf, size, cred)); 2441*7c478bd9Sstevel@tonic-gate } 2442*7c478bd9Sstevel@tonic-gate 2443*7c478bd9Sstevel@tonic-gate /* 2444*7c478bd9Sstevel@tonic-gate * This function updates the value of a property specified by its name 2445*7c478bd9Sstevel@tonic-gate */ 2446*7c478bd9Sstevel@tonic-gate int 2447*7c478bd9Sstevel@tonic-gate ptree_update_propval_by_name(picl_nodehdl_t nodeh, const char *pname, 2448*7c478bd9Sstevel@tonic-gate const void *vbuf, size_t size) 2449*7c478bd9Sstevel@tonic-gate { 2450*7c478bd9Sstevel@tonic-gate return (xptree_update_propval_by_name_with_cred(nodeh, pname, vbuf, 2451*7c478bd9Sstevel@tonic-gate size, picld_cred)); 2452*7c478bd9Sstevel@tonic-gate } 2453*7c478bd9Sstevel@tonic-gate 2454*7c478bd9Sstevel@tonic-gate /* 2455*7c478bd9Sstevel@tonic-gate * This function retrieves the handle of a property by its name 2456*7c478bd9Sstevel@tonic-gate */ 2457*7c478bd9Sstevel@tonic-gate int 2458*7c478bd9Sstevel@tonic-gate ptree_get_prop_by_name(picl_nodehdl_t nodeh, const char *pname, 2459*7c478bd9Sstevel@tonic-gate picl_prophdl_t *proph) 2460*7c478bd9Sstevel@tonic-gate { 2461*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2462*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2463*7c478bd9Sstevel@tonic-gate int err; 2464*7c478bd9Sstevel@tonic-gate 2465*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2466*7c478bd9Sstevel@tonic-gate nodep = NULL; 2467*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep); /* lock node */ 2468*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2469*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2470*7c478bd9Sstevel@tonic-gate return (err); 2471*7c478bd9Sstevel@tonic-gate } 2472*7c478bd9Sstevel@tonic-gate 2473*7c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) { 2474*7c478bd9Sstevel@tonic-gate err = PICL_RESERVEDNAME; 2475*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2476*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2477*7c478bd9Sstevel@tonic-gate return (err); 2478*7c478bd9Sstevel@tonic-gate } 2479*7c478bd9Sstevel@tonic-gate 2480*7c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 2481*7c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) 2482*7c478bd9Sstevel@tonic-gate *proph = propp->ptree_hdl; 2483*7c478bd9Sstevel@tonic-gate 2484*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2485*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2486*7c478bd9Sstevel@tonic-gate return (err); 2487*7c478bd9Sstevel@tonic-gate } 2488*7c478bd9Sstevel@tonic-gate 2489*7c478bd9Sstevel@tonic-gate /* 2490*7c478bd9Sstevel@tonic-gate * This function returns the handle of the first property 2491*7c478bd9Sstevel@tonic-gate */ 2492*7c478bd9Sstevel@tonic-gate int 2493*7c478bd9Sstevel@tonic-gate ptree_get_first_prop(picl_nodehdl_t nodeh, picl_prophdl_t *proph) 2494*7c478bd9Sstevel@tonic-gate { 2495*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 2496*7c478bd9Sstevel@tonic-gate int err; 2497*7c478bd9Sstevel@tonic-gate 2498*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2499*7c478bd9Sstevel@tonic-gate pobj = NULL; 2500*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &pobj); /* lock node */ 2501*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2502*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2503*7c478bd9Sstevel@tonic-gate return (err); 2504*7c478bd9Sstevel@tonic-gate } 2505*7c478bd9Sstevel@tonic-gate 2506*7c478bd9Sstevel@tonic-gate if (pobj->first_prop) 2507*7c478bd9Sstevel@tonic-gate *proph = pobj->first_prop->ptree_hdl; 2508*7c478bd9Sstevel@tonic-gate else 2509*7c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 2510*7c478bd9Sstevel@tonic-gate 2511*7c478bd9Sstevel@tonic-gate unlock_node(pobj); /* unlock node */ 2512*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2513*7c478bd9Sstevel@tonic-gate return (err); 2514*7c478bd9Sstevel@tonic-gate } 2515*7c478bd9Sstevel@tonic-gate 2516*7c478bd9Sstevel@tonic-gate /* 2517*7c478bd9Sstevel@tonic-gate * This function returns the handle of next property in the list 2518*7c478bd9Sstevel@tonic-gate */ 2519*7c478bd9Sstevel@tonic-gate int 2520*7c478bd9Sstevel@tonic-gate ptree_get_next_prop(picl_prophdl_t proph, picl_prophdl_t *nextproph) 2521*7c478bd9Sstevel@tonic-gate { 2522*7c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 2523*7c478bd9Sstevel@tonic-gate picl_obj_t *propp; 2524*7c478bd9Sstevel@tonic-gate int err; 2525*7c478bd9Sstevel@tonic-gate 2526*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 2527*7c478bd9Sstevel@tonic-gate nodep = propp = NULL; 2528*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp); 2529*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2530*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2531*7c478bd9Sstevel@tonic-gate return (err); 2532*7c478bd9Sstevel@tonic-gate } 2533*7c478bd9Sstevel@tonic-gate 2534*7c478bd9Sstevel@tonic-gate if (propp->next_prop) { 2535*7c478bd9Sstevel@tonic-gate *nextproph = propp->next_prop->ptree_hdl; 2536*7c478bd9Sstevel@tonic-gate } else 2537*7c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 2538*7c478bd9Sstevel@tonic-gate 2539*7c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 2540*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 2541*7c478bd9Sstevel@tonic-gate return (err); 2542*7c478bd9Sstevel@tonic-gate } 2543*7c478bd9Sstevel@tonic-gate 2544*7c478bd9Sstevel@tonic-gate /* 2545*7c478bd9Sstevel@tonic-gate * These functions are called by ptree_get_node_by_path() 2546*7c478bd9Sstevel@tonic-gate * Append a prop expression entry to the list 2547*7c478bd9Sstevel@tonic-gate */ 2548*7c478bd9Sstevel@tonic-gate static prop_list_t * 2549*7c478bd9Sstevel@tonic-gate append_entry_to_list(prop_list_t *el, prop_list_t *list) 2550*7c478bd9Sstevel@tonic-gate { 2551*7c478bd9Sstevel@tonic-gate prop_list_t *ptr; 2552*7c478bd9Sstevel@tonic-gate 2553*7c478bd9Sstevel@tonic-gate if (el == NULL) 2554*7c478bd9Sstevel@tonic-gate return (list); 2555*7c478bd9Sstevel@tonic-gate 2556*7c478bd9Sstevel@tonic-gate if (list == NULL) { 2557*7c478bd9Sstevel@tonic-gate list = el; 2558*7c478bd9Sstevel@tonic-gate return (list); 2559*7c478bd9Sstevel@tonic-gate } 2560*7c478bd9Sstevel@tonic-gate 2561*7c478bd9Sstevel@tonic-gate /* 2562*7c478bd9Sstevel@tonic-gate * Add it to the end of list 2563*7c478bd9Sstevel@tonic-gate */ 2564*7c478bd9Sstevel@tonic-gate ptr = list; 2565*7c478bd9Sstevel@tonic-gate 2566*7c478bd9Sstevel@tonic-gate while (ptr->next != NULL) 2567*7c478bd9Sstevel@tonic-gate ptr = ptr->next; 2568*7c478bd9Sstevel@tonic-gate 2569*7c478bd9Sstevel@tonic-gate ptr->next = el; 2570*7c478bd9Sstevel@tonic-gate 2571*7c478bd9Sstevel@tonic-gate return (list); 2572*7c478bd9Sstevel@tonic-gate } 2573*7c478bd9Sstevel@tonic-gate 2574*7c478bd9Sstevel@tonic-gate /* 2575*7c478bd9Sstevel@tonic-gate * Free the property expression list 2576*7c478bd9Sstevel@tonic-gate */ 2577*7c478bd9Sstevel@tonic-gate static void 2578*7c478bd9Sstevel@tonic-gate free_list(prop_list_t *list) 2579*7c478bd9Sstevel@tonic-gate { 2580*7c478bd9Sstevel@tonic-gate prop_list_t *ptr; 2581*7c478bd9Sstevel@tonic-gate prop_list_t *tmp; 2582*7c478bd9Sstevel@tonic-gate 2583*7c478bd9Sstevel@tonic-gate for (ptr = list; ptr != NULL; ptr = tmp) { 2584*7c478bd9Sstevel@tonic-gate tmp = ptr->next; 2585*7c478bd9Sstevel@tonic-gate free(ptr); 2586*7c478bd9Sstevel@tonic-gate } 2587*7c478bd9Sstevel@tonic-gate } 2588*7c478bd9Sstevel@tonic-gate 2589*7c478bd9Sstevel@tonic-gate static int 2590*7c478bd9Sstevel@tonic-gate parse_prl(char *prl, char **name, char **baddr, prop_list_t **plist) 2591*7c478bd9Sstevel@tonic-gate { 2592*7c478bd9Sstevel@tonic-gate char *propptr; 2593*7c478bd9Sstevel@tonic-gate char *ptr; 2594*7c478bd9Sstevel@tonic-gate char *pname; 2595*7c478bd9Sstevel@tonic-gate char *pval; 2596*7c478bd9Sstevel@tonic-gate prop_list_t *el; 2597*7c478bd9Sstevel@tonic-gate 2598*7c478bd9Sstevel@tonic-gate if (prl == NULL) 2599*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2600*7c478bd9Sstevel@tonic-gate 2601*7c478bd9Sstevel@tonic-gate if ((prl[0] == '@') || (prl[0] == '?')) 2602*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2603*7c478bd9Sstevel@tonic-gate 2604*7c478bd9Sstevel@tonic-gate *name = prl; 2605*7c478bd9Sstevel@tonic-gate 2606*7c478bd9Sstevel@tonic-gate /* 2607*7c478bd9Sstevel@tonic-gate * get property expression 2608*7c478bd9Sstevel@tonic-gate */ 2609*7c478bd9Sstevel@tonic-gate ptr = strchr(prl, '?'); 2610*7c478bd9Sstevel@tonic-gate 2611*7c478bd9Sstevel@tonic-gate if (ptr != NULL) { 2612*7c478bd9Sstevel@tonic-gate *ptr = '\0'; 2613*7c478bd9Sstevel@tonic-gate propptr = ptr + 1; 2614*7c478bd9Sstevel@tonic-gate } else 2615*7c478bd9Sstevel@tonic-gate propptr = NULL; 2616*7c478bd9Sstevel@tonic-gate 2617*7c478bd9Sstevel@tonic-gate /* 2618*7c478bd9Sstevel@tonic-gate * get bus value 2619*7c478bd9Sstevel@tonic-gate */ 2620*7c478bd9Sstevel@tonic-gate ptr = strchr(prl, '@'); 2621*7c478bd9Sstevel@tonic-gate 2622*7c478bd9Sstevel@tonic-gate if (ptr != NULL) { 2623*7c478bd9Sstevel@tonic-gate *ptr = '\0'; 2624*7c478bd9Sstevel@tonic-gate *baddr = ptr + 1; 2625*7c478bd9Sstevel@tonic-gate if (strlen(*baddr) == 0) /* no bus value after @ */ 2626*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2627*7c478bd9Sstevel@tonic-gate } 2628*7c478bd9Sstevel@tonic-gate 2629*7c478bd9Sstevel@tonic-gate /* 2630*7c478bd9Sstevel@tonic-gate * create the prop list 2631*7c478bd9Sstevel@tonic-gate */ 2632*7c478bd9Sstevel@tonic-gate while (propptr != NULL) { 2633*7c478bd9Sstevel@tonic-gate pname = propptr; 2634*7c478bd9Sstevel@tonic-gate pval = NULL; 2635*7c478bd9Sstevel@tonic-gate 2636*7c478bd9Sstevel@tonic-gate ptr = strchr(propptr, '?'); 2637*7c478bd9Sstevel@tonic-gate 2638*7c478bd9Sstevel@tonic-gate if (ptr != NULL) { /* more ?<prop>=<propval> */ 2639*7c478bd9Sstevel@tonic-gate *ptr = '\0'; 2640*7c478bd9Sstevel@tonic-gate propptr = ptr + 1; 2641*7c478bd9Sstevel@tonic-gate } else 2642*7c478bd9Sstevel@tonic-gate propptr = NULL; 2643*7c478bd9Sstevel@tonic-gate 2644*7c478bd9Sstevel@tonic-gate if (strlen(pname) == 0) /* no prop exp after ? */ 2645*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2646*7c478bd9Sstevel@tonic-gate 2647*7c478bd9Sstevel@tonic-gate ptr = strchr(pname, '='); 2648*7c478bd9Sstevel@tonic-gate if (ptr != NULL) { /* not void prop */ 2649*7c478bd9Sstevel@tonic-gate *ptr = '\0'; 2650*7c478bd9Sstevel@tonic-gate pval = ptr + 1; 2651*7c478bd9Sstevel@tonic-gate /* 2652*7c478bd9Sstevel@tonic-gate * <prop>= is treated as void property 2653*7c478bd9Sstevel@tonic-gate */ 2654*7c478bd9Sstevel@tonic-gate if (strlen(pval) == 0) 2655*7c478bd9Sstevel@tonic-gate pval = NULL; 2656*7c478bd9Sstevel@tonic-gate } 2657*7c478bd9Sstevel@tonic-gate 2658*7c478bd9Sstevel@tonic-gate el = (prop_list_t *)malloc(sizeof (prop_list_t)); 2659*7c478bd9Sstevel@tonic-gate el->pname = pname; 2660*7c478bd9Sstevel@tonic-gate el->pval = pval; 2661*7c478bd9Sstevel@tonic-gate el->next = NULL; 2662*7c478bd9Sstevel@tonic-gate *plist = append_entry_to_list(el, *plist); 2663*7c478bd9Sstevel@tonic-gate } 2664*7c478bd9Sstevel@tonic-gate 2665*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2666*7c478bd9Sstevel@tonic-gate } 2667*7c478bd9Sstevel@tonic-gate 2668*7c478bd9Sstevel@tonic-gate static int 2669*7c478bd9Sstevel@tonic-gate prop_match(ptree_propinfo_t pinfo, void *vbuf, char *val) 2670*7c478bd9Sstevel@tonic-gate { 2671*7c478bd9Sstevel@tonic-gate int8_t cval; 2672*7c478bd9Sstevel@tonic-gate uint8_t ucval; 2673*7c478bd9Sstevel@tonic-gate int16_t sval; 2674*7c478bd9Sstevel@tonic-gate uint16_t usval; 2675*7c478bd9Sstevel@tonic-gate int32_t intval; 2676*7c478bd9Sstevel@tonic-gate uint32_t uintval; 2677*7c478bd9Sstevel@tonic-gate int64_t llval; 2678*7c478bd9Sstevel@tonic-gate uint64_t ullval; 2679*7c478bd9Sstevel@tonic-gate float fval; 2680*7c478bd9Sstevel@tonic-gate double dval; 2681*7c478bd9Sstevel@tonic-gate 2682*7c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.type) { 2683*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 2684*7c478bd9Sstevel@tonic-gate if (strcasecmp(pinfo.piclinfo.name, PICL_PROP_CLASSNAME) == 0) { 2685*7c478bd9Sstevel@tonic-gate if (strcmp(val, PICL_CLASS_PICL) == 0) 2686*7c478bd9Sstevel@tonic-gate return (1); 2687*7c478bd9Sstevel@tonic-gate } 2688*7c478bd9Sstevel@tonic-gate if (strcmp(val, (char *)vbuf) == 0) 2689*7c478bd9Sstevel@tonic-gate return (1); 2690*7c478bd9Sstevel@tonic-gate else 2691*7c478bd9Sstevel@tonic-gate return (0); 2692*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_INT: 2693*7c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.size) { 2694*7c478bd9Sstevel@tonic-gate case sizeof (int8_t): 2695*7c478bd9Sstevel@tonic-gate cval = (int8_t)strtol(val, (char **)NULL, 0); 2696*7c478bd9Sstevel@tonic-gate return (cval == *(char *)vbuf); 2697*7c478bd9Sstevel@tonic-gate case sizeof (int16_t): 2698*7c478bd9Sstevel@tonic-gate sval = (int16_t)strtol(val, (char **)NULL, 0); 2699*7c478bd9Sstevel@tonic-gate return (sval == *(int16_t *)vbuf); 2700*7c478bd9Sstevel@tonic-gate case sizeof (int32_t): 2701*7c478bd9Sstevel@tonic-gate intval = (int32_t)strtol(val, (char **)NULL, 0); 2702*7c478bd9Sstevel@tonic-gate return (intval == *(int32_t *)vbuf); 2703*7c478bd9Sstevel@tonic-gate case sizeof (int64_t): 2704*7c478bd9Sstevel@tonic-gate llval = strtoll(val, (char **)NULL, 0); 2705*7c478bd9Sstevel@tonic-gate return (llval == *(int64_t *)vbuf); 2706*7c478bd9Sstevel@tonic-gate default: 2707*7c478bd9Sstevel@tonic-gate return (0); 2708*7c478bd9Sstevel@tonic-gate } 2709*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_UNSIGNED_INT: 2710*7c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.size) { 2711*7c478bd9Sstevel@tonic-gate case sizeof (uint8_t): 2712*7c478bd9Sstevel@tonic-gate ucval = (uint8_t)strtoul(val, (char **)NULL, 0); 2713*7c478bd9Sstevel@tonic-gate return (ucval == *(uint8_t *)vbuf); 2714*7c478bd9Sstevel@tonic-gate case sizeof (uint16_t): 2715*7c478bd9Sstevel@tonic-gate usval = (uint16_t)strtoul(val, (char **)NULL, 0); 2716*7c478bd9Sstevel@tonic-gate return (usval == *(uint16_t *)vbuf); 2717*7c478bd9Sstevel@tonic-gate case sizeof (uint32_t): 2718*7c478bd9Sstevel@tonic-gate uintval = (uint32_t)strtoul(val, (char **)NULL, 0); 2719*7c478bd9Sstevel@tonic-gate return (uintval == *(uint32_t *)vbuf); 2720*7c478bd9Sstevel@tonic-gate case sizeof (uint64_t): 2721*7c478bd9Sstevel@tonic-gate ullval = strtoull(val, (char **)NULL, 0); 2722*7c478bd9Sstevel@tonic-gate return (ullval == *(uint64_t *)vbuf); 2723*7c478bd9Sstevel@tonic-gate default: 2724*7c478bd9Sstevel@tonic-gate return (0); 2725*7c478bd9Sstevel@tonic-gate } 2726*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_FLOAT: 2727*7c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.size) { 2728*7c478bd9Sstevel@tonic-gate case sizeof (float): 2729*7c478bd9Sstevel@tonic-gate fval = (float)strtod(val, (char **)NULL); 2730*7c478bd9Sstevel@tonic-gate return (fval == *(float *)vbuf); 2731*7c478bd9Sstevel@tonic-gate case sizeof (double): 2732*7c478bd9Sstevel@tonic-gate dval = strtod(val, (char **)NULL); 2733*7c478bd9Sstevel@tonic-gate return (dval == *(double *)vbuf); 2734*7c478bd9Sstevel@tonic-gate default: 2735*7c478bd9Sstevel@tonic-gate return (0); 2736*7c478bd9Sstevel@tonic-gate } 2737*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_VOID: 2738*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_TIMESTAMP: 2739*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_TABLE: 2740*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_REFERENCE: 2741*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_BYTEARRAY: 2742*7c478bd9Sstevel@tonic-gate case PICL_PTYPE_UNKNOWN: 2743*7c478bd9Sstevel@tonic-gate default: 2744*7c478bd9Sstevel@tonic-gate return (0); 2745*7c478bd9Sstevel@tonic-gate } 2746*7c478bd9Sstevel@tonic-gate } 2747*7c478bd9Sstevel@tonic-gate 2748*7c478bd9Sstevel@tonic-gate static int 2749*7c478bd9Sstevel@tonic-gate check_propval(picl_nodehdl_t nodeh, char *pname, char *pval) 2750*7c478bd9Sstevel@tonic-gate { 2751*7c478bd9Sstevel@tonic-gate int err; 2752*7c478bd9Sstevel@tonic-gate picl_prophdl_t proph; 2753*7c478bd9Sstevel@tonic-gate ptree_propinfo_t pinfo; 2754*7c478bd9Sstevel@tonic-gate void *vbuf; 2755*7c478bd9Sstevel@tonic-gate 2756*7c478bd9Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, pname, &proph); 2757*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2758*7c478bd9Sstevel@tonic-gate return (err); 2759*7c478bd9Sstevel@tonic-gate 2760*7c478bd9Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 2761*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2762*7c478bd9Sstevel@tonic-gate return (err); 2763*7c478bd9Sstevel@tonic-gate 2764*7c478bd9Sstevel@tonic-gate if (pval == NULL) { /* void type */ 2765*7c478bd9Sstevel@tonic-gate if (pinfo.piclinfo.type != PICL_PTYPE_VOID) 2766*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2767*7c478bd9Sstevel@tonic-gate } else { 2768*7c478bd9Sstevel@tonic-gate vbuf = alloca(pinfo.piclinfo.size); 2769*7c478bd9Sstevel@tonic-gate if (vbuf == NULL) 2770*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2771*7c478bd9Sstevel@tonic-gate err = ptree_get_propval(proph, vbuf, 2772*7c478bd9Sstevel@tonic-gate pinfo.piclinfo.size); 2773*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2774*7c478bd9Sstevel@tonic-gate return (err); 2775*7c478bd9Sstevel@tonic-gate 2776*7c478bd9Sstevel@tonic-gate if (!prop_match(pinfo, vbuf, pval)) 2777*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2778*7c478bd9Sstevel@tonic-gate } 2779*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2780*7c478bd9Sstevel@tonic-gate } 2781*7c478bd9Sstevel@tonic-gate 2782*7c478bd9Sstevel@tonic-gate static int 2783*7c478bd9Sstevel@tonic-gate get_child_by_path(picl_nodehdl_t rooth, char *prl, 2784*7c478bd9Sstevel@tonic-gate picl_nodehdl_t *nodeh, char *pname) 2785*7c478bd9Sstevel@tonic-gate { 2786*7c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 2787*7c478bd9Sstevel@tonic-gate int err; 2788*7c478bd9Sstevel@tonic-gate char *nameval; 2789*7c478bd9Sstevel@tonic-gate char *nodename; 2790*7c478bd9Sstevel@tonic-gate char *path; 2791*7c478bd9Sstevel@tonic-gate char *baddr; 2792*7c478bd9Sstevel@tonic-gate char *busval; 2793*7c478bd9Sstevel@tonic-gate prop_list_t *plist; 2794*7c478bd9Sstevel@tonic-gate prop_list_t *ptr; 2795*7c478bd9Sstevel@tonic-gate 2796*7c478bd9Sstevel@tonic-gate if (prl == NULL) 2797*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2798*7c478bd9Sstevel@tonic-gate 2799*7c478bd9Sstevel@tonic-gate path = alloca(strlen(prl) + 1); 2800*7c478bd9Sstevel@tonic-gate if (path == NULL) 2801*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2802*7c478bd9Sstevel@tonic-gate 2803*7c478bd9Sstevel@tonic-gate (void) strcpy(path, prl); 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate plist = NULL; 2806*7c478bd9Sstevel@tonic-gate nodename = NULL; 2807*7c478bd9Sstevel@tonic-gate baddr = NULL; 2808*7c478bd9Sstevel@tonic-gate 2809*7c478bd9Sstevel@tonic-gate err = parse_prl(path, &nodename, &baddr, &plist); 2810*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2811*7c478bd9Sstevel@tonic-gate free_list(plist); 2812*7c478bd9Sstevel@tonic-gate return (err); 2813*7c478bd9Sstevel@tonic-gate } 2814*7c478bd9Sstevel@tonic-gate 2815*7c478bd9Sstevel@tonic-gate if (nodename == NULL) 2816*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2817*7c478bd9Sstevel@tonic-gate 2818*7c478bd9Sstevel@tonic-gate nameval = alloca(strlen(nodename) + 1); 2819*7c478bd9Sstevel@tonic-gate if (nameval == NULL) { 2820*7c478bd9Sstevel@tonic-gate free_list(plist); 2821*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2822*7c478bd9Sstevel@tonic-gate } 2823*7c478bd9Sstevel@tonic-gate 2824*7c478bd9Sstevel@tonic-gate if (baddr != NULL) { 2825*7c478bd9Sstevel@tonic-gate busval = alloca(strlen(baddr) + 1); 2826*7c478bd9Sstevel@tonic-gate if (busval == NULL) { 2827*7c478bd9Sstevel@tonic-gate free_list(plist); 2828*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2829*7c478bd9Sstevel@tonic-gate } 2830*7c478bd9Sstevel@tonic-gate } 2831*7c478bd9Sstevel@tonic-gate 2832*7c478bd9Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 2833*7c478bd9Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 2834*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 2835*7c478bd9Sstevel@tonic-gate sizeof (picl_nodehdl_t))) { 2836*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 2837*7c478bd9Sstevel@tonic-gate free_list(plist); 2838*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2839*7c478bd9Sstevel@tonic-gate } 2840*7c478bd9Sstevel@tonic-gate 2841*7c478bd9Sstevel@tonic-gate /* 2842*7c478bd9Sstevel@tonic-gate * compare name 2843*7c478bd9Sstevel@tonic-gate */ 2844*7c478bd9Sstevel@tonic-gate if ((strcmp(pname, PICL_PROP_CLASSNAME) != 0) || 2845*7c478bd9Sstevel@tonic-gate (strcmp(nodename, PICL_CLASS_PICL) != 0)) { 2846*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, pname, 2847*7c478bd9Sstevel@tonic-gate nameval, (strlen(nodename) + 1)); 2848*7c478bd9Sstevel@tonic-gate 2849*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2850*7c478bd9Sstevel@tonic-gate continue; 2851*7c478bd9Sstevel@tonic-gate if (strcmp(nameval, nodename) != 0) 2852*7c478bd9Sstevel@tonic-gate continue; 2853*7c478bd9Sstevel@tonic-gate } 2854*7c478bd9Sstevel@tonic-gate 2855*7c478bd9Sstevel@tonic-gate /* 2856*7c478bd9Sstevel@tonic-gate * compare device address with bus-addr prop first 2857*7c478bd9Sstevel@tonic-gate * then with UnitAddress property 2858*7c478bd9Sstevel@tonic-gate */ 2859*7c478bd9Sstevel@tonic-gate if (baddr != NULL) { /* compare bus-addr prop */ 2860*7c478bd9Sstevel@tonic-gate if ((ptree_get_propval_by_name(chdh, PICL_PROP_BUS_ADDR, 2861*7c478bd9Sstevel@tonic-gate busval, (strlen(baddr) + 1)) != PICL_SUCCESS) && 2862*7c478bd9Sstevel@tonic-gate (ptree_get_propval_by_name(chdh, 2863*7c478bd9Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, busval, 2864*7c478bd9Sstevel@tonic-gate (strlen(baddr) + 1)) != PICL_SUCCESS)) 2865*7c478bd9Sstevel@tonic-gate continue; 2866*7c478bd9Sstevel@tonic-gate 2867*7c478bd9Sstevel@tonic-gate if (strcmp(busval, baddr) != 0) 2868*7c478bd9Sstevel@tonic-gate continue; /* not match */ 2869*7c478bd9Sstevel@tonic-gate } 2870*7c478bd9Sstevel@tonic-gate 2871*7c478bd9Sstevel@tonic-gate if (plist == NULL) { /* no prop expression */ 2872*7c478bd9Sstevel@tonic-gate *nodeh = chdh; 2873*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2874*7c478bd9Sstevel@tonic-gate } 2875*7c478bd9Sstevel@tonic-gate 2876*7c478bd9Sstevel@tonic-gate /* 2877*7c478bd9Sstevel@tonic-gate * compare the property expression list 2878*7c478bd9Sstevel@tonic-gate */ 2879*7c478bd9Sstevel@tonic-gate ptr = plist; 2880*7c478bd9Sstevel@tonic-gate 2881*7c478bd9Sstevel@tonic-gate while (ptr != NULL) { 2882*7c478bd9Sstevel@tonic-gate err = check_propval(chdh, ptr->pname, ptr->pval); 2883*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2884*7c478bd9Sstevel@tonic-gate break; 2885*7c478bd9Sstevel@tonic-gate 2886*7c478bd9Sstevel@tonic-gate ptr = ptr->next; 2887*7c478bd9Sstevel@tonic-gate } 2888*7c478bd9Sstevel@tonic-gate if (ptr == NULL) { 2889*7c478bd9Sstevel@tonic-gate *nodeh = chdh; 2890*7c478bd9Sstevel@tonic-gate free_list(plist); 2891*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2892*7c478bd9Sstevel@tonic-gate } 2893*7c478bd9Sstevel@tonic-gate } 2894*7c478bd9Sstevel@tonic-gate free_list(plist); 2895*7c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 2896*7c478bd9Sstevel@tonic-gate } 2897*7c478bd9Sstevel@tonic-gate 2898*7c478bd9Sstevel@tonic-gate /* 2899*7c478bd9Sstevel@tonic-gate * This functions returns the handle of node specified by its path 2900*7c478bd9Sstevel@tonic-gate */ 2901*7c478bd9Sstevel@tonic-gate int 2902*7c478bd9Sstevel@tonic-gate ptree_get_node_by_path(const char *piclprl, picl_nodehdl_t *handle) 2903*7c478bd9Sstevel@tonic-gate { 2904*7c478bd9Sstevel@tonic-gate picl_nodehdl_t rooth; 2905*7c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 2906*7c478bd9Sstevel@tonic-gate char *path; 2907*7c478bd9Sstevel@tonic-gate char *ptr; 2908*7c478bd9Sstevel@tonic-gate char *defprop; 2909*7c478bd9Sstevel@tonic-gate char *tokindex; 2910*7c478bd9Sstevel@tonic-gate int err; 2911*7c478bd9Sstevel@tonic-gate int len; 2912*7c478bd9Sstevel@tonic-gate int npflg; /* namepath flag */ 2913*7c478bd9Sstevel@tonic-gate 2914*7c478bd9Sstevel@tonic-gate 2915*7c478bd9Sstevel@tonic-gate path = alloca(strlen(piclprl) + 1); 2916*7c478bd9Sstevel@tonic-gate if (path == NULL) 2917*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2918*7c478bd9Sstevel@tonic-gate (void) strcpy(path, piclprl); 2919*7c478bd9Sstevel@tonic-gate 2920*7c478bd9Sstevel@tonic-gate npflg = 1; /* default */ 2921*7c478bd9Sstevel@tonic-gate defprop = path; 2922*7c478bd9Sstevel@tonic-gate if (path[0] == '/') { 2923*7c478bd9Sstevel@tonic-gate ptr = &path[1]; 2924*7c478bd9Sstevel@tonic-gate } else if ((tokindex = strchr(path, ':')) != NULL) { 2925*7c478bd9Sstevel@tonic-gate *tokindex = '\0'; 2926*7c478bd9Sstevel@tonic-gate ++tokindex; 2927*7c478bd9Sstevel@tonic-gate if (*tokindex == '/') 2928*7c478bd9Sstevel@tonic-gate ptr = tokindex + 1; 2929*7c478bd9Sstevel@tonic-gate else 2930*7c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 2931*7c478bd9Sstevel@tonic-gate npflg = 0; 2932*7c478bd9Sstevel@tonic-gate } else 2933*7c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 2934*7c478bd9Sstevel@tonic-gate 2935*7c478bd9Sstevel@tonic-gate err = ptree_get_root(&rooth); 2936*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2937*7c478bd9Sstevel@tonic-gate return (err); 2938*7c478bd9Sstevel@tonic-gate 2939*7c478bd9Sstevel@tonic-gate for (chdh = rooth, tokindex = strchr(ptr, '/'); 2940*7c478bd9Sstevel@tonic-gate tokindex != NULL; 2941*7c478bd9Sstevel@tonic-gate ptr = tokindex + 1, tokindex = strchr(ptr, '/')) { 2942*7c478bd9Sstevel@tonic-gate *tokindex = '\0'; 2943*7c478bd9Sstevel@tonic-gate if (npflg) 2944*7c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, 2945*7c478bd9Sstevel@tonic-gate PICL_PROP_NAME); 2946*7c478bd9Sstevel@tonic-gate else 2947*7c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, 2948*7c478bd9Sstevel@tonic-gate defprop); 2949*7c478bd9Sstevel@tonic-gate 2950*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2951*7c478bd9Sstevel@tonic-gate return (err); 2952*7c478bd9Sstevel@tonic-gate } 2953*7c478bd9Sstevel@tonic-gate 2954*7c478bd9Sstevel@tonic-gate /* 2955*7c478bd9Sstevel@tonic-gate * check if last token is empty or not 2956*7c478bd9Sstevel@tonic-gate * eg. /a/b/c/ or /a/b/c 2957*7c478bd9Sstevel@tonic-gate */ 2958*7c478bd9Sstevel@tonic-gate if (*ptr == '\0') { 2959*7c478bd9Sstevel@tonic-gate *handle = chdh; 2960*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2961*7c478bd9Sstevel@tonic-gate } 2962*7c478bd9Sstevel@tonic-gate 2963*7c478bd9Sstevel@tonic-gate len = strcspn(ptr, " \t\n"); 2964*7c478bd9Sstevel@tonic-gate if (len == 0) { 2965*7c478bd9Sstevel@tonic-gate *handle = chdh; 2966*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2967*7c478bd9Sstevel@tonic-gate } 2968*7c478bd9Sstevel@tonic-gate 2969*7c478bd9Sstevel@tonic-gate ptr[len] = '\0'; 2970*7c478bd9Sstevel@tonic-gate if (npflg) 2971*7c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, PICL_PROP_NAME); 2972*7c478bd9Sstevel@tonic-gate else 2973*7c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, defprop); 2974*7c478bd9Sstevel@tonic-gate 2975*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 2976*7c478bd9Sstevel@tonic-gate return (err); 2977*7c478bd9Sstevel@tonic-gate 2978*7c478bd9Sstevel@tonic-gate *handle = chdh; 2979*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2980*7c478bd9Sstevel@tonic-gate } 2981*7c478bd9Sstevel@tonic-gate 2982*7c478bd9Sstevel@tonic-gate /* 2983*7c478bd9Sstevel@tonic-gate * Initialize propinfo 2984*7c478bd9Sstevel@tonic-gate */ 2985*7c478bd9Sstevel@tonic-gate int 2986*7c478bd9Sstevel@tonic-gate ptree_init_propinfo(ptree_propinfo_t *infop, int version, int ptype, int pmode, 2987*7c478bd9Sstevel@tonic-gate size_t psize, char *pname, int (*readfn)(ptree_rarg_t *, void *), 2988*7c478bd9Sstevel@tonic-gate int (*writefn)(ptree_warg_t *, const void *)) 2989*7c478bd9Sstevel@tonic-gate { 2990*7c478bd9Sstevel@tonic-gate if (version != PTREE_PROPINFO_VERSION_1) 2991*7c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 2992*7c478bd9Sstevel@tonic-gate if ((infop == NULL) || (pname == NULL)) 2993*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 2994*7c478bd9Sstevel@tonic-gate infop->version = version; 2995*7c478bd9Sstevel@tonic-gate infop->piclinfo.type = ptype; 2996*7c478bd9Sstevel@tonic-gate infop->piclinfo.accessmode = pmode; 2997*7c478bd9Sstevel@tonic-gate infop->piclinfo.size = psize; 2998*7c478bd9Sstevel@tonic-gate infop->read = readfn; 2999*7c478bd9Sstevel@tonic-gate infop->write = writefn; 3000*7c478bd9Sstevel@tonic-gate (void) strlcpy(infop->piclinfo.name, pname, PICL_PROPNAMELEN_MAX); 3001*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3002*7c478bd9Sstevel@tonic-gate } 3003*7c478bd9Sstevel@tonic-gate 3004*7c478bd9Sstevel@tonic-gate /* 3005*7c478bd9Sstevel@tonic-gate * Creates a property, adds it to the node, and returns the property 3006*7c478bd9Sstevel@tonic-gate * handle to the caller if successful and proph is not NULL 3007*7c478bd9Sstevel@tonic-gate */ 3008*7c478bd9Sstevel@tonic-gate int 3009*7c478bd9Sstevel@tonic-gate ptree_create_and_add_prop(picl_nodehdl_t nodeh, ptree_propinfo_t *infop, 3010*7c478bd9Sstevel@tonic-gate void *vbuf, picl_prophdl_t *proph) 3011*7c478bd9Sstevel@tonic-gate { 3012*7c478bd9Sstevel@tonic-gate int err; 3013*7c478bd9Sstevel@tonic-gate picl_prophdl_t tmph; 3014*7c478bd9Sstevel@tonic-gate 3015*7c478bd9Sstevel@tonic-gate err = ptree_create_prop(infop, vbuf, &tmph); 3016*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3017*7c478bd9Sstevel@tonic-gate return (err); 3018*7c478bd9Sstevel@tonic-gate err = ptree_add_prop(nodeh, tmph); 3019*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 3020*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_prop(tmph); 3021*7c478bd9Sstevel@tonic-gate return (err); 3022*7c478bd9Sstevel@tonic-gate } 3023*7c478bd9Sstevel@tonic-gate if (proph) 3024*7c478bd9Sstevel@tonic-gate *proph = tmph; 3025*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3026*7c478bd9Sstevel@tonic-gate } 3027*7c478bd9Sstevel@tonic-gate 3028*7c478bd9Sstevel@tonic-gate /* 3029*7c478bd9Sstevel@tonic-gate * Creates a node, adds it to its parent node, and returns the node 3030*7c478bd9Sstevel@tonic-gate * handle to the caller if successful 3031*7c478bd9Sstevel@tonic-gate */ 3032*7c478bd9Sstevel@tonic-gate int 3033*7c478bd9Sstevel@tonic-gate ptree_create_and_add_node(picl_nodehdl_t rooth, const char *name, 3034*7c478bd9Sstevel@tonic-gate const char *classname, picl_nodehdl_t *nodeh) 3035*7c478bd9Sstevel@tonic-gate { 3036*7c478bd9Sstevel@tonic-gate picl_nodehdl_t tmph; 3037*7c478bd9Sstevel@tonic-gate int err; 3038*7c478bd9Sstevel@tonic-gate 3039*7c478bd9Sstevel@tonic-gate err = ptree_create_node(name, classname, &tmph); 3040*7c478bd9Sstevel@tonic-gate 3041*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3042*7c478bd9Sstevel@tonic-gate return (err); 3043*7c478bd9Sstevel@tonic-gate 3044*7c478bd9Sstevel@tonic-gate err = ptree_add_node(rooth, tmph); 3045*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 3046*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(tmph); 3047*7c478bd9Sstevel@tonic-gate return (err); 3048*7c478bd9Sstevel@tonic-gate } 3049*7c478bd9Sstevel@tonic-gate 3050*7c478bd9Sstevel@tonic-gate *nodeh = tmph; 3051*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3052*7c478bd9Sstevel@tonic-gate } 3053*7c478bd9Sstevel@tonic-gate 3054*7c478bd9Sstevel@tonic-gate 3055*7c478bd9Sstevel@tonic-gate /* 3056*7c478bd9Sstevel@tonic-gate * recursively visit all nodes 3057*7c478bd9Sstevel@tonic-gate */ 3058*7c478bd9Sstevel@tonic-gate static int 3059*7c478bd9Sstevel@tonic-gate do_walk(picl_nodehdl_t rooth, const char *classname, 3060*7c478bd9Sstevel@tonic-gate void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args)) 3061*7c478bd9Sstevel@tonic-gate { 3062*7c478bd9Sstevel@tonic-gate int err; 3063*7c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 3064*7c478bd9Sstevel@tonic-gate char classval[PICL_CLASSNAMELEN_MAX]; 3065*7c478bd9Sstevel@tonic-gate 3066*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 3067*7c478bd9Sstevel@tonic-gate sizeof (chdh)); 3068*7c478bd9Sstevel@tonic-gate while (err == PICL_SUCCESS) { 3069*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_CLASSNAME, 3070*7c478bd9Sstevel@tonic-gate classval, sizeof (classval)); 3071*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3072*7c478bd9Sstevel@tonic-gate return (err); 3073*7c478bd9Sstevel@tonic-gate 3074*7c478bd9Sstevel@tonic-gate if ((classname == NULL) || (strcmp(classname, classval) == 0)) { 3075*7c478bd9Sstevel@tonic-gate err = callback_fn(chdh, c_args); 3076*7c478bd9Sstevel@tonic-gate if (err != PICL_WALK_CONTINUE) 3077*7c478bd9Sstevel@tonic-gate return (err); 3078*7c478bd9Sstevel@tonic-gate } 3079*7c478bd9Sstevel@tonic-gate 3080*7c478bd9Sstevel@tonic-gate if ((err = do_walk(chdh, classname, c_args, callback_fn)) != 3081*7c478bd9Sstevel@tonic-gate PICL_WALK_CONTINUE) 3082*7c478bd9Sstevel@tonic-gate return (err); 3083*7c478bd9Sstevel@tonic-gate 3084*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 3085*7c478bd9Sstevel@tonic-gate sizeof (chdh)); 3086*7c478bd9Sstevel@tonic-gate } 3087*7c478bd9Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) /* end of a branch */ 3088*7c478bd9Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 3089*7c478bd9Sstevel@tonic-gate return (err); 3090*7c478bd9Sstevel@tonic-gate 3091*7c478bd9Sstevel@tonic-gate } 3092*7c478bd9Sstevel@tonic-gate 3093*7c478bd9Sstevel@tonic-gate /* 3094*7c478bd9Sstevel@tonic-gate * This function visits all the nodes in the subtree rooted at <rooth>. 3095*7c478bd9Sstevel@tonic-gate * For each node that matches the class name specified, the callback 3096*7c478bd9Sstevel@tonic-gate * function is invoked. 3097*7c478bd9Sstevel@tonic-gate */ 3098*7c478bd9Sstevel@tonic-gate int 3099*7c478bd9Sstevel@tonic-gate ptree_walk_tree_by_class(picl_nodehdl_t rooth, const char *classname, 3100*7c478bd9Sstevel@tonic-gate void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args)) 3101*7c478bd9Sstevel@tonic-gate { 3102*7c478bd9Sstevel@tonic-gate int err; 3103*7c478bd9Sstevel@tonic-gate 3104*7c478bd9Sstevel@tonic-gate if (callback_fn == NULL) 3105*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 3106*7c478bd9Sstevel@tonic-gate err = do_walk(rooth, classname, c_args, callback_fn); 3107*7c478bd9Sstevel@tonic-gate if ((err == PICL_WALK_CONTINUE) || (err == PICL_WALK_TERMINATE)) 3108*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3109*7c478bd9Sstevel@tonic-gate return (err); 3110*7c478bd9Sstevel@tonic-gate } 3111*7c478bd9Sstevel@tonic-gate 3112*7c478bd9Sstevel@tonic-gate static int 3113*7c478bd9Sstevel@tonic-gate compare_propval(picl_nodehdl_t nodeh, char *pname, picl_prop_type_t ptype, 3114*7c478bd9Sstevel@tonic-gate void *pval, size_t valsize) 3115*7c478bd9Sstevel@tonic-gate { 3116*7c478bd9Sstevel@tonic-gate int err; 3117*7c478bd9Sstevel@tonic-gate picl_prophdl_t proph; 3118*7c478bd9Sstevel@tonic-gate ptree_propinfo_t propinfo; 3119*7c478bd9Sstevel@tonic-gate void *vbuf; 3120*7c478bd9Sstevel@tonic-gate 3121*7c478bd9Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, pname, &proph); 3122*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3123*7c478bd9Sstevel@tonic-gate return (0); 3124*7c478bd9Sstevel@tonic-gate err = ptree_get_propinfo(proph, &propinfo); 3125*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3126*7c478bd9Sstevel@tonic-gate return (0); 3127*7c478bd9Sstevel@tonic-gate if (propinfo.piclinfo.type != ptype) 3128*7c478bd9Sstevel@tonic-gate return (0); 3129*7c478bd9Sstevel@tonic-gate if (propinfo.piclinfo.type == PICL_PTYPE_VOID) 3130*7c478bd9Sstevel@tonic-gate return (1); 3131*7c478bd9Sstevel@tonic-gate if (pval == NULL) 3132*7c478bd9Sstevel@tonic-gate return (0); 3133*7c478bd9Sstevel@tonic-gate if (valsize > propinfo.piclinfo.size) 3134*7c478bd9Sstevel@tonic-gate return (0); 3135*7c478bd9Sstevel@tonic-gate vbuf = alloca(propinfo.piclinfo.size); 3136*7c478bd9Sstevel@tonic-gate if (vbuf == NULL) 3137*7c478bd9Sstevel@tonic-gate return (0); 3138*7c478bd9Sstevel@tonic-gate err = ptree_get_propval(proph, vbuf, propinfo.piclinfo.size); 3139*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3140*7c478bd9Sstevel@tonic-gate return (0); 3141*7c478bd9Sstevel@tonic-gate if (memcmp(vbuf, pval, valsize) == 0) 3142*7c478bd9Sstevel@tonic-gate return (1); 3143*7c478bd9Sstevel@tonic-gate return (0); 3144*7c478bd9Sstevel@tonic-gate } 3145*7c478bd9Sstevel@tonic-gate 3146*7c478bd9Sstevel@tonic-gate 3147*7c478bd9Sstevel@tonic-gate /* 3148*7c478bd9Sstevel@tonic-gate * This function traverses the subtree and finds a node that has a property 3149*7c478bd9Sstevel@tonic-gate * of the specified name and type with the specified value. 3150*7c478bd9Sstevel@tonic-gate * The matched node in the tree is returned in retnodeh. If there is 3151*7c478bd9Sstevel@tonic-gate * no node with that property, then PICL_NODENOTFOUND is returned. 3152*7c478bd9Sstevel@tonic-gate */ 3153*7c478bd9Sstevel@tonic-gate int 3154*7c478bd9Sstevel@tonic-gate ptree_find_node(picl_nodehdl_t rooth, char *pname, picl_prop_type_t ptype, 3155*7c478bd9Sstevel@tonic-gate void *pval, size_t valsize, picl_nodehdl_t *retnodeh) 3156*7c478bd9Sstevel@tonic-gate { 3157*7c478bd9Sstevel@tonic-gate int err; 3158*7c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 3159*7c478bd9Sstevel@tonic-gate 3160*7c478bd9Sstevel@tonic-gate if (pname == NULL) 3161*7c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 3162*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 3163*7c478bd9Sstevel@tonic-gate sizeof (chdh)); 3164*7c478bd9Sstevel@tonic-gate 3165*7c478bd9Sstevel@tonic-gate while (err == PICL_SUCCESS) { 3166*7c478bd9Sstevel@tonic-gate if (compare_propval(chdh, pname, ptype, pval, valsize)) { 3167*7c478bd9Sstevel@tonic-gate if (retnodeh) 3168*7c478bd9Sstevel@tonic-gate *retnodeh = chdh; 3169*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3170*7c478bd9Sstevel@tonic-gate } 3171*7c478bd9Sstevel@tonic-gate 3172*7c478bd9Sstevel@tonic-gate err = ptree_find_node(chdh, pname, ptype, pval, valsize, 3173*7c478bd9Sstevel@tonic-gate retnodeh); 3174*7c478bd9Sstevel@tonic-gate if (err != PICL_NODENOTFOUND) 3175*7c478bd9Sstevel@tonic-gate return (err); 3176*7c478bd9Sstevel@tonic-gate 3177*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 3178*7c478bd9Sstevel@tonic-gate sizeof (chdh)); 3179*7c478bd9Sstevel@tonic-gate } 3180*7c478bd9Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 3181*7c478bd9Sstevel@tonic-gate return (PICL_NODENOTFOUND); 3182*7c478bd9Sstevel@tonic-gate return (err); 3183*7c478bd9Sstevel@tonic-gate } 3184*7c478bd9Sstevel@tonic-gate 3185*7c478bd9Sstevel@tonic-gate /* 3186*7c478bd9Sstevel@tonic-gate * This function gets the frutree parent for a given node. 3187*7c478bd9Sstevel@tonic-gate * Traverse up the tree and look for the following properties: 3188*7c478bd9Sstevel@tonic-gate * Frutree parent reference properties: 3189*7c478bd9Sstevel@tonic-gate * _fru_parent 3190*7c478bd9Sstevel@tonic-gate * _location_parent 3191*7c478bd9Sstevel@tonic-gate * _port_parent 3192*7c478bd9Sstevel@tonic-gate * If the frutree reference property is found, return its value. 3193*7c478bd9Sstevel@tonic-gate * Else, return the handle of /frutree/chassis. 3194*7c478bd9Sstevel@tonic-gate */ 3195*7c478bd9Sstevel@tonic-gate int 3196*7c478bd9Sstevel@tonic-gate ptree_get_frutree_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruh) 3197*7c478bd9Sstevel@tonic-gate { 3198*7c478bd9Sstevel@tonic-gate int err; 3199*7c478bd9Sstevel@tonic-gate picl_nodehdl_t nparh; 3200*7c478bd9Sstevel@tonic-gate picl_nodehdl_t fruparh; 3201*7c478bd9Sstevel@tonic-gate 3202*7c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 3203*7c478bd9Sstevel@tonic-gate nparh = nodeh; 3204*7c478bd9Sstevel@tonic-gate while (err == PICL_SUCCESS) { 3205*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, PICL_REFPROP_FRU_PARENT, 3206*7c478bd9Sstevel@tonic-gate &fruparh, sizeof (fruparh)); 3207*7c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 3208*7c478bd9Sstevel@tonic-gate *fruh = fruparh; 3209*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3210*7c478bd9Sstevel@tonic-gate } 3211*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, 3212*7c478bd9Sstevel@tonic-gate PICL_REFPROP_LOC_PARENT, &fruparh, sizeof (fruparh)); 3213*7c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 3214*7c478bd9Sstevel@tonic-gate *fruh = fruparh; 3215*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3216*7c478bd9Sstevel@tonic-gate } 3217*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, PICL_REFPROP_PORT_PARENT, 3218*7c478bd9Sstevel@tonic-gate &fruparh, sizeof (fruparh)); 3219*7c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 3220*7c478bd9Sstevel@tonic-gate *fruh = fruparh; 3221*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3222*7c478bd9Sstevel@tonic-gate } 3223*7c478bd9Sstevel@tonic-gate 3224*7c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, PICL_PROP_PARENT, &nparh, 3225*7c478bd9Sstevel@tonic-gate sizeof (nparh)); 3226*7c478bd9Sstevel@tonic-gate } 3227*7c478bd9Sstevel@tonic-gate 3228*7c478bd9Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) { /* return /frutree/chassis handle */ 3229*7c478bd9Sstevel@tonic-gate err = ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, &fruparh); 3230*7c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 3231*7c478bd9Sstevel@tonic-gate *fruh = fruparh; 3232*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3233*7c478bd9Sstevel@tonic-gate } 3234*7c478bd9Sstevel@tonic-gate } 3235*7c478bd9Sstevel@tonic-gate return (err); 3236*7c478bd9Sstevel@tonic-gate } 3237*7c478bd9Sstevel@tonic-gate 3238*7c478bd9Sstevel@tonic-gate /* 3239*7c478bd9Sstevel@tonic-gate * This function is called by plug-ins to register with the daemon 3240*7c478bd9Sstevel@tonic-gate */ 3241*7c478bd9Sstevel@tonic-gate int 3242*7c478bd9Sstevel@tonic-gate picld_plugin_register(picld_plugin_reg_t *regp) 3243*7c478bd9Sstevel@tonic-gate { 3244*7c478bd9Sstevel@tonic-gate picld_plugin_reg_list_t *el; 3245*7c478bd9Sstevel@tonic-gate picld_plugin_reg_list_t *tmp; 3246*7c478bd9Sstevel@tonic-gate 3247*7c478bd9Sstevel@tonic-gate if (regp == NULL) 3248*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3249*7c478bd9Sstevel@tonic-gate 3250*7c478bd9Sstevel@tonic-gate if (regp->version != PICLD_PLUGIN_VERSION_1) 3251*7c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 3252*7c478bd9Sstevel@tonic-gate 3253*7c478bd9Sstevel@tonic-gate el = malloc(sizeof (picld_plugin_reg_list_t)); 3254*7c478bd9Sstevel@tonic-gate if (el == NULL) 3255*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3256*7c478bd9Sstevel@tonic-gate el->reg.version = regp->version; 3257*7c478bd9Sstevel@tonic-gate el->reg.critical = regp->critical; 3258*7c478bd9Sstevel@tonic-gate if (regp->name) 3259*7c478bd9Sstevel@tonic-gate el->reg.name = strdup(regp->name); 3260*7c478bd9Sstevel@tonic-gate if (el->reg.name == NULL) 3261*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3262*7c478bd9Sstevel@tonic-gate 3263*7c478bd9Sstevel@tonic-gate el->reg.plugin_init = regp->plugin_init; 3264*7c478bd9Sstevel@tonic-gate el->reg.plugin_fini = regp->plugin_fini; 3265*7c478bd9Sstevel@tonic-gate el->next = NULL; 3266*7c478bd9Sstevel@tonic-gate 3267*7c478bd9Sstevel@tonic-gate if (plugin_reg_list == NULL) { 3268*7c478bd9Sstevel@tonic-gate plugin_reg_list = el; 3269*7c478bd9Sstevel@tonic-gate } else { /* add to end */ 3270*7c478bd9Sstevel@tonic-gate tmp = plugin_reg_list; 3271*7c478bd9Sstevel@tonic-gate while (tmp->next != NULL) 3272*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 3273*7c478bd9Sstevel@tonic-gate tmp->next = el; 3274*7c478bd9Sstevel@tonic-gate } 3275*7c478bd9Sstevel@tonic-gate 3276*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3277*7c478bd9Sstevel@tonic-gate } 3278*7c478bd9Sstevel@tonic-gate 3279*7c478bd9Sstevel@tonic-gate /* 3280*7c478bd9Sstevel@tonic-gate * Call fini routines of the registered plugins 3281*7c478bd9Sstevel@tonic-gate */ 3282*7c478bd9Sstevel@tonic-gate static void 3283*7c478bd9Sstevel@tonic-gate plugin_fini(picld_plugin_reg_list_t *p) 3284*7c478bd9Sstevel@tonic-gate { 3285*7c478bd9Sstevel@tonic-gate if (p == NULL) 3286*7c478bd9Sstevel@tonic-gate return; 3287*7c478bd9Sstevel@tonic-gate 3288*7c478bd9Sstevel@tonic-gate plugin_fini(p->next); 3289*7c478bd9Sstevel@tonic-gate if (p->reg.plugin_fini) 3290*7c478bd9Sstevel@tonic-gate (p->reg.plugin_fini)(); 3291*7c478bd9Sstevel@tonic-gate } 3292*7c478bd9Sstevel@tonic-gate 3293*7c478bd9Sstevel@tonic-gate /* 3294*7c478bd9Sstevel@tonic-gate * Create PICL Tree 3295*7c478bd9Sstevel@tonic-gate */ 3296*7c478bd9Sstevel@tonic-gate 3297*7c478bd9Sstevel@tonic-gate static void 3298*7c478bd9Sstevel@tonic-gate init_plugin_reg_list(void) 3299*7c478bd9Sstevel@tonic-gate { 3300*7c478bd9Sstevel@tonic-gate plugin_reg_list = NULL; 3301*7c478bd9Sstevel@tonic-gate } 3302*7c478bd9Sstevel@tonic-gate 3303*7c478bd9Sstevel@tonic-gate static int 3304*7c478bd9Sstevel@tonic-gate picltree_set_root(picl_nodehdl_t rooth) 3305*7c478bd9Sstevel@tonic-gate { 3306*7c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 3307*7c478bd9Sstevel@tonic-gate int err; 3308*7c478bd9Sstevel@tonic-gate 3309*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 3310*7c478bd9Sstevel@tonic-gate pobj = NULL; 3311*7c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, rooth, &pobj); /* lock node */ 3312*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 3313*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 3314*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3315*7c478bd9Sstevel@tonic-gate } 3316*7c478bd9Sstevel@tonic-gate piclize_node(pobj); 3317*7c478bd9Sstevel@tonic-gate picl_root_obj = pobj; 3318*7c478bd9Sstevel@tonic-gate ptree_root_hdl = pobj->ptree_hdl; 3319*7c478bd9Sstevel@tonic-gate unlock_node(pobj); /* unlock node */ 3320*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 3321*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3322*7c478bd9Sstevel@tonic-gate } 3323*7c478bd9Sstevel@tonic-gate 3324*7c478bd9Sstevel@tonic-gate static int 3325*7c478bd9Sstevel@tonic-gate picltree_init(void) 3326*7c478bd9Sstevel@tonic-gate { 3327*7c478bd9Sstevel@tonic-gate (void) rwlock_init(&ptree_rwlock, USYNC_THREAD, NULL); 3328*7c478bd9Sstevel@tonic-gate (void) rwlock_init(&picltbl_rwlock, USYNC_THREAD, NULL); 3329*7c478bd9Sstevel@tonic-gate 3330*7c478bd9Sstevel@tonic-gate if (hash_init(&picltbl) < 0) 3331*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3332*7c478bd9Sstevel@tonic-gate if (hash_init(&ptreetbl) < 0) 3333*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3334*7c478bd9Sstevel@tonic-gate 3335*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&ptreehdl_lock, NULL) != 0) 3336*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3337*7c478bd9Sstevel@tonic-gate 3338*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&piclhdl_lock, NULL) != 0) 3339*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3340*7c478bd9Sstevel@tonic-gate 3341*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&evtq_lock, NULL) != 0) 3342*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3343*7c478bd9Sstevel@tonic-gate if (pthread_cond_init(&evtq_cv, NULL) != 0) 3344*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3345*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&evthandler_lock, NULL) != 0) 3346*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3347*7c478bd9Sstevel@tonic-gate 3348*7c478bd9Sstevel@tonic-gate picl_root_obj = NULL; 3349*7c478bd9Sstevel@tonic-gate eventqp = NULL; 3350*7c478bd9Sstevel@tonic-gate evt_handlers = NULL; 3351*7c478bd9Sstevel@tonic-gate ptree_root_hdl = PICL_INVALID_PICLHDL; 3352*7c478bd9Sstevel@tonic-gate 3353*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3354*7c478bd9Sstevel@tonic-gate } 3355*7c478bd9Sstevel@tonic-gate 3356*7c478bd9Sstevel@tonic-gate static void 3357*7c478bd9Sstevel@tonic-gate add_unique_plugin_to_list(char *path, char *name) 3358*7c478bd9Sstevel@tonic-gate { 3359*7c478bd9Sstevel@tonic-gate char *buf; 3360*7c478bd9Sstevel@tonic-gate picld_plugin_desc_t *pl; 3361*7c478bd9Sstevel@tonic-gate picld_plugin_desc_t *tmp; 3362*7c478bd9Sstevel@tonic-gate 3363*7c478bd9Sstevel@tonic-gate pl = plugin_desc; 3364*7c478bd9Sstevel@tonic-gate while (pl != NULL) { 3365*7c478bd9Sstevel@tonic-gate if (strcmp(pl->libname, name) == 0) 3366*7c478bd9Sstevel@tonic-gate return; 3367*7c478bd9Sstevel@tonic-gate else 3368*7c478bd9Sstevel@tonic-gate pl = pl->next; 3369*7c478bd9Sstevel@tonic-gate } 3370*7c478bd9Sstevel@tonic-gate 3371*7c478bd9Sstevel@tonic-gate pl = malloc(sizeof (picld_plugin_desc_t)); 3372*7c478bd9Sstevel@tonic-gate if (pl == NULL) 3373*7c478bd9Sstevel@tonic-gate return; 3374*7c478bd9Sstevel@tonic-gate 3375*7c478bd9Sstevel@tonic-gate pl->libname = strdup(name); 3376*7c478bd9Sstevel@tonic-gate if (pl->libname == NULL) 3377*7c478bd9Sstevel@tonic-gate return; 3378*7c478bd9Sstevel@tonic-gate buf = alloca(strlen(name) + strlen(path) + 2); 3379*7c478bd9Sstevel@tonic-gate if (buf == NULL) 3380*7c478bd9Sstevel@tonic-gate return; 3381*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, path); 3382*7c478bd9Sstevel@tonic-gate (void) strcat(buf, name); 3383*7c478bd9Sstevel@tonic-gate pl->pathname = strdup(buf); 3384*7c478bd9Sstevel@tonic-gate if (pl->pathname == NULL) 3385*7c478bd9Sstevel@tonic-gate return; 3386*7c478bd9Sstevel@tonic-gate 3387*7c478bd9Sstevel@tonic-gate pl->next = NULL; 3388*7c478bd9Sstevel@tonic-gate 3389*7c478bd9Sstevel@tonic-gate if (plugin_desc == NULL) 3390*7c478bd9Sstevel@tonic-gate plugin_desc = pl; 3391*7c478bd9Sstevel@tonic-gate else { 3392*7c478bd9Sstevel@tonic-gate tmp = plugin_desc; 3393*7c478bd9Sstevel@tonic-gate while (tmp->next != NULL) 3394*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 3395*7c478bd9Sstevel@tonic-gate tmp->next = pl; 3396*7c478bd9Sstevel@tonic-gate } 3397*7c478bd9Sstevel@tonic-gate } 3398*7c478bd9Sstevel@tonic-gate 3399*7c478bd9Sstevel@tonic-gate static void 3400*7c478bd9Sstevel@tonic-gate get_plugins_from_dir(char *dirname) 3401*7c478bd9Sstevel@tonic-gate { 3402*7c478bd9Sstevel@tonic-gate struct dirent *ent; 3403*7c478bd9Sstevel@tonic-gate DIR *dir; 3404*7c478bd9Sstevel@tonic-gate int len; 3405*7c478bd9Sstevel@tonic-gate int solen = strlen(SO_VERS) + 1; 3406*7c478bd9Sstevel@tonic-gate 3407*7c478bd9Sstevel@tonic-gate if ((dir = opendir(dirname)) == NULL) 3408*7c478bd9Sstevel@tonic-gate return; 3409*7c478bd9Sstevel@tonic-gate 3410*7c478bd9Sstevel@tonic-gate while ((ent = readdir(dir)) != NULL) { 3411*7c478bd9Sstevel@tonic-gate if ((strcmp(ent->d_name, ".") == 0) || 3412*7c478bd9Sstevel@tonic-gate (strcmp(ent->d_name, "..") == 0)) 3413*7c478bd9Sstevel@tonic-gate continue; 3414*7c478bd9Sstevel@tonic-gate 3415*7c478bd9Sstevel@tonic-gate len = strlen(ent->d_name) + 1; 3416*7c478bd9Sstevel@tonic-gate if (len < solen) 3417*7c478bd9Sstevel@tonic-gate continue; 3418*7c478bd9Sstevel@tonic-gate 3419*7c478bd9Sstevel@tonic-gate if (strcmp(ent->d_name + (len - solen), SO_VERS) == 0) 3420*7c478bd9Sstevel@tonic-gate add_unique_plugin_to_list(dirname, ent->d_name); 3421*7c478bd9Sstevel@tonic-gate } 3422*7c478bd9Sstevel@tonic-gate 3423*7c478bd9Sstevel@tonic-gate (void) closedir(dir); 3424*7c478bd9Sstevel@tonic-gate } 3425*7c478bd9Sstevel@tonic-gate 3426*7c478bd9Sstevel@tonic-gate 3427*7c478bd9Sstevel@tonic-gate static void 3428*7c478bd9Sstevel@tonic-gate init_plugin_list(void) 3429*7c478bd9Sstevel@tonic-gate { 3430*7c478bd9Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 3431*7c478bd9Sstevel@tonic-gate char pname[PATH_MAX]; 3432*7c478bd9Sstevel@tonic-gate 3433*7c478bd9Sstevel@tonic-gate plugin_desc = NULL; 3434*7c478bd9Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 3435*7c478bd9Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 3436*7c478bd9Sstevel@tonic-gate if (access(pname, R_OK) == 0) 3437*7c478bd9Sstevel@tonic-gate get_plugins_from_dir(pname); 3438*7c478bd9Sstevel@tonic-gate } 3439*7c478bd9Sstevel@tonic-gate 3440*7c478bd9Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 3441*7c478bd9Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 3442*7c478bd9Sstevel@tonic-gate if (access(pname, R_OK) == 0) 3443*7c478bd9Sstevel@tonic-gate get_plugins_from_dir(pname); 3444*7c478bd9Sstevel@tonic-gate } 3445*7c478bd9Sstevel@tonic-gate 3446*7c478bd9Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/", PICLD_COMMON_PLUGIN_DIR); 3447*7c478bd9Sstevel@tonic-gate if (access(pname, R_OK) == 0) 3448*7c478bd9Sstevel@tonic-gate get_plugins_from_dir(pname); 3449*7c478bd9Sstevel@tonic-gate } 3450*7c478bd9Sstevel@tonic-gate 3451*7c478bd9Sstevel@tonic-gate static void 3452*7c478bd9Sstevel@tonic-gate load_plugins(void) 3453*7c478bd9Sstevel@tonic-gate { 3454*7c478bd9Sstevel@tonic-gate picld_plugin_desc_t *pl; 3455*7c478bd9Sstevel@tonic-gate 3456*7c478bd9Sstevel@tonic-gate pl = plugin_desc; 3457*7c478bd9Sstevel@tonic-gate while (pl != NULL) { 3458*7c478bd9Sstevel@tonic-gate pl->dlh = dlopen(pl->pathname, RTLD_LAZY|RTLD_LOCAL); 3459*7c478bd9Sstevel@tonic-gate if (pl->dlh == NULL) { 3460*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, dlerror()); 3461*7c478bd9Sstevel@tonic-gate return; 3462*7c478bd9Sstevel@tonic-gate } 3463*7c478bd9Sstevel@tonic-gate pl = pl->next; 3464*7c478bd9Sstevel@tonic-gate } 3465*7c478bd9Sstevel@tonic-gate } 3466*7c478bd9Sstevel@tonic-gate 3467*7c478bd9Sstevel@tonic-gate 3468*7c478bd9Sstevel@tonic-gate 3469*7c478bd9Sstevel@tonic-gate static int 3470*7c478bd9Sstevel@tonic-gate add_root_props(picl_nodehdl_t rooth) 3471*7c478bd9Sstevel@tonic-gate { 3472*7c478bd9Sstevel@tonic-gate int err; 3473*7c478bd9Sstevel@tonic-gate picl_prophdl_t proph; 3474*7c478bd9Sstevel@tonic-gate ptree_propinfo_t pinfo; 3475*7c478bd9Sstevel@tonic-gate float picl_vers; 3476*7c478bd9Sstevel@tonic-gate 3477*7c478bd9Sstevel@tonic-gate #define PICL_PROP_PICL_VERSION "PICLVersion" 3478*7c478bd9Sstevel@tonic-gate #define PICL_VERSION 1.1 3479*7c478bd9Sstevel@tonic-gate 3480*7c478bd9Sstevel@tonic-gate err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION_1, 3481*7c478bd9Sstevel@tonic-gate PICL_PTYPE_FLOAT, PICL_READ, sizeof (picl_vers), 3482*7c478bd9Sstevel@tonic-gate PICL_PROP_PICL_VERSION, NULL, NULL); 3483*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3484*7c478bd9Sstevel@tonic-gate return (err); 3485*7c478bd9Sstevel@tonic-gate 3486*7c478bd9Sstevel@tonic-gate picl_vers = PICL_VERSION; 3487*7c478bd9Sstevel@tonic-gate err = ptree_create_and_add_prop(rooth, &pinfo, &picl_vers, &proph); 3488*7c478bd9Sstevel@tonic-gate return (err); 3489*7c478bd9Sstevel@tonic-gate } 3490*7c478bd9Sstevel@tonic-gate 3491*7c478bd9Sstevel@tonic-gate static int 3492*7c478bd9Sstevel@tonic-gate construct_picltree(void) 3493*7c478bd9Sstevel@tonic-gate { 3494*7c478bd9Sstevel@tonic-gate int err; 3495*7c478bd9Sstevel@tonic-gate picld_plugin_reg_list_t *iter; 3496*7c478bd9Sstevel@tonic-gate picl_nodehdl_t rhdl; 3497*7c478bd9Sstevel@tonic-gate 3498*7c478bd9Sstevel@tonic-gate /* 3499*7c478bd9Sstevel@tonic-gate * Create "/" node 3500*7c478bd9Sstevel@tonic-gate */ 3501*7c478bd9Sstevel@tonic-gate if ((err = ptree_create_node(PICL_NODE_ROOT, PICL_CLASS_PICL, 3502*7c478bd9Sstevel@tonic-gate &rhdl)) != PICL_SUCCESS) { 3503*7c478bd9Sstevel@tonic-gate return (err); 3504*7c478bd9Sstevel@tonic-gate } 3505*7c478bd9Sstevel@tonic-gate 3506*7c478bd9Sstevel@tonic-gate if (picltree_set_root(rhdl) != PICL_SUCCESS) { 3507*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3508*7c478bd9Sstevel@tonic-gate } 3509*7c478bd9Sstevel@tonic-gate 3510*7c478bd9Sstevel@tonic-gate err = add_root_props(rhdl); 3511*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3512*7c478bd9Sstevel@tonic-gate return (err); 3513*7c478bd9Sstevel@tonic-gate 3514*7c478bd9Sstevel@tonic-gate /* 3515*7c478bd9Sstevel@tonic-gate * Initialize the registered plug-in modules 3516*7c478bd9Sstevel@tonic-gate */ 3517*7c478bd9Sstevel@tonic-gate iter = plugin_reg_list; 3518*7c478bd9Sstevel@tonic-gate while (iter != NULL) { 3519*7c478bd9Sstevel@tonic-gate if (iter->reg.plugin_init) 3520*7c478bd9Sstevel@tonic-gate (iter->reg.plugin_init)(); 3521*7c478bd9Sstevel@tonic-gate iter = iter->next; 3522*7c478bd9Sstevel@tonic-gate } 3523*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3524*7c478bd9Sstevel@tonic-gate } 3525*7c478bd9Sstevel@tonic-gate 3526*7c478bd9Sstevel@tonic-gate void 3527*7c478bd9Sstevel@tonic-gate xptree_destroy(void) 3528*7c478bd9Sstevel@tonic-gate { 3529*7c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_destroy: picl_root_obj = %s\n", 3530*7c478bd9Sstevel@tonic-gate (picl_root_obj == NULL ? "NULL" : "not-NULL")); 3531*7c478bd9Sstevel@tonic-gate 3532*7c478bd9Sstevel@tonic-gate if (picl_root_obj == NULL) 3533*7c478bd9Sstevel@tonic-gate return; 3534*7c478bd9Sstevel@tonic-gate 3535*7c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_destroy: call plugin_fini\n"); 3536*7c478bd9Sstevel@tonic-gate plugin_fini(plugin_reg_list); 3537*7c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_destroy: plugin_fini DONE\n"); 3538*7c478bd9Sstevel@tonic-gate 3539*7c478bd9Sstevel@tonic-gate (void) ptree_delete_node(picl_root_obj->ptree_hdl); 3540*7c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(picl_root_obj->ptree_hdl); 3541*7c478bd9Sstevel@tonic-gate 3542*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); 3543*7c478bd9Sstevel@tonic-gate picl_root_obj = NULL; 3544*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 3545*7c478bd9Sstevel@tonic-gate } 3546*7c478bd9Sstevel@tonic-gate 3547*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3548*7c478bd9Sstevel@tonic-gate int 3549*7c478bd9Sstevel@tonic-gate xptree_initialize(int flg) 3550*7c478bd9Sstevel@tonic-gate { 3551*7c478bd9Sstevel@tonic-gate int err; 3552*7c478bd9Sstevel@tonic-gate pthread_attr_t attr; 3553*7c478bd9Sstevel@tonic-gate pthread_t tid; 3554*7c478bd9Sstevel@tonic-gate 3555*7c478bd9Sstevel@tonic-gate picld_pid = getpid(); 3556*7c478bd9Sstevel@tonic-gate picld_cred.dc_euid = geteuid(); 3557*7c478bd9Sstevel@tonic-gate picld_cred.dc_egid = getegid(); 3558*7c478bd9Sstevel@tonic-gate picld_cred.dc_ruid = getuid(); 3559*7c478bd9Sstevel@tonic-gate picld_cred.dc_rgid = getgid(); 3560*7c478bd9Sstevel@tonic-gate picld_cred.dc_pid = getpid(); 3561*7c478bd9Sstevel@tonic-gate 3562*7c478bd9Sstevel@tonic-gate picl_hdl_hi = 1; 3563*7c478bd9Sstevel@tonic-gate ptree_hdl_hi = 1; 3564*7c478bd9Sstevel@tonic-gate ptree_generation = 1; 3565*7c478bd9Sstevel@tonic-gate qempty_wait = 0; 3566*7c478bd9Sstevel@tonic-gate 3567*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&ptree_refresh_mutex, NULL) != 0) 3568*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3569*7c478bd9Sstevel@tonic-gate 3570*7c478bd9Sstevel@tonic-gate if (picltree_init() != PICL_SUCCESS) 3571*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3572*7c478bd9Sstevel@tonic-gate 3573*7c478bd9Sstevel@tonic-gate init_plugin_reg_list(); 3574*7c478bd9Sstevel@tonic-gate init_plugin_list(); 3575*7c478bd9Sstevel@tonic-gate load_plugins(); 3576*7c478bd9Sstevel@tonic-gate 3577*7c478bd9Sstevel@tonic-gate err = construct_picltree(); 3578*7c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 3579*7c478bd9Sstevel@tonic-gate return (err); 3580*7c478bd9Sstevel@tonic-gate 3581*7c478bd9Sstevel@tonic-gate /* 3582*7c478bd9Sstevel@tonic-gate * Dispatch events after all plug-ins have initialized 3583*7c478bd9Sstevel@tonic-gate */ 3584*7c478bd9Sstevel@tonic-gate if (pthread_attr_init(&attr) != 0) 3585*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3586*7c478bd9Sstevel@tonic-gate 3587*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 3588*7c478bd9Sstevel@tonic-gate if (pthread_create(&tid, &attr, ptree_event_thread, NULL)) 3589*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3590*7c478bd9Sstevel@tonic-gate 3591*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3592*7c478bd9Sstevel@tonic-gate } 3593*7c478bd9Sstevel@tonic-gate 3594*7c478bd9Sstevel@tonic-gate int 3595*7c478bd9Sstevel@tonic-gate xptree_reinitialize(void) 3596*7c478bd9Sstevel@tonic-gate { 3597*7c478bd9Sstevel@tonic-gate int err; 3598*7c478bd9Sstevel@tonic-gate 3599*7c478bd9Sstevel@tonic-gate /* 3600*7c478bd9Sstevel@tonic-gate * Wait for eventq to become empty 3601*7c478bd9Sstevel@tonic-gate */ 3602*7c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_reinitialize: wait for evtq empty\n"); 3603*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 3604*7c478bd9Sstevel@tonic-gate qempty_wait = 1; 3605*7c478bd9Sstevel@tonic-gate while (eventqp != NULL) 3606*7c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&evtq_empty, &evtq_lock); 3607*7c478bd9Sstevel@tonic-gate qempty_wait = 0; 3608*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 3609*7c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_reinitialize: evtq empty is EMPTY\n"); 3610*7c478bd9Sstevel@tonic-gate 3611*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); 3612*7c478bd9Sstevel@tonic-gate picl_root_obj = NULL; 3613*7c478bd9Sstevel@tonic-gate ptree_root_hdl = PICL_INVALID_PICLHDL; 3614*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 3615*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptree_refresh_mutex); 3616*7c478bd9Sstevel@tonic-gate ++ptree_generation; 3617*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 3618*7c478bd9Sstevel@tonic-gate 3619*7c478bd9Sstevel@tonic-gate err = construct_picltree(); 3620*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptree_refresh_mutex); 3621*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&ptree_refresh_cond); 3622*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 3623*7c478bd9Sstevel@tonic-gate 3624*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 3625*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evtq_cv); 3626*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 3627*7c478bd9Sstevel@tonic-gate 3628*7c478bd9Sstevel@tonic-gate return (err); 3629*7c478bd9Sstevel@tonic-gate } 3630*7c478bd9Sstevel@tonic-gate 3631*7c478bd9Sstevel@tonic-gate /* 3632*7c478bd9Sstevel@tonic-gate * This function is called by the PICL daemon on behalf of clients to 3633*7c478bd9Sstevel@tonic-gate * wait for a tree refresh 3634*7c478bd9Sstevel@tonic-gate */ 3635*7c478bd9Sstevel@tonic-gate int 3636*7c478bd9Sstevel@tonic-gate xptree_refresh_notify(uint32_t secs) 3637*7c478bd9Sstevel@tonic-gate { 3638*7c478bd9Sstevel@tonic-gate int curgen; 3639*7c478bd9Sstevel@tonic-gate int ret; 3640*7c478bd9Sstevel@tonic-gate timespec_t to; 3641*7c478bd9Sstevel@tonic-gate 3642*7c478bd9Sstevel@tonic-gate if (pthread_mutex_lock(&ptree_refresh_mutex) != 0) 3643*7c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3644*7c478bd9Sstevel@tonic-gate 3645*7c478bd9Sstevel@tonic-gate curgen = ptree_generation; 3646*7c478bd9Sstevel@tonic-gate 3647*7c478bd9Sstevel@tonic-gate while (curgen == ptree_generation) { 3648*7c478bd9Sstevel@tonic-gate if (secs == 0) /* wait forever */ 3649*7c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&ptree_refresh_cond, 3650*7c478bd9Sstevel@tonic-gate &ptree_refresh_mutex); 3651*7c478bd9Sstevel@tonic-gate else { 3652*7c478bd9Sstevel@tonic-gate to.tv_sec = secs; 3653*7c478bd9Sstevel@tonic-gate to.tv_nsec = 0; 3654*7c478bd9Sstevel@tonic-gate ret = pthread_cond_reltimedwait_np(&ptree_refresh_cond, 3655*7c478bd9Sstevel@tonic-gate &ptree_refresh_mutex, &to); 3656*7c478bd9Sstevel@tonic-gate if (ret == ETIMEDOUT) 3657*7c478bd9Sstevel@tonic-gate break; 3658*7c478bd9Sstevel@tonic-gate } 3659*7c478bd9Sstevel@tonic-gate } 3660*7c478bd9Sstevel@tonic-gate 3661*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 3662*7c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3663*7c478bd9Sstevel@tonic-gate } 3664*7c478bd9Sstevel@tonic-gate 3665*7c478bd9Sstevel@tonic-gate /*VARARGS2*/ 3666*7c478bd9Sstevel@tonic-gate void 3667*7c478bd9Sstevel@tonic-gate dbg_print(int level, const char *fmt, ...) 3668*7c478bd9Sstevel@tonic-gate { 3669*7c478bd9Sstevel@tonic-gate if (verbose_level >= level) { 3670*7c478bd9Sstevel@tonic-gate va_list ap; 3671*7c478bd9Sstevel@tonic-gate 3672*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 3673*7c478bd9Sstevel@tonic-gate (void) vprintf(fmt, ap); 3674*7c478bd9Sstevel@tonic-gate va_end(ap); 3675*7c478bd9Sstevel@tonic-gate } 3676*7c478bd9Sstevel@tonic-gate } 3677*7c478bd9Sstevel@tonic-gate 3678*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3679*7c478bd9Sstevel@tonic-gate void 3680*7c478bd9Sstevel@tonic-gate dbg_exec(int level, void (*fn)(void *args), void *args) 3681*7c478bd9Sstevel@tonic-gate { 3682*7c478bd9Sstevel@tonic-gate if (verbose_level > level) 3683*7c478bd9Sstevel@tonic-gate (*fn)(args); 3684*7c478bd9Sstevel@tonic-gate } 3685