17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*23a1cceaSRoger A. Faulkner * Common Development and Distribution License (the "License"). 6*23a1cceaSRoger A. Faulkner * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 22*23a1cceaSRoger A. Faulkner /* 23*23a1cceaSRoger A. Faulkner * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 24*23a1cceaSRoger A. Faulkner */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * This module implements the PTree interface and the PICL to PTree calls 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Note: 327c478bd9Sstevel@tonic-gate * PICL Node and Property Handles Table: 337c478bd9Sstevel@tonic-gate * A node or property in PICL tree has two handles: a ptree handle, which is 347c478bd9Sstevel@tonic-gate * used by plug-ins and the libpicltree interface, and a picl handle 357c478bd9Sstevel@tonic-gate * which is used by clients and the libpicl interface. 367c478bd9Sstevel@tonic-gate * The mapping of ptree handles to the internal PICL object (picl_obj_t) is 377c478bd9Sstevel@tonic-gate * kept in a ptree hash table (ptreetbl), and the mapping of a picl handle 387c478bd9Sstevel@tonic-gate * to its ptree handle is kept in the picl hash table (picltbl). 397c478bd9Sstevel@tonic-gate * The reader/writer lock, ptree_rwlock, is held when reading or modifying ptree 407c478bd9Sstevel@tonic-gate * hash table (ptreetbl) and/or the PICL tree structure (nodes and linkages 417c478bd9Sstevel@tonic-gate * between them). The reader/writer lock, picltbl_rwlock, is held when reading 427c478bd9Sstevel@tonic-gate * or modifying picl hash table (picltbl). 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * The mutex, ptreehdl_lock, is used to control allocation of ptree handles. 457c478bd9Sstevel@tonic-gate * The mutex, piclhdl_lock, is used to control allocation of picl handles. 467c478bd9Sstevel@tonic-gate * 477c478bd9Sstevel@tonic-gate * The mutex, ptree_refresh_mutex, and the condition, ptree_refresh_cond, 487c478bd9Sstevel@tonic-gate * are used to synchronize PICL refreshes (ptree_refresh) and to wait/signal 497c478bd9Sstevel@tonic-gate * change in PICL tree structure. 507c478bd9Sstevel@tonic-gate * 517c478bd9Sstevel@tonic-gate * The counter, picl_hdl_hi, is the hi water mark for allocated picl handles. 527c478bd9Sstevel@tonic-gate * The counter, ptree_hdl_hi, is the hi water mark for allocated ptree handles. 537c478bd9Sstevel@tonic-gate * A stale handle error is returned for handle values below the hi water 547c478bd9Sstevel@tonic-gate * mark, and invalid handles are returned for handle values above the hi water 557c478bd9Sstevel@tonic-gate * mark or when the process id field of the handle does not match. 567c478bd9Sstevel@tonic-gate * 577c478bd9Sstevel@tonic-gate * Locking Scheme: 587c478bd9Sstevel@tonic-gate * The structure of the PICL tree is controlled by the ptree_rwlock. The 597c478bd9Sstevel@tonic-gate * properties of a node are controlled by individual node locks. The 607c478bd9Sstevel@tonic-gate * piclize-ing or unpiclize-ing of a node is controlled by picltbl_rwlock. 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * Two-Phase Locking scheme: lock acquire phase and lock release phase. 637c478bd9Sstevel@tonic-gate * 647c478bd9Sstevel@tonic-gate * Lock Ordering: 657c478bd9Sstevel@tonic-gate * The ptree_rwlock and node locks are always acquired in the following order: 667c478bd9Sstevel@tonic-gate * lock ptree_rwlock 677c478bd9Sstevel@tonic-gate * lock node 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * Lock Strategy: 707c478bd9Sstevel@tonic-gate * There are three locks: 717c478bd9Sstevel@tonic-gate * ptree_rwlock: a reader lock is obtained to do ptree hash table 727c478bd9Sstevel@tonic-gate * lookups and traverse tree. A writer lock is obtained 737c478bd9Sstevel@tonic-gate * when creating or destroying nodes from the ptree, 747c478bd9Sstevel@tonic-gate * or when modifying node linkages: parent, peer, child. 757c478bd9Sstevel@tonic-gate * picltbl_rwlock: a reader lock is obtained for picl hash table lookups. 767c478bd9Sstevel@tonic-gate * A writer lock is obtained when piclize-ing or 777c478bd9Sstevel@tonic-gate * unpiclize-ing nodes or properties. 787c478bd9Sstevel@tonic-gate * node_lock: This is a reader/writer lock for properties of a node. 797c478bd9Sstevel@tonic-gate * A reader lock is obtained before reading property 807c478bd9Sstevel@tonic-gate * values. A writer lock is obtained when adding or 817c478bd9Sstevel@tonic-gate * removing properties and when modifying a property value. 827c478bd9Sstevel@tonic-gate * 837c478bd9Sstevel@tonic-gate * Never hold more than one node lock at a time. 847c478bd9Sstevel@tonic-gate * 857c478bd9Sstevel@tonic-gate * Event Locking: 867c478bd9Sstevel@tonic-gate * There are two locks: 877c478bd9Sstevel@tonic-gate * evtq_lock: this lock protects the event queue. It is obtained 887c478bd9Sstevel@tonic-gate * to queue events that are posted and to unqueue 897c478bd9Sstevel@tonic-gate * events to be dispatched. 907c478bd9Sstevel@tonic-gate * evtq_cv: condition variable is protected by evtq_lock. It is 917c478bd9Sstevel@tonic-gate * used by the ptree event thread to wait for events 927c478bd9Sstevel@tonic-gate * until eventqp is not NULL. 937c478bd9Sstevel@tonic-gate * evtq_empty: condition variable protected by evtq_lock. It is 947c478bd9Sstevel@tonic-gate * used to signal when the eventq becomes empty. The 957c478bd9Sstevel@tonic-gate * reinitialization process waits on this condition. 967c478bd9Sstevel@tonic-gate * evthandler_lock: this protects the event handler list. It is obtained 977c478bd9Sstevel@tonic-gate * to add event handlers on registration and to remove 987c478bd9Sstevel@tonic-gate * event handlers on unregistration. 997c478bd9Sstevel@tonic-gate * (handler)->cv: condition variable per handler protected by 1007c478bd9Sstevel@tonic-gate * evthandler_lock. It is used to wait until the 1017c478bd9Sstevel@tonic-gate * event handler completes execution (execflg == 0) 1027c478bd9Sstevel@tonic-gate * before unregistering the handler. 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate #include <stdio.h> 1067c478bd9Sstevel@tonic-gate #include <string.h> 1077c478bd9Sstevel@tonic-gate #include <strings.h> 1087c478bd9Sstevel@tonic-gate #include <stdlib.h> 1097c478bd9Sstevel@tonic-gate #include <stdarg.h> 1107c478bd9Sstevel@tonic-gate #include <alloca.h> 1117c478bd9Sstevel@tonic-gate #include <assert.h> 1127c478bd9Sstevel@tonic-gate #include <errno.h> 1137c478bd9Sstevel@tonic-gate #include <unistd.h> 1147c478bd9Sstevel@tonic-gate #include <limits.h> 1157c478bd9Sstevel@tonic-gate #include <libintl.h> 1167c478bd9Sstevel@tonic-gate #include <syslog.h> 1177c478bd9Sstevel@tonic-gate #include <pthread.h> 1187c478bd9Sstevel@tonic-gate #include <synch.h> 1197c478bd9Sstevel@tonic-gate #include <setjmp.h> 1207c478bd9Sstevel@tonic-gate #include <signal.h> 1217c478bd9Sstevel@tonic-gate #include <dlfcn.h> 1227c478bd9Sstevel@tonic-gate #include <dirent.h> 1237c478bd9Sstevel@tonic-gate #include <door.h> 1247c478bd9Sstevel@tonic-gate #include <time.h> 1257c478bd9Sstevel@tonic-gate #include <inttypes.h> 1267c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 1277c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 1287c478bd9Sstevel@tonic-gate #include <picl.h> 1297c478bd9Sstevel@tonic-gate #include <picltree.h> 1307c478bd9Sstevel@tonic-gate #include "picldefs.h" 1317c478bd9Sstevel@tonic-gate #include "ptree_impl.h" 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate #define SO_VERS ".so.1" 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate static hash_t picltbl; /* client handles to picl obj */ 1367c478bd9Sstevel@tonic-gate static hash_t ptreetbl; /* ptree handles to picl obj */ 1377c478bd9Sstevel@tonic-gate static pthread_mutex_t ptreehdl_lock; 1387c478bd9Sstevel@tonic-gate static pthread_mutex_t piclhdl_lock; 1397c478bd9Sstevel@tonic-gate static pthread_mutex_t ptree_refresh_mutex; 1407c478bd9Sstevel@tonic-gate static rwlock_t picltbl_rwlock; /* PICL handle table lock */ 1417c478bd9Sstevel@tonic-gate static rwlock_t ptree_rwlock; /* PICL tree lock */ 1427c478bd9Sstevel@tonic-gate static pthread_cond_t ptree_refresh_cond = PTHREAD_COND_INITIALIZER; 1437c478bd9Sstevel@tonic-gate static uint32_t ptree_hdl_hi = 1; 1447c478bd9Sstevel@tonic-gate static uint32_t picl_hdl_hi = 1; 1457c478bd9Sstevel@tonic-gate static picl_obj_t *picl_root_obj = NULL; 1467c478bd9Sstevel@tonic-gate static picl_nodehdl_t ptree_root_hdl = PICL_INVALID_PICLHDL; 1477c478bd9Sstevel@tonic-gate static int ptree_generation = 0; 1487c478bd9Sstevel@tonic-gate static pid_t picld_pid; 1497c478bd9Sstevel@tonic-gate static door_cred_t picld_cred; 1507c478bd9Sstevel@tonic-gate static int qempty_wait; /* evtq_empty condition waiter flag */ 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate static picld_plugin_reg_list_t *plugin_reg_list = NULL; 1537c478bd9Sstevel@tonic-gate static picld_plugin_desc_t *plugin_desc; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate static eventq_t *eventqp; /* PICL events queue */ 1567c478bd9Sstevel@tonic-gate static pthread_mutex_t evtq_lock = PTHREAD_MUTEX_INITIALIZER; 1577c478bd9Sstevel@tonic-gate static pthread_cond_t evtq_cv = PTHREAD_COND_INITIALIZER; 1587c478bd9Sstevel@tonic-gate static pthread_cond_t evtq_empty = PTHREAD_COND_INITIALIZER; 1597c478bd9Sstevel@tonic-gate static evt_handler_t *evt_handlers; /* Event handler list */ 1607c478bd9Sstevel@tonic-gate static pthread_mutex_t evthandler_lock = PTHREAD_MUTEX_INITIALIZER; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * PICL daemon verbose level 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate int verbose_level; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * Event handler free functions 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate static void 1727c478bd9Sstevel@tonic-gate free_handler(evt_handler_t *evhp) 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate if (evhp->ename) 1757c478bd9Sstevel@tonic-gate free(evhp->ename); 1767c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evhp->cv); 1777c478bd9Sstevel@tonic-gate (void) pthread_cond_destroy(&evhp->cv); 1787c478bd9Sstevel@tonic-gate free(evhp); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * queue_event to events queue 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate static void 1867c478bd9Sstevel@tonic-gate queue_event(eventq_t *evt) 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate eventq_t *tmpp; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate evt->next = NULL; 1917c478bd9Sstevel@tonic-gate if (eventqp == NULL) 1927c478bd9Sstevel@tonic-gate eventqp = evt; 1937c478bd9Sstevel@tonic-gate else { 1947c478bd9Sstevel@tonic-gate tmpp = eventqp; 1957c478bd9Sstevel@tonic-gate while (tmpp->next != NULL) 1967c478bd9Sstevel@tonic-gate tmpp = tmpp->next; 1977c478bd9Sstevel@tonic-gate tmpp->next = evt; 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * unqueue_event from the specified eventq 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate static eventq_t * 2057c478bd9Sstevel@tonic-gate unqueue_event(eventq_t **qp) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate eventq_t *evtp; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate evtp = *qp; 2107c478bd9Sstevel@tonic-gate if (evtp != NULL) 2117c478bd9Sstevel@tonic-gate *qp = evtp->next; 2127c478bd9Sstevel@tonic-gate return (evtp); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * register an event handler by adding it to the list 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate int 2197c478bd9Sstevel@tonic-gate ptree_register_handler(const char *ename, 2207c478bd9Sstevel@tonic-gate void (*evt_handler)(const char *ename, const void *earg, size_t size, 2217c478bd9Sstevel@tonic-gate void *cookie), void *cookie) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate evt_handler_t *ent; 2247c478bd9Sstevel@tonic-gate evt_handler_t *iter; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate if (ename == NULL) 2277c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * Initialize event handler entry 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate ent = malloc(sizeof (*ent)); 2337c478bd9Sstevel@tonic-gate if (ent == NULL) 2347c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2357c478bd9Sstevel@tonic-gate ent->ename = strdup(ename); 2367c478bd9Sstevel@tonic-gate if (ent->ename == NULL) { 2377c478bd9Sstevel@tonic-gate free(ent); 2387c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate ent->cookie = cookie; 2417c478bd9Sstevel@tonic-gate ent->evt_handler = evt_handler; 2427c478bd9Sstevel@tonic-gate ent->execflg = 0; 2437c478bd9Sstevel@tonic-gate ent->wakeupflg = 0; 2447c478bd9Sstevel@tonic-gate (void) pthread_cond_init(&ent->cv, NULL); 2457c478bd9Sstevel@tonic-gate ent->next = NULL; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * add handler to the handler list 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 2517c478bd9Sstevel@tonic-gate if (evt_handlers == NULL) { 2527c478bd9Sstevel@tonic-gate evt_handlers = ent; 2537c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 2547c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate iter = evt_handlers; 2577c478bd9Sstevel@tonic-gate while (iter->next != NULL) 2587c478bd9Sstevel@tonic-gate iter = iter->next; 2597c478bd9Sstevel@tonic-gate iter->next = ent; 2607c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * unregister handler 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate void 2697c478bd9Sstevel@tonic-gate ptree_unregister_handler(const char *ename, 2707c478bd9Sstevel@tonic-gate void (*evt_handler)(const char *ename, const void *earg, size_t size, 2717c478bd9Sstevel@tonic-gate void *cookie), void *cookie) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate evt_handler_t *evhdlrp, **evhdlrpp; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate if (ename == NULL) 2767c478bd9Sstevel@tonic-gate return; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * unlink handler from handler list 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate retry: 2847c478bd9Sstevel@tonic-gate for (evhdlrpp = &evt_handlers; (evhdlrp = *evhdlrpp) != NULL; 2857c478bd9Sstevel@tonic-gate evhdlrpp = &evhdlrp->next) { 2867c478bd9Sstevel@tonic-gate if ((evhdlrp->cookie != cookie) || 2877c478bd9Sstevel@tonic-gate (strcmp(evhdlrp->ename, ename) != 0) || 2887c478bd9Sstevel@tonic-gate (evhdlrp->evt_handler != evt_handler)) 2897c478bd9Sstevel@tonic-gate continue; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * If the handler is in execution, release the lock 2937c478bd9Sstevel@tonic-gate * and wait for it to complete and retry. 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate if (evhdlrp->execflg) { 2967c478bd9Sstevel@tonic-gate evhdlrp->wakeupflg = 1; 2977c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&evhdlrp->cv, 2987c478bd9Sstevel@tonic-gate &evthandler_lock); 2997c478bd9Sstevel@tonic-gate goto retry; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * Unlink this handler from the linked list 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate *evhdlrpp = evhdlrp->next; 3067c478bd9Sstevel@tonic-gate free_handler(evhdlrp); 3077c478bd9Sstevel@tonic-gate break; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * Call all registered handlers for the event 3157c478bd9Sstevel@tonic-gate */ 3167c478bd9Sstevel@tonic-gate static void 3177c478bd9Sstevel@tonic-gate call_event_handlers(eventq_t *ev) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate evt_handler_t *iter; 3207c478bd9Sstevel@tonic-gate void (*evhandler)(const char *, const void *, size_t, void *); 3217c478bd9Sstevel@tonic-gate void (*completion_handler)(char *ename, void *earg, size_t size); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 3247c478bd9Sstevel@tonic-gate iter = evt_handlers; 3257c478bd9Sstevel@tonic-gate while (iter != NULL) { 3267c478bd9Sstevel@tonic-gate if (strcmp(iter->ename, ev->ename) == 0) { 3277c478bd9Sstevel@tonic-gate evhandler = iter->evt_handler; 3287c478bd9Sstevel@tonic-gate iter->execflg = 1; 3297c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 3307c478bd9Sstevel@tonic-gate if (evhandler) { 3317c478bd9Sstevel@tonic-gate dbg_print(2, "ptree_evthr: Invoking evthdlr:%p" 3327c478bd9Sstevel@tonic-gate " ename:%s\n", evhandler, ev->ename); 3337c478bd9Sstevel@tonic-gate (*evhandler)(ev->ename, ev->earg, ev->size, 3347c478bd9Sstevel@tonic-gate iter->cookie); 3357c478bd9Sstevel@tonic-gate dbg_print(2, "ptree_evthr: done evthdlr:%p " 3367c478bd9Sstevel@tonic-gate "ename:%s\n", evhandler, ev->ename); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evthandler_lock); 3397c478bd9Sstevel@tonic-gate iter->execflg = 0; 3407c478bd9Sstevel@tonic-gate if (iter->wakeupflg) { 3417c478bd9Sstevel@tonic-gate iter->wakeupflg = 0; 3427c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&iter->cv); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate iter = iter->next; 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evthandler_lock); 3487c478bd9Sstevel@tonic-gate if ((completion_handler = ev->completion_handler) != NULL) { 3497c478bd9Sstevel@tonic-gate dbg_print(2, 3507c478bd9Sstevel@tonic-gate "ptree_evthr: Invoking completion hdlr:%p ename:%s\n", 3517c478bd9Sstevel@tonic-gate completion_handler, ev->ename); 3527c478bd9Sstevel@tonic-gate (*completion_handler)((char *)ev->ename, (void *)ev->earg, 3537c478bd9Sstevel@tonic-gate ev->size); 3547c478bd9Sstevel@tonic-gate dbg_print(2, "ptree_evthr: done completion hdlr:%p ename:%s\n", 3557c478bd9Sstevel@tonic-gate completion_handler, ev->ename); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptree_refresh_mutex); 3587c478bd9Sstevel@tonic-gate ++ptree_generation; 3597c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&ptree_refresh_cond); 3607c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * This function is called by a plug-in to post an event 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate int 3677c478bd9Sstevel@tonic-gate ptree_post_event(const char *ename, const void *earg, size_t size, 3687c478bd9Sstevel@tonic-gate void (*completion_handler)(char *ename, void *earg, size_t size)) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate eventq_t *evt; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate if (ename == NULL) 3737c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate evt = malloc(sizeof (*evt)); 3767c478bd9Sstevel@tonic-gate if (evt == NULL) 3777c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 3787c478bd9Sstevel@tonic-gate evt->ename = ename; 3797c478bd9Sstevel@tonic-gate evt->earg = earg; 3807c478bd9Sstevel@tonic-gate evt->size = size; 3817c478bd9Sstevel@tonic-gate evt->completion_handler = completion_handler; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 3847c478bd9Sstevel@tonic-gate queue_event(evt); 3857c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evtq_cv); 3867c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 3877c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* 3917c478bd9Sstevel@tonic-gate * PICLTREE event thread 3927c478bd9Sstevel@tonic-gate */ 3937c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3947c478bd9Sstevel@tonic-gate static void * 3957c478bd9Sstevel@tonic-gate ptree_event_thread(void *argp) 3967c478bd9Sstevel@tonic-gate { 3977c478bd9Sstevel@tonic-gate eventq_t *evt; 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate for (;;) { 4007c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 4017c478bd9Sstevel@tonic-gate while (eventqp == NULL) { 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * Signal empty queue 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate if (qempty_wait) 4067c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evtq_empty); 4077c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&evtq_cv, &evtq_lock); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate if ((evt = unqueue_event(&eventqp)) != NULL) { 4107c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 4117c478bd9Sstevel@tonic-gate call_event_handlers(evt); 4127c478bd9Sstevel@tonic-gate free(evt); 4137c478bd9Sstevel@tonic-gate } else 4147c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4177c478bd9Sstevel@tonic-gate return (NULL); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4227c478bd9Sstevel@tonic-gate * Create a new element 4237c478bd9Sstevel@tonic-gate */ 4247c478bd9Sstevel@tonic-gate static hash_elem_t * 4257c478bd9Sstevel@tonic-gate hash_newobj(uint32_t hdl_val, void *obj_val) 4267c478bd9Sstevel@tonic-gate { 4277c478bd9Sstevel@tonic-gate hash_elem_t *n; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate n = malloc(sizeof (*n)); 4307c478bd9Sstevel@tonic-gate if (n == NULL) 4317c478bd9Sstevel@tonic-gate return (NULL); 4327c478bd9Sstevel@tonic-gate n->hdl = hdl_val; 4337c478bd9Sstevel@tonic-gate n->hash_obj = obj_val; 4347c478bd9Sstevel@tonic-gate n->next = NULL; 4357c478bd9Sstevel@tonic-gate return (n); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate static hash_elem_t * 4397c478bd9Sstevel@tonic-gate hash_newhdl(uint32_t picl_hdl, uint32_t ptreeh) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate hash_elem_t *n; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate n = malloc(sizeof (*n)); 4447c478bd9Sstevel@tonic-gate if (n == NULL) 4457c478bd9Sstevel@tonic-gate return (NULL); 4467c478bd9Sstevel@tonic-gate n->hdl = picl_hdl; 4477c478bd9Sstevel@tonic-gate n->hash_hdl = ptreeh; 4487c478bd9Sstevel@tonic-gate n->next = NULL; 4497c478bd9Sstevel@tonic-gate return (n); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /* 4537c478bd9Sstevel@tonic-gate * Initialize a hash table by setting all entries to NULL 4547c478bd9Sstevel@tonic-gate */ 4557c478bd9Sstevel@tonic-gate static int 4567c478bd9Sstevel@tonic-gate hash_init(hash_t *htbl) 4577c478bd9Sstevel@tonic-gate { 4587c478bd9Sstevel@tonic-gate int i; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate htbl->hash_size = HASH_TBL_SIZE; 4617c478bd9Sstevel@tonic-gate htbl->tbl = malloc(sizeof (hash_elem_t *) * HASH_TBL_SIZE); 4627c478bd9Sstevel@tonic-gate if (htbl->tbl == NULL) 4637c478bd9Sstevel@tonic-gate return (-1); 4647c478bd9Sstevel@tonic-gate for (i = 0; i < htbl->hash_size; ++i) 4657c478bd9Sstevel@tonic-gate htbl->tbl[i] = NULL; 4667c478bd9Sstevel@tonic-gate return (0); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * Lock free function to add an entry in the hash table 4717c478bd9Sstevel@tonic-gate */ 4727c478bd9Sstevel@tonic-gate static int 4737c478bd9Sstevel@tonic-gate hash_add_newobj(hash_t *htbl, picl_hdl_t hdl, void *pobj) 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate int indx; 4767c478bd9Sstevel@tonic-gate hash_elem_t *n; 4777c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate n = hash_newobj(hash_val, pobj); 4807c478bd9Sstevel@tonic-gate if (n == NULL) 4817c478bd9Sstevel@tonic-gate return (-1); 4827c478bd9Sstevel@tonic-gate indx = HASH_INDEX(htbl->hash_size, hash_val); 4837c478bd9Sstevel@tonic-gate n->next = htbl->tbl[indx]; 4847c478bd9Sstevel@tonic-gate htbl->tbl[indx] = n; 4857c478bd9Sstevel@tonic-gate return (0); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate static int 4897c478bd9Sstevel@tonic-gate hash_add_newhdl(hash_t *htbl, picl_hdl_t piclh, picl_hdl_t ptreeh) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate int indx; 4927c478bd9Sstevel@tonic-gate hash_elem_t *n; 4937c478bd9Sstevel@tonic-gate uint32_t picl_val = HASH_VAL(piclh); 4947c478bd9Sstevel@tonic-gate uint32_t ptree_val = HASH_VAL(ptreeh); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate n = hash_newhdl(picl_val, ptree_val); 4977c478bd9Sstevel@tonic-gate if (n == NULL) 4987c478bd9Sstevel@tonic-gate return (-1); 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate indx = HASH_INDEX(htbl->hash_size, picl_val); 5017c478bd9Sstevel@tonic-gate n->next = htbl->tbl[indx]; 5027c478bd9Sstevel@tonic-gate htbl->tbl[indx] = n; 5037c478bd9Sstevel@tonic-gate return (0); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate /* 5077c478bd9Sstevel@tonic-gate * Lock free function to remove the handle from the hash table 5087c478bd9Sstevel@tonic-gate * Returns -1 if element not found, 0 if successful 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate static int 5117c478bd9Sstevel@tonic-gate hash_remove(hash_t *htbl, picl_hdl_t hdl) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate hash_elem_t *nxt; 5147c478bd9Sstevel@tonic-gate hash_elem_t *cur; 5157c478bd9Sstevel@tonic-gate int i; 5167c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate i = HASH_INDEX(htbl->hash_size, hash_val); 5197c478bd9Sstevel@tonic-gate if (htbl->tbl[i] == NULL) 5207c478bd9Sstevel@tonic-gate return (-1); 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate cur = htbl->tbl[i]; 5237c478bd9Sstevel@tonic-gate if (cur->hdl == hash_val) { 5247c478bd9Sstevel@tonic-gate htbl->tbl[i] = cur->next; 5257c478bd9Sstevel@tonic-gate free(cur); 5267c478bd9Sstevel@tonic-gate return (0); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate nxt = cur->next; 5297c478bd9Sstevel@tonic-gate while (nxt != NULL) { 5307c478bd9Sstevel@tonic-gate if (nxt->hdl == hash_val) { 5317c478bd9Sstevel@tonic-gate cur->next = nxt->next; 5327c478bd9Sstevel@tonic-gate free(nxt); 5337c478bd9Sstevel@tonic-gate return (0); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate cur = nxt; 5367c478bd9Sstevel@tonic-gate nxt = nxt->next; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate return (-1); 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* 5427c478bd9Sstevel@tonic-gate * Lock free function to lookup the hash table for a given handle 5437c478bd9Sstevel@tonic-gate * Returns NULL if not found 5447c478bd9Sstevel@tonic-gate */ 5457c478bd9Sstevel@tonic-gate static void * 5467c478bd9Sstevel@tonic-gate hash_lookup_obj(hash_t *htbl, picl_hdl_t hdl) 5477c478bd9Sstevel@tonic-gate { 5487c478bd9Sstevel@tonic-gate hash_elem_t *tmp; 5497c478bd9Sstevel@tonic-gate int i; 5507c478bd9Sstevel@tonic-gate uint32_t hash_val; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate hash_val = HASH_VAL(hdl); 5537c478bd9Sstevel@tonic-gate i = HASH_INDEX(htbl->hash_size, hash_val); 5547c478bd9Sstevel@tonic-gate tmp = htbl->tbl[i]; 5557c478bd9Sstevel@tonic-gate while (tmp != NULL) { 5567c478bd9Sstevel@tonic-gate if (tmp->hdl == hash_val) 5577c478bd9Sstevel@tonic-gate return (tmp->hash_obj); 5587c478bd9Sstevel@tonic-gate tmp = tmp->next; 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate return (NULL); 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate static picl_hdl_t 5647c478bd9Sstevel@tonic-gate hash_lookup_hdl(hash_t *htbl, picl_hdl_t hdl) 5657c478bd9Sstevel@tonic-gate { 5667c478bd9Sstevel@tonic-gate hash_elem_t *tmp; 5677c478bd9Sstevel@tonic-gate int i; 5687c478bd9Sstevel@tonic-gate uint32_t hash_val; 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate hash_val = HASH_VAL(hdl); 5717c478bd9Sstevel@tonic-gate i = HASH_INDEX(htbl->hash_size, hash_val); 5727c478bd9Sstevel@tonic-gate tmp = htbl->tbl[i]; 5737c478bd9Sstevel@tonic-gate while (tmp != NULL) { 5747c478bd9Sstevel@tonic-gate if (tmp->hdl == hash_val) 5757c478bd9Sstevel@tonic-gate return (MAKE_HANDLE(picld_pid, tmp->hash_hdl)); 5767c478bd9Sstevel@tonic-gate tmp = tmp->next; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate return (PICL_INVALID_PICLHDL); 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* 5827c478bd9Sstevel@tonic-gate * Is the PICL handle stale or invalid handle? 5837c478bd9Sstevel@tonic-gate */ 5847c478bd9Sstevel@tonic-gate static int 5857c478bd9Sstevel@tonic-gate picl_hdl_error(picl_hdl_t hdl) 5867c478bd9Sstevel@tonic-gate { 5877c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 5887c478bd9Sstevel@tonic-gate pid_t pid = GET_PID(hdl); 5897c478bd9Sstevel@tonic-gate int err; 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&piclhdl_lock); 5927c478bd9Sstevel@tonic-gate err = PICL_STALEHANDLE; 5937c478bd9Sstevel@tonic-gate if ((pid != picld_pid) || (hash_val >= picl_hdl_hi) || 5947c478bd9Sstevel@tonic-gate (hash_val == NULL)) 5957c478bd9Sstevel@tonic-gate err = PICL_INVALIDHANDLE; 5967c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&piclhdl_lock); 5977c478bd9Sstevel@tonic-gate return (err); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate /* 6017c478bd9Sstevel@tonic-gate * Is the Ptree handle stale or invalid handle? 6027c478bd9Sstevel@tonic-gate */ 6037c478bd9Sstevel@tonic-gate static int 6047c478bd9Sstevel@tonic-gate ptree_hdl_error(picl_hdl_t hdl) 6057c478bd9Sstevel@tonic-gate { 6067c478bd9Sstevel@tonic-gate uint32_t hash_val = HASH_VAL(hdl); 6077c478bd9Sstevel@tonic-gate pid_t pid = GET_PID(hdl); 6087c478bd9Sstevel@tonic-gate int err; 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptreehdl_lock); 6117c478bd9Sstevel@tonic-gate err = PICL_STALEHANDLE; 6127c478bd9Sstevel@tonic-gate if ((pid != picld_pid) || (hash_val >= ptree_hdl_hi) || 6137c478bd9Sstevel@tonic-gate (hash_val == NULL)) 6147c478bd9Sstevel@tonic-gate err = PICL_INVALIDHANDLE; 6157c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptreehdl_lock); 6167c478bd9Sstevel@tonic-gate return (err); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* 6207c478bd9Sstevel@tonic-gate * For a PICL handle, return the PTree handle and the PICL object 6217c478bd9Sstevel@tonic-gate * Locks and releases the PICL table. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate int 6247c478bd9Sstevel@tonic-gate cvt_picl2ptree(picl_hdl_t hdl, picl_hdl_t *ptree_hdl) 6257c478bd9Sstevel@tonic-gate { 6267c478bd9Sstevel@tonic-gate picl_hdl_t tmph; 6277c478bd9Sstevel@tonic-gate int err; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate (void) rw_rdlock(&picltbl_rwlock); /* lock picl */ 6307c478bd9Sstevel@tonic-gate tmph = hash_lookup_hdl(&picltbl, hdl); 6317c478bd9Sstevel@tonic-gate if (tmph == PICL_INVALID_PICLHDL) { 6327c478bd9Sstevel@tonic-gate err = picl_hdl_error(hdl); 6337c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); /* unlock picl */ 6347c478bd9Sstevel@tonic-gate return (err); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate *ptree_hdl = tmph; 6377c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); /* unlock picl */ 6387c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate /* 6427c478bd9Sstevel@tonic-gate * Allocate a ptree handle 6437c478bd9Sstevel@tonic-gate */ 6447c478bd9Sstevel@tonic-gate static picl_hdl_t 6457c478bd9Sstevel@tonic-gate alloc_ptreehdl(void) 6467c478bd9Sstevel@tonic-gate { 6477c478bd9Sstevel@tonic-gate picl_hdl_t hdl; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptreehdl_lock); /* lock ptreehdl */ 6507c478bd9Sstevel@tonic-gate hdl = MAKE_HANDLE(picld_pid, ptree_hdl_hi); 6517c478bd9Sstevel@tonic-gate ++ptree_hdl_hi; 6527c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptreehdl_lock); /* unlock ptreehdl */ 6537c478bd9Sstevel@tonic-gate return (hdl); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * Allocate a picl handle 6587c478bd9Sstevel@tonic-gate * A PICL handle is ptree_hdl value with 1 in MSB of handle value. 6597c478bd9Sstevel@tonic-gate * If a ptree handle already has 1 in MSB, then it cannot be piclized 6607c478bd9Sstevel@tonic-gate * and the daemon must be restarted. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate static picl_hdl_t 6637c478bd9Sstevel@tonic-gate alloc_piclhdl(void) 6647c478bd9Sstevel@tonic-gate { 6657c478bd9Sstevel@tonic-gate picl_hdl_t hdl; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&piclhdl_lock); /* lock piclhdl */ 6687c478bd9Sstevel@tonic-gate hdl = MAKE_HANDLE(picld_pid, picl_hdl_hi); 6697c478bd9Sstevel@tonic-gate ++picl_hdl_hi; 6707c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&piclhdl_lock); /* unlock piclhdl */ 6717c478bd9Sstevel@tonic-gate return (hdl); 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * Allocate and add handle to PTree hash table 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate static void 6787c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(picl_obj_t *pobj) 6797c478bd9Sstevel@tonic-gate { 6807c478bd9Sstevel@tonic-gate pobj->ptree_hdl = alloc_ptreehdl(); 6817c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); 6827c478bd9Sstevel@tonic-gate (void) hash_add_newobj(&ptreetbl, pobj->ptree_hdl, pobj); 6837c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* 6877c478bd9Sstevel@tonic-gate * Lock a picl node object 6887c478bd9Sstevel@tonic-gate */ 6897c478bd9Sstevel@tonic-gate static int 6907c478bd9Sstevel@tonic-gate lock_obj(int rw, picl_obj_t *nodep) 6917c478bd9Sstevel@tonic-gate { 6927c478bd9Sstevel@tonic-gate if (rw == RDLOCK_NODE) 6937c478bd9Sstevel@tonic-gate (void) rw_rdlock(&nodep->node_lock); 6947c478bd9Sstevel@tonic-gate else if (rw == WRLOCK_NODE) 6957c478bd9Sstevel@tonic-gate (void) rw_wrlock(&nodep->node_lock); 6967c478bd9Sstevel@tonic-gate else 6977c478bd9Sstevel@tonic-gate return (-1); 6987c478bd9Sstevel@tonic-gate return (0); 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate /* 7027c478bd9Sstevel@tonic-gate * Release the picl node object. 7037c478bd9Sstevel@tonic-gate * This function may be called with a NULL object pointer. 7047c478bd9Sstevel@tonic-gate */ 7057c478bd9Sstevel@tonic-gate static void 7067c478bd9Sstevel@tonic-gate unlock_node(picl_obj_t *nodep) 7077c478bd9Sstevel@tonic-gate { 7087c478bd9Sstevel@tonic-gate if (nodep == NULL) 7097c478bd9Sstevel@tonic-gate return; 7107c478bd9Sstevel@tonic-gate (void) rw_unlock(&nodep->node_lock); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate /* 7147c478bd9Sstevel@tonic-gate * This function locks the node of a property and returns the node object 7157c478bd9Sstevel@tonic-gate * and the property object. 7167c478bd9Sstevel@tonic-gate */ 7177c478bd9Sstevel@tonic-gate static int 7187c478bd9Sstevel@tonic-gate lookup_and_lock_propnode(int rw, picl_prophdl_t proph, picl_obj_t **nodep, 7197c478bd9Sstevel@tonic-gate picl_obj_t **propp) 7207c478bd9Sstevel@tonic-gate { 7217c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 7227c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, proph); 7257c478bd9Sstevel@tonic-gate if (pobj == NULL) 7267c478bd9Sstevel@tonic-gate return (ptree_hdl_error(proph)); 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * Get the property's or table entry's node object 7307c478bd9Sstevel@tonic-gate */ 7317c478bd9Sstevel@tonic-gate nobj = NULL; 7327c478bd9Sstevel@tonic-gate if (pobj->obj_type == PICL_OBJ_PROP) 7337c478bd9Sstevel@tonic-gate nobj = pobj->prop_node; 7347c478bd9Sstevel@tonic-gate else if (pobj->obj_type == (PICL_OBJ_PROP|PICL_OBJ_TABLEENTRY)) 7357c478bd9Sstevel@tonic-gate nobj = pobj->prop_table->prop_node; 7367c478bd9Sstevel@tonic-gate else { 7377c478bd9Sstevel@tonic-gate *propp = pobj; /* return the prop */ 7387c478bd9Sstevel@tonic-gate return (PICL_NOTPROP); 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate if (nobj && (lock_obj(rw, nobj) < 0)) /* Lock node */ 7427c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate *nodep = nobj; 7457c478bd9Sstevel@tonic-gate *propp = pobj; 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate /* 7517c478bd9Sstevel@tonic-gate * This function locks the node of a table and returns the node object 7527c478bd9Sstevel@tonic-gate * and the table object. 7537c478bd9Sstevel@tonic-gate */ 7547c478bd9Sstevel@tonic-gate static int 7557c478bd9Sstevel@tonic-gate lookup_and_lock_tablenode(int rw, picl_prophdl_t tblh, picl_obj_t **nodep, 7567c478bd9Sstevel@tonic-gate picl_obj_t **tblobj) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 7597c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, tblh); 7627c478bd9Sstevel@tonic-gate if (pobj == NULL) 7637c478bd9Sstevel@tonic-gate return (ptree_hdl_error(tblh)); 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate /* 7667c478bd9Sstevel@tonic-gate * Get the property's or table entry's node object 7677c478bd9Sstevel@tonic-gate */ 7687c478bd9Sstevel@tonic-gate nobj = NULL; 7697c478bd9Sstevel@tonic-gate if (pobj->obj_type != PICL_OBJ_TABLE) 7707c478bd9Sstevel@tonic-gate return (PICL_NOTTABLE); 7717c478bd9Sstevel@tonic-gate nobj = pobj->prop_node; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate if (nobj && (lock_obj(rw, nobj) < 0)) /* Lock node */ 7747c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate *nodep = nobj; 7777c478bd9Sstevel@tonic-gate *tblobj = pobj; 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate /* 7837c478bd9Sstevel@tonic-gate * This locks the node of a table or a table entry and returns the 7847c478bd9Sstevel@tonic-gate * node object and the table or table entry object 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate static int 7877c478bd9Sstevel@tonic-gate lookup_and_lock_tableprop_node(int rw, picl_prophdl_t tblproph, 7887c478bd9Sstevel@tonic-gate picl_obj_t **nodep, picl_obj_t **tblpropp) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 7917c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, tblproph); 7947c478bd9Sstevel@tonic-gate if (pobj == NULL) 7957c478bd9Sstevel@tonic-gate return (ptree_hdl_error(tblproph)); 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * Get the property's or table entry's node object 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate nobj = NULL; 8017c478bd9Sstevel@tonic-gate if ((pobj->obj_type != PICL_OBJ_TABLE) && /* not a table */ 8027c478bd9Sstevel@tonic-gate !(pobj->obj_type & PICL_OBJ_TABLEENTRY)) /* or an entry */ 8037c478bd9Sstevel@tonic-gate return (PICL_NOTTABLE); 8047c478bd9Sstevel@tonic-gate if (pobj->obj_type == PICL_OBJ_TABLE) 8057c478bd9Sstevel@tonic-gate nobj = pobj->prop_node; 8067c478bd9Sstevel@tonic-gate else 8077c478bd9Sstevel@tonic-gate nobj = pobj->prop_table->prop_node; 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate if (nobj && (lock_obj(rw, nobj) < 0)) /* Lock node */ 8107c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate *tblpropp = pobj; 8137c478bd9Sstevel@tonic-gate *nodep = nobj; 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate /* 8197c478bd9Sstevel@tonic-gate * Lock the node corresponding to the given handle and return its object 8207c478bd9Sstevel@tonic-gate */ 8217c478bd9Sstevel@tonic-gate static int 8227c478bd9Sstevel@tonic-gate lookup_and_lock_node(int rw, picl_nodehdl_t nodeh, picl_obj_t **nodep) 8237c478bd9Sstevel@tonic-gate { 8247c478bd9Sstevel@tonic-gate picl_obj_t *nobj; 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate nobj = hash_lookup_obj(&ptreetbl, nodeh); 8277c478bd9Sstevel@tonic-gate if (nobj == NULL) 8287c478bd9Sstevel@tonic-gate return (ptree_hdl_error(nodeh)); 8297c478bd9Sstevel@tonic-gate else if (nobj->obj_type != PICL_OBJ_NODE) 8307c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 8317c478bd9Sstevel@tonic-gate if (lock_obj(rw, nobj) < 0) /* Lock node */ 8327c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 8337c478bd9Sstevel@tonic-gate *nodep = nobj; 8347c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate /* 8387c478bd9Sstevel@tonic-gate * Is the property name a restricted property name? 8397c478bd9Sstevel@tonic-gate */ 8407c478bd9Sstevel@tonic-gate static int 8417c478bd9Sstevel@tonic-gate picl_restricted(const char *name) 8427c478bd9Sstevel@tonic-gate { 8437c478bd9Sstevel@tonic-gate if (strcmp(name, PICL_PROP_CLASSNAME) == 0) 8447c478bd9Sstevel@tonic-gate return (0); /* not restricted */ 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate if ((name[0] == '_') && (strchr(&name[1], '_') == NULL)) 8477c478bd9Sstevel@tonic-gate return (1); 8487c478bd9Sstevel@tonic-gate return (0); 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate /* 8527c478bd9Sstevel@tonic-gate * Check the value size with the property size 8537c478bd9Sstevel@tonic-gate * Return PICL_INVALIDARG if the size does not match exactly for strongly 8547c478bd9Sstevel@tonic-gate * typed properties. 8557c478bd9Sstevel@tonic-gate * For charstring reads allow sizes that match the value size 8567c478bd9Sstevel@tonic-gate * For bytearray return PICL_VALUETOOBIG 8577c478bd9Sstevel@tonic-gate * if the size is greater than the buffer size. 8587c478bd9Sstevel@tonic-gate */ 8597c478bd9Sstevel@tonic-gate static int 8607c478bd9Sstevel@tonic-gate check_propsize(int op, picl_obj_t *propp, size_t sz) 8617c478bd9Sstevel@tonic-gate { 8627c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) { 8637c478bd9Sstevel@tonic-gate if (sz != propp->prop_size) 8647c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 8657c478bd9Sstevel@tonic-gate else 8667c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate /* 8707c478bd9Sstevel@tonic-gate * check size for non-volatile properties 8717c478bd9Sstevel@tonic-gate */ 8727c478bd9Sstevel@tonic-gate switch (propp->prop_type) { 8737c478bd9Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 8747c478bd9Sstevel@tonic-gate if ((op == PROP_READ) && 8757c478bd9Sstevel@tonic-gate (strlen(propp->prop_val) >= sz)) 8767c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 8777c478bd9Sstevel@tonic-gate if ((op == PROP_WRITE) && (sz > propp->prop_size)) 8787c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 8797c478bd9Sstevel@tonic-gate break; 8807c478bd9Sstevel@tonic-gate case PICL_PTYPE_BYTEARRAY: 8817c478bd9Sstevel@tonic-gate if (op == PROP_WRITE) { 8827c478bd9Sstevel@tonic-gate if (sz > propp->prop_size) 8837c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 8847c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); /* allow small writes */ 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate /* fall through for reads */ 8877c478bd9Sstevel@tonic-gate default: 8887c478bd9Sstevel@tonic-gate if (propp->prop_size != sz) 8897c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 8907c478bd9Sstevel@tonic-gate break; 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate void 8967c478bd9Sstevel@tonic-gate cvt_ptree2picl(picl_hdl_t *handlep) 8977c478bd9Sstevel@tonic-gate { 8987c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); 9017c478bd9Sstevel@tonic-gate pobj = hash_lookup_obj(&ptreetbl, *handlep); 9027c478bd9Sstevel@tonic-gate if (pobj == NULL) 9037c478bd9Sstevel@tonic-gate *handlep = PICL_INVALID_PICLHDL; 9047c478bd9Sstevel@tonic-gate else 9057c478bd9Sstevel@tonic-gate (void) memcpy(handlep, &pobj->picl_hdl, sizeof (*handlep)); 9067c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate /* 9107c478bd9Sstevel@tonic-gate * The caller of the piclize() set of functions is assumed to hold 9117c478bd9Sstevel@tonic-gate * the ptree_rwlock(). 9127c478bd9Sstevel@tonic-gate */ 9137c478bd9Sstevel@tonic-gate static void 9147c478bd9Sstevel@tonic-gate piclize_obj(picl_obj_t *pobj) 9157c478bd9Sstevel@tonic-gate { 9167c478bd9Sstevel@tonic-gate (void) rw_wrlock(&picltbl_rwlock); 9177c478bd9Sstevel@tonic-gate pobj->picl_hdl = alloc_piclhdl(); 9187c478bd9Sstevel@tonic-gate (void) hash_add_newhdl(&picltbl, pobj->picl_hdl, pobj->ptree_hdl); 9197c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate static void 9237c478bd9Sstevel@tonic-gate piclize_table(picl_obj_t *tbl_obj) 9247c478bd9Sstevel@tonic-gate { 9257c478bd9Sstevel@tonic-gate picl_obj_t *rowp; 9267c478bd9Sstevel@tonic-gate picl_obj_t *colp; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate for (rowp = tbl_obj->next_row; rowp != NULL; rowp = rowp->next_col) 9297c478bd9Sstevel@tonic-gate for (colp = rowp; colp != NULL; colp = colp->next_row) 9307c478bd9Sstevel@tonic-gate piclize_obj(colp); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate static void 9347c478bd9Sstevel@tonic-gate piclize_prop(picl_obj_t *propp) 9357c478bd9Sstevel@tonic-gate { 9367c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 9377c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate piclize_obj(propp); 9407c478bd9Sstevel@tonic-gate if (!(propp->prop_mode & PICL_VOLATILE) && 9417c478bd9Sstevel@tonic-gate (propp->prop_type == PICL_PTYPE_TABLE)) { 9427c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)propp->prop_val; 9437c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 9447c478bd9Sstevel@tonic-gate if (tbl_obj == NULL) 9457c478bd9Sstevel@tonic-gate return; 9467c478bd9Sstevel@tonic-gate piclize_obj(tbl_obj); 9477c478bd9Sstevel@tonic-gate piclize_table(tbl_obj); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate /* 9527c478bd9Sstevel@tonic-gate * Function to create PICL handles for a subtree and add them to 9537c478bd9Sstevel@tonic-gate * the table 9547c478bd9Sstevel@tonic-gate */ 9557c478bd9Sstevel@tonic-gate static void 9567c478bd9Sstevel@tonic-gate piclize_node(picl_obj_t *nodep) 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate picl_obj_t *propp; 9597c478bd9Sstevel@tonic-gate picl_obj_t *chdp; 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate piclize_obj(nodep); 9627c478bd9Sstevel@tonic-gate propp = nodep->first_prop; 9637c478bd9Sstevel@tonic-gate while (propp != NULL) { 9647c478bd9Sstevel@tonic-gate piclize_prop(propp); 9657c478bd9Sstevel@tonic-gate propp = propp->next_prop; 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate /* go through the children */ 9697c478bd9Sstevel@tonic-gate for (chdp = nodep->child_node; chdp != NULL; chdp = chdp->sibling_node) 9707c478bd9Sstevel@tonic-gate piclize_node(chdp); 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate /* 9747c478bd9Sstevel@tonic-gate * Function to remove PICL handles 9757c478bd9Sstevel@tonic-gate */ 9767c478bd9Sstevel@tonic-gate static void 9777c478bd9Sstevel@tonic-gate unpiclize_obj(picl_obj_t *pobj) 9787c478bd9Sstevel@tonic-gate { 9797c478bd9Sstevel@tonic-gate (void) rw_wrlock(&picltbl_rwlock); 9807c478bd9Sstevel@tonic-gate (void) hash_remove(&picltbl, pobj->picl_hdl); 9817c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 9827c478bd9Sstevel@tonic-gate (void) rw_unlock(&picltbl_rwlock); 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate static void 9867c478bd9Sstevel@tonic-gate unpiclize_table(picl_obj_t *tbl_obj) 9877c478bd9Sstevel@tonic-gate { 9887c478bd9Sstevel@tonic-gate picl_obj_t *rowp; 9897c478bd9Sstevel@tonic-gate picl_obj_t *colp; 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate for (rowp = tbl_obj->next_row; rowp != NULL; rowp = rowp->next_col) 9927c478bd9Sstevel@tonic-gate for (colp = rowp; colp != NULL; colp = colp->next_row) 9937c478bd9Sstevel@tonic-gate unpiclize_obj(colp); 9947c478bd9Sstevel@tonic-gate unpiclize_obj(tbl_obj); 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate static void 9987c478bd9Sstevel@tonic-gate unpiclize_prop(picl_obj_t *propp) 9997c478bd9Sstevel@tonic-gate { 10007c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 10017c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate if (!IS_PICLIZED(propp)) 10047c478bd9Sstevel@tonic-gate return; 10057c478bd9Sstevel@tonic-gate unpiclize_obj(propp); 10067c478bd9Sstevel@tonic-gate if (!(propp->prop_mode & PICL_VOLATILE) && 10077c478bd9Sstevel@tonic-gate (propp->prop_type == PICL_PTYPE_TABLE)) { 10087c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)propp->prop_val; 10097c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 10107c478bd9Sstevel@tonic-gate unpiclize_table(tbl_obj); 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate /* 10157c478bd9Sstevel@tonic-gate * Function to remove PICL handles for a subtree and its 10167c478bd9Sstevel@tonic-gate * properties 10177c478bd9Sstevel@tonic-gate */ 10187c478bd9Sstevel@tonic-gate static void 10197c478bd9Sstevel@tonic-gate unpiclize_node(picl_obj_t *nodep) 10207c478bd9Sstevel@tonic-gate { 10217c478bd9Sstevel@tonic-gate picl_obj_t *propp; 10227c478bd9Sstevel@tonic-gate picl_obj_t *chdp; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate if (!IS_PICLIZED(nodep)) 10267c478bd9Sstevel@tonic-gate return; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate unpiclize_obj(nodep); 10297c478bd9Sstevel@tonic-gate propp = nodep->first_prop; 10307c478bd9Sstevel@tonic-gate while (propp != NULL) { 10317c478bd9Sstevel@tonic-gate unpiclize_prop(propp); 10327c478bd9Sstevel@tonic-gate propp = propp->next_prop; 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate /* go through the children */ 10367c478bd9Sstevel@tonic-gate for (chdp = nodep->child_node; chdp != NULL; chdp = chdp->sibling_node) 10377c478bd9Sstevel@tonic-gate unpiclize_node(chdp); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate /* 10427c478bd9Sstevel@tonic-gate * The caller holds the lock on the ptree_lock when calling this. 10437c478bd9Sstevel@tonic-gate * If ret is not NULL then this function returns the referenced object. 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate static int 10467c478bd9Sstevel@tonic-gate lookup_verify_ref_prop(picl_obj_t *propp, picl_obj_t **ret) 10477c478bd9Sstevel@tonic-gate { 10487c478bd9Sstevel@tonic-gate picl_nodehdl_t refh; 10497c478bd9Sstevel@tonic-gate picl_obj_t *refobj; 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate refh = *(picl_nodehdl_t *)propp->prop_val; 10527c478bd9Sstevel@tonic-gate refobj = hash_lookup_obj(&ptreetbl, refh); 10537c478bd9Sstevel@tonic-gate if (refobj == NULL) 10547c478bd9Sstevel@tonic-gate return (ptree_hdl_error(refh)); 10557c478bd9Sstevel@tonic-gate else if (refobj->obj_type != PICL_OBJ_NODE) 10567c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 10577c478bd9Sstevel@tonic-gate if (ret) 10587c478bd9Sstevel@tonic-gate *ret = refobj; 10597c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate /* 10637c478bd9Sstevel@tonic-gate * The caller holds the lock on ptree_lock when calling this. 10647c478bd9Sstevel@tonic-gate * If ret is not NULL, then this function returns the table object 10657c478bd9Sstevel@tonic-gate */ 10667c478bd9Sstevel@tonic-gate static int 10677c478bd9Sstevel@tonic-gate lookup_verify_table_prop(picl_obj_t *propp, picl_obj_t **ret) 10687c478bd9Sstevel@tonic-gate { 10697c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 10707c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)propp->prop_val; 10737c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 10747c478bd9Sstevel@tonic-gate if (tbl_obj == NULL) 10757c478bd9Sstevel@tonic-gate return (ptree_hdl_error(tblh)); 10767c478bd9Sstevel@tonic-gate else if (!(tbl_obj->obj_type & PICL_OBJ_TABLE)) 10777c478bd9Sstevel@tonic-gate return (PICL_NOTTABLE); 10787c478bd9Sstevel@tonic-gate if (ret) 10797c478bd9Sstevel@tonic-gate *ret = tbl_obj; 10807c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate static int 10847c478bd9Sstevel@tonic-gate lookup_verify_prop_handle(picl_prophdl_t proph, picl_obj_t **ret) 10857c478bd9Sstevel@tonic-gate { 10867c478bd9Sstevel@tonic-gate picl_obj_t *propp; 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate propp = hash_lookup_obj(&ptreetbl, proph); 10897c478bd9Sstevel@tonic-gate if (propp == NULL) 10907c478bd9Sstevel@tonic-gate return (ptree_hdl_error(proph)); 10917c478bd9Sstevel@tonic-gate else if (!(propp->obj_type & PICL_OBJ_PROP)) 10927c478bd9Sstevel@tonic-gate return (PICL_NOTPROP); 10937c478bd9Sstevel@tonic-gate if (ret) 10947c478bd9Sstevel@tonic-gate *ret = propp; 10957c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate static int 10997c478bd9Sstevel@tonic-gate lookup_verify_node_handle(picl_nodehdl_t nodeh, picl_obj_t **ret) 11007c478bd9Sstevel@tonic-gate { 11017c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate nodep = hash_lookup_obj(&ptreetbl, nodeh); 11047c478bd9Sstevel@tonic-gate if (nodep == NULL) 11057c478bd9Sstevel@tonic-gate return (ptree_hdl_error(nodeh)); 11067c478bd9Sstevel@tonic-gate else if (nodep->obj_type != PICL_OBJ_NODE) 11077c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 11087c478bd9Sstevel@tonic-gate if (ret) 11097c478bd9Sstevel@tonic-gate *ret = nodep; 11107c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate static int 11147c478bd9Sstevel@tonic-gate lookup_prop_by_name(picl_obj_t *nodep, const char *pname, picl_obj_t **ret) 11157c478bd9Sstevel@tonic-gate { 11167c478bd9Sstevel@tonic-gate picl_obj_t *propp; 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_PARENT) == 0) { 11197c478bd9Sstevel@tonic-gate if (nodep->parent_node == NULL) 11207c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 11217c478bd9Sstevel@tonic-gate else 11227c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_CHILD) == 0) { 11257c478bd9Sstevel@tonic-gate if (nodep->child_node == NULL) 11267c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 11277c478bd9Sstevel@tonic-gate else 11287c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_PEER) == 0) { 11317c478bd9Sstevel@tonic-gate if (nodep->sibling_node == NULL) 11327c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 11337c478bd9Sstevel@tonic-gate else 11347c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 11357c478bd9Sstevel@tonic-gate } 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate propp = nodep->first_prop; 11387c478bd9Sstevel@tonic-gate while (propp != NULL) { 11397c478bd9Sstevel@tonic-gate if (strcmp(propp->prop_name, pname) == 0) { 11407c478bd9Sstevel@tonic-gate if (ret) 11417c478bd9Sstevel@tonic-gate *ret = propp; 11427c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 11437c478bd9Sstevel@tonic-gate } 11447c478bd9Sstevel@tonic-gate propp = propp->next_prop; 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 11477c478bd9Sstevel@tonic-gate } 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate /* 11507c478bd9Sstevel@tonic-gate * This function locks the ptree, verifies that the handle is a reference 11517c478bd9Sstevel@tonic-gate * to a node of specified class name, releases the lock 11527c478bd9Sstevel@tonic-gate */ 11537c478bd9Sstevel@tonic-gate static int 11547c478bd9Sstevel@tonic-gate check_ref_handle(picl_nodehdl_t refh, char *clname) 11557c478bd9Sstevel@tonic-gate { 11567c478bd9Sstevel@tonic-gate picl_obj_t *refobj; 11577c478bd9Sstevel@tonic-gate picl_obj_t *propp; 11587c478bd9Sstevel@tonic-gate int err; 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* Lock ptree */ 11617c478bd9Sstevel@tonic-gate refobj = hash_lookup_obj(&ptreetbl, refh); 11627c478bd9Sstevel@tonic-gate if ((refobj == NULL) || !(refobj->obj_type & PICL_OBJ_NODE)) { 11637c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 11647c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(refobj, PICL_PROP_CLASSNAME, &propp); 11687c478bd9Sstevel@tonic-gate if ((err != PICL_SUCCESS) || (propp->prop_val == NULL) || 11697c478bd9Sstevel@tonic-gate (strcmp(propp->prop_val, clname) != 0)) 11707c478bd9Sstevel@tonic-gate err = PICL_INVREFERENCE; 11717c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 11727c478bd9Sstevel@tonic-gate return (err); 11737c478bd9Sstevel@tonic-gate } 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate static int 11767c478bd9Sstevel@tonic-gate check_table_handle(picl_prophdl_t tblh) 11777c478bd9Sstevel@tonic-gate { 11787c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 11797c478bd9Sstevel@tonic-gate int err; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); 11827c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 11837c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 11847c478bd9Sstevel@tonic-gate if ((tbl_obj == NULL) || !(tbl_obj->obj_type & PICL_OBJ_TABLE)) 11857c478bd9Sstevel@tonic-gate err = PICL_NOTTABLE; 11867c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 11877c478bd9Sstevel@tonic-gate return (err); 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate /* 11917c478bd9Sstevel@tonic-gate * PICLTree Interface routines for plug-in modules 11927c478bd9Sstevel@tonic-gate */ 11937c478bd9Sstevel@tonic-gate int 11947c478bd9Sstevel@tonic-gate ptree_get_root(picl_nodehdl_t *rooth) 11957c478bd9Sstevel@tonic-gate { 11967c478bd9Sstevel@tonic-gate *rooth = ptree_root_hdl; 11977c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate /* 12017c478bd9Sstevel@tonic-gate * Lock free create a property object 12027c478bd9Sstevel@tonic-gate */ 12037c478bd9Sstevel@tonic-gate static int 12047c478bd9Sstevel@tonic-gate create_propobj(const ptree_propinfo_t *pinfo, const void *valbuf, 12057c478bd9Sstevel@tonic-gate picl_obj_t **pobjp) 12067c478bd9Sstevel@tonic-gate { 12077c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate if (pinfo->version != PTREE_PROPINFO_VERSION_1) 12107c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE) && 12137c478bd9Sstevel@tonic-gate (pinfo->piclinfo.type != PICL_PTYPE_VOID) && 12147c478bd9Sstevel@tonic-gate (valbuf == NULL)) 12157c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate pobj = malloc(sizeof (picl_obj_t)); 12187c478bd9Sstevel@tonic-gate if (pobj == NULL) 12197c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate pobj->obj_type = PICL_OBJ_PROP; 12227c478bd9Sstevel@tonic-gate pobj->pinfo_ver = pinfo->version; 12237c478bd9Sstevel@tonic-gate pobj->prop_type = pinfo->piclinfo.type; 12247c478bd9Sstevel@tonic-gate pobj->prop_mode = pinfo->piclinfo.accessmode; 12257c478bd9Sstevel@tonic-gate pobj->prop_size = pinfo->piclinfo.size; 12267c478bd9Sstevel@tonic-gate (void) strcpy(pobj->prop_name, pinfo->piclinfo.name); 12277c478bd9Sstevel@tonic-gate pobj->read_func = pinfo->read; 12287c478bd9Sstevel@tonic-gate pobj->write_func = pinfo->write; 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate pobj->prop_val = NULL; 12317c478bd9Sstevel@tonic-gate if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE)) { 12327c478bd9Sstevel@tonic-gate pobj->prop_val = malloc(pinfo->piclinfo.size); 12337c478bd9Sstevel@tonic-gate if (pobj->prop_val == NULL) { 12347c478bd9Sstevel@tonic-gate free(pobj); 12357c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate if (pobj->prop_type == PICL_PTYPE_CHARSTRING) 12387c478bd9Sstevel@tonic-gate (void) strlcpy(pobj->prop_val, valbuf, 12397c478bd9Sstevel@tonic-gate pinfo->piclinfo.size); 12407c478bd9Sstevel@tonic-gate else 12417c478bd9Sstevel@tonic-gate (void) memcpy(pobj->prop_val, valbuf, 12427c478bd9Sstevel@tonic-gate pinfo->piclinfo.size); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate pobj->prop_node = NULL; 12457c478bd9Sstevel@tonic-gate pobj->ptree_hdl = PICL_INVALID_PICLHDL; 12467c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 12477c478bd9Sstevel@tonic-gate pobj->next_prop = NULL; 12487c478bd9Sstevel@tonic-gate pobj->next_row = NULL; 12497c478bd9Sstevel@tonic-gate pobj->next_col = NULL; 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate *pobjp = pobj; 12527c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate /* 12567c478bd9Sstevel@tonic-gate * Check for valid arguments, create a property object, 12577c478bd9Sstevel@tonic-gate * Lock ptree_rwlock, add the new property handle, release the lock 12587c478bd9Sstevel@tonic-gate * For reference properties and table properties, the handles are verified 12597c478bd9Sstevel@tonic-gate * before creating the property. 12607c478bd9Sstevel@tonic-gate */ 12617c478bd9Sstevel@tonic-gate int 12627c478bd9Sstevel@tonic-gate ptree_create_prop(const ptree_propinfo_t *pinfo, const void *valbuf, 12637c478bd9Sstevel@tonic-gate picl_prophdl_t *proph) 12647c478bd9Sstevel@tonic-gate { 12657c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 12667c478bd9Sstevel@tonic-gate picl_nodehdl_t refh; 12677c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 12687c478bd9Sstevel@tonic-gate int err; 12697c478bd9Sstevel@tonic-gate char *ptr; 12707c478bd9Sstevel@tonic-gate int refflag; 12717c478bd9Sstevel@tonic-gate char classname[PICL_PROPNAMELEN_MAX]; 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate if (pinfo == NULL) 12747c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 12757c478bd9Sstevel@tonic-gate if (pinfo->version != PTREE_PROPINFO_VERSION_1) 12767c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 12777c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.size >= PICL_PROPSIZE_MAX) 12787c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 12797c478bd9Sstevel@tonic-gate if (picl_restricted(pinfo->piclinfo.name)) 12807c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate refflag = 0; 12837c478bd9Sstevel@tonic-gate if ((pinfo->piclinfo.name[0] == '_') && 12847c478bd9Sstevel@tonic-gate (strchr(&pinfo->piclinfo.name[1], '_') != NULL)) 12857c478bd9Sstevel@tonic-gate refflag = 1; 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.type == PICL_PTYPE_REFERENCE) { 12887c478bd9Sstevel@tonic-gate if (refflag == 0) 12897c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 12907c478bd9Sstevel@tonic-gate /* 12917c478bd9Sstevel@tonic-gate * check valid reference handle for non-volatiles 12927c478bd9Sstevel@tonic-gate */ 12937c478bd9Sstevel@tonic-gate if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE)) { 12947c478bd9Sstevel@tonic-gate if (valbuf == NULL) 12957c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 12967c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.size != sizeof (picl_nodehdl_t)) 12977c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 12987c478bd9Sstevel@tonic-gate (void) strcpy(classname, pinfo->piclinfo.name); 12997c478bd9Sstevel@tonic-gate ptr = strchr(&classname[1], '_'); 13007c478bd9Sstevel@tonic-gate *ptr = '\0'; 13017c478bd9Sstevel@tonic-gate refh = *(picl_hdl_t *)valbuf; 13027c478bd9Sstevel@tonic-gate err = check_ref_handle(refh, &classname[1]); 13037c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 13047c478bd9Sstevel@tonic-gate return (err); 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate } else if (refflag == 1) 13077c478bd9Sstevel@tonic-gate return (PICL_INVREFERENCE); 13087c478bd9Sstevel@tonic-gate else if ((pinfo->piclinfo.type == PICL_PTYPE_TABLE) && 13097c478bd9Sstevel@tonic-gate (!(pinfo->piclinfo.accessmode & PICL_VOLATILE))) { 13107c478bd9Sstevel@tonic-gate if (pinfo->piclinfo.size != sizeof (picl_prophdl_t)) 13117c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 13127c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)valbuf; 13137c478bd9Sstevel@tonic-gate err = check_table_handle(tblh); 13147c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 13157c478bd9Sstevel@tonic-gate return (err); 13167c478bd9Sstevel@tonic-gate } else if ((strcmp(pinfo->piclinfo.name, PICL_PROP_CLASSNAME) == 0) && 13177c478bd9Sstevel@tonic-gate ((pinfo->piclinfo.type != PICL_PTYPE_CHARSTRING) || 13187c478bd9Sstevel@tonic-gate (strlen(valbuf) >= PICL_CLASSNAMELEN_MAX))) 13197c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 13207c478bd9Sstevel@tonic-gate else if ((strcmp(pinfo->piclinfo.name, PICL_PROP_NAME) == 0) && 13217c478bd9Sstevel@tonic-gate (pinfo->piclinfo.type != PICL_PTYPE_CHARSTRING)) 13227c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 13237c478bd9Sstevel@tonic-gate /* 13247c478bd9Sstevel@tonic-gate * No locks held when you get here 13257c478bd9Sstevel@tonic-gate */ 13267c478bd9Sstevel@tonic-gate err = create_propobj(pinfo, valbuf, &pobj); 13277c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 13287c478bd9Sstevel@tonic-gate return (err); 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(pobj); 13317c478bd9Sstevel@tonic-gate *proph = pobj->ptree_hdl; 13327c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate /* 13367c478bd9Sstevel@tonic-gate * Lock free routine to destroy table entries 13377c478bd9Sstevel@tonic-gate * This function removes the destroyed handles from the hash table 13387c478bd9Sstevel@tonic-gate * Uses lock free routines: hash_lookup() and hash_remove() 13397c478bd9Sstevel@tonic-gate */ 13407c478bd9Sstevel@tonic-gate static void 13417c478bd9Sstevel@tonic-gate destroy_table(picl_obj_t *pobj) 13427c478bd9Sstevel@tonic-gate { 13437c478bd9Sstevel@tonic-gate picl_prophdl_t tblh; 13447c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 13457c478bd9Sstevel@tonic-gate picl_obj_t *rowp; 13467c478bd9Sstevel@tonic-gate picl_obj_t *colp; 13477c478bd9Sstevel@tonic-gate picl_obj_t *freep; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate tblh = *(picl_prophdl_t *)pobj->prop_val; 13507c478bd9Sstevel@tonic-gate tbl_obj = hash_lookup_obj(&ptreetbl, tblh); 13517c478bd9Sstevel@tonic-gate if (tbl_obj == NULL) 13527c478bd9Sstevel@tonic-gate return; 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate assert(tbl_obj->obj_type & PICL_OBJ_TABLE); 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* Delete all entries */ 13577c478bd9Sstevel@tonic-gate rowp = tbl_obj->next_row; 13587c478bd9Sstevel@tonic-gate while (rowp != NULL) { 13597c478bd9Sstevel@tonic-gate colp = rowp; 13607c478bd9Sstevel@tonic-gate rowp = rowp->next_col; 13617c478bd9Sstevel@tonic-gate while (colp != NULL) { 13627c478bd9Sstevel@tonic-gate freep = colp; 13637c478bd9Sstevel@tonic-gate colp = colp->next_row; 13647c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, freep->ptree_hdl); 13657c478bd9Sstevel@tonic-gate if (freep->prop_val) 13667c478bd9Sstevel@tonic-gate free(freep->prop_val); 13677c478bd9Sstevel@tonic-gate free(freep); 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate } 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, tbl_obj->ptree_hdl); 13727c478bd9Sstevel@tonic-gate free(tbl_obj); 13737c478bd9Sstevel@tonic-gate } 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate /* 13777c478bd9Sstevel@tonic-gate * Lock free function that frees up a property object and removes the 13787c478bd9Sstevel@tonic-gate * handles from Ptree table 13797c478bd9Sstevel@tonic-gate */ 13807c478bd9Sstevel@tonic-gate static void 13817c478bd9Sstevel@tonic-gate destroy_propobj(picl_obj_t *propp) 13827c478bd9Sstevel@tonic-gate { 13837c478bd9Sstevel@tonic-gate if (propp->prop_type == PICL_PTYPE_TABLE) 13847c478bd9Sstevel@tonic-gate destroy_table(propp); 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, propp->ptree_hdl); 13877c478bd9Sstevel@tonic-gate if (propp->prop_val) 13887c478bd9Sstevel@tonic-gate free(propp->prop_val); 13897c478bd9Sstevel@tonic-gate free(propp); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate /* 13937c478bd9Sstevel@tonic-gate * This function destroys a previously deleted property. 13947c478bd9Sstevel@tonic-gate * A deleted property does not have an associated node. 13957c478bd9Sstevel@tonic-gate * All memory allocated for this property are freed 13967c478bd9Sstevel@tonic-gate */ 13977c478bd9Sstevel@tonic-gate int 13987c478bd9Sstevel@tonic-gate ptree_destroy_prop(picl_prophdl_t proph) 13997c478bd9Sstevel@tonic-gate { 14007c478bd9Sstevel@tonic-gate picl_obj_t *propp; 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* Exclusive Lock ptree */ 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate propp = hash_lookup_obj(&ptreetbl, proph); 14057c478bd9Sstevel@tonic-gate if (propp == NULL) { 14067c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 14077c478bd9Sstevel@tonic-gate return (ptree_hdl_error(proph)); 14087c478bd9Sstevel@tonic-gate } 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate /* Is the prop still attached to a node? */ 14117c478bd9Sstevel@tonic-gate if (propp->prop_node != NULL) { 14127c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 14137c478bd9Sstevel@tonic-gate return (PICL_CANTDESTROY); 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate destroy_propobj(propp); 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 14197c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate * This function adds a property to the property list of a node and adds 14247c478bd9Sstevel@tonic-gate * it to the PICL table if the node has a PICL handle. 14257c478bd9Sstevel@tonic-gate * This function locks the picl_rwlock and ptree_rwlock. 14267c478bd9Sstevel@tonic-gate */ 14277c478bd9Sstevel@tonic-gate int 14287c478bd9Sstevel@tonic-gate ptree_add_prop(picl_nodehdl_t nodeh, picl_prophdl_t proph) 14297c478bd9Sstevel@tonic-gate { 14307c478bd9Sstevel@tonic-gate int err; 14317c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 14327c478bd9Sstevel@tonic-gate picl_obj_t *propp; 14337c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 14347c478bd9Sstevel@tonic-gate picl_obj_t *refobj; 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* RDLock ptree */ 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate /* 14397c478bd9Sstevel@tonic-gate * Verify property handle 14407c478bd9Sstevel@tonic-gate */ 14417c478bd9Sstevel@tonic-gate err = lookup_verify_prop_handle(proph, &propp); 14427c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 14437c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 14447c478bd9Sstevel@tonic-gate return (err); 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate if (propp->prop_node != NULL) { 14487c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 14497c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate nodep = NULL; 14537c478bd9Sstevel@tonic-gate /* 14547c478bd9Sstevel@tonic-gate * Exclusive Lock the node's properties 14557c478bd9Sstevel@tonic-gate */ 14567c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(WRLOCK_NODE, nodeh, &nodep); 14577c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 14587c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 14597c478bd9Sstevel@tonic-gate return (err); 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* 14637c478bd9Sstevel@tonic-gate * check if prop already exists 14647c478bd9Sstevel@tonic-gate */ 14657c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, propp->prop_name, NULL); 14667c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 14677c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 14687c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 14697c478bd9Sstevel@tonic-gate return (PICL_PROPEXISTS); 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate /* 14737c478bd9Sstevel@tonic-gate * Verify property's value 14747c478bd9Sstevel@tonic-gate */ 14757c478bd9Sstevel@tonic-gate tbl_obj = NULL; 14767c478bd9Sstevel@tonic-gate switch (propp->prop_type) { 14777c478bd9Sstevel@tonic-gate case PICL_PTYPE_TABLE: 14787c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) 14797c478bd9Sstevel@tonic-gate break; 14807c478bd9Sstevel@tonic-gate err = lookup_verify_table_prop(propp, &tbl_obj); 14817c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 14827c478bd9Sstevel@tonic-gate unlock_node(nodep); 14837c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 14847c478bd9Sstevel@tonic-gate return (err); 14857c478bd9Sstevel@tonic-gate } 14867c478bd9Sstevel@tonic-gate tbl_obj->prop_node = nodep; /* set table's nodep */ 14877c478bd9Sstevel@tonic-gate tbl_obj->table_prop = propp; /* set table prop */ 14887c478bd9Sstevel@tonic-gate break; 14897c478bd9Sstevel@tonic-gate case PICL_PTYPE_REFERENCE: 14907c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) 14917c478bd9Sstevel@tonic-gate break; 14927c478bd9Sstevel@tonic-gate err = lookup_verify_ref_prop(propp, &refobj); 14937c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 14947c478bd9Sstevel@tonic-gate unlock_node(nodep); 14957c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 14967c478bd9Sstevel@tonic-gate return (err); 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate if (IS_PICLIZED(nodep) && !IS_PICLIZED(refobj)) { 14997c478bd9Sstevel@tonic-gate unlock_node(nodep); 15007c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 15017c478bd9Sstevel@tonic-gate return (err); 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate break; 15047c478bd9Sstevel@tonic-gate default: 15057c478bd9Sstevel@tonic-gate break; 15067c478bd9Sstevel@tonic-gate } 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate if (IS_PICLIZED(nodep)) 15097c478bd9Sstevel@tonic-gate piclize_prop(propp); 15107c478bd9Sstevel@tonic-gate /* 15117c478bd9Sstevel@tonic-gate * Add prop to beginning of list 15127c478bd9Sstevel@tonic-gate */ 15137c478bd9Sstevel@tonic-gate propp->prop_node = nodep; /* set prop's nodep */ 15147c478bd9Sstevel@tonic-gate propp->next_prop = nodep->first_prop; 15157c478bd9Sstevel@tonic-gate nodep->first_prop = propp; 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 15187c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 15197c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate /* 15237c478bd9Sstevel@tonic-gate * Lock free function that unlinks a property from its node 15247c478bd9Sstevel@tonic-gate */ 15257c478bd9Sstevel@tonic-gate static int 15267c478bd9Sstevel@tonic-gate unlink_prop(picl_obj_t *nodep, picl_obj_t *propp) 15277c478bd9Sstevel@tonic-gate { 15287c478bd9Sstevel@tonic-gate picl_obj_t *iterp; 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate iterp = nodep->first_prop; 15317c478bd9Sstevel@tonic-gate if (iterp == propp) { /* first property */ 15327c478bd9Sstevel@tonic-gate nodep->first_prop = iterp->next_prop; 15337c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate while ((iterp != NULL) && (iterp->next_prop != propp)) 15367c478bd9Sstevel@tonic-gate iterp = iterp->next_prop; 15377c478bd9Sstevel@tonic-gate if (iterp == NULL) 15387c478bd9Sstevel@tonic-gate return (PICL_PROPNOTFOUND); 15397c478bd9Sstevel@tonic-gate iterp->next_prop = propp->next_prop; 15407c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 15417c478bd9Sstevel@tonic-gate } 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate /* 15447c478bd9Sstevel@tonic-gate * This function deletes the specified property from the property list 15457c478bd9Sstevel@tonic-gate * of its node and removes the handle from PICL table, if the node 15467c478bd9Sstevel@tonic-gate * was piclized. 15477c478bd9Sstevel@tonic-gate */ 15487c478bd9Sstevel@tonic-gate int 15497c478bd9Sstevel@tonic-gate ptree_delete_prop(picl_prophdl_t proph) 15507c478bd9Sstevel@tonic-gate { 15517c478bd9Sstevel@tonic-gate int err; 15527c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 15537c478bd9Sstevel@tonic-gate picl_obj_t *propp; 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 15567c478bd9Sstevel@tonic-gate /* 15577c478bd9Sstevel@tonic-gate * Lookup the property's node and lock it if there is one 15587c478bd9Sstevel@tonic-gate * return the objects for the property and the node 15597c478bd9Sstevel@tonic-gate */ 15607c478bd9Sstevel@tonic-gate nodep = propp = NULL; 15617c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(WRLOCK_NODE, proph, &nodep, &propp); 15627c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 15637c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 15647c478bd9Sstevel@tonic-gate return (err); 15657c478bd9Sstevel@tonic-gate } else if (nodep == NULL) { 15667c478bd9Sstevel@tonic-gate /* Nothing to do - already deleted! */ 15677c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 15687c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate if (propp->obj_type & PICL_OBJ_TABLEENTRY) { 15727c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 15737c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 15747c478bd9Sstevel@tonic-gate return (PICL_NOTPROP); 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gate err = unlink_prop(nodep, propp); 15787c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 15797c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 15807c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 15817c478bd9Sstevel@tonic-gate return (err); 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate propp->prop_node = NULL; /* reset prop's nodep */ 15857c478bd9Sstevel@tonic-gate propp->next_prop = NULL; 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate unpiclize_prop(propp); 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate unlock_node(nodep); /* Unlock node */ 15907c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 15917c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate /* 15957c478bd9Sstevel@tonic-gate * Create a table object and return its handle 15967c478bd9Sstevel@tonic-gate */ 15977c478bd9Sstevel@tonic-gate int 15987c478bd9Sstevel@tonic-gate ptree_create_table(picl_prophdl_t *tblh) 15997c478bd9Sstevel@tonic-gate { 16007c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate pobj = malloc(sizeof (picl_obj_t)); 16037c478bd9Sstevel@tonic-gate if (pobj == NULL) 16047c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 16057c478bd9Sstevel@tonic-gate pobj->obj_type = PICL_OBJ_TABLE; 16067c478bd9Sstevel@tonic-gate pobj->prop_val = NULL; 16077c478bd9Sstevel@tonic-gate pobj->prop_node = NULL; 16087c478bd9Sstevel@tonic-gate pobj->ptree_hdl = PICL_INVALID_PICLHDL; 16097c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 16107c478bd9Sstevel@tonic-gate pobj->table_prop = NULL; 16117c478bd9Sstevel@tonic-gate pobj->next_row = NULL; 16127c478bd9Sstevel@tonic-gate pobj->next_col = NULL; 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(pobj); 16157c478bd9Sstevel@tonic-gate *tblh = pobj->ptree_hdl; 16167c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* 16207c478bd9Sstevel@tonic-gate * Add the properties in <props> array as a row in the table 16217c478bd9Sstevel@tonic-gate * Add PICL handles if the table has a valid PICL handle 16227c478bd9Sstevel@tonic-gate */ 16237c478bd9Sstevel@tonic-gate int 16247c478bd9Sstevel@tonic-gate ptree_add_row_to_table(picl_prophdl_t tblh, int nprops, 16257c478bd9Sstevel@tonic-gate const picl_prophdl_t *props) 16267c478bd9Sstevel@tonic-gate { 16277c478bd9Sstevel@tonic-gate picl_obj_t *tbl_obj; 16287c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 16297c478bd9Sstevel@tonic-gate picl_obj_t *lastrow; 16307c478bd9Sstevel@tonic-gate picl_obj_t **newrow; 16317c478bd9Sstevel@tonic-gate int i; 16327c478bd9Sstevel@tonic-gate int err; 16337c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 16347c478bd9Sstevel@tonic-gate int picl_it; 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate if (nprops < 1) 16377c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate newrow = malloc(sizeof (picl_obj_t *) * nprops); 16407c478bd9Sstevel@tonic-gate if (newrow == NULL) 16417c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* Lock ptree */ 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate err = lookup_and_lock_tablenode(WRLOCK_NODE, tblh, &nodep, &tbl_obj); 16467c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 16477c478bd9Sstevel@tonic-gate free(newrow); 16487c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 16497c478bd9Sstevel@tonic-gate return (err); 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate /* 16537c478bd9Sstevel@tonic-gate * make sure all are either props or table handles 16547c478bd9Sstevel@tonic-gate */ 16557c478bd9Sstevel@tonic-gate for (i = 0; i < nprops; ++i) { 16567c478bd9Sstevel@tonic-gate pobj = newrow[i] = hash_lookup_obj(&ptreetbl, props[i]); 16577c478bd9Sstevel@tonic-gate if (pobj == NULL) { /* no object */ 16587c478bd9Sstevel@tonic-gate err = ptree_hdl_error(props[i]); 16597c478bd9Sstevel@tonic-gate break; 16607c478bd9Sstevel@tonic-gate } 16617c478bd9Sstevel@tonic-gate if ((!(pobj->obj_type & PICL_OBJ_PROP)) && 16627c478bd9Sstevel@tonic-gate (!(pobj->obj_type & PICL_OBJ_TABLE))) { 16637c478bd9Sstevel@tonic-gate err = PICL_NOTPROP; 16647c478bd9Sstevel@tonic-gate break; 16657c478bd9Sstevel@tonic-gate } 16667c478bd9Sstevel@tonic-gate if (IS_PICLIZED(pobj) || (pobj->prop_table != NULL) || 16677c478bd9Sstevel@tonic-gate (pobj->prop_node != NULL)) { 16687c478bd9Sstevel@tonic-gate err = PICL_INVALIDARG; 16697c478bd9Sstevel@tonic-gate break; 16707c478bd9Sstevel@tonic-gate } 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 16747c478bd9Sstevel@tonic-gate free(newrow); 16757c478bd9Sstevel@tonic-gate unlock_node(nodep); 16767c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock table */ 16777c478bd9Sstevel@tonic-gate return (err); 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate /* 16817c478bd9Sstevel@tonic-gate * Mark all props as table entries, set up row linkages 16827c478bd9Sstevel@tonic-gate */ 16837c478bd9Sstevel@tonic-gate picl_it = 0; 16847c478bd9Sstevel@tonic-gate if (IS_PICLIZED(tbl_obj)) 16857c478bd9Sstevel@tonic-gate picl_it = 1; 16867c478bd9Sstevel@tonic-gate for (i = 0; i < nprops; ++i) { 16877c478bd9Sstevel@tonic-gate newrow[i]->obj_type |= PICL_OBJ_TABLEENTRY; 16887c478bd9Sstevel@tonic-gate newrow[i]->prop_table = tbl_obj; 16897c478bd9Sstevel@tonic-gate newrow[i]->next_prop = NULL; 16907c478bd9Sstevel@tonic-gate newrow[i]->next_col = NULL; 16917c478bd9Sstevel@tonic-gate if (picl_it) 16927c478bd9Sstevel@tonic-gate piclize_obj(newrow[i]); 16937c478bd9Sstevel@tonic-gate if (i != nprops - 1) 16947c478bd9Sstevel@tonic-gate newrow[i]->next_row = newrow[i+1]; 16957c478bd9Sstevel@tonic-gate } 16967c478bd9Sstevel@tonic-gate newrow[nprops - 1]->next_row = NULL; 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate if (tbl_obj->next_row == NULL) { /* add first row */ 16997c478bd9Sstevel@tonic-gate tbl_obj->next_row = newrow[0]; 17007c478bd9Sstevel@tonic-gate tbl_obj->next_col = newrow[0]; 17017c478bd9Sstevel@tonic-gate } else { 17027c478bd9Sstevel@tonic-gate lastrow = tbl_obj->next_row; 17037c478bd9Sstevel@tonic-gate while (lastrow->next_col != NULL) 17047c478bd9Sstevel@tonic-gate lastrow = lastrow->next_col; 17057c478bd9Sstevel@tonic-gate i = 0; 17067c478bd9Sstevel@tonic-gate while (lastrow != NULL) { 17077c478bd9Sstevel@tonic-gate lastrow->next_col = newrow[i]; 17087c478bd9Sstevel@tonic-gate lastrow = lastrow->next_row; 17097c478bd9Sstevel@tonic-gate ++i; 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 17147c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* Unlock ptree */ 17157c478bd9Sstevel@tonic-gate free(newrow); 17167c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 17177c478bd9Sstevel@tonic-gate } 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate /* 17207c478bd9Sstevel@tonic-gate * This function returns the handle of the next property in the row 17217c478bd9Sstevel@tonic-gate */ 17227c478bd9Sstevel@tonic-gate int 17237c478bd9Sstevel@tonic-gate ptree_get_next_by_row(picl_prophdl_t proph, picl_prophdl_t *nextrowh) 17247c478bd9Sstevel@tonic-gate { 17257c478bd9Sstevel@tonic-gate int err; 17267c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 17277c478bd9Sstevel@tonic-gate picl_obj_t *propp; 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate nodep = propp = NULL; 17327c478bd9Sstevel@tonic-gate /* 17337c478bd9Sstevel@tonic-gate * proph could be a table handle or a table entry handle 17347c478bd9Sstevel@tonic-gate * Look it up as a table entry handle first, check error code 17357c478bd9Sstevel@tonic-gate * to see if it is a table handle 17367c478bd9Sstevel@tonic-gate */ 17377c478bd9Sstevel@tonic-gate err = lookup_and_lock_tableprop_node(RDLOCK_NODE, proph, &nodep, 17387c478bd9Sstevel@tonic-gate &propp); 17397c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 17407c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 17417c478bd9Sstevel@tonic-gate return (err); 17427c478bd9Sstevel@tonic-gate } 17437c478bd9Sstevel@tonic-gate 17447c478bd9Sstevel@tonic-gate if (propp->next_row) 17457c478bd9Sstevel@tonic-gate *nextrowh = propp->next_row->ptree_hdl; 17467c478bd9Sstevel@tonic-gate else 17477c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 17507c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 17517c478bd9Sstevel@tonic-gate return (err); 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate int 17557c478bd9Sstevel@tonic-gate ptree_get_next_by_col(picl_prophdl_t proph, picl_prophdl_t *nextcolh) 17567c478bd9Sstevel@tonic-gate { 17577c478bd9Sstevel@tonic-gate int err; 17587c478bd9Sstevel@tonic-gate picl_obj_t *propp; 17597c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 17627c478bd9Sstevel@tonic-gate nodep = propp = NULL; 17637c478bd9Sstevel@tonic-gate /* 17647c478bd9Sstevel@tonic-gate * proph could be a table handle or a table entry handle 17657c478bd9Sstevel@tonic-gate * Look it up as a table entry handle first, check error code 17667c478bd9Sstevel@tonic-gate * to see if it is a table handle 17677c478bd9Sstevel@tonic-gate */ 17687c478bd9Sstevel@tonic-gate err = lookup_and_lock_tableprop_node(RDLOCK_NODE, proph, &nodep, 17697c478bd9Sstevel@tonic-gate &propp); 17707c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 17717c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 17727c478bd9Sstevel@tonic-gate return (err); 17737c478bd9Sstevel@tonic-gate } 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate if (propp->next_col) 17767c478bd9Sstevel@tonic-gate *nextcolh = propp->next_col->ptree_hdl; 17777c478bd9Sstevel@tonic-gate else 17787c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 17797c478bd9Sstevel@tonic-gate 17807c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 17817c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 17827c478bd9Sstevel@tonic-gate return (err); 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate /* 17867c478bd9Sstevel@tonic-gate * This function creates node object and adds its handle to the Ptree 17877c478bd9Sstevel@tonic-gate */ 17887c478bd9Sstevel@tonic-gate int 17897c478bd9Sstevel@tonic-gate ptree_create_node(const char *name, const char *clname, picl_nodehdl_t *nodeh) 17907c478bd9Sstevel@tonic-gate { 17917c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 17927c478bd9Sstevel@tonic-gate ptree_propinfo_t propinfo; 17937c478bd9Sstevel@tonic-gate picl_prophdl_t phdl; 17947c478bd9Sstevel@tonic-gate picl_prophdl_t cphdl; 17957c478bd9Sstevel@tonic-gate int err; 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate if ((name == NULL) || (*name == '\0') || 17987c478bd9Sstevel@tonic-gate (clname == NULL) || (*clname == '\0')) 17997c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate if ((strlen(name) >= PICL_PROPNAMELEN_MAX) || 18027c478bd9Sstevel@tonic-gate (strlen(clname) >= PICL_CLASSNAMELEN_MAX)) 18037c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate /* 18067c478bd9Sstevel@tonic-gate * Create the picl object for node 18077c478bd9Sstevel@tonic-gate */ 18087c478bd9Sstevel@tonic-gate pobj = malloc(sizeof (picl_obj_t)); 18097c478bd9Sstevel@tonic-gate if (pobj == NULL) 18107c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 18117c478bd9Sstevel@tonic-gate pobj->obj_type = PICL_OBJ_NODE; 18127c478bd9Sstevel@tonic-gate pobj->first_prop = NULL; 18137c478bd9Sstevel@tonic-gate pobj->ptree_hdl = PICL_INVALID_PICLHDL; 18147c478bd9Sstevel@tonic-gate pobj->picl_hdl = PICL_INVALID_PICLHDL; 18157c478bd9Sstevel@tonic-gate pobj->parent_node = NULL; 18167c478bd9Sstevel@tonic-gate pobj->sibling_node = NULL; 18177c478bd9Sstevel@tonic-gate pobj->child_node = NULL; 18187c478bd9Sstevel@tonic-gate pobj->node_classname = strdup(clname); 18197c478bd9Sstevel@tonic-gate if (pobj->node_classname == NULL) { 18207c478bd9Sstevel@tonic-gate free(pobj); 18217c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 18227c478bd9Sstevel@tonic-gate } 18237c478bd9Sstevel@tonic-gate (void) rwlock_init(&pobj->node_lock, USYNC_THREAD, NULL); 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate alloc_and_add_to_ptree(pobj); /* commit the node */ 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate /* 18287c478bd9Sstevel@tonic-gate * create name property 18297c478bd9Sstevel@tonic-gate */ 18307c478bd9Sstevel@tonic-gate propinfo.version = PTREE_PROPINFO_VERSION_1; 18317c478bd9Sstevel@tonic-gate propinfo.piclinfo.type = PICL_PTYPE_CHARSTRING; 18327c478bd9Sstevel@tonic-gate propinfo.piclinfo.accessmode = PICL_READ; 18337c478bd9Sstevel@tonic-gate propinfo.piclinfo.size = strlen(name) + 1; 18347c478bd9Sstevel@tonic-gate (void) strcpy(propinfo.piclinfo.name, PICL_PROP_NAME); 18357c478bd9Sstevel@tonic-gate propinfo.read = NULL; 18367c478bd9Sstevel@tonic-gate propinfo.write = NULL; 18377c478bd9Sstevel@tonic-gate err = ptree_create_prop(&propinfo, (const void *)name, &phdl); 18387c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18397c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 18407c478bd9Sstevel@tonic-gate return (err); 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate err = ptree_add_prop(pobj->ptree_hdl, phdl); 18437c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18447c478bd9Sstevel@tonic-gate (void) ptree_destroy_prop(phdl); 18457c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 18467c478bd9Sstevel@tonic-gate return (err); 18477c478bd9Sstevel@tonic-gate } 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate /* 18507c478bd9Sstevel@tonic-gate * create picl classname property 18517c478bd9Sstevel@tonic-gate */ 18527c478bd9Sstevel@tonic-gate propinfo.piclinfo.size = strlen(clname) + 1; 18537c478bd9Sstevel@tonic-gate (void) strcpy(propinfo.piclinfo.name, PICL_PROP_CLASSNAME); 18547c478bd9Sstevel@tonic-gate propinfo.read = NULL; 18557c478bd9Sstevel@tonic-gate propinfo.write = NULL; 18567c478bd9Sstevel@tonic-gate err = ptree_create_prop(&propinfo, (const void *)clname, &cphdl); 18577c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18587c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 18597c478bd9Sstevel@tonic-gate return (err); 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate err = ptree_add_prop(pobj->ptree_hdl, cphdl); 18627c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18637c478bd9Sstevel@tonic-gate (void) ptree_destroy_prop(cphdl); 18647c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(pobj->ptree_hdl); 18657c478bd9Sstevel@tonic-gate return (err); 18667c478bd9Sstevel@tonic-gate } 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate *nodeh = pobj->ptree_hdl; 18697c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 18707c478bd9Sstevel@tonic-gate } 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate /* 18737c478bd9Sstevel@tonic-gate * Destroy a node/subtree freeing up space 18747c478bd9Sstevel@tonic-gate * Removed destroyed objects' handles from PTree table 18757c478bd9Sstevel@tonic-gate */ 18767c478bd9Sstevel@tonic-gate static void 18777c478bd9Sstevel@tonic-gate destroy_subtree(picl_obj_t *nodep) 18787c478bd9Sstevel@tonic-gate { 18797c478bd9Sstevel@tonic-gate picl_obj_t *iterp; 18807c478bd9Sstevel@tonic-gate picl_obj_t *freep; 18817c478bd9Sstevel@tonic-gate picl_obj_t *chdp; 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate if (nodep == NULL) 18847c478bd9Sstevel@tonic-gate return; 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate chdp = nodep->child_node; 18877c478bd9Sstevel@tonic-gate while (chdp != NULL) { 18887c478bd9Sstevel@tonic-gate freep = chdp; 18897c478bd9Sstevel@tonic-gate chdp = chdp->sibling_node; 18907c478bd9Sstevel@tonic-gate destroy_subtree(freep); 18917c478bd9Sstevel@tonic-gate } 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate /* 18947c478bd9Sstevel@tonic-gate * Lock the node 18957c478bd9Sstevel@tonic-gate */ 18967c478bd9Sstevel@tonic-gate (void) lock_obj(WRLOCK_NODE, nodep); 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate /* 18997c478bd9Sstevel@tonic-gate * destroy all properties associated with this node 19007c478bd9Sstevel@tonic-gate */ 19017c478bd9Sstevel@tonic-gate iterp = nodep->first_prop; 19027c478bd9Sstevel@tonic-gate while (iterp != NULL) { 19037c478bd9Sstevel@tonic-gate freep = iterp; 19047c478bd9Sstevel@tonic-gate iterp = iterp->next_prop; 19057c478bd9Sstevel@tonic-gate destroy_propobj(freep); 19067c478bd9Sstevel@tonic-gate } 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate (void) hash_remove(&ptreetbl, nodep->ptree_hdl); 19097c478bd9Sstevel@tonic-gate (void) rwlock_destroy(&nodep->node_lock); 19107c478bd9Sstevel@tonic-gate free(nodep->node_classname); 19117c478bd9Sstevel@tonic-gate free(nodep); 19127c478bd9Sstevel@tonic-gate } 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate /* 19157c478bd9Sstevel@tonic-gate * This function destroys a previously deleted node/subtree. All the properties 19167c478bd9Sstevel@tonic-gate * are freed and removed from the PTree table. 19177c478bd9Sstevel@tonic-gate * Only one destroy is in progress at any time. 19187c478bd9Sstevel@tonic-gate */ 19197c478bd9Sstevel@tonic-gate int 19207c478bd9Sstevel@tonic-gate ptree_destroy_node(picl_nodehdl_t nodeh) 19217c478bd9Sstevel@tonic-gate { 19227c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 19237c478bd9Sstevel@tonic-gate picl_obj_t *parp; 19247c478bd9Sstevel@tonic-gate picl_obj_t *np; 19257c478bd9Sstevel@tonic-gate int err; 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* exclusive wrlock ptree */ 19287c478bd9Sstevel@tonic-gate nodep = NULL; 19297c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(nodeh, &nodep); 19307c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 19317c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 19327c478bd9Sstevel@tonic-gate return (err); 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate /* 19367c478bd9Sstevel@tonic-gate * Has this node/subtree been deleted? 19377c478bd9Sstevel@tonic-gate */ 19387c478bd9Sstevel@tonic-gate if (IS_PICLIZED(nodep)) { 19397c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 19407c478bd9Sstevel@tonic-gate return (PICL_CANTDESTROY); 19417c478bd9Sstevel@tonic-gate } 19427c478bd9Sstevel@tonic-gate 19437c478bd9Sstevel@tonic-gate /* 19447c478bd9Sstevel@tonic-gate * update parent's child list to repair the tree when 19457c478bd9Sstevel@tonic-gate * parent is not null 19467c478bd9Sstevel@tonic-gate */ 19477c478bd9Sstevel@tonic-gate parp = nodep->parent_node; 19487c478bd9Sstevel@tonic-gate if (parp == NULL) { /* root */ 19497c478bd9Sstevel@tonic-gate destroy_subtree(nodep); 19507c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 19517c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 19527c478bd9Sstevel@tonic-gate } 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate np = parp->child_node; 19557c478bd9Sstevel@tonic-gate if (np == nodep) { /* first child */ 19567c478bd9Sstevel@tonic-gate parp->child_node = nodep->sibling_node; 19577c478bd9Sstevel@tonic-gate } else { 19587c478bd9Sstevel@tonic-gate while ((np != NULL) && (np->sibling_node != nodep)) 19597c478bd9Sstevel@tonic-gate np = np->sibling_node; 19607c478bd9Sstevel@tonic-gate if (np != NULL) 19617c478bd9Sstevel@tonic-gate np->sibling_node = nodep->sibling_node; 19627c478bd9Sstevel@tonic-gate } 19637c478bd9Sstevel@tonic-gate 19647c478bd9Sstevel@tonic-gate destroy_subtree(nodep); 19657c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 19667c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 19677c478bd9Sstevel@tonic-gate } 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate /* 19707c478bd9Sstevel@tonic-gate * This function deletes a node/subtree from the tree and removes the handles 19717c478bd9Sstevel@tonic-gate * from PICL table 19727c478bd9Sstevel@tonic-gate */ 19737c478bd9Sstevel@tonic-gate int 19747c478bd9Sstevel@tonic-gate ptree_delete_node(picl_nodehdl_t nodeh) 19757c478bd9Sstevel@tonic-gate { 19767c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 19777c478bd9Sstevel@tonic-gate picl_obj_t *parp; 19787c478bd9Sstevel@tonic-gate picl_obj_t *np; 19797c478bd9Sstevel@tonic-gate int err; 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* exclusive wrlock ptree */ 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate nodep = NULL; 19847c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(nodeh, &nodep); 19857c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 19867c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 19877c478bd9Sstevel@tonic-gate return (err); 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate 19907c478bd9Sstevel@tonic-gate /* 19917c478bd9Sstevel@tonic-gate * unparent it 19927c478bd9Sstevel@tonic-gate */ 19937c478bd9Sstevel@tonic-gate parp = nodep->parent_node; 19947c478bd9Sstevel@tonic-gate if (parp != NULL) { 19957c478bd9Sstevel@tonic-gate np = parp->child_node; 19967c478bd9Sstevel@tonic-gate if (np == nodep) /* first child */ 19977c478bd9Sstevel@tonic-gate parp->child_node = nodep->sibling_node; 19987c478bd9Sstevel@tonic-gate else { 19997c478bd9Sstevel@tonic-gate while ((np != NULL) && (np->sibling_node != nodep)) 20007c478bd9Sstevel@tonic-gate np = np->sibling_node; 20017c478bd9Sstevel@tonic-gate if (np != NULL) 20027c478bd9Sstevel@tonic-gate np->sibling_node = nodep->sibling_node; 20037c478bd9Sstevel@tonic-gate } 20047c478bd9Sstevel@tonic-gate } 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate nodep->parent_node = NULL; 20077c478bd9Sstevel@tonic-gate nodep->sibling_node = NULL; 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate unpiclize_node(nodep); 20107c478bd9Sstevel@tonic-gate 20117c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 20127c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 20137c478bd9Sstevel@tonic-gate } 20147c478bd9Sstevel@tonic-gate 20157c478bd9Sstevel@tonic-gate /* 20167c478bd9Sstevel@tonic-gate * This function adds a node as a child of another node 20177c478bd9Sstevel@tonic-gate */ 20187c478bd9Sstevel@tonic-gate int 20197c478bd9Sstevel@tonic-gate ptree_add_node(picl_nodehdl_t parh, picl_nodehdl_t chdh) 20207c478bd9Sstevel@tonic-gate { 20217c478bd9Sstevel@tonic-gate picl_obj_t *pnodep; 20227c478bd9Sstevel@tonic-gate picl_obj_t *cnodep; 20237c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 20247c478bd9Sstevel@tonic-gate int err; 20257c478bd9Sstevel@tonic-gate 20267c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); /* exclusive lock ptree */ 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate pnodep = cnodep = NULL; 20297c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(parh, &pnodep); 20307c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 20317c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 20327c478bd9Sstevel@tonic-gate return (err); 20337c478bd9Sstevel@tonic-gate } 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate err = lookup_verify_node_handle(chdh, &cnodep); 20367c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 20377c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 20387c478bd9Sstevel@tonic-gate return (err); 20397c478bd9Sstevel@tonic-gate } 20407c478bd9Sstevel@tonic-gate 20417c478bd9Sstevel@tonic-gate /* is chdh already a child? */ 20427c478bd9Sstevel@tonic-gate if (cnodep->parent_node != NULL) { 20437c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 20447c478bd9Sstevel@tonic-gate return (PICL_CANTPARENT); 20457c478bd9Sstevel@tonic-gate } 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate /* 20487c478bd9Sstevel@tonic-gate * append child to children list 20497c478bd9Sstevel@tonic-gate */ 20507c478bd9Sstevel@tonic-gate cnodep->parent_node = pnodep; 20517c478bd9Sstevel@tonic-gate if (pnodep->child_node == NULL) 20527c478bd9Sstevel@tonic-gate pnodep->child_node = cnodep; 20537c478bd9Sstevel@tonic-gate else { 20547c478bd9Sstevel@tonic-gate for (nodep = pnodep->child_node; nodep->sibling_node != NULL; 20557c478bd9Sstevel@tonic-gate nodep = nodep->sibling_node) 20567c478bd9Sstevel@tonic-gate continue; 20577c478bd9Sstevel@tonic-gate nodep->sibling_node = cnodep; 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate 20617c478bd9Sstevel@tonic-gate /* piclize */ 20627c478bd9Sstevel@tonic-gate if (IS_PICLIZED(pnodep)) 20637c478bd9Sstevel@tonic-gate piclize_node(cnodep); 20647c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 20657c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 20667c478bd9Sstevel@tonic-gate } 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate static void 20697c478bd9Sstevel@tonic-gate copy_propinfo_ver_1(ptree_propinfo_t *pinfo, picl_obj_t *propp) 20707c478bd9Sstevel@tonic-gate { 20717c478bd9Sstevel@tonic-gate pinfo->version = propp->pinfo_ver; 20727c478bd9Sstevel@tonic-gate pinfo->piclinfo.type = propp->prop_type; 20737c478bd9Sstevel@tonic-gate pinfo->piclinfo.accessmode = propp->prop_mode; 20747c478bd9Sstevel@tonic-gate pinfo->piclinfo.size = propp->prop_size; 20757c478bd9Sstevel@tonic-gate (void) strcpy(pinfo->piclinfo.name, propp->prop_name); 20767c478bd9Sstevel@tonic-gate pinfo->read = propp->read_func; 20777c478bd9Sstevel@tonic-gate pinfo->write = propp->write_func; 20787c478bd9Sstevel@tonic-gate } 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate static void 20817c478bd9Sstevel@tonic-gate copy_reserved_propinfo_ver_1(ptree_propinfo_t *pinfo, const char *pname) 20827c478bd9Sstevel@tonic-gate { 20837c478bd9Sstevel@tonic-gate pinfo->version = PTREE_PROPINFO_VERSION_1; 20847c478bd9Sstevel@tonic-gate pinfo->piclinfo.type = PICL_PTYPE_REFERENCE; 20857c478bd9Sstevel@tonic-gate pinfo->piclinfo.accessmode = PICL_READ; 20867c478bd9Sstevel@tonic-gate pinfo->piclinfo.size = sizeof (picl_nodehdl_t); 20877c478bd9Sstevel@tonic-gate (void) strcpy(pinfo->piclinfo.name, pname); 20887c478bd9Sstevel@tonic-gate pinfo->read = NULL; 20897c478bd9Sstevel@tonic-gate pinfo->write = NULL; 20907c478bd9Sstevel@tonic-gate } 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate /* 20937c478bd9Sstevel@tonic-gate * This function returns the property information to a plug-in 20947c478bd9Sstevel@tonic-gate */ 20957c478bd9Sstevel@tonic-gate int 20967c478bd9Sstevel@tonic-gate ptree_get_propinfo(picl_prophdl_t proph, ptree_propinfo_t *pinfo) 20977c478bd9Sstevel@tonic-gate { 20987c478bd9Sstevel@tonic-gate int err; 20997c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 21007c478bd9Sstevel@tonic-gate picl_obj_t *propp; 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 21037c478bd9Sstevel@tonic-gate nodep = propp = NULL; 21047c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp); 21057c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 21067c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 21077c478bd9Sstevel@tonic-gate return (err); 21087c478bd9Sstevel@tonic-gate } 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate if (propp->pinfo_ver == PTREE_PROPINFO_VERSION_1) 21117c478bd9Sstevel@tonic-gate copy_propinfo_ver_1(pinfo, propp); 21127c478bd9Sstevel@tonic-gate else 21137c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 21167c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 21177c478bd9Sstevel@tonic-gate return (err); 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate /* 21217c478bd9Sstevel@tonic-gate * This function returns the property information to a plug-in 21227c478bd9Sstevel@tonic-gate */ 21237c478bd9Sstevel@tonic-gate int 21247c478bd9Sstevel@tonic-gate xptree_get_propinfo_by_name(picl_nodehdl_t nodeh, const char *pname, 21257c478bd9Sstevel@tonic-gate ptree_propinfo_t *pinfo) 21267c478bd9Sstevel@tonic-gate { 21277c478bd9Sstevel@tonic-gate int err; 21287c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 21297c478bd9Sstevel@tonic-gate picl_obj_t *propp; 21307c478bd9Sstevel@tonic-gate 21317c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 21327c478bd9Sstevel@tonic-gate nodep = propp = NULL; 21337c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep); /* lock node */ 21347c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 21357c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 21367c478bd9Sstevel@tonic-gate return (err); 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 21407c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 21417c478bd9Sstevel@tonic-gate unlock_node(nodep); 21427c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 21437c478bd9Sstevel@tonic-gate return (err); 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) 21477c478bd9Sstevel@tonic-gate copy_reserved_propinfo_ver_1(pinfo, pname); 21487c478bd9Sstevel@tonic-gate else if (propp->pinfo_ver == PTREE_PROPINFO_VERSION_1) 21497c478bd9Sstevel@tonic-gate copy_propinfo_ver_1(pinfo, propp); 21507c478bd9Sstevel@tonic-gate else 21517c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 21547c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 21557c478bd9Sstevel@tonic-gate return (err); 21567c478bd9Sstevel@tonic-gate } 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate /* 21597c478bd9Sstevel@tonic-gate * This function must be called only after a lookup_prop_by_name() returns 21607c478bd9Sstevel@tonic-gate * success and only if picl_restricted() returns true. 21617c478bd9Sstevel@tonic-gate */ 21627c478bd9Sstevel@tonic-gate static int 21637c478bd9Sstevel@tonic-gate read_reserved_propval_and_unlock(picl_obj_t *nodep, const char *pname, 21647c478bd9Sstevel@tonic-gate void *vbuf, size_t size) 21657c478bd9Sstevel@tonic-gate { 21667c478bd9Sstevel@tonic-gate void *srcp; 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate if (size != sizeof (picl_nodehdl_t)) 21697c478bd9Sstevel@tonic-gate return (PICL_VALUETOOBIG); 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate if (strcmp(pname, PICL_PROP_PARENT) == 0) 21727c478bd9Sstevel@tonic-gate srcp = &nodep->parent_node->ptree_hdl; 21737c478bd9Sstevel@tonic-gate else if (strcmp(pname, PICL_PROP_CHILD) == 0) 21747c478bd9Sstevel@tonic-gate srcp = &nodep->child_node->ptree_hdl; 21757c478bd9Sstevel@tonic-gate else if (strcmp(pname, PICL_PROP_PEER) == 0) 21767c478bd9Sstevel@tonic-gate srcp = &nodep->sibling_node->ptree_hdl; 21777c478bd9Sstevel@tonic-gate else 21787c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate (void) memcpy(vbuf, srcp, sizeof (picl_nodehdl_t)); 21817c478bd9Sstevel@tonic-gate unlock_node(nodep); 21827c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 21837c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 21847c478bd9Sstevel@tonic-gate } 21857c478bd9Sstevel@tonic-gate 21867c478bd9Sstevel@tonic-gate /* 21877c478bd9Sstevel@tonic-gate * Returns the property value in the buffer and releases the node and 21887c478bd9Sstevel@tonic-gate * ptree locks. 21897c478bd9Sstevel@tonic-gate * For volatile properties, this function releases the locks on ptree 21907c478bd9Sstevel@tonic-gate * table and the node before calling the plug-in provided access function 21917c478bd9Sstevel@tonic-gate */ 21927c478bd9Sstevel@tonic-gate static int 21937c478bd9Sstevel@tonic-gate read_propval_and_unlock(picl_obj_t *nodep, picl_obj_t *propp, void *vbuf, 21947c478bd9Sstevel@tonic-gate door_cred_t cred) 21957c478bd9Sstevel@tonic-gate { 21967c478bd9Sstevel@tonic-gate int err; 21977c478bd9Sstevel@tonic-gate int (*volrd)(ptree_rarg_t *arg, void *buf); 21987c478bd9Sstevel@tonic-gate 21997c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 22007c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) { 22017c478bd9Sstevel@tonic-gate ptree_rarg_t rarg; 22027c478bd9Sstevel@tonic-gate 22037c478bd9Sstevel@tonic-gate if (nodep) 22047c478bd9Sstevel@tonic-gate rarg.nodeh = nodep->ptree_hdl; 22057c478bd9Sstevel@tonic-gate else 22067c478bd9Sstevel@tonic-gate rarg.nodeh = PICL_INVALID_PICLHDL; 22077c478bd9Sstevel@tonic-gate rarg.proph = propp->ptree_hdl; 22087c478bd9Sstevel@tonic-gate rarg.cred = cred; 22097c478bd9Sstevel@tonic-gate volrd = propp->read_func; 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 22127c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate if (volrd == NULL) 22157c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 22167c478bd9Sstevel@tonic-gate else 22177c478bd9Sstevel@tonic-gate err = (volrd)(&rarg, vbuf); 22187c478bd9Sstevel@tonic-gate return (err); 22197c478bd9Sstevel@tonic-gate } else if (propp->prop_type == PICL_PTYPE_CHARSTRING) 22207c478bd9Sstevel@tonic-gate (void) strlcpy(vbuf, propp->prop_val, propp->prop_size); 22217c478bd9Sstevel@tonic-gate else 22227c478bd9Sstevel@tonic-gate (void) memcpy(vbuf, propp->prop_val, propp->prop_size); 22237c478bd9Sstevel@tonic-gate 22247c478bd9Sstevel@tonic-gate unlock_node(nodep); 22257c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 22267c478bd9Sstevel@tonic-gate return (err); 22277c478bd9Sstevel@tonic-gate } 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate int 22307c478bd9Sstevel@tonic-gate xptree_get_propval_with_cred(picl_prophdl_t proph, void *vbuf, size_t size, 22317c478bd9Sstevel@tonic-gate door_cred_t cred) 22327c478bd9Sstevel@tonic-gate { 22337c478bd9Sstevel@tonic-gate picl_obj_t *propp; 22347c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 22357c478bd9Sstevel@tonic-gate int err; 22367c478bd9Sstevel@tonic-gate 22377c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 22387c478bd9Sstevel@tonic-gate nodep = propp = NULL; 22397c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp); 22407c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 22417c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 22427c478bd9Sstevel@tonic-gate return (err); 22437c478bd9Sstevel@tonic-gate } 22447c478bd9Sstevel@tonic-gate 22457c478bd9Sstevel@tonic-gate err = check_propsize(PROP_READ, propp, size); 22467c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 22477c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 22487c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 22497c478bd9Sstevel@tonic-gate return (err); 22507c478bd9Sstevel@tonic-gate } 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate return (read_propval_and_unlock(nodep, propp, vbuf, cred)); 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate /* 22567c478bd9Sstevel@tonic-gate * This function gets the credentials and calls get_propval_with_cred. 22577c478bd9Sstevel@tonic-gate */ 22587c478bd9Sstevel@tonic-gate int 22597c478bd9Sstevel@tonic-gate ptree_get_propval(picl_prophdl_t proph, void *vbuf, size_t size) 22607c478bd9Sstevel@tonic-gate { 22617c478bd9Sstevel@tonic-gate return (xptree_get_propval_with_cred(proph, vbuf, size, picld_cred)); 22627c478bd9Sstevel@tonic-gate } 22637c478bd9Sstevel@tonic-gate 22647c478bd9Sstevel@tonic-gate /* 22657c478bd9Sstevel@tonic-gate * This function retrieves a property's value by by its name 22667c478bd9Sstevel@tonic-gate * For volatile properties, the locks on ptree and node are released 22677c478bd9Sstevel@tonic-gate * before calling the plug-in provided access function 22687c478bd9Sstevel@tonic-gate */ 22697c478bd9Sstevel@tonic-gate int 22707c478bd9Sstevel@tonic-gate xptree_get_propval_by_name_with_cred(picl_nodehdl_t nodeh, const char *pname, 22717c478bd9Sstevel@tonic-gate void *vbuf, size_t size, door_cred_t cred) 22727c478bd9Sstevel@tonic-gate { 22737c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 22747c478bd9Sstevel@tonic-gate picl_obj_t *propp; 22757c478bd9Sstevel@tonic-gate int err; 22767c478bd9Sstevel@tonic-gate 22777c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 22787c478bd9Sstevel@tonic-gate 22797c478bd9Sstevel@tonic-gate nodep = NULL; 22807c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep); /* lock node */ 22817c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 22827c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 22837c478bd9Sstevel@tonic-gate return (err); 22847c478bd9Sstevel@tonic-gate } 22857c478bd9Sstevel@tonic-gate 22867c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 22877c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 22887c478bd9Sstevel@tonic-gate unlock_node(nodep); 22897c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 22907c478bd9Sstevel@tonic-gate return (err); 22917c478bd9Sstevel@tonic-gate } 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) 22947c478bd9Sstevel@tonic-gate return (read_reserved_propval_and_unlock(nodep, pname, vbuf, 22957c478bd9Sstevel@tonic-gate size)); 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate err = check_propsize(PROP_READ, propp, size); 22987c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 22997c478bd9Sstevel@tonic-gate unlock_node(nodep); 23007c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 23017c478bd9Sstevel@tonic-gate return (err); 23027c478bd9Sstevel@tonic-gate } 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate return (read_propval_and_unlock(nodep, propp, vbuf, cred)); 23057c478bd9Sstevel@tonic-gate } 23067c478bd9Sstevel@tonic-gate 23077c478bd9Sstevel@tonic-gate /* 23087c478bd9Sstevel@tonic-gate * This function is used by plugins to get a value of a property 23097c478bd9Sstevel@tonic-gate * looking it up by its name. 23107c478bd9Sstevel@tonic-gate */ 23117c478bd9Sstevel@tonic-gate int 23127c478bd9Sstevel@tonic-gate ptree_get_propval_by_name(picl_nodehdl_t nodeh, const char *pname, void *vbuf, 23137c478bd9Sstevel@tonic-gate size_t size) 23147c478bd9Sstevel@tonic-gate { 23157c478bd9Sstevel@tonic-gate return (xptree_get_propval_by_name_with_cred(nodeh, pname, vbuf, size, 23167c478bd9Sstevel@tonic-gate picld_cred)); 23177c478bd9Sstevel@tonic-gate } 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate /* 23207c478bd9Sstevel@tonic-gate * This function updates a property's value. 23217c478bd9Sstevel@tonic-gate * For volatile properties, the locks on the node and the ptree table 23227c478bd9Sstevel@tonic-gate * are released before calling the plug-in provided access function. 23237c478bd9Sstevel@tonic-gate */ 23247c478bd9Sstevel@tonic-gate static int 23257c478bd9Sstevel@tonic-gate write_propval_and_unlock(picl_obj_t *nodep, picl_obj_t *propp, const void *vbuf, 23267c478bd9Sstevel@tonic-gate size_t size, door_cred_t cred) 23277c478bd9Sstevel@tonic-gate { 23287c478bd9Sstevel@tonic-gate int err; 23297c478bd9Sstevel@tonic-gate int (*volwr)(ptree_warg_t *arg, const void *buf); 23307c478bd9Sstevel@tonic-gate 23317c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 23327c478bd9Sstevel@tonic-gate if (propp->prop_mode & PICL_VOLATILE) { 23337c478bd9Sstevel@tonic-gate ptree_warg_t warg; 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate if (nodep) 23367c478bd9Sstevel@tonic-gate warg.nodeh = nodep->ptree_hdl; 23377c478bd9Sstevel@tonic-gate else 23387c478bd9Sstevel@tonic-gate warg.nodeh = PICL_INVALID_PICLHDL; 23397c478bd9Sstevel@tonic-gate warg.proph = propp->ptree_hdl; 23407c478bd9Sstevel@tonic-gate warg.cred = cred; 23417c478bd9Sstevel@tonic-gate volwr = propp->write_func; 23427c478bd9Sstevel@tonic-gate 23437c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 23447c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate if (volwr == NULL) 23477c478bd9Sstevel@tonic-gate err = PICL_FAILURE; 23487c478bd9Sstevel@tonic-gate else 23497c478bd9Sstevel@tonic-gate err = (volwr)(&warg, vbuf); 23507c478bd9Sstevel@tonic-gate return (err); 23517c478bd9Sstevel@tonic-gate } else 23527c478bd9Sstevel@tonic-gate (void) memcpy(propp->prop_val, vbuf, size); 23537c478bd9Sstevel@tonic-gate 23547c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 23557c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 23567c478bd9Sstevel@tonic-gate return (err); 23577c478bd9Sstevel@tonic-gate } 23587c478bd9Sstevel@tonic-gate 23597c478bd9Sstevel@tonic-gate int 23607c478bd9Sstevel@tonic-gate xptree_update_propval_with_cred(picl_prophdl_t proph, const void *vbuf, 23617c478bd9Sstevel@tonic-gate size_t size, door_cred_t cred) 23627c478bd9Sstevel@tonic-gate { 23637c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 23647c478bd9Sstevel@tonic-gate picl_obj_t *propp; 23657c478bd9Sstevel@tonic-gate int err; 23667c478bd9Sstevel@tonic-gate 23677c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 23687c478bd9Sstevel@tonic-gate nodep = propp = NULL; 23697c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(WRLOCK_NODE, proph, &nodep, &propp); 23707c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 23717c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 23727c478bd9Sstevel@tonic-gate return (err); 23737c478bd9Sstevel@tonic-gate } 23747c478bd9Sstevel@tonic-gate 23757c478bd9Sstevel@tonic-gate err = check_propsize(PROP_WRITE, propp, size); 23767c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 23777c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 23787c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 23797c478bd9Sstevel@tonic-gate return (err); 23807c478bd9Sstevel@tonic-gate } 23817c478bd9Sstevel@tonic-gate 23827c478bd9Sstevel@tonic-gate return (write_propval_and_unlock(nodep, propp, vbuf, size, cred)); 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate /* 23867c478bd9Sstevel@tonic-gate * Ptree function used by plug-ins to update a property's value 23877c478bd9Sstevel@tonic-gate * calls update_propval_with_cred(), which releases locks for volatile props 23887c478bd9Sstevel@tonic-gate */ 23897c478bd9Sstevel@tonic-gate int 23907c478bd9Sstevel@tonic-gate ptree_update_propval(picl_prophdl_t proph, const void *vbuf, size_t size) 23917c478bd9Sstevel@tonic-gate { 23927c478bd9Sstevel@tonic-gate return (xptree_update_propval_with_cred(proph, vbuf, size, picld_cred)); 23937c478bd9Sstevel@tonic-gate } 23947c478bd9Sstevel@tonic-gate 23957c478bd9Sstevel@tonic-gate /* 23967c478bd9Sstevel@tonic-gate * This function writes/updates a property's value by looking it up 23977c478bd9Sstevel@tonic-gate * by its name. 23987c478bd9Sstevel@tonic-gate * For volatile properties this function releases the locks on the 23997c478bd9Sstevel@tonic-gate * node and the ptree table. 24007c478bd9Sstevel@tonic-gate */ 24017c478bd9Sstevel@tonic-gate int 24027c478bd9Sstevel@tonic-gate xptree_update_propval_by_name_with_cred(picl_nodehdl_t nodeh, const char *pname, 24037c478bd9Sstevel@tonic-gate const void *vbuf, size_t size, door_cred_t cred) 24047c478bd9Sstevel@tonic-gate { 24057c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 24067c478bd9Sstevel@tonic-gate picl_obj_t *propp; 24077c478bd9Sstevel@tonic-gate int err; 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 24107c478bd9Sstevel@tonic-gate nodep = NULL; 24117c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(WRLOCK_NODE, nodeh, &nodep); /* lock node */ 24127c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24137c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 24147c478bd9Sstevel@tonic-gate return (err); 24157c478bd9Sstevel@tonic-gate } 24167c478bd9Sstevel@tonic-gate 24177c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) { 24187c478bd9Sstevel@tonic-gate unlock_node(nodep); 24197c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 24207c478bd9Sstevel@tonic-gate return (PICL_RESERVEDNAME); 24217c478bd9Sstevel@tonic-gate } 24227c478bd9Sstevel@tonic-gate 24237c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 24247c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24257c478bd9Sstevel@tonic-gate unlock_node(nodep); 24267c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 24277c478bd9Sstevel@tonic-gate return (err); 24287c478bd9Sstevel@tonic-gate } 24297c478bd9Sstevel@tonic-gate 24307c478bd9Sstevel@tonic-gate err = check_propsize(PROP_WRITE, propp, size); 24317c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24327c478bd9Sstevel@tonic-gate unlock_node(nodep); 24337c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 24347c478bd9Sstevel@tonic-gate return (err); 24357c478bd9Sstevel@tonic-gate } 24367c478bd9Sstevel@tonic-gate 24377c478bd9Sstevel@tonic-gate return (write_propval_and_unlock(nodep, propp, vbuf, size, cred)); 24387c478bd9Sstevel@tonic-gate } 24397c478bd9Sstevel@tonic-gate 24407c478bd9Sstevel@tonic-gate /* 24417c478bd9Sstevel@tonic-gate * This function updates the value of a property specified by its name 24427c478bd9Sstevel@tonic-gate */ 24437c478bd9Sstevel@tonic-gate int 24447c478bd9Sstevel@tonic-gate ptree_update_propval_by_name(picl_nodehdl_t nodeh, const char *pname, 24457c478bd9Sstevel@tonic-gate const void *vbuf, size_t size) 24467c478bd9Sstevel@tonic-gate { 24477c478bd9Sstevel@tonic-gate return (xptree_update_propval_by_name_with_cred(nodeh, pname, vbuf, 24487c478bd9Sstevel@tonic-gate size, picld_cred)); 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate /* 24527c478bd9Sstevel@tonic-gate * This function retrieves the handle of a property by its name 24537c478bd9Sstevel@tonic-gate */ 24547c478bd9Sstevel@tonic-gate int 24557c478bd9Sstevel@tonic-gate ptree_get_prop_by_name(picl_nodehdl_t nodeh, const char *pname, 24567c478bd9Sstevel@tonic-gate picl_prophdl_t *proph) 24577c478bd9Sstevel@tonic-gate { 24587c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 24597c478bd9Sstevel@tonic-gate picl_obj_t *propp; 24607c478bd9Sstevel@tonic-gate int err; 24617c478bd9Sstevel@tonic-gate 24627c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 24637c478bd9Sstevel@tonic-gate nodep = NULL; 24647c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep); /* lock node */ 24657c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24667c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 24677c478bd9Sstevel@tonic-gate return (err); 24687c478bd9Sstevel@tonic-gate } 24697c478bd9Sstevel@tonic-gate 24707c478bd9Sstevel@tonic-gate if (picl_restricted(pname)) { 24717c478bd9Sstevel@tonic-gate err = PICL_RESERVEDNAME; 24727c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 24737c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 24747c478bd9Sstevel@tonic-gate return (err); 24757c478bd9Sstevel@tonic-gate } 24767c478bd9Sstevel@tonic-gate 24777c478bd9Sstevel@tonic-gate err = lookup_prop_by_name(nodep, pname, &propp); 24787c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) 24797c478bd9Sstevel@tonic-gate *proph = propp->ptree_hdl; 24807c478bd9Sstevel@tonic-gate 24817c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 24827c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 24837c478bd9Sstevel@tonic-gate return (err); 24847c478bd9Sstevel@tonic-gate } 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate /* 24877c478bd9Sstevel@tonic-gate * This function returns the handle of the first property 24887c478bd9Sstevel@tonic-gate */ 24897c478bd9Sstevel@tonic-gate int 24907c478bd9Sstevel@tonic-gate ptree_get_first_prop(picl_nodehdl_t nodeh, picl_prophdl_t *proph) 24917c478bd9Sstevel@tonic-gate { 24927c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 24937c478bd9Sstevel@tonic-gate int err; 24947c478bd9Sstevel@tonic-gate 24957c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 24967c478bd9Sstevel@tonic-gate pobj = NULL; 24977c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &pobj); /* lock node */ 24987c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24997c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 25007c478bd9Sstevel@tonic-gate return (err); 25017c478bd9Sstevel@tonic-gate } 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate if (pobj->first_prop) 25047c478bd9Sstevel@tonic-gate *proph = pobj->first_prop->ptree_hdl; 25057c478bd9Sstevel@tonic-gate else 25067c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate unlock_node(pobj); /* unlock node */ 25097c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 25107c478bd9Sstevel@tonic-gate return (err); 25117c478bd9Sstevel@tonic-gate } 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate /* 25147c478bd9Sstevel@tonic-gate * This function returns the handle of next property in the list 25157c478bd9Sstevel@tonic-gate */ 25167c478bd9Sstevel@tonic-gate int 25177c478bd9Sstevel@tonic-gate ptree_get_next_prop(picl_prophdl_t proph, picl_prophdl_t *nextproph) 25187c478bd9Sstevel@tonic-gate { 25197c478bd9Sstevel@tonic-gate picl_obj_t *nodep; 25207c478bd9Sstevel@tonic-gate picl_obj_t *propp; 25217c478bd9Sstevel@tonic-gate int err; 25227c478bd9Sstevel@tonic-gate 25237c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 25247c478bd9Sstevel@tonic-gate nodep = propp = NULL; 25257c478bd9Sstevel@tonic-gate err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp); 25267c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 25277c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 25287c478bd9Sstevel@tonic-gate return (err); 25297c478bd9Sstevel@tonic-gate } 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate if (propp->next_prop) { 25327c478bd9Sstevel@tonic-gate *nextproph = propp->next_prop->ptree_hdl; 25337c478bd9Sstevel@tonic-gate } else 25347c478bd9Sstevel@tonic-gate err = PICL_ENDOFLIST; 25357c478bd9Sstevel@tonic-gate 25367c478bd9Sstevel@tonic-gate unlock_node(nodep); /* unlock node */ 25377c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 25387c478bd9Sstevel@tonic-gate return (err); 25397c478bd9Sstevel@tonic-gate } 25407c478bd9Sstevel@tonic-gate 25417c478bd9Sstevel@tonic-gate /* 25427c478bd9Sstevel@tonic-gate * These functions are called by ptree_get_node_by_path() 25437c478bd9Sstevel@tonic-gate * Append a prop expression entry to the list 25447c478bd9Sstevel@tonic-gate */ 25457c478bd9Sstevel@tonic-gate static prop_list_t * 25467c478bd9Sstevel@tonic-gate append_entry_to_list(prop_list_t *el, prop_list_t *list) 25477c478bd9Sstevel@tonic-gate { 25487c478bd9Sstevel@tonic-gate prop_list_t *ptr; 25497c478bd9Sstevel@tonic-gate 25507c478bd9Sstevel@tonic-gate if (el == NULL) 25517c478bd9Sstevel@tonic-gate return (list); 25527c478bd9Sstevel@tonic-gate 25537c478bd9Sstevel@tonic-gate if (list == NULL) { 25547c478bd9Sstevel@tonic-gate list = el; 25557c478bd9Sstevel@tonic-gate return (list); 25567c478bd9Sstevel@tonic-gate } 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate /* 25597c478bd9Sstevel@tonic-gate * Add it to the end of list 25607c478bd9Sstevel@tonic-gate */ 25617c478bd9Sstevel@tonic-gate ptr = list; 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate while (ptr->next != NULL) 25647c478bd9Sstevel@tonic-gate ptr = ptr->next; 25657c478bd9Sstevel@tonic-gate 25667c478bd9Sstevel@tonic-gate ptr->next = el; 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate return (list); 25697c478bd9Sstevel@tonic-gate } 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate /* 25727c478bd9Sstevel@tonic-gate * Free the property expression list 25737c478bd9Sstevel@tonic-gate */ 25747c478bd9Sstevel@tonic-gate static void 25757c478bd9Sstevel@tonic-gate free_list(prop_list_t *list) 25767c478bd9Sstevel@tonic-gate { 25777c478bd9Sstevel@tonic-gate prop_list_t *ptr; 25787c478bd9Sstevel@tonic-gate prop_list_t *tmp; 25797c478bd9Sstevel@tonic-gate 25807c478bd9Sstevel@tonic-gate for (ptr = list; ptr != NULL; ptr = tmp) { 25817c478bd9Sstevel@tonic-gate tmp = ptr->next; 25827c478bd9Sstevel@tonic-gate free(ptr); 25837c478bd9Sstevel@tonic-gate } 25847c478bd9Sstevel@tonic-gate } 25857c478bd9Sstevel@tonic-gate 25867c478bd9Sstevel@tonic-gate static int 25877c478bd9Sstevel@tonic-gate parse_prl(char *prl, char **name, char **baddr, prop_list_t **plist) 25887c478bd9Sstevel@tonic-gate { 25897c478bd9Sstevel@tonic-gate char *propptr; 25907c478bd9Sstevel@tonic-gate char *ptr; 25917c478bd9Sstevel@tonic-gate char *pname; 25927c478bd9Sstevel@tonic-gate char *pval; 25937c478bd9Sstevel@tonic-gate prop_list_t *el; 25947c478bd9Sstevel@tonic-gate 25957c478bd9Sstevel@tonic-gate if (prl == NULL) 25967c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 25977c478bd9Sstevel@tonic-gate 25987c478bd9Sstevel@tonic-gate if ((prl[0] == '@') || (prl[0] == '?')) 25997c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 26007c478bd9Sstevel@tonic-gate 26017c478bd9Sstevel@tonic-gate *name = prl; 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate /* 26047c478bd9Sstevel@tonic-gate * get property expression 26057c478bd9Sstevel@tonic-gate */ 26067c478bd9Sstevel@tonic-gate ptr = strchr(prl, '?'); 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate if (ptr != NULL) { 26097c478bd9Sstevel@tonic-gate *ptr = '\0'; 26107c478bd9Sstevel@tonic-gate propptr = ptr + 1; 26117c478bd9Sstevel@tonic-gate } else 26127c478bd9Sstevel@tonic-gate propptr = NULL; 26137c478bd9Sstevel@tonic-gate 26147c478bd9Sstevel@tonic-gate /* 26157c478bd9Sstevel@tonic-gate * get bus value 26167c478bd9Sstevel@tonic-gate */ 26177c478bd9Sstevel@tonic-gate ptr = strchr(prl, '@'); 26187c478bd9Sstevel@tonic-gate 26197c478bd9Sstevel@tonic-gate if (ptr != NULL) { 26207c478bd9Sstevel@tonic-gate *ptr = '\0'; 26217c478bd9Sstevel@tonic-gate *baddr = ptr + 1; 26227c478bd9Sstevel@tonic-gate if (strlen(*baddr) == 0) /* no bus value after @ */ 26237c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 26247c478bd9Sstevel@tonic-gate } 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate /* 26277c478bd9Sstevel@tonic-gate * create the prop list 26287c478bd9Sstevel@tonic-gate */ 26297c478bd9Sstevel@tonic-gate while (propptr != NULL) { 26307c478bd9Sstevel@tonic-gate pname = propptr; 26317c478bd9Sstevel@tonic-gate pval = NULL; 26327c478bd9Sstevel@tonic-gate 26337c478bd9Sstevel@tonic-gate ptr = strchr(propptr, '?'); 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate if (ptr != NULL) { /* more ?<prop>=<propval> */ 26367c478bd9Sstevel@tonic-gate *ptr = '\0'; 26377c478bd9Sstevel@tonic-gate propptr = ptr + 1; 26387c478bd9Sstevel@tonic-gate } else 26397c478bd9Sstevel@tonic-gate propptr = NULL; 26407c478bd9Sstevel@tonic-gate 26417c478bd9Sstevel@tonic-gate if (strlen(pname) == 0) /* no prop exp after ? */ 26427c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 26437c478bd9Sstevel@tonic-gate 26447c478bd9Sstevel@tonic-gate ptr = strchr(pname, '='); 26457c478bd9Sstevel@tonic-gate if (ptr != NULL) { /* not void prop */ 26467c478bd9Sstevel@tonic-gate *ptr = '\0'; 26477c478bd9Sstevel@tonic-gate pval = ptr + 1; 26487c478bd9Sstevel@tonic-gate /* 26497c478bd9Sstevel@tonic-gate * <prop>= is treated as void property 26507c478bd9Sstevel@tonic-gate */ 26517c478bd9Sstevel@tonic-gate if (strlen(pval) == 0) 26527c478bd9Sstevel@tonic-gate pval = NULL; 26537c478bd9Sstevel@tonic-gate } 26547c478bd9Sstevel@tonic-gate 26557c478bd9Sstevel@tonic-gate el = (prop_list_t *)malloc(sizeof (prop_list_t)); 26567c478bd9Sstevel@tonic-gate el->pname = pname; 26577c478bd9Sstevel@tonic-gate el->pval = pval; 26587c478bd9Sstevel@tonic-gate el->next = NULL; 26597c478bd9Sstevel@tonic-gate *plist = append_entry_to_list(el, *plist); 26607c478bd9Sstevel@tonic-gate } 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 26637c478bd9Sstevel@tonic-gate } 26647c478bd9Sstevel@tonic-gate 26657c478bd9Sstevel@tonic-gate static int 26667c478bd9Sstevel@tonic-gate prop_match(ptree_propinfo_t pinfo, void *vbuf, char *val) 26677c478bd9Sstevel@tonic-gate { 26687c478bd9Sstevel@tonic-gate int8_t cval; 26697c478bd9Sstevel@tonic-gate uint8_t ucval; 26707c478bd9Sstevel@tonic-gate int16_t sval; 26717c478bd9Sstevel@tonic-gate uint16_t usval; 26727c478bd9Sstevel@tonic-gate int32_t intval; 26737c478bd9Sstevel@tonic-gate uint32_t uintval; 26747c478bd9Sstevel@tonic-gate int64_t llval; 26757c478bd9Sstevel@tonic-gate uint64_t ullval; 26767c478bd9Sstevel@tonic-gate float fval; 26777c478bd9Sstevel@tonic-gate double dval; 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.type) { 26807c478bd9Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 26817c478bd9Sstevel@tonic-gate if (strcasecmp(pinfo.piclinfo.name, PICL_PROP_CLASSNAME) == 0) { 26827c478bd9Sstevel@tonic-gate if (strcmp(val, PICL_CLASS_PICL) == 0) 26837c478bd9Sstevel@tonic-gate return (1); 26847c478bd9Sstevel@tonic-gate } 26857c478bd9Sstevel@tonic-gate if (strcmp(val, (char *)vbuf) == 0) 26867c478bd9Sstevel@tonic-gate return (1); 26877c478bd9Sstevel@tonic-gate else 26887c478bd9Sstevel@tonic-gate return (0); 26897c478bd9Sstevel@tonic-gate case PICL_PTYPE_INT: 26907c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.size) { 26917c478bd9Sstevel@tonic-gate case sizeof (int8_t): 26927c478bd9Sstevel@tonic-gate cval = (int8_t)strtol(val, (char **)NULL, 0); 26937c478bd9Sstevel@tonic-gate return (cval == *(char *)vbuf); 26947c478bd9Sstevel@tonic-gate case sizeof (int16_t): 26957c478bd9Sstevel@tonic-gate sval = (int16_t)strtol(val, (char **)NULL, 0); 26967c478bd9Sstevel@tonic-gate return (sval == *(int16_t *)vbuf); 26977c478bd9Sstevel@tonic-gate case sizeof (int32_t): 26987c478bd9Sstevel@tonic-gate intval = (int32_t)strtol(val, (char **)NULL, 0); 26997c478bd9Sstevel@tonic-gate return (intval == *(int32_t *)vbuf); 27007c478bd9Sstevel@tonic-gate case sizeof (int64_t): 27017c478bd9Sstevel@tonic-gate llval = strtoll(val, (char **)NULL, 0); 27027c478bd9Sstevel@tonic-gate return (llval == *(int64_t *)vbuf); 27037c478bd9Sstevel@tonic-gate default: 27047c478bd9Sstevel@tonic-gate return (0); 27057c478bd9Sstevel@tonic-gate } 27067c478bd9Sstevel@tonic-gate case PICL_PTYPE_UNSIGNED_INT: 27077c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.size) { 27087c478bd9Sstevel@tonic-gate case sizeof (uint8_t): 27097c478bd9Sstevel@tonic-gate ucval = (uint8_t)strtoul(val, (char **)NULL, 0); 27107c478bd9Sstevel@tonic-gate return (ucval == *(uint8_t *)vbuf); 27117c478bd9Sstevel@tonic-gate case sizeof (uint16_t): 27127c478bd9Sstevel@tonic-gate usval = (uint16_t)strtoul(val, (char **)NULL, 0); 27137c478bd9Sstevel@tonic-gate return (usval == *(uint16_t *)vbuf); 27147c478bd9Sstevel@tonic-gate case sizeof (uint32_t): 27157c478bd9Sstevel@tonic-gate uintval = (uint32_t)strtoul(val, (char **)NULL, 0); 27167c478bd9Sstevel@tonic-gate return (uintval == *(uint32_t *)vbuf); 27177c478bd9Sstevel@tonic-gate case sizeof (uint64_t): 27187c478bd9Sstevel@tonic-gate ullval = strtoull(val, (char **)NULL, 0); 27197c478bd9Sstevel@tonic-gate return (ullval == *(uint64_t *)vbuf); 27207c478bd9Sstevel@tonic-gate default: 27217c478bd9Sstevel@tonic-gate return (0); 27227c478bd9Sstevel@tonic-gate } 27237c478bd9Sstevel@tonic-gate case PICL_PTYPE_FLOAT: 27247c478bd9Sstevel@tonic-gate switch (pinfo.piclinfo.size) { 27257c478bd9Sstevel@tonic-gate case sizeof (float): 27267c478bd9Sstevel@tonic-gate fval = (float)strtod(val, (char **)NULL); 27277c478bd9Sstevel@tonic-gate return (fval == *(float *)vbuf); 27287c478bd9Sstevel@tonic-gate case sizeof (double): 27297c478bd9Sstevel@tonic-gate dval = strtod(val, (char **)NULL); 27307c478bd9Sstevel@tonic-gate return (dval == *(double *)vbuf); 27317c478bd9Sstevel@tonic-gate default: 27327c478bd9Sstevel@tonic-gate return (0); 27337c478bd9Sstevel@tonic-gate } 27347c478bd9Sstevel@tonic-gate case PICL_PTYPE_VOID: 27357c478bd9Sstevel@tonic-gate case PICL_PTYPE_TIMESTAMP: 27367c478bd9Sstevel@tonic-gate case PICL_PTYPE_TABLE: 27377c478bd9Sstevel@tonic-gate case PICL_PTYPE_REFERENCE: 27387c478bd9Sstevel@tonic-gate case PICL_PTYPE_BYTEARRAY: 27397c478bd9Sstevel@tonic-gate case PICL_PTYPE_UNKNOWN: 27407c478bd9Sstevel@tonic-gate default: 27417c478bd9Sstevel@tonic-gate return (0); 27427c478bd9Sstevel@tonic-gate } 27437c478bd9Sstevel@tonic-gate } 27447c478bd9Sstevel@tonic-gate 27457c478bd9Sstevel@tonic-gate static int 27467c478bd9Sstevel@tonic-gate check_propval(picl_nodehdl_t nodeh, char *pname, char *pval) 27477c478bd9Sstevel@tonic-gate { 27487c478bd9Sstevel@tonic-gate int err; 27497c478bd9Sstevel@tonic-gate picl_prophdl_t proph; 27507c478bd9Sstevel@tonic-gate ptree_propinfo_t pinfo; 27517c478bd9Sstevel@tonic-gate void *vbuf; 27527c478bd9Sstevel@tonic-gate 27537c478bd9Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, pname, &proph); 27547c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 27557c478bd9Sstevel@tonic-gate return (err); 27567c478bd9Sstevel@tonic-gate 27577c478bd9Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 27587c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 27597c478bd9Sstevel@tonic-gate return (err); 27607c478bd9Sstevel@tonic-gate 27617c478bd9Sstevel@tonic-gate if (pval == NULL) { /* void type */ 27627c478bd9Sstevel@tonic-gate if (pinfo.piclinfo.type != PICL_PTYPE_VOID) 27637c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 27647c478bd9Sstevel@tonic-gate } else { 27657c478bd9Sstevel@tonic-gate vbuf = alloca(pinfo.piclinfo.size); 27667c478bd9Sstevel@tonic-gate if (vbuf == NULL) 27677c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 27687c478bd9Sstevel@tonic-gate err = ptree_get_propval(proph, vbuf, 27697c478bd9Sstevel@tonic-gate pinfo.piclinfo.size); 27707c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 27717c478bd9Sstevel@tonic-gate return (err); 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate if (!prop_match(pinfo, vbuf, pval)) 27747c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 27757c478bd9Sstevel@tonic-gate } 27767c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 27777c478bd9Sstevel@tonic-gate } 27787c478bd9Sstevel@tonic-gate 27797c478bd9Sstevel@tonic-gate static int 27807c478bd9Sstevel@tonic-gate get_child_by_path(picl_nodehdl_t rooth, char *prl, 27817c478bd9Sstevel@tonic-gate picl_nodehdl_t *nodeh, char *pname) 27827c478bd9Sstevel@tonic-gate { 27837c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 27847c478bd9Sstevel@tonic-gate int err; 27857c478bd9Sstevel@tonic-gate char *nameval; 27867c478bd9Sstevel@tonic-gate char *nodename; 27877c478bd9Sstevel@tonic-gate char *path; 27887c478bd9Sstevel@tonic-gate char *baddr; 27897c478bd9Sstevel@tonic-gate char *busval; 27907c478bd9Sstevel@tonic-gate prop_list_t *plist; 27917c478bd9Sstevel@tonic-gate prop_list_t *ptr; 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate if (prl == NULL) 27947c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 27957c478bd9Sstevel@tonic-gate 2796*23a1cceaSRoger A. Faulkner path = strdupa(prl); 27977c478bd9Sstevel@tonic-gate if (path == NULL) 27987c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 27997c478bd9Sstevel@tonic-gate 28007c478bd9Sstevel@tonic-gate plist = NULL; 28017c478bd9Sstevel@tonic-gate nodename = NULL; 28027c478bd9Sstevel@tonic-gate baddr = NULL; 28037c478bd9Sstevel@tonic-gate 28047c478bd9Sstevel@tonic-gate err = parse_prl(path, &nodename, &baddr, &plist); 28057c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 28067c478bd9Sstevel@tonic-gate free_list(plist); 28077c478bd9Sstevel@tonic-gate return (err); 28087c478bd9Sstevel@tonic-gate } 28097c478bd9Sstevel@tonic-gate 28107c478bd9Sstevel@tonic-gate if (nodename == NULL) 28117c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 28127c478bd9Sstevel@tonic-gate 28137c478bd9Sstevel@tonic-gate nameval = alloca(strlen(nodename) + 1); 28147c478bd9Sstevel@tonic-gate if (nameval == NULL) { 28157c478bd9Sstevel@tonic-gate free_list(plist); 28167c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 28177c478bd9Sstevel@tonic-gate } 28187c478bd9Sstevel@tonic-gate 28197c478bd9Sstevel@tonic-gate if (baddr != NULL) { 28207c478bd9Sstevel@tonic-gate busval = alloca(strlen(baddr) + 1); 28217c478bd9Sstevel@tonic-gate if (busval == NULL) { 28227c478bd9Sstevel@tonic-gate free_list(plist); 28237c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 28247c478bd9Sstevel@tonic-gate } 28257c478bd9Sstevel@tonic-gate } 28267c478bd9Sstevel@tonic-gate 28277c478bd9Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 28287c478bd9Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 28297c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 28307c478bd9Sstevel@tonic-gate sizeof (picl_nodehdl_t))) { 28317c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 28327c478bd9Sstevel@tonic-gate free_list(plist); 28337c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 28347c478bd9Sstevel@tonic-gate } 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate /* 28377c478bd9Sstevel@tonic-gate * compare name 28387c478bd9Sstevel@tonic-gate */ 28397c478bd9Sstevel@tonic-gate if ((strcmp(pname, PICL_PROP_CLASSNAME) != 0) || 28407c478bd9Sstevel@tonic-gate (strcmp(nodename, PICL_CLASS_PICL) != 0)) { 28417c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, pname, 28427c478bd9Sstevel@tonic-gate nameval, (strlen(nodename) + 1)); 28437c478bd9Sstevel@tonic-gate 28447c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 28457c478bd9Sstevel@tonic-gate continue; 28467c478bd9Sstevel@tonic-gate if (strcmp(nameval, nodename) != 0) 28477c478bd9Sstevel@tonic-gate continue; 28487c478bd9Sstevel@tonic-gate } 28497c478bd9Sstevel@tonic-gate 28507c478bd9Sstevel@tonic-gate /* 28517c478bd9Sstevel@tonic-gate * compare device address with bus-addr prop first 28527c478bd9Sstevel@tonic-gate * then with UnitAddress property 28537c478bd9Sstevel@tonic-gate */ 28547c478bd9Sstevel@tonic-gate if (baddr != NULL) { /* compare bus-addr prop */ 28557c478bd9Sstevel@tonic-gate if ((ptree_get_propval_by_name(chdh, PICL_PROP_BUS_ADDR, 28567c478bd9Sstevel@tonic-gate busval, (strlen(baddr) + 1)) != PICL_SUCCESS) && 28577c478bd9Sstevel@tonic-gate (ptree_get_propval_by_name(chdh, 28587c478bd9Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, busval, 28597c478bd9Sstevel@tonic-gate (strlen(baddr) + 1)) != PICL_SUCCESS)) 28607c478bd9Sstevel@tonic-gate continue; 28617c478bd9Sstevel@tonic-gate 28627c478bd9Sstevel@tonic-gate if (strcmp(busval, baddr) != 0) 28637c478bd9Sstevel@tonic-gate continue; /* not match */ 28647c478bd9Sstevel@tonic-gate } 28657c478bd9Sstevel@tonic-gate 28667c478bd9Sstevel@tonic-gate if (plist == NULL) { /* no prop expression */ 28677c478bd9Sstevel@tonic-gate *nodeh = chdh; 28687c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 28697c478bd9Sstevel@tonic-gate } 28707c478bd9Sstevel@tonic-gate 28717c478bd9Sstevel@tonic-gate /* 28727c478bd9Sstevel@tonic-gate * compare the property expression list 28737c478bd9Sstevel@tonic-gate */ 28747c478bd9Sstevel@tonic-gate ptr = plist; 28757c478bd9Sstevel@tonic-gate 28767c478bd9Sstevel@tonic-gate while (ptr != NULL) { 28777c478bd9Sstevel@tonic-gate err = check_propval(chdh, ptr->pname, ptr->pval); 28787c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 28797c478bd9Sstevel@tonic-gate break; 28807c478bd9Sstevel@tonic-gate 28817c478bd9Sstevel@tonic-gate ptr = ptr->next; 28827c478bd9Sstevel@tonic-gate } 28837c478bd9Sstevel@tonic-gate if (ptr == NULL) { 28847c478bd9Sstevel@tonic-gate *nodeh = chdh; 28857c478bd9Sstevel@tonic-gate free_list(plist); 28867c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 28877c478bd9Sstevel@tonic-gate } 28887c478bd9Sstevel@tonic-gate } 28897c478bd9Sstevel@tonic-gate free_list(plist); 28907c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 28917c478bd9Sstevel@tonic-gate } 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate /* 28947c478bd9Sstevel@tonic-gate * This functions returns the handle of node specified by its path 28957c478bd9Sstevel@tonic-gate */ 28967c478bd9Sstevel@tonic-gate int 28977c478bd9Sstevel@tonic-gate ptree_get_node_by_path(const char *piclprl, picl_nodehdl_t *handle) 28987c478bd9Sstevel@tonic-gate { 28997c478bd9Sstevel@tonic-gate picl_nodehdl_t rooth; 29007c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 29017c478bd9Sstevel@tonic-gate char *path; 29027c478bd9Sstevel@tonic-gate char *ptr; 29037c478bd9Sstevel@tonic-gate char *defprop; 29047c478bd9Sstevel@tonic-gate char *tokindex; 29057c478bd9Sstevel@tonic-gate int err; 29067c478bd9Sstevel@tonic-gate int len; 29077c478bd9Sstevel@tonic-gate int npflg; /* namepath flag */ 29087c478bd9Sstevel@tonic-gate 29097c478bd9Sstevel@tonic-gate 2910*23a1cceaSRoger A. Faulkner path = strdupa(piclprl); 29117c478bd9Sstevel@tonic-gate if (path == NULL) 29127c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 29137c478bd9Sstevel@tonic-gate 29147c478bd9Sstevel@tonic-gate npflg = 1; /* default */ 29157c478bd9Sstevel@tonic-gate defprop = path; 29167c478bd9Sstevel@tonic-gate if (path[0] == '/') { 29177c478bd9Sstevel@tonic-gate ptr = &path[1]; 29187c478bd9Sstevel@tonic-gate } else if ((tokindex = strchr(path, ':')) != NULL) { 29197c478bd9Sstevel@tonic-gate *tokindex = '\0'; 29207c478bd9Sstevel@tonic-gate ++tokindex; 29217c478bd9Sstevel@tonic-gate if (*tokindex == '/') 29227c478bd9Sstevel@tonic-gate ptr = tokindex + 1; 29237c478bd9Sstevel@tonic-gate else 29247c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 29257c478bd9Sstevel@tonic-gate npflg = 0; 29267c478bd9Sstevel@tonic-gate } else 29277c478bd9Sstevel@tonic-gate return (PICL_NOTNODE); 29287c478bd9Sstevel@tonic-gate 29297c478bd9Sstevel@tonic-gate err = ptree_get_root(&rooth); 29307c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 29317c478bd9Sstevel@tonic-gate return (err); 29327c478bd9Sstevel@tonic-gate 29337c478bd9Sstevel@tonic-gate for (chdh = rooth, tokindex = strchr(ptr, '/'); 29347c478bd9Sstevel@tonic-gate tokindex != NULL; 29357c478bd9Sstevel@tonic-gate ptr = tokindex + 1, tokindex = strchr(ptr, '/')) { 29367c478bd9Sstevel@tonic-gate *tokindex = '\0'; 29377c478bd9Sstevel@tonic-gate if (npflg) 29387c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, 29397c478bd9Sstevel@tonic-gate PICL_PROP_NAME); 29407c478bd9Sstevel@tonic-gate else 29417c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, 29427c478bd9Sstevel@tonic-gate defprop); 29437c478bd9Sstevel@tonic-gate 29447c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 29457c478bd9Sstevel@tonic-gate return (err); 29467c478bd9Sstevel@tonic-gate } 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate /* 29497c478bd9Sstevel@tonic-gate * check if last token is empty or not 29507c478bd9Sstevel@tonic-gate * eg. /a/b/c/ or /a/b/c 29517c478bd9Sstevel@tonic-gate */ 29527c478bd9Sstevel@tonic-gate if (*ptr == '\0') { 29537c478bd9Sstevel@tonic-gate *handle = chdh; 29547c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 29557c478bd9Sstevel@tonic-gate } 29567c478bd9Sstevel@tonic-gate 29577c478bd9Sstevel@tonic-gate len = strcspn(ptr, " \t\n"); 29587c478bd9Sstevel@tonic-gate if (len == 0) { 29597c478bd9Sstevel@tonic-gate *handle = chdh; 29607c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 29617c478bd9Sstevel@tonic-gate } 29627c478bd9Sstevel@tonic-gate 29637c478bd9Sstevel@tonic-gate ptr[len] = '\0'; 29647c478bd9Sstevel@tonic-gate if (npflg) 29657c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, PICL_PROP_NAME); 29667c478bd9Sstevel@tonic-gate else 29677c478bd9Sstevel@tonic-gate err = get_child_by_path(chdh, ptr, &chdh, defprop); 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 29707c478bd9Sstevel@tonic-gate return (err); 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate *handle = chdh; 29737c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 29747c478bd9Sstevel@tonic-gate } 29757c478bd9Sstevel@tonic-gate 29767c478bd9Sstevel@tonic-gate /* 29777c478bd9Sstevel@tonic-gate * Initialize propinfo 29787c478bd9Sstevel@tonic-gate */ 29797c478bd9Sstevel@tonic-gate int 29807c478bd9Sstevel@tonic-gate ptree_init_propinfo(ptree_propinfo_t *infop, int version, int ptype, int pmode, 29817c478bd9Sstevel@tonic-gate size_t psize, char *pname, int (*readfn)(ptree_rarg_t *, void *), 29827c478bd9Sstevel@tonic-gate int (*writefn)(ptree_warg_t *, const void *)) 29837c478bd9Sstevel@tonic-gate { 29847c478bd9Sstevel@tonic-gate if (version != PTREE_PROPINFO_VERSION_1) 29857c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 29867c478bd9Sstevel@tonic-gate if ((infop == NULL) || (pname == NULL)) 29877c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 29887c478bd9Sstevel@tonic-gate infop->version = version; 29897c478bd9Sstevel@tonic-gate infop->piclinfo.type = ptype; 29907c478bd9Sstevel@tonic-gate infop->piclinfo.accessmode = pmode; 29917c478bd9Sstevel@tonic-gate infop->piclinfo.size = psize; 29927c478bd9Sstevel@tonic-gate infop->read = readfn; 29937c478bd9Sstevel@tonic-gate infop->write = writefn; 29947c478bd9Sstevel@tonic-gate (void) strlcpy(infop->piclinfo.name, pname, PICL_PROPNAMELEN_MAX); 29957c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 29967c478bd9Sstevel@tonic-gate } 29977c478bd9Sstevel@tonic-gate 29987c478bd9Sstevel@tonic-gate /* 29997c478bd9Sstevel@tonic-gate * Creates a property, adds it to the node, and returns the property 30007c478bd9Sstevel@tonic-gate * handle to the caller if successful and proph is not NULL 30017c478bd9Sstevel@tonic-gate */ 30027c478bd9Sstevel@tonic-gate int 30037c478bd9Sstevel@tonic-gate ptree_create_and_add_prop(picl_nodehdl_t nodeh, ptree_propinfo_t *infop, 30047c478bd9Sstevel@tonic-gate void *vbuf, picl_prophdl_t *proph) 30057c478bd9Sstevel@tonic-gate { 30067c478bd9Sstevel@tonic-gate int err; 30077c478bd9Sstevel@tonic-gate picl_prophdl_t tmph; 30087c478bd9Sstevel@tonic-gate 30097c478bd9Sstevel@tonic-gate err = ptree_create_prop(infop, vbuf, &tmph); 30107c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 30117c478bd9Sstevel@tonic-gate return (err); 30127c478bd9Sstevel@tonic-gate err = ptree_add_prop(nodeh, tmph); 30137c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 30147c478bd9Sstevel@tonic-gate (void) ptree_destroy_prop(tmph); 30157c478bd9Sstevel@tonic-gate return (err); 30167c478bd9Sstevel@tonic-gate } 30177c478bd9Sstevel@tonic-gate if (proph) 30187c478bd9Sstevel@tonic-gate *proph = tmph; 30197c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 30207c478bd9Sstevel@tonic-gate } 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate /* 30237c478bd9Sstevel@tonic-gate * Creates a node, adds it to its parent node, and returns the node 30247c478bd9Sstevel@tonic-gate * handle to the caller if successful 30257c478bd9Sstevel@tonic-gate */ 30267c478bd9Sstevel@tonic-gate int 30277c478bd9Sstevel@tonic-gate ptree_create_and_add_node(picl_nodehdl_t rooth, const char *name, 30287c478bd9Sstevel@tonic-gate const char *classname, picl_nodehdl_t *nodeh) 30297c478bd9Sstevel@tonic-gate { 30307c478bd9Sstevel@tonic-gate picl_nodehdl_t tmph; 30317c478bd9Sstevel@tonic-gate int err; 30327c478bd9Sstevel@tonic-gate 30337c478bd9Sstevel@tonic-gate err = ptree_create_node(name, classname, &tmph); 30347c478bd9Sstevel@tonic-gate 30357c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 30367c478bd9Sstevel@tonic-gate return (err); 30377c478bd9Sstevel@tonic-gate 30387c478bd9Sstevel@tonic-gate err = ptree_add_node(rooth, tmph); 30397c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 30407c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(tmph); 30417c478bd9Sstevel@tonic-gate return (err); 30427c478bd9Sstevel@tonic-gate } 30437c478bd9Sstevel@tonic-gate 30447c478bd9Sstevel@tonic-gate *nodeh = tmph; 30457c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 30467c478bd9Sstevel@tonic-gate } 30477c478bd9Sstevel@tonic-gate 30487c478bd9Sstevel@tonic-gate 30497c478bd9Sstevel@tonic-gate /* 30507c478bd9Sstevel@tonic-gate * recursively visit all nodes 30517c478bd9Sstevel@tonic-gate */ 30527c478bd9Sstevel@tonic-gate static int 30537c478bd9Sstevel@tonic-gate do_walk(picl_nodehdl_t rooth, const char *classname, 30547c478bd9Sstevel@tonic-gate void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args)) 30557c478bd9Sstevel@tonic-gate { 30567c478bd9Sstevel@tonic-gate int err; 30577c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 30587c478bd9Sstevel@tonic-gate char classval[PICL_CLASSNAMELEN_MAX]; 30597c478bd9Sstevel@tonic-gate 30607c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 30617c478bd9Sstevel@tonic-gate sizeof (chdh)); 30627c478bd9Sstevel@tonic-gate while (err == PICL_SUCCESS) { 30637c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_CLASSNAME, 30647c478bd9Sstevel@tonic-gate classval, sizeof (classval)); 30657c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 30667c478bd9Sstevel@tonic-gate return (err); 30677c478bd9Sstevel@tonic-gate 30687c478bd9Sstevel@tonic-gate if ((classname == NULL) || (strcmp(classname, classval) == 0)) { 30697c478bd9Sstevel@tonic-gate err = callback_fn(chdh, c_args); 30707c478bd9Sstevel@tonic-gate if (err != PICL_WALK_CONTINUE) 30717c478bd9Sstevel@tonic-gate return (err); 30727c478bd9Sstevel@tonic-gate } 30737c478bd9Sstevel@tonic-gate 30747c478bd9Sstevel@tonic-gate if ((err = do_walk(chdh, classname, c_args, callback_fn)) != 30757c478bd9Sstevel@tonic-gate PICL_WALK_CONTINUE) 30767c478bd9Sstevel@tonic-gate return (err); 30777c478bd9Sstevel@tonic-gate 30787c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 30797c478bd9Sstevel@tonic-gate sizeof (chdh)); 30807c478bd9Sstevel@tonic-gate } 30817c478bd9Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) /* end of a branch */ 30827c478bd9Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 30837c478bd9Sstevel@tonic-gate return (err); 30847c478bd9Sstevel@tonic-gate 30857c478bd9Sstevel@tonic-gate } 30867c478bd9Sstevel@tonic-gate 30877c478bd9Sstevel@tonic-gate /* 30887c478bd9Sstevel@tonic-gate * This function visits all the nodes in the subtree rooted at <rooth>. 30897c478bd9Sstevel@tonic-gate * For each node that matches the class name specified, the callback 30907c478bd9Sstevel@tonic-gate * function is invoked. 30917c478bd9Sstevel@tonic-gate */ 30927c478bd9Sstevel@tonic-gate int 30937c478bd9Sstevel@tonic-gate ptree_walk_tree_by_class(picl_nodehdl_t rooth, const char *classname, 30947c478bd9Sstevel@tonic-gate void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args)) 30957c478bd9Sstevel@tonic-gate { 30967c478bd9Sstevel@tonic-gate int err; 30977c478bd9Sstevel@tonic-gate 30987c478bd9Sstevel@tonic-gate if (callback_fn == NULL) 30997c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 31007c478bd9Sstevel@tonic-gate err = do_walk(rooth, classname, c_args, callback_fn); 31017c478bd9Sstevel@tonic-gate if ((err == PICL_WALK_CONTINUE) || (err == PICL_WALK_TERMINATE)) 31027c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 31037c478bd9Sstevel@tonic-gate return (err); 31047c478bd9Sstevel@tonic-gate } 31057c478bd9Sstevel@tonic-gate 31067c478bd9Sstevel@tonic-gate static int 31077c478bd9Sstevel@tonic-gate compare_propval(picl_nodehdl_t nodeh, char *pname, picl_prop_type_t ptype, 31087c478bd9Sstevel@tonic-gate void *pval, size_t valsize) 31097c478bd9Sstevel@tonic-gate { 31107c478bd9Sstevel@tonic-gate int err; 31117c478bd9Sstevel@tonic-gate picl_prophdl_t proph; 31127c478bd9Sstevel@tonic-gate ptree_propinfo_t propinfo; 31137c478bd9Sstevel@tonic-gate void *vbuf; 31147c478bd9Sstevel@tonic-gate 31157c478bd9Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, pname, &proph); 31167c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 31177c478bd9Sstevel@tonic-gate return (0); 31187c478bd9Sstevel@tonic-gate err = ptree_get_propinfo(proph, &propinfo); 31197c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 31207c478bd9Sstevel@tonic-gate return (0); 31217c478bd9Sstevel@tonic-gate if (propinfo.piclinfo.type != ptype) 31227c478bd9Sstevel@tonic-gate return (0); 31237c478bd9Sstevel@tonic-gate if (propinfo.piclinfo.type == PICL_PTYPE_VOID) 31247c478bd9Sstevel@tonic-gate return (1); 31257c478bd9Sstevel@tonic-gate if (pval == NULL) 31267c478bd9Sstevel@tonic-gate return (0); 31277c478bd9Sstevel@tonic-gate if (valsize > propinfo.piclinfo.size) 31287c478bd9Sstevel@tonic-gate return (0); 31297c478bd9Sstevel@tonic-gate vbuf = alloca(propinfo.piclinfo.size); 31307c478bd9Sstevel@tonic-gate if (vbuf == NULL) 31317c478bd9Sstevel@tonic-gate return (0); 31327c478bd9Sstevel@tonic-gate err = ptree_get_propval(proph, vbuf, propinfo.piclinfo.size); 31337c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 31347c478bd9Sstevel@tonic-gate return (0); 31357c478bd9Sstevel@tonic-gate if (memcmp(vbuf, pval, valsize) == 0) 31367c478bd9Sstevel@tonic-gate return (1); 31377c478bd9Sstevel@tonic-gate return (0); 31387c478bd9Sstevel@tonic-gate } 31397c478bd9Sstevel@tonic-gate 31407c478bd9Sstevel@tonic-gate 31417c478bd9Sstevel@tonic-gate /* 31427c478bd9Sstevel@tonic-gate * This function traverses the subtree and finds a node that has a property 31437c478bd9Sstevel@tonic-gate * of the specified name and type with the specified value. 31447c478bd9Sstevel@tonic-gate * The matched node in the tree is returned in retnodeh. If there is 31457c478bd9Sstevel@tonic-gate * no node with that property, then PICL_NODENOTFOUND is returned. 31467c478bd9Sstevel@tonic-gate */ 31477c478bd9Sstevel@tonic-gate int 31487c478bd9Sstevel@tonic-gate ptree_find_node(picl_nodehdl_t rooth, char *pname, picl_prop_type_t ptype, 31497c478bd9Sstevel@tonic-gate void *pval, size_t valsize, picl_nodehdl_t *retnodeh) 31507c478bd9Sstevel@tonic-gate { 31517c478bd9Sstevel@tonic-gate int err; 31527c478bd9Sstevel@tonic-gate picl_nodehdl_t chdh; 31537c478bd9Sstevel@tonic-gate 31547c478bd9Sstevel@tonic-gate if (pname == NULL) 31557c478bd9Sstevel@tonic-gate return (PICL_INVALIDARG); 31567c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 31577c478bd9Sstevel@tonic-gate sizeof (chdh)); 31587c478bd9Sstevel@tonic-gate 31597c478bd9Sstevel@tonic-gate while (err == PICL_SUCCESS) { 31607c478bd9Sstevel@tonic-gate if (compare_propval(chdh, pname, ptype, pval, valsize)) { 31617c478bd9Sstevel@tonic-gate if (retnodeh) 31627c478bd9Sstevel@tonic-gate *retnodeh = chdh; 31637c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 31647c478bd9Sstevel@tonic-gate } 31657c478bd9Sstevel@tonic-gate 31667c478bd9Sstevel@tonic-gate err = ptree_find_node(chdh, pname, ptype, pval, valsize, 31677c478bd9Sstevel@tonic-gate retnodeh); 31687c478bd9Sstevel@tonic-gate if (err != PICL_NODENOTFOUND) 31697c478bd9Sstevel@tonic-gate return (err); 31707c478bd9Sstevel@tonic-gate 31717c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 31727c478bd9Sstevel@tonic-gate sizeof (chdh)); 31737c478bd9Sstevel@tonic-gate } 31747c478bd9Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 31757c478bd9Sstevel@tonic-gate return (PICL_NODENOTFOUND); 31767c478bd9Sstevel@tonic-gate return (err); 31777c478bd9Sstevel@tonic-gate } 31787c478bd9Sstevel@tonic-gate 31797c478bd9Sstevel@tonic-gate /* 31807c478bd9Sstevel@tonic-gate * This function gets the frutree parent for a given node. 31817c478bd9Sstevel@tonic-gate * Traverse up the tree and look for the following properties: 31827c478bd9Sstevel@tonic-gate * Frutree parent reference properties: 31837c478bd9Sstevel@tonic-gate * _fru_parent 31847c478bd9Sstevel@tonic-gate * _location_parent 31857c478bd9Sstevel@tonic-gate * _port_parent 31867c478bd9Sstevel@tonic-gate * If the frutree reference property is found, return its value. 31877c478bd9Sstevel@tonic-gate * Else, return the handle of /frutree/chassis. 31887c478bd9Sstevel@tonic-gate */ 31897c478bd9Sstevel@tonic-gate int 31907c478bd9Sstevel@tonic-gate ptree_get_frutree_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruh) 31917c478bd9Sstevel@tonic-gate { 31927c478bd9Sstevel@tonic-gate int err; 31937c478bd9Sstevel@tonic-gate picl_nodehdl_t nparh; 31947c478bd9Sstevel@tonic-gate picl_nodehdl_t fruparh; 31957c478bd9Sstevel@tonic-gate 31967c478bd9Sstevel@tonic-gate err = PICL_SUCCESS; 31977c478bd9Sstevel@tonic-gate nparh = nodeh; 31987c478bd9Sstevel@tonic-gate while (err == PICL_SUCCESS) { 31997c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, PICL_REFPROP_FRU_PARENT, 32007c478bd9Sstevel@tonic-gate &fruparh, sizeof (fruparh)); 32017c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 32027c478bd9Sstevel@tonic-gate *fruh = fruparh; 32037c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 32047c478bd9Sstevel@tonic-gate } 32057c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, 32067c478bd9Sstevel@tonic-gate PICL_REFPROP_LOC_PARENT, &fruparh, sizeof (fruparh)); 32077c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 32087c478bd9Sstevel@tonic-gate *fruh = fruparh; 32097c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 32107c478bd9Sstevel@tonic-gate } 32117c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, PICL_REFPROP_PORT_PARENT, 32127c478bd9Sstevel@tonic-gate &fruparh, sizeof (fruparh)); 32137c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 32147c478bd9Sstevel@tonic-gate *fruh = fruparh; 32157c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 32167c478bd9Sstevel@tonic-gate } 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate err = ptree_get_propval_by_name(nparh, PICL_PROP_PARENT, &nparh, 32197c478bd9Sstevel@tonic-gate sizeof (nparh)); 32207c478bd9Sstevel@tonic-gate } 32217c478bd9Sstevel@tonic-gate 32227c478bd9Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) { /* return /frutree/chassis handle */ 32237c478bd9Sstevel@tonic-gate err = ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, &fruparh); 32247c478bd9Sstevel@tonic-gate if (err == PICL_SUCCESS) { 32257c478bd9Sstevel@tonic-gate *fruh = fruparh; 32267c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 32277c478bd9Sstevel@tonic-gate } 32287c478bd9Sstevel@tonic-gate } 32297c478bd9Sstevel@tonic-gate return (err); 32307c478bd9Sstevel@tonic-gate } 32317c478bd9Sstevel@tonic-gate 32327c478bd9Sstevel@tonic-gate /* 32337c478bd9Sstevel@tonic-gate * This function is called by plug-ins to register with the daemon 32347c478bd9Sstevel@tonic-gate */ 32357c478bd9Sstevel@tonic-gate int 32367c478bd9Sstevel@tonic-gate picld_plugin_register(picld_plugin_reg_t *regp) 32377c478bd9Sstevel@tonic-gate { 32387c478bd9Sstevel@tonic-gate picld_plugin_reg_list_t *el; 32397c478bd9Sstevel@tonic-gate picld_plugin_reg_list_t *tmp; 32407c478bd9Sstevel@tonic-gate 32417c478bd9Sstevel@tonic-gate if (regp == NULL) 32427c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 32437c478bd9Sstevel@tonic-gate 32447c478bd9Sstevel@tonic-gate if (regp->version != PICLD_PLUGIN_VERSION_1) 32457c478bd9Sstevel@tonic-gate return (PICL_NOTSUPPORTED); 32467c478bd9Sstevel@tonic-gate 32477c478bd9Sstevel@tonic-gate el = malloc(sizeof (picld_plugin_reg_list_t)); 32487c478bd9Sstevel@tonic-gate if (el == NULL) 32497c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 32507c478bd9Sstevel@tonic-gate el->reg.version = regp->version; 32517c478bd9Sstevel@tonic-gate el->reg.critical = regp->critical; 32527c478bd9Sstevel@tonic-gate if (regp->name) 32537c478bd9Sstevel@tonic-gate el->reg.name = strdup(regp->name); 32547c478bd9Sstevel@tonic-gate if (el->reg.name == NULL) 32557c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 32567c478bd9Sstevel@tonic-gate 32577c478bd9Sstevel@tonic-gate el->reg.plugin_init = regp->plugin_init; 32587c478bd9Sstevel@tonic-gate el->reg.plugin_fini = regp->plugin_fini; 32597c478bd9Sstevel@tonic-gate el->next = NULL; 32607c478bd9Sstevel@tonic-gate 32617c478bd9Sstevel@tonic-gate if (plugin_reg_list == NULL) { 32627c478bd9Sstevel@tonic-gate plugin_reg_list = el; 32637c478bd9Sstevel@tonic-gate } else { /* add to end */ 32647c478bd9Sstevel@tonic-gate tmp = plugin_reg_list; 32657c478bd9Sstevel@tonic-gate while (tmp->next != NULL) 32667c478bd9Sstevel@tonic-gate tmp = tmp->next; 32677c478bd9Sstevel@tonic-gate tmp->next = el; 32687c478bd9Sstevel@tonic-gate } 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 32717c478bd9Sstevel@tonic-gate } 32727c478bd9Sstevel@tonic-gate 32737c478bd9Sstevel@tonic-gate /* 32747c478bd9Sstevel@tonic-gate * Call fini routines of the registered plugins 32757c478bd9Sstevel@tonic-gate */ 32767c478bd9Sstevel@tonic-gate static void 32777c478bd9Sstevel@tonic-gate plugin_fini(picld_plugin_reg_list_t *p) 32787c478bd9Sstevel@tonic-gate { 32797c478bd9Sstevel@tonic-gate if (p == NULL) 32807c478bd9Sstevel@tonic-gate return; 32817c478bd9Sstevel@tonic-gate 32827c478bd9Sstevel@tonic-gate plugin_fini(p->next); 32837c478bd9Sstevel@tonic-gate if (p->reg.plugin_fini) 32847c478bd9Sstevel@tonic-gate (p->reg.plugin_fini)(); 32857c478bd9Sstevel@tonic-gate } 32867c478bd9Sstevel@tonic-gate 32877c478bd9Sstevel@tonic-gate /* 32887c478bd9Sstevel@tonic-gate * Create PICL Tree 32897c478bd9Sstevel@tonic-gate */ 32907c478bd9Sstevel@tonic-gate 32917c478bd9Sstevel@tonic-gate static void 32927c478bd9Sstevel@tonic-gate init_plugin_reg_list(void) 32937c478bd9Sstevel@tonic-gate { 32947c478bd9Sstevel@tonic-gate plugin_reg_list = NULL; 32957c478bd9Sstevel@tonic-gate } 32967c478bd9Sstevel@tonic-gate 32977c478bd9Sstevel@tonic-gate static int 32987c478bd9Sstevel@tonic-gate picltree_set_root(picl_nodehdl_t rooth) 32997c478bd9Sstevel@tonic-gate { 33007c478bd9Sstevel@tonic-gate picl_obj_t *pobj; 33017c478bd9Sstevel@tonic-gate int err; 33027c478bd9Sstevel@tonic-gate 33037c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ptree_rwlock); /* lock ptree */ 33047c478bd9Sstevel@tonic-gate pobj = NULL; 33057c478bd9Sstevel@tonic-gate err = lookup_and_lock_node(RDLOCK_NODE, rooth, &pobj); /* lock node */ 33067c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) { 33077c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 33087c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33097c478bd9Sstevel@tonic-gate } 33107c478bd9Sstevel@tonic-gate piclize_node(pobj); 33117c478bd9Sstevel@tonic-gate picl_root_obj = pobj; 33127c478bd9Sstevel@tonic-gate ptree_root_hdl = pobj->ptree_hdl; 33137c478bd9Sstevel@tonic-gate unlock_node(pobj); /* unlock node */ 33147c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); /* unlock ptree */ 33157c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 33167c478bd9Sstevel@tonic-gate } 33177c478bd9Sstevel@tonic-gate 33187c478bd9Sstevel@tonic-gate static int 33197c478bd9Sstevel@tonic-gate picltree_init(void) 33207c478bd9Sstevel@tonic-gate { 33217c478bd9Sstevel@tonic-gate (void) rwlock_init(&ptree_rwlock, USYNC_THREAD, NULL); 33227c478bd9Sstevel@tonic-gate (void) rwlock_init(&picltbl_rwlock, USYNC_THREAD, NULL); 33237c478bd9Sstevel@tonic-gate 33247c478bd9Sstevel@tonic-gate if (hash_init(&picltbl) < 0) 33257c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33267c478bd9Sstevel@tonic-gate if (hash_init(&ptreetbl) < 0) 33277c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33287c478bd9Sstevel@tonic-gate 33297c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&ptreehdl_lock, NULL) != 0) 33307c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33317c478bd9Sstevel@tonic-gate 33327c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&piclhdl_lock, NULL) != 0) 33337c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33347c478bd9Sstevel@tonic-gate 33357c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&evtq_lock, NULL) != 0) 33367c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33377c478bd9Sstevel@tonic-gate if (pthread_cond_init(&evtq_cv, NULL) != 0) 33387c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33397c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&evthandler_lock, NULL) != 0) 33407c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 33417c478bd9Sstevel@tonic-gate 33427c478bd9Sstevel@tonic-gate picl_root_obj = NULL; 33437c478bd9Sstevel@tonic-gate eventqp = NULL; 33447c478bd9Sstevel@tonic-gate evt_handlers = NULL; 33457c478bd9Sstevel@tonic-gate ptree_root_hdl = PICL_INVALID_PICLHDL; 33467c478bd9Sstevel@tonic-gate 33477c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 33487c478bd9Sstevel@tonic-gate } 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate static void 33517c478bd9Sstevel@tonic-gate add_unique_plugin_to_list(char *path, char *name) 33527c478bd9Sstevel@tonic-gate { 33537c478bd9Sstevel@tonic-gate char *buf; 33547c478bd9Sstevel@tonic-gate picld_plugin_desc_t *pl; 33557c478bd9Sstevel@tonic-gate picld_plugin_desc_t *tmp; 33567c478bd9Sstevel@tonic-gate 33577c478bd9Sstevel@tonic-gate pl = plugin_desc; 33587c478bd9Sstevel@tonic-gate while (pl != NULL) { 33597c478bd9Sstevel@tonic-gate if (strcmp(pl->libname, name) == 0) 33607c478bd9Sstevel@tonic-gate return; 33617c478bd9Sstevel@tonic-gate else 33627c478bd9Sstevel@tonic-gate pl = pl->next; 33637c478bd9Sstevel@tonic-gate } 33647c478bd9Sstevel@tonic-gate 33657c478bd9Sstevel@tonic-gate pl = malloc(sizeof (picld_plugin_desc_t)); 33667c478bd9Sstevel@tonic-gate if (pl == NULL) 33677c478bd9Sstevel@tonic-gate return; 33687c478bd9Sstevel@tonic-gate 33697c478bd9Sstevel@tonic-gate pl->libname = strdup(name); 33707c478bd9Sstevel@tonic-gate if (pl->libname == NULL) 33717c478bd9Sstevel@tonic-gate return; 33727c478bd9Sstevel@tonic-gate buf = alloca(strlen(name) + strlen(path) + 2); 33737c478bd9Sstevel@tonic-gate if (buf == NULL) 33747c478bd9Sstevel@tonic-gate return; 33757c478bd9Sstevel@tonic-gate (void) strcpy(buf, path); 33767c478bd9Sstevel@tonic-gate (void) strcat(buf, name); 33777c478bd9Sstevel@tonic-gate pl->pathname = strdup(buf); 33787c478bd9Sstevel@tonic-gate if (pl->pathname == NULL) 33797c478bd9Sstevel@tonic-gate return; 33807c478bd9Sstevel@tonic-gate 33817c478bd9Sstevel@tonic-gate pl->next = NULL; 33827c478bd9Sstevel@tonic-gate 33837c478bd9Sstevel@tonic-gate if (plugin_desc == NULL) 33847c478bd9Sstevel@tonic-gate plugin_desc = pl; 33857c478bd9Sstevel@tonic-gate else { 33867c478bd9Sstevel@tonic-gate tmp = plugin_desc; 33877c478bd9Sstevel@tonic-gate while (tmp->next != NULL) 33887c478bd9Sstevel@tonic-gate tmp = tmp->next; 33897c478bd9Sstevel@tonic-gate tmp->next = pl; 33907c478bd9Sstevel@tonic-gate } 33917c478bd9Sstevel@tonic-gate } 33927c478bd9Sstevel@tonic-gate 33937c478bd9Sstevel@tonic-gate static void 33947c478bd9Sstevel@tonic-gate get_plugins_from_dir(char *dirname) 33957c478bd9Sstevel@tonic-gate { 33967c478bd9Sstevel@tonic-gate struct dirent *ent; 33977c478bd9Sstevel@tonic-gate DIR *dir; 33987c478bd9Sstevel@tonic-gate int len; 33997c478bd9Sstevel@tonic-gate int solen = strlen(SO_VERS) + 1; 34007c478bd9Sstevel@tonic-gate 34017c478bd9Sstevel@tonic-gate if ((dir = opendir(dirname)) == NULL) 34027c478bd9Sstevel@tonic-gate return; 34037c478bd9Sstevel@tonic-gate 34047c478bd9Sstevel@tonic-gate while ((ent = readdir(dir)) != NULL) { 34057c478bd9Sstevel@tonic-gate if ((strcmp(ent->d_name, ".") == 0) || 34067c478bd9Sstevel@tonic-gate (strcmp(ent->d_name, "..") == 0)) 34077c478bd9Sstevel@tonic-gate continue; 34087c478bd9Sstevel@tonic-gate 34097c478bd9Sstevel@tonic-gate len = strlen(ent->d_name) + 1; 34107c478bd9Sstevel@tonic-gate if (len < solen) 34117c478bd9Sstevel@tonic-gate continue; 34127c478bd9Sstevel@tonic-gate 34137c478bd9Sstevel@tonic-gate if (strcmp(ent->d_name + (len - solen), SO_VERS) == 0) 34147c478bd9Sstevel@tonic-gate add_unique_plugin_to_list(dirname, ent->d_name); 34157c478bd9Sstevel@tonic-gate } 34167c478bd9Sstevel@tonic-gate 34177c478bd9Sstevel@tonic-gate (void) closedir(dir); 34187c478bd9Sstevel@tonic-gate } 34197c478bd9Sstevel@tonic-gate 34207c478bd9Sstevel@tonic-gate 34217c478bd9Sstevel@tonic-gate static void 34227c478bd9Sstevel@tonic-gate init_plugin_list(void) 34237c478bd9Sstevel@tonic-gate { 34247c478bd9Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 34257c478bd9Sstevel@tonic-gate char pname[PATH_MAX]; 34267c478bd9Sstevel@tonic-gate 34277c478bd9Sstevel@tonic-gate plugin_desc = NULL; 34287c478bd9Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 34297c478bd9Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 34307c478bd9Sstevel@tonic-gate if (access(pname, R_OK) == 0) 34317c478bd9Sstevel@tonic-gate get_plugins_from_dir(pname); 34327c478bd9Sstevel@tonic-gate } 34337c478bd9Sstevel@tonic-gate 34347c478bd9Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 34357c478bd9Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 34367c478bd9Sstevel@tonic-gate if (access(pname, R_OK) == 0) 34377c478bd9Sstevel@tonic-gate get_plugins_from_dir(pname); 34387c478bd9Sstevel@tonic-gate } 34397c478bd9Sstevel@tonic-gate 34407c478bd9Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/", PICLD_COMMON_PLUGIN_DIR); 34417c478bd9Sstevel@tonic-gate if (access(pname, R_OK) == 0) 34427c478bd9Sstevel@tonic-gate get_plugins_from_dir(pname); 34437c478bd9Sstevel@tonic-gate } 34447c478bd9Sstevel@tonic-gate 34457c478bd9Sstevel@tonic-gate static void 34467c478bd9Sstevel@tonic-gate load_plugins(void) 34477c478bd9Sstevel@tonic-gate { 34487c478bd9Sstevel@tonic-gate picld_plugin_desc_t *pl; 34497c478bd9Sstevel@tonic-gate 34507c478bd9Sstevel@tonic-gate pl = plugin_desc; 34517c478bd9Sstevel@tonic-gate while (pl != NULL) { 34527c478bd9Sstevel@tonic-gate pl->dlh = dlopen(pl->pathname, RTLD_LAZY|RTLD_LOCAL); 34537c478bd9Sstevel@tonic-gate if (pl->dlh == NULL) { 34547c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, dlerror()); 34557c478bd9Sstevel@tonic-gate return; 34567c478bd9Sstevel@tonic-gate } 34577c478bd9Sstevel@tonic-gate pl = pl->next; 34587c478bd9Sstevel@tonic-gate } 34597c478bd9Sstevel@tonic-gate } 34607c478bd9Sstevel@tonic-gate 34617c478bd9Sstevel@tonic-gate 34627c478bd9Sstevel@tonic-gate 34637c478bd9Sstevel@tonic-gate static int 34647c478bd9Sstevel@tonic-gate add_root_props(picl_nodehdl_t rooth) 34657c478bd9Sstevel@tonic-gate { 34667c478bd9Sstevel@tonic-gate int err; 34677c478bd9Sstevel@tonic-gate picl_prophdl_t proph; 34687c478bd9Sstevel@tonic-gate ptree_propinfo_t pinfo; 34697c478bd9Sstevel@tonic-gate float picl_vers; 34707c478bd9Sstevel@tonic-gate 34717c478bd9Sstevel@tonic-gate #define PICL_PROP_PICL_VERSION "PICLVersion" 34727c478bd9Sstevel@tonic-gate #define PICL_VERSION 1.1 34737c478bd9Sstevel@tonic-gate 34747c478bd9Sstevel@tonic-gate err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION_1, 34757c478bd9Sstevel@tonic-gate PICL_PTYPE_FLOAT, PICL_READ, sizeof (picl_vers), 34767c478bd9Sstevel@tonic-gate PICL_PROP_PICL_VERSION, NULL, NULL); 34777c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 34787c478bd9Sstevel@tonic-gate return (err); 34797c478bd9Sstevel@tonic-gate 34807c478bd9Sstevel@tonic-gate picl_vers = PICL_VERSION; 34817c478bd9Sstevel@tonic-gate err = ptree_create_and_add_prop(rooth, &pinfo, &picl_vers, &proph); 34827c478bd9Sstevel@tonic-gate return (err); 34837c478bd9Sstevel@tonic-gate } 34847c478bd9Sstevel@tonic-gate 34857c478bd9Sstevel@tonic-gate static int 34867c478bd9Sstevel@tonic-gate construct_picltree(void) 34877c478bd9Sstevel@tonic-gate { 34887c478bd9Sstevel@tonic-gate int err; 34897c478bd9Sstevel@tonic-gate picld_plugin_reg_list_t *iter; 34907c478bd9Sstevel@tonic-gate picl_nodehdl_t rhdl; 34917c478bd9Sstevel@tonic-gate 34927c478bd9Sstevel@tonic-gate /* 34937c478bd9Sstevel@tonic-gate * Create "/" node 34947c478bd9Sstevel@tonic-gate */ 34957c478bd9Sstevel@tonic-gate if ((err = ptree_create_node(PICL_NODE_ROOT, PICL_CLASS_PICL, 34967c478bd9Sstevel@tonic-gate &rhdl)) != PICL_SUCCESS) { 34977c478bd9Sstevel@tonic-gate return (err); 34987c478bd9Sstevel@tonic-gate } 34997c478bd9Sstevel@tonic-gate 35007c478bd9Sstevel@tonic-gate if (picltree_set_root(rhdl) != PICL_SUCCESS) { 35017c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 35027c478bd9Sstevel@tonic-gate } 35037c478bd9Sstevel@tonic-gate 35047c478bd9Sstevel@tonic-gate err = add_root_props(rhdl); 35057c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 35067c478bd9Sstevel@tonic-gate return (err); 35077c478bd9Sstevel@tonic-gate 35087c478bd9Sstevel@tonic-gate /* 35097c478bd9Sstevel@tonic-gate * Initialize the registered plug-in modules 35107c478bd9Sstevel@tonic-gate */ 35117c478bd9Sstevel@tonic-gate iter = plugin_reg_list; 35127c478bd9Sstevel@tonic-gate while (iter != NULL) { 35137c478bd9Sstevel@tonic-gate if (iter->reg.plugin_init) 35147c478bd9Sstevel@tonic-gate (iter->reg.plugin_init)(); 35157c478bd9Sstevel@tonic-gate iter = iter->next; 35167c478bd9Sstevel@tonic-gate } 35177c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 35187c478bd9Sstevel@tonic-gate } 35197c478bd9Sstevel@tonic-gate 35207c478bd9Sstevel@tonic-gate void 35217c478bd9Sstevel@tonic-gate xptree_destroy(void) 35227c478bd9Sstevel@tonic-gate { 35237c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_destroy: picl_root_obj = %s\n", 35247c478bd9Sstevel@tonic-gate (picl_root_obj == NULL ? "NULL" : "not-NULL")); 35257c478bd9Sstevel@tonic-gate 35267c478bd9Sstevel@tonic-gate if (picl_root_obj == NULL) 35277c478bd9Sstevel@tonic-gate return; 35287c478bd9Sstevel@tonic-gate 35297c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_destroy: call plugin_fini\n"); 35307c478bd9Sstevel@tonic-gate plugin_fini(plugin_reg_list); 35317c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_destroy: plugin_fini DONE\n"); 35327c478bd9Sstevel@tonic-gate 35337c478bd9Sstevel@tonic-gate (void) ptree_delete_node(picl_root_obj->ptree_hdl); 35347c478bd9Sstevel@tonic-gate (void) ptree_destroy_node(picl_root_obj->ptree_hdl); 35357c478bd9Sstevel@tonic-gate 35367c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); 35377c478bd9Sstevel@tonic-gate picl_root_obj = NULL; 35387c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 35397c478bd9Sstevel@tonic-gate } 35407c478bd9Sstevel@tonic-gate 35417c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 35427c478bd9Sstevel@tonic-gate int 35437c478bd9Sstevel@tonic-gate xptree_initialize(int flg) 35447c478bd9Sstevel@tonic-gate { 35457c478bd9Sstevel@tonic-gate int err; 35467c478bd9Sstevel@tonic-gate pthread_attr_t attr; 35477c478bd9Sstevel@tonic-gate pthread_t tid; 35487c478bd9Sstevel@tonic-gate 35497c478bd9Sstevel@tonic-gate picld_pid = getpid(); 35507c478bd9Sstevel@tonic-gate picld_cred.dc_euid = geteuid(); 35517c478bd9Sstevel@tonic-gate picld_cred.dc_egid = getegid(); 35527c478bd9Sstevel@tonic-gate picld_cred.dc_ruid = getuid(); 35537c478bd9Sstevel@tonic-gate picld_cred.dc_rgid = getgid(); 35547c478bd9Sstevel@tonic-gate picld_cred.dc_pid = getpid(); 35557c478bd9Sstevel@tonic-gate 35567c478bd9Sstevel@tonic-gate picl_hdl_hi = 1; 35577c478bd9Sstevel@tonic-gate ptree_hdl_hi = 1; 35587c478bd9Sstevel@tonic-gate ptree_generation = 1; 35597c478bd9Sstevel@tonic-gate qempty_wait = 0; 35607c478bd9Sstevel@tonic-gate 35617c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&ptree_refresh_mutex, NULL) != 0) 35627c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 35637c478bd9Sstevel@tonic-gate 35647c478bd9Sstevel@tonic-gate if (picltree_init() != PICL_SUCCESS) 35657c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 35667c478bd9Sstevel@tonic-gate 35677c478bd9Sstevel@tonic-gate init_plugin_reg_list(); 35687c478bd9Sstevel@tonic-gate init_plugin_list(); 35697c478bd9Sstevel@tonic-gate load_plugins(); 35707c478bd9Sstevel@tonic-gate 35717c478bd9Sstevel@tonic-gate err = construct_picltree(); 35727c478bd9Sstevel@tonic-gate if (err != PICL_SUCCESS) 35737c478bd9Sstevel@tonic-gate return (err); 35747c478bd9Sstevel@tonic-gate 35757c478bd9Sstevel@tonic-gate /* 35767c478bd9Sstevel@tonic-gate * Dispatch events after all plug-ins have initialized 35777c478bd9Sstevel@tonic-gate */ 35787c478bd9Sstevel@tonic-gate if (pthread_attr_init(&attr) != 0) 35797c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 35807c478bd9Sstevel@tonic-gate 35817c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 35827c478bd9Sstevel@tonic-gate if (pthread_create(&tid, &attr, ptree_event_thread, NULL)) 35837c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 35847c478bd9Sstevel@tonic-gate 35857c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 35867c478bd9Sstevel@tonic-gate } 35877c478bd9Sstevel@tonic-gate 35887c478bd9Sstevel@tonic-gate int 35897c478bd9Sstevel@tonic-gate xptree_reinitialize(void) 35907c478bd9Sstevel@tonic-gate { 35917c478bd9Sstevel@tonic-gate int err; 35927c478bd9Sstevel@tonic-gate 35937c478bd9Sstevel@tonic-gate /* 35947c478bd9Sstevel@tonic-gate * Wait for eventq to become empty 35957c478bd9Sstevel@tonic-gate */ 35967c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_reinitialize: wait for evtq empty\n"); 35977c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 35987c478bd9Sstevel@tonic-gate qempty_wait = 1; 35997c478bd9Sstevel@tonic-gate while (eventqp != NULL) 36007c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&evtq_empty, &evtq_lock); 36017c478bd9Sstevel@tonic-gate qempty_wait = 0; 36027c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 36037c478bd9Sstevel@tonic-gate dbg_print(1, "xptree_reinitialize: evtq empty is EMPTY\n"); 36047c478bd9Sstevel@tonic-gate 36057c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ptree_rwlock); 36067c478bd9Sstevel@tonic-gate picl_root_obj = NULL; 36077c478bd9Sstevel@tonic-gate ptree_root_hdl = PICL_INVALID_PICLHDL; 36087c478bd9Sstevel@tonic-gate (void) rw_unlock(&ptree_rwlock); 36097c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptree_refresh_mutex); 36107c478bd9Sstevel@tonic-gate ++ptree_generation; 36117c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 36127c478bd9Sstevel@tonic-gate 36137c478bd9Sstevel@tonic-gate err = construct_picltree(); 36147c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ptree_refresh_mutex); 36157c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&ptree_refresh_cond); 36167c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 36177c478bd9Sstevel@tonic-gate 36187c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&evtq_lock); 36197c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&evtq_cv); 36207c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&evtq_lock); 36217c478bd9Sstevel@tonic-gate 36227c478bd9Sstevel@tonic-gate return (err); 36237c478bd9Sstevel@tonic-gate } 36247c478bd9Sstevel@tonic-gate 36257c478bd9Sstevel@tonic-gate /* 36267c478bd9Sstevel@tonic-gate * This function is called by the PICL daemon on behalf of clients to 36277c478bd9Sstevel@tonic-gate * wait for a tree refresh 36287c478bd9Sstevel@tonic-gate */ 36297c478bd9Sstevel@tonic-gate int 36307c478bd9Sstevel@tonic-gate xptree_refresh_notify(uint32_t secs) 36317c478bd9Sstevel@tonic-gate { 36327c478bd9Sstevel@tonic-gate int curgen; 36337c478bd9Sstevel@tonic-gate int ret; 36347c478bd9Sstevel@tonic-gate timespec_t to; 36357c478bd9Sstevel@tonic-gate 3636cec46d77Sanbui if (secs != 0) { 36377c478bd9Sstevel@tonic-gate if (pthread_mutex_lock(&ptree_refresh_mutex) != 0) 36387c478bd9Sstevel@tonic-gate return (PICL_FAILURE); 36397c478bd9Sstevel@tonic-gate 36407c478bd9Sstevel@tonic-gate curgen = ptree_generation; 36417c478bd9Sstevel@tonic-gate 36427c478bd9Sstevel@tonic-gate while (curgen == ptree_generation) { 36434c4e8250Sanbui if (secs == UINT32_MAX) /* wait forever */ 36447c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&ptree_refresh_cond, 36457c478bd9Sstevel@tonic-gate &ptree_refresh_mutex); 36467c478bd9Sstevel@tonic-gate else { 36477c478bd9Sstevel@tonic-gate to.tv_sec = secs; 36487c478bd9Sstevel@tonic-gate to.tv_nsec = 0; 3649cec46d77Sanbui ret = pthread_cond_reltimedwait_np( 3650cec46d77Sanbui &ptree_refresh_cond, 36517c478bd9Sstevel@tonic-gate &ptree_refresh_mutex, &to); 36527c478bd9Sstevel@tonic-gate if (ret == ETIMEDOUT) 36537c478bd9Sstevel@tonic-gate break; 36547c478bd9Sstevel@tonic-gate } 36557c478bd9Sstevel@tonic-gate } 36567c478bd9Sstevel@tonic-gate 36577c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ptree_refresh_mutex); 3658cec46d77Sanbui } 3659cec46d77Sanbui 36607c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 36617c478bd9Sstevel@tonic-gate } 36627c478bd9Sstevel@tonic-gate 36637c478bd9Sstevel@tonic-gate /*VARARGS2*/ 36647c478bd9Sstevel@tonic-gate void 36657c478bd9Sstevel@tonic-gate dbg_print(int level, const char *fmt, ...) 36667c478bd9Sstevel@tonic-gate { 36677c478bd9Sstevel@tonic-gate if (verbose_level >= level) { 36687c478bd9Sstevel@tonic-gate va_list ap; 36697c478bd9Sstevel@tonic-gate 36707c478bd9Sstevel@tonic-gate va_start(ap, fmt); 36717c478bd9Sstevel@tonic-gate (void) vprintf(fmt, ap); 36727c478bd9Sstevel@tonic-gate va_end(ap); 36737c478bd9Sstevel@tonic-gate } 36747c478bd9Sstevel@tonic-gate } 36757c478bd9Sstevel@tonic-gate 36767c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 36777c478bd9Sstevel@tonic-gate void 36787c478bd9Sstevel@tonic-gate dbg_exec(int level, void (*fn)(void *args), void *args) 36797c478bd9Sstevel@tonic-gate { 36807c478bd9Sstevel@tonic-gate if (verbose_level > level) 36817c478bd9Sstevel@tonic-gate (*fn)(args); 36827c478bd9Sstevel@tonic-gate } 3683