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