xref: /onnv-gate/usr/src/lib/libpicltree/picltree.c (revision 13093:48f2dbca79a2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*13093SRoger.Faulkner@Oracle.COM  * Common Development and Distribution License (the "License").
6*13093SRoger.Faulkner@Oracle.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This module implements the PTree interface and the PICL to PTree calls
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * Note:
320Sstevel@tonic-gate  * PICL Node and Property Handles Table:
330Sstevel@tonic-gate  * A node or property in PICL tree has two handles: a ptree handle, which is
340Sstevel@tonic-gate  * used by plug-ins and the libpicltree interface, and a picl handle
350Sstevel@tonic-gate  * which is used by clients and the libpicl interface.
360Sstevel@tonic-gate  * The mapping of ptree handles to the internal PICL object (picl_obj_t) is
370Sstevel@tonic-gate  * kept in a ptree hash table (ptreetbl), and the mapping of a picl handle
380Sstevel@tonic-gate  * to its ptree handle is kept in the picl hash table (picltbl).
390Sstevel@tonic-gate  * The reader/writer lock, ptree_rwlock, is held when reading or modifying ptree
400Sstevel@tonic-gate  * hash table (ptreetbl) and/or the PICL tree structure (nodes and linkages
410Sstevel@tonic-gate  * between them). The reader/writer lock, picltbl_rwlock, is held when reading
420Sstevel@tonic-gate  * or modifying picl hash table (picltbl).
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  * The mutex, ptreehdl_lock, is used to control allocation of ptree handles.
450Sstevel@tonic-gate  * The mutex, piclhdl_lock, is used to control allocation of picl handles.
460Sstevel@tonic-gate  *
470Sstevel@tonic-gate  * The mutex, ptree_refresh_mutex, and the condition, ptree_refresh_cond,
480Sstevel@tonic-gate  * are used to synchronize PICL refreshes (ptree_refresh) and to wait/signal
490Sstevel@tonic-gate  * change in PICL tree structure.
500Sstevel@tonic-gate  *
510Sstevel@tonic-gate  * The counter, picl_hdl_hi, is the hi water mark for allocated picl handles.
520Sstevel@tonic-gate  * The counter, ptree_hdl_hi, is the hi water mark for allocated ptree handles.
530Sstevel@tonic-gate  * A stale handle error is returned for handle values below the hi water
540Sstevel@tonic-gate  * mark, and invalid handles are returned for handle values above the hi water
550Sstevel@tonic-gate  * mark or when the process id field of the handle does not match.
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  * Locking Scheme:
580Sstevel@tonic-gate  * The structure of the PICL tree is controlled by the ptree_rwlock. The
590Sstevel@tonic-gate  * properties of a node are controlled by individual node locks. The
600Sstevel@tonic-gate  * piclize-ing or unpiclize-ing of a node is controlled by picltbl_rwlock.
610Sstevel@tonic-gate  *
620Sstevel@tonic-gate  * Two-Phase Locking scheme: lock acquire phase and lock release phase.
630Sstevel@tonic-gate  *
640Sstevel@tonic-gate  * Lock Ordering:
650Sstevel@tonic-gate  * The ptree_rwlock and node locks are always acquired in the following order:
660Sstevel@tonic-gate  *	lock ptree_rwlock
670Sstevel@tonic-gate  *	lock node
680Sstevel@tonic-gate  *
690Sstevel@tonic-gate  * Lock Strategy:
700Sstevel@tonic-gate  * There are three locks:
710Sstevel@tonic-gate  *	ptree_rwlock:	a reader lock is obtained to do ptree hash table
720Sstevel@tonic-gate  *			lookups and traverse tree. A writer lock is obtained
730Sstevel@tonic-gate  *			when creating or destroying nodes from the ptree,
740Sstevel@tonic-gate  *			or when modifying node linkages: parent, peer, child.
750Sstevel@tonic-gate  *	picltbl_rwlock:	a reader lock is obtained for picl hash table lookups.
760Sstevel@tonic-gate  *			A writer lock is obtained when piclize-ing or
770Sstevel@tonic-gate  *			unpiclize-ing nodes or properties.
780Sstevel@tonic-gate  *	node_lock:	This is a reader/writer lock for properties of a node.
790Sstevel@tonic-gate  *			A reader lock is obtained before reading property
800Sstevel@tonic-gate  *			values. A writer lock is obtained when adding or
810Sstevel@tonic-gate  *			removing properties and when modifying a property value.
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * Never hold more than one node lock at a time.
840Sstevel@tonic-gate  *
850Sstevel@tonic-gate  * Event Locking:
860Sstevel@tonic-gate  * There are two locks:
870Sstevel@tonic-gate  *	evtq_lock:	this lock protects the event queue. It is obtained
880Sstevel@tonic-gate  *			to queue events that are posted and to unqueue
890Sstevel@tonic-gate  *			events to be dispatched.
900Sstevel@tonic-gate  *	evtq_cv:	condition variable is protected by evtq_lock. It is
910Sstevel@tonic-gate  *			used by the ptree event thread to wait for events
920Sstevel@tonic-gate  *			until eventqp is not NULL.
930Sstevel@tonic-gate  *	evtq_empty:	condition variable protected by evtq_lock. It is
940Sstevel@tonic-gate  *			used to signal when the eventq becomes empty. The
950Sstevel@tonic-gate  *			reinitialization process waits on this condition.
960Sstevel@tonic-gate  *     evthandler_lock: this protects the event handler list. It is obtained
970Sstevel@tonic-gate  *			to add event handlers on registration and to remove
980Sstevel@tonic-gate  *			event handlers on unregistration.
990Sstevel@tonic-gate  *      (handler)->cv:	condition variable per handler protected by
1000Sstevel@tonic-gate  *			evthandler_lock.  It is used to wait until the
1010Sstevel@tonic-gate  *			event handler completes execution (execflg == 0)
1020Sstevel@tonic-gate  *			before unregistering the handler.
1030Sstevel@tonic-gate  */
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate #include <stdio.h>
1060Sstevel@tonic-gate #include <string.h>
1070Sstevel@tonic-gate #include <strings.h>
1080Sstevel@tonic-gate #include <stdlib.h>
1090Sstevel@tonic-gate #include <stdarg.h>
1100Sstevel@tonic-gate #include <alloca.h>
1110Sstevel@tonic-gate #include <assert.h>
1120Sstevel@tonic-gate #include <errno.h>
1130Sstevel@tonic-gate #include <unistd.h>
1140Sstevel@tonic-gate #include <limits.h>
1150Sstevel@tonic-gate #include <libintl.h>
1160Sstevel@tonic-gate #include <syslog.h>
1170Sstevel@tonic-gate #include <pthread.h>
1180Sstevel@tonic-gate #include <synch.h>
1190Sstevel@tonic-gate #include <setjmp.h>
1200Sstevel@tonic-gate #include <signal.h>
1210Sstevel@tonic-gate #include <dlfcn.h>
1220Sstevel@tonic-gate #include <dirent.h>
1230Sstevel@tonic-gate #include <door.h>
1240Sstevel@tonic-gate #include <time.h>
1250Sstevel@tonic-gate #include <inttypes.h>
1260Sstevel@tonic-gate #include <sys/systeminfo.h>
1270Sstevel@tonic-gate #include <sys/utsname.h>
1280Sstevel@tonic-gate #include <picl.h>
1290Sstevel@tonic-gate #include <picltree.h>
1300Sstevel@tonic-gate #include "picldefs.h"
1310Sstevel@tonic-gate #include "ptree_impl.h"
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate #define	SO_VERS	".so.1"
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate static	hash_t		picltbl;	/* client handles to picl obj */
1360Sstevel@tonic-gate static	hash_t		ptreetbl;	/* ptree handles to picl obj */
1370Sstevel@tonic-gate static	pthread_mutex_t	ptreehdl_lock;
1380Sstevel@tonic-gate static	pthread_mutex_t	piclhdl_lock;
1390Sstevel@tonic-gate static	pthread_mutex_t	ptree_refresh_mutex;
1400Sstevel@tonic-gate static	rwlock_t	picltbl_rwlock;	/* PICL handle table lock */
1410Sstevel@tonic-gate static	rwlock_t	ptree_rwlock;	/* PICL tree lock */
1420Sstevel@tonic-gate static	pthread_cond_t	ptree_refresh_cond = PTHREAD_COND_INITIALIZER;
1430Sstevel@tonic-gate static	uint32_t	ptree_hdl_hi = 1;
1440Sstevel@tonic-gate static	uint32_t	picl_hdl_hi = 1;
1450Sstevel@tonic-gate static	picl_obj_t	*picl_root_obj = NULL;
1460Sstevel@tonic-gate static	picl_nodehdl_t	ptree_root_hdl = PICL_INVALID_PICLHDL;
1470Sstevel@tonic-gate static	int		ptree_generation = 0;
1480Sstevel@tonic-gate static	pid_t		picld_pid;
1490Sstevel@tonic-gate static	door_cred_t	picld_cred;
1500Sstevel@tonic-gate static	int		qempty_wait;	/* evtq_empty condition waiter flag */
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate static	picld_plugin_reg_list_t		*plugin_reg_list = NULL;
1530Sstevel@tonic-gate static	picld_plugin_desc_t		*plugin_desc;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate static	eventq_t	*eventqp;	/* PICL events queue */
1560Sstevel@tonic-gate static	pthread_mutex_t	evtq_lock = PTHREAD_MUTEX_INITIALIZER;
1570Sstevel@tonic-gate static	pthread_cond_t	evtq_cv = PTHREAD_COND_INITIALIZER;
1580Sstevel@tonic-gate static	pthread_cond_t	evtq_empty = PTHREAD_COND_INITIALIZER;
1590Sstevel@tonic-gate static	evt_handler_t	*evt_handlers;	/* Event handler list */
1600Sstevel@tonic-gate static	pthread_mutex_t	evthandler_lock = PTHREAD_MUTEX_INITIALIZER;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate /*
1630Sstevel@tonic-gate  * PICL daemon verbose level
1640Sstevel@tonic-gate  */
1650Sstevel@tonic-gate int	verbose_level;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate  * Event handler free functions
1700Sstevel@tonic-gate  */
1710Sstevel@tonic-gate static void
free_handler(evt_handler_t * evhp)1720Sstevel@tonic-gate free_handler(evt_handler_t *evhp)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate 	if (evhp->ename)
1750Sstevel@tonic-gate 		free(evhp->ename);
1760Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&evhp->cv);
1770Sstevel@tonic-gate 	(void) pthread_cond_destroy(&evhp->cv);
1780Sstevel@tonic-gate 	free(evhp);
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate /*
1830Sstevel@tonic-gate  * queue_event to events queue
1840Sstevel@tonic-gate  */
1850Sstevel@tonic-gate static void
queue_event(eventq_t * evt)1860Sstevel@tonic-gate queue_event(eventq_t *evt)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate 	eventq_t	*tmpp;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	evt->next = NULL;
1910Sstevel@tonic-gate 	if (eventqp == NULL)
1920Sstevel@tonic-gate 		eventqp = evt;
1930Sstevel@tonic-gate 	else {
1940Sstevel@tonic-gate 		tmpp = eventqp;
1950Sstevel@tonic-gate 		while (tmpp->next != NULL)
1960Sstevel@tonic-gate 			tmpp = tmpp->next;
1970Sstevel@tonic-gate 		tmpp->next = evt;
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate  * unqueue_event from the specified eventq
2030Sstevel@tonic-gate  */
2040Sstevel@tonic-gate static eventq_t *
unqueue_event(eventq_t ** qp)2050Sstevel@tonic-gate unqueue_event(eventq_t **qp)
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate 	eventq_t	*evtp;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	evtp = *qp;
2100Sstevel@tonic-gate 	if (evtp != NULL)
2110Sstevel@tonic-gate 		*qp = evtp->next;
2120Sstevel@tonic-gate 	return (evtp);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate /*
2160Sstevel@tonic-gate  * register an event handler by adding it to the list
2170Sstevel@tonic-gate  */
2180Sstevel@tonic-gate int
ptree_register_handler(const char * ename,void (* evt_handler)(const char * ename,const void * earg,size_t size,void * cookie),void * cookie)2190Sstevel@tonic-gate ptree_register_handler(const char *ename,
2200Sstevel@tonic-gate     void (*evt_handler)(const char *ename, const void *earg, size_t size,
2210Sstevel@tonic-gate     void *cookie), void *cookie)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate 	evt_handler_t	*ent;
2240Sstevel@tonic-gate 	evt_handler_t	*iter;
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	if (ename == NULL)
2270Sstevel@tonic-gate 		return (PICL_INVALIDARG);
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	/*
2300Sstevel@tonic-gate 	 * Initialize event handler entry
2310Sstevel@tonic-gate 	 */
2320Sstevel@tonic-gate 	ent = malloc(sizeof (*ent));
2330Sstevel@tonic-gate 	if (ent == NULL)
2340Sstevel@tonic-gate 		return (PICL_FAILURE);
2350Sstevel@tonic-gate 	ent->ename = strdup(ename);
2360Sstevel@tonic-gate 	if (ent->ename == NULL) {
2370Sstevel@tonic-gate 		free(ent);
2380Sstevel@tonic-gate 		return (PICL_FAILURE);
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 	ent->cookie = cookie;
2410Sstevel@tonic-gate 	ent->evt_handler = evt_handler;
2420Sstevel@tonic-gate 	ent->execflg = 0;
2430Sstevel@tonic-gate 	ent->wakeupflg = 0;
2440Sstevel@tonic-gate 	(void) pthread_cond_init(&ent->cv, NULL);
2450Sstevel@tonic-gate 	ent->next = NULL;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	/*
2480Sstevel@tonic-gate 	 * add handler to the handler list
2490Sstevel@tonic-gate 	 */
2500Sstevel@tonic-gate 	(void) pthread_mutex_lock(&evthandler_lock);
2510Sstevel@tonic-gate 	if (evt_handlers == NULL) {
2520Sstevel@tonic-gate 		evt_handlers = ent;
2530Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&evthandler_lock);
2540Sstevel@tonic-gate 		return (PICL_SUCCESS);
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 	iter = evt_handlers;
2570Sstevel@tonic-gate 	while (iter->next != NULL)
2580Sstevel@tonic-gate 		iter = iter->next;
2590Sstevel@tonic-gate 	iter->next = ent;
2600Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&evthandler_lock);
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	return (PICL_SUCCESS);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate /*
2660Sstevel@tonic-gate  * unregister handler
2670Sstevel@tonic-gate  */
2680Sstevel@tonic-gate void
ptree_unregister_handler(const char * ename,void (* evt_handler)(const char * ename,const void * earg,size_t size,void * cookie),void * cookie)2690Sstevel@tonic-gate ptree_unregister_handler(const char *ename,
2700Sstevel@tonic-gate     void (*evt_handler)(const char *ename, const void *earg, size_t size,
2710Sstevel@tonic-gate     void *cookie), void *cookie)
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate 	evt_handler_t	*evhdlrp, **evhdlrpp;
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	if (ename == NULL)
2760Sstevel@tonic-gate 		return;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	/*
2790Sstevel@tonic-gate 	 * unlink handler from handler list
2800Sstevel@tonic-gate 	 */
2810Sstevel@tonic-gate 	(void) pthread_mutex_lock(&evthandler_lock);
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate retry:
2840Sstevel@tonic-gate 	for (evhdlrpp = &evt_handlers; (evhdlrp = *evhdlrpp) != NULL;
2850Sstevel@tonic-gate 	    evhdlrpp = &evhdlrp->next) {
2860Sstevel@tonic-gate 		if ((evhdlrp->cookie != cookie) ||
2870Sstevel@tonic-gate 		    (strcmp(evhdlrp->ename, ename) != 0) ||
2880Sstevel@tonic-gate 		    (evhdlrp->evt_handler != evt_handler))
2890Sstevel@tonic-gate 			continue;
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 		/*
2920Sstevel@tonic-gate 		 * If the handler is in execution, release the lock
2930Sstevel@tonic-gate 		 * and wait for it to complete and retry.
2940Sstevel@tonic-gate 		 */
2950Sstevel@tonic-gate 		if (evhdlrp->execflg) {
2960Sstevel@tonic-gate 			evhdlrp->wakeupflg = 1;
2970Sstevel@tonic-gate 			(void) pthread_cond_wait(&evhdlrp->cv,
2980Sstevel@tonic-gate 			    &evthandler_lock);
2990Sstevel@tonic-gate 			goto retry;
3000Sstevel@tonic-gate 		}
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 		/*
3030Sstevel@tonic-gate 		 * Unlink this handler from the linked list
3040Sstevel@tonic-gate 		 */
3050Sstevel@tonic-gate 		*evhdlrpp = evhdlrp->next;
3060Sstevel@tonic-gate 		free_handler(evhdlrp);
3070Sstevel@tonic-gate 		break;
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&evthandler_lock);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate  * Call all registered handlers for the event
3150Sstevel@tonic-gate  */
3160Sstevel@tonic-gate static void
call_event_handlers(eventq_t * ev)3170Sstevel@tonic-gate call_event_handlers(eventq_t *ev)
3180Sstevel@tonic-gate {
3190Sstevel@tonic-gate 	evt_handler_t	*iter;
3200Sstevel@tonic-gate 	void	(*evhandler)(const char *, const void *, size_t, void *);
3210Sstevel@tonic-gate 	void	(*completion_handler)(char *ename, void *earg, size_t size);
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	(void) pthread_mutex_lock(&evthandler_lock);
3240Sstevel@tonic-gate 	iter = evt_handlers;
3250Sstevel@tonic-gate 	while (iter != NULL) {
3260Sstevel@tonic-gate 		if (strcmp(iter->ename, ev->ename) == 0) {
3270Sstevel@tonic-gate 			evhandler = iter->evt_handler;
3280Sstevel@tonic-gate 			iter->execflg = 1;
3290Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&evthandler_lock);
3300Sstevel@tonic-gate 			if (evhandler) {
3310Sstevel@tonic-gate 				dbg_print(2, "ptree_evthr: Invoking evthdlr:%p"
3320Sstevel@tonic-gate 				    " ename:%s\n", evhandler, ev->ename);
3330Sstevel@tonic-gate 				(*evhandler)(ev->ename, ev->earg, ev->size,
3340Sstevel@tonic-gate 				    iter->cookie);
3350Sstevel@tonic-gate 				dbg_print(2, "ptree_evthr: done evthdlr:%p "
3360Sstevel@tonic-gate 				    "ename:%s\n", evhandler, ev->ename);
3370Sstevel@tonic-gate 			}
3380Sstevel@tonic-gate 			(void) pthread_mutex_lock(&evthandler_lock);
3390Sstevel@tonic-gate 			iter->execflg = 0;
3400Sstevel@tonic-gate 			if (iter->wakeupflg) {
3410Sstevel@tonic-gate 				iter->wakeupflg = 0;
3420Sstevel@tonic-gate 				(void) pthread_cond_broadcast(&iter->cv);
3430Sstevel@tonic-gate 			}
3440Sstevel@tonic-gate 		}
3450Sstevel@tonic-gate 		iter = iter->next;
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&evthandler_lock);
3480Sstevel@tonic-gate 	if ((completion_handler = ev->completion_handler) != NULL) {
3490Sstevel@tonic-gate 		dbg_print(2,
3500Sstevel@tonic-gate 		    "ptree_evthr: Invoking completion hdlr:%p ename:%s\n",
3510Sstevel@tonic-gate 		    completion_handler, ev->ename);
3520Sstevel@tonic-gate 		(*completion_handler)((char *)ev->ename, (void *)ev->earg,
3530Sstevel@tonic-gate 		    ev->size);
3540Sstevel@tonic-gate 		dbg_print(2, "ptree_evthr: done completion hdlr:%p ename:%s\n",
3550Sstevel@tonic-gate 		    completion_handler, ev->ename);
3560Sstevel@tonic-gate 	}
3570Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ptree_refresh_mutex);
3580Sstevel@tonic-gate 	++ptree_generation;
3590Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&ptree_refresh_cond);
3600Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ptree_refresh_mutex);
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate /*
3640Sstevel@tonic-gate  * This function is called by a plug-in to post an event
3650Sstevel@tonic-gate  */
3660Sstevel@tonic-gate int
ptree_post_event(const char * ename,const void * earg,size_t size,void (* completion_handler)(char * ename,void * earg,size_t size))3670Sstevel@tonic-gate ptree_post_event(const char *ename, const void *earg, size_t size,
3680Sstevel@tonic-gate     void (*completion_handler)(char *ename, void *earg, size_t size))
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate 	eventq_t	*evt;
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	if (ename == NULL)
3730Sstevel@tonic-gate 		return (PICL_INVALIDARG);
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	evt = malloc(sizeof (*evt));
3760Sstevel@tonic-gate 	if (evt == NULL)
3770Sstevel@tonic-gate 		return (PICL_FAILURE);
3780Sstevel@tonic-gate 	evt->ename = ename;
3790Sstevel@tonic-gate 	evt->earg = earg;
3800Sstevel@tonic-gate 	evt->size = size;
3810Sstevel@tonic-gate 	evt->completion_handler = completion_handler;
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	(void) pthread_mutex_lock(&evtq_lock);
3840Sstevel@tonic-gate 	queue_event(evt);
3850Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&evtq_cv);
3860Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&evtq_lock);
3870Sstevel@tonic-gate 	return (PICL_SUCCESS);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate  * PICLTREE event thread
3920Sstevel@tonic-gate  */
3930Sstevel@tonic-gate /*ARGSUSED*/
3940Sstevel@tonic-gate static void *
ptree_event_thread(void * argp)3950Sstevel@tonic-gate ptree_event_thread(void *argp)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 	eventq_t	*evt;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	for (;;) {
4000Sstevel@tonic-gate 		(void) pthread_mutex_lock(&evtq_lock);
4010Sstevel@tonic-gate 		while (eventqp == NULL) {
4020Sstevel@tonic-gate 			/*
4030Sstevel@tonic-gate 			 * Signal empty queue
4040Sstevel@tonic-gate 			 */
4050Sstevel@tonic-gate 			if (qempty_wait)
4060Sstevel@tonic-gate 				(void) pthread_cond_broadcast(&evtq_empty);
4070Sstevel@tonic-gate 			(void) pthread_cond_wait(&evtq_cv, &evtq_lock);
4080Sstevel@tonic-gate 		}
4090Sstevel@tonic-gate 		if ((evt = unqueue_event(&eventqp)) != NULL) {
4100Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&evtq_lock);
4110Sstevel@tonic-gate 			call_event_handlers(evt);
4120Sstevel@tonic-gate 			free(evt);
4130Sstevel@tonic-gate 		} else
4140Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&evtq_lock);
4150Sstevel@tonic-gate 	}
4160Sstevel@tonic-gate 	/*NOTREACHED*/
4170Sstevel@tonic-gate 	return (NULL);
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate /*
4220Sstevel@tonic-gate  * Create a new element
4230Sstevel@tonic-gate  */
4240Sstevel@tonic-gate static hash_elem_t *
hash_newobj(uint32_t hdl_val,void * obj_val)4250Sstevel@tonic-gate hash_newobj(uint32_t hdl_val, void *obj_val)
4260Sstevel@tonic-gate {
4270Sstevel@tonic-gate 	hash_elem_t	*n;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	n = malloc(sizeof (*n));
4300Sstevel@tonic-gate 	if (n == NULL)
4310Sstevel@tonic-gate 		return (NULL);
4320Sstevel@tonic-gate 	n->hdl = hdl_val;
4330Sstevel@tonic-gate 	n->hash_obj = obj_val;
4340Sstevel@tonic-gate 	n->next = NULL;
4350Sstevel@tonic-gate 	return (n);
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate static hash_elem_t *
hash_newhdl(uint32_t picl_hdl,uint32_t ptreeh)4390Sstevel@tonic-gate hash_newhdl(uint32_t picl_hdl, uint32_t ptreeh)
4400Sstevel@tonic-gate {
4410Sstevel@tonic-gate 	hash_elem_t	*n;
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	n = malloc(sizeof (*n));
4440Sstevel@tonic-gate 	if (n == NULL)
4450Sstevel@tonic-gate 		return (NULL);
4460Sstevel@tonic-gate 	n->hdl = picl_hdl;
4470Sstevel@tonic-gate 	n->hash_hdl = ptreeh;
4480Sstevel@tonic-gate 	n->next = NULL;
4490Sstevel@tonic-gate 	return (n);
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate /*
4530Sstevel@tonic-gate  * Initialize a hash table by setting all entries to NULL
4540Sstevel@tonic-gate  */
4550Sstevel@tonic-gate static int
hash_init(hash_t * htbl)4560Sstevel@tonic-gate hash_init(hash_t *htbl)
4570Sstevel@tonic-gate {
4580Sstevel@tonic-gate 	int	i;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	htbl->hash_size = HASH_TBL_SIZE;
4610Sstevel@tonic-gate 	htbl->tbl = malloc(sizeof (hash_elem_t *) * HASH_TBL_SIZE);
4620Sstevel@tonic-gate 	if (htbl->tbl == NULL)
4630Sstevel@tonic-gate 		return (-1);
4640Sstevel@tonic-gate 	for (i = 0; i < htbl->hash_size; ++i)
4650Sstevel@tonic-gate 		htbl->tbl[i] = NULL;
4660Sstevel@tonic-gate 	return (0);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate /*
4700Sstevel@tonic-gate  * Lock free function to add an entry in the hash table
4710Sstevel@tonic-gate  */
4720Sstevel@tonic-gate static int
hash_add_newobj(hash_t * htbl,picl_hdl_t hdl,void * pobj)4730Sstevel@tonic-gate hash_add_newobj(hash_t *htbl, picl_hdl_t hdl, void *pobj)
4740Sstevel@tonic-gate {
4750Sstevel@tonic-gate 	int		indx;
4760Sstevel@tonic-gate 	hash_elem_t	*n;
4770Sstevel@tonic-gate 	uint32_t	hash_val = HASH_VAL(hdl);
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	n = hash_newobj(hash_val, pobj);
4800Sstevel@tonic-gate 	if (n == NULL)
4810Sstevel@tonic-gate 		return (-1);
4820Sstevel@tonic-gate 	indx = HASH_INDEX(htbl->hash_size, hash_val);
4830Sstevel@tonic-gate 	n->next = htbl->tbl[indx];
4840Sstevel@tonic-gate 	htbl->tbl[indx] = n;
4850Sstevel@tonic-gate 	return (0);
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate static int
hash_add_newhdl(hash_t * htbl,picl_hdl_t piclh,picl_hdl_t ptreeh)4890Sstevel@tonic-gate hash_add_newhdl(hash_t *htbl, picl_hdl_t piclh, picl_hdl_t ptreeh)
4900Sstevel@tonic-gate {
4910Sstevel@tonic-gate 	int		indx;
4920Sstevel@tonic-gate 	hash_elem_t	*n;
4930Sstevel@tonic-gate 	uint32_t	picl_val = HASH_VAL(piclh);
4940Sstevel@tonic-gate 	uint32_t	ptree_val = HASH_VAL(ptreeh);
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	n = hash_newhdl(picl_val, ptree_val);
4970Sstevel@tonic-gate 	if (n == NULL)
4980Sstevel@tonic-gate 		return (-1);
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 	indx = HASH_INDEX(htbl->hash_size, picl_val);
5010Sstevel@tonic-gate 	n->next = htbl->tbl[indx];
5020Sstevel@tonic-gate 	htbl->tbl[indx] = n;
5030Sstevel@tonic-gate 	return (0);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate /*
5070Sstevel@tonic-gate  * Lock free function to remove the handle from the hash table
5080Sstevel@tonic-gate  * Returns -1 if element not found, 0 if successful
5090Sstevel@tonic-gate  */
5100Sstevel@tonic-gate static int
hash_remove(hash_t * htbl,picl_hdl_t hdl)5110Sstevel@tonic-gate hash_remove(hash_t *htbl, picl_hdl_t hdl)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 	hash_elem_t	*nxt;
5140Sstevel@tonic-gate 	hash_elem_t	*cur;
5150Sstevel@tonic-gate 	int		i;
5160Sstevel@tonic-gate 	uint32_t	hash_val = HASH_VAL(hdl);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	i = HASH_INDEX(htbl->hash_size, hash_val);
5190Sstevel@tonic-gate 	if (htbl->tbl[i] == NULL)
5200Sstevel@tonic-gate 		return (-1);
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	cur = htbl->tbl[i];
5230Sstevel@tonic-gate 	if (cur->hdl == hash_val) {
5240Sstevel@tonic-gate 		htbl->tbl[i] = cur->next;
5250Sstevel@tonic-gate 		free(cur);
5260Sstevel@tonic-gate 		return (0);
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 	nxt = cur->next;
5290Sstevel@tonic-gate 	while (nxt != NULL) {
5300Sstevel@tonic-gate 		if (nxt->hdl == hash_val) {
5310Sstevel@tonic-gate 			cur->next = nxt->next;
5320Sstevel@tonic-gate 			free(nxt);
5330Sstevel@tonic-gate 			return (0);
5340Sstevel@tonic-gate 		}
5350Sstevel@tonic-gate 		cur = nxt;
5360Sstevel@tonic-gate 		nxt = nxt->next;
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 	return (-1);
5390Sstevel@tonic-gate }
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate /*
5420Sstevel@tonic-gate  * Lock free function to lookup the hash table for a given handle
5430Sstevel@tonic-gate  * Returns NULL if not found
5440Sstevel@tonic-gate  */
5450Sstevel@tonic-gate static void *
hash_lookup_obj(hash_t * htbl,picl_hdl_t hdl)5460Sstevel@tonic-gate hash_lookup_obj(hash_t *htbl, picl_hdl_t hdl)
5470Sstevel@tonic-gate {
5480Sstevel@tonic-gate 	hash_elem_t	*tmp;
5490Sstevel@tonic-gate 	int		i;
5500Sstevel@tonic-gate 	uint32_t	hash_val;
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	hash_val = HASH_VAL(hdl);
5530Sstevel@tonic-gate 	i = HASH_INDEX(htbl->hash_size, hash_val);
5540Sstevel@tonic-gate 	tmp = htbl->tbl[i];
5550Sstevel@tonic-gate 	while (tmp != NULL) {
5560Sstevel@tonic-gate 		if (tmp->hdl == hash_val)
5570Sstevel@tonic-gate 			return (tmp->hash_obj);
5580Sstevel@tonic-gate 		tmp = tmp->next;
5590Sstevel@tonic-gate 	}
5600Sstevel@tonic-gate 	return (NULL);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate static picl_hdl_t
hash_lookup_hdl(hash_t * htbl,picl_hdl_t hdl)5640Sstevel@tonic-gate hash_lookup_hdl(hash_t *htbl, picl_hdl_t hdl)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate 	hash_elem_t	*tmp;
5670Sstevel@tonic-gate 	int		i;
5680Sstevel@tonic-gate 	uint32_t	hash_val;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	hash_val = HASH_VAL(hdl);
5710Sstevel@tonic-gate 	i = HASH_INDEX(htbl->hash_size, hash_val);
5720Sstevel@tonic-gate 	tmp = htbl->tbl[i];
5730Sstevel@tonic-gate 	while (tmp != NULL) {
5740Sstevel@tonic-gate 		if (tmp->hdl == hash_val)
5750Sstevel@tonic-gate 			return (MAKE_HANDLE(picld_pid, tmp->hash_hdl));
5760Sstevel@tonic-gate 		tmp = tmp->next;
5770Sstevel@tonic-gate 	}
5780Sstevel@tonic-gate 	return (PICL_INVALID_PICLHDL);
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate /*
5820Sstevel@tonic-gate  * Is the PICL handle stale or invalid handle?
5830Sstevel@tonic-gate  */
5840Sstevel@tonic-gate static int
picl_hdl_error(picl_hdl_t hdl)5850Sstevel@tonic-gate picl_hdl_error(picl_hdl_t hdl)
5860Sstevel@tonic-gate {
5870Sstevel@tonic-gate 	uint32_t	hash_val = HASH_VAL(hdl);
5880Sstevel@tonic-gate 	pid_t		pid = GET_PID(hdl);
5890Sstevel@tonic-gate 	int		err;
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	(void) pthread_mutex_lock(&piclhdl_lock);
5920Sstevel@tonic-gate 	err = PICL_STALEHANDLE;
5930Sstevel@tonic-gate 	if ((pid != picld_pid) || (hash_val >= picl_hdl_hi) ||
5940Sstevel@tonic-gate 	    (hash_val == NULL))
5950Sstevel@tonic-gate 		err = PICL_INVALIDHANDLE;
5960Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&piclhdl_lock);
5970Sstevel@tonic-gate 	return (err);
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate /*
6010Sstevel@tonic-gate  * Is the Ptree handle stale or invalid handle?
6020Sstevel@tonic-gate  */
6030Sstevel@tonic-gate static int
ptree_hdl_error(picl_hdl_t hdl)6040Sstevel@tonic-gate ptree_hdl_error(picl_hdl_t hdl)
6050Sstevel@tonic-gate {
6060Sstevel@tonic-gate 	uint32_t	hash_val = HASH_VAL(hdl);
6070Sstevel@tonic-gate 	pid_t		pid = GET_PID(hdl);
6080Sstevel@tonic-gate 	int		err;
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ptreehdl_lock);
6110Sstevel@tonic-gate 	err = PICL_STALEHANDLE;
6120Sstevel@tonic-gate 	if ((pid != picld_pid) || (hash_val >= ptree_hdl_hi) ||
6130Sstevel@tonic-gate 	    (hash_val == NULL))
6140Sstevel@tonic-gate 		err = PICL_INVALIDHANDLE;
6150Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ptreehdl_lock);
6160Sstevel@tonic-gate 	return (err);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate /*
6200Sstevel@tonic-gate  * For a PICL handle, return the PTree handle and the PICL object
6210Sstevel@tonic-gate  * Locks and releases the PICL table.
6220Sstevel@tonic-gate  */
6230Sstevel@tonic-gate int
cvt_picl2ptree(picl_hdl_t hdl,picl_hdl_t * ptree_hdl)6240Sstevel@tonic-gate cvt_picl2ptree(picl_hdl_t hdl, picl_hdl_t *ptree_hdl)
6250Sstevel@tonic-gate {
6260Sstevel@tonic-gate 	picl_hdl_t 	tmph;
6270Sstevel@tonic-gate 	int		err;
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 	(void) rw_rdlock(&picltbl_rwlock);		/* lock picl */
6300Sstevel@tonic-gate 	tmph = hash_lookup_hdl(&picltbl, hdl);
6310Sstevel@tonic-gate 	if (tmph == PICL_INVALID_PICLHDL) {
6320Sstevel@tonic-gate 		err = picl_hdl_error(hdl);
6330Sstevel@tonic-gate 		(void) rw_unlock(&picltbl_rwlock);	/* unlock picl */
6340Sstevel@tonic-gate 		return (err);
6350Sstevel@tonic-gate 	}
6360Sstevel@tonic-gate 	*ptree_hdl = tmph;
6370Sstevel@tonic-gate 	(void) rw_unlock(&picltbl_rwlock);		/* unlock picl */
6380Sstevel@tonic-gate 	return (PICL_SUCCESS);
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate /*
6420Sstevel@tonic-gate  * Allocate a ptree handle
6430Sstevel@tonic-gate  */
6440Sstevel@tonic-gate static picl_hdl_t
alloc_ptreehdl(void)6450Sstevel@tonic-gate alloc_ptreehdl(void)
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate 	picl_hdl_t hdl;
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ptreehdl_lock);	/* lock ptreehdl */
6500Sstevel@tonic-gate 	hdl = MAKE_HANDLE(picld_pid, ptree_hdl_hi);
6510Sstevel@tonic-gate 	++ptree_hdl_hi;
6520Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ptreehdl_lock); /* unlock ptreehdl */
6530Sstevel@tonic-gate 	return (hdl);
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate /*
6570Sstevel@tonic-gate  * Allocate a picl handle
6580Sstevel@tonic-gate  * A PICL handle is ptree_hdl value with 1 in MSB of handle value.
6590Sstevel@tonic-gate  * If a ptree handle already has 1 in MSB, then it cannot be piclized
6600Sstevel@tonic-gate  * and the daemon must be restarted.
6610Sstevel@tonic-gate  */
6620Sstevel@tonic-gate static picl_hdl_t
alloc_piclhdl(void)6630Sstevel@tonic-gate alloc_piclhdl(void)
6640Sstevel@tonic-gate {
6650Sstevel@tonic-gate 	picl_hdl_t hdl;
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 	(void) pthread_mutex_lock(&piclhdl_lock);	/* lock piclhdl */
6680Sstevel@tonic-gate 	hdl = MAKE_HANDLE(picld_pid, picl_hdl_hi);
6690Sstevel@tonic-gate 	++picl_hdl_hi;
6700Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&piclhdl_lock);	/* unlock piclhdl */
6710Sstevel@tonic-gate 	return (hdl);
6720Sstevel@tonic-gate }
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate /*
6750Sstevel@tonic-gate  * Allocate and add handle to PTree hash table
6760Sstevel@tonic-gate  */
6770Sstevel@tonic-gate static void
alloc_and_add_to_ptree(picl_obj_t * pobj)6780Sstevel@tonic-gate alloc_and_add_to_ptree(picl_obj_t *pobj)
6790Sstevel@tonic-gate {
6800Sstevel@tonic-gate 	pobj->ptree_hdl = alloc_ptreehdl();
6810Sstevel@tonic-gate 	(void) rw_wrlock(&ptree_rwlock);
6820Sstevel@tonic-gate 	(void) hash_add_newobj(&ptreetbl, pobj->ptree_hdl, pobj);
6830Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate /*
6870Sstevel@tonic-gate  * Lock a picl node object
6880Sstevel@tonic-gate  */
6890Sstevel@tonic-gate static int
lock_obj(int rw,picl_obj_t * nodep)6900Sstevel@tonic-gate lock_obj(int rw, picl_obj_t *nodep)
6910Sstevel@tonic-gate {
6920Sstevel@tonic-gate 	if (rw == RDLOCK_NODE)
6930Sstevel@tonic-gate 		(void) rw_rdlock(&nodep->node_lock);
6940Sstevel@tonic-gate 	else if (rw == WRLOCK_NODE)
6950Sstevel@tonic-gate 		(void) rw_wrlock(&nodep->node_lock);
6960Sstevel@tonic-gate 	else
6970Sstevel@tonic-gate 		return (-1);
6980Sstevel@tonic-gate 	return (0);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate  * Release the picl node object.
7030Sstevel@tonic-gate  * This function may be called with a NULL object pointer.
7040Sstevel@tonic-gate  */
7050Sstevel@tonic-gate static void
unlock_node(picl_obj_t * nodep)7060Sstevel@tonic-gate unlock_node(picl_obj_t *nodep)
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate 	if (nodep == NULL)
7090Sstevel@tonic-gate 		return;
7100Sstevel@tonic-gate 	(void) rw_unlock(&nodep->node_lock);
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate /*
7140Sstevel@tonic-gate  * This function locks the node of a property and returns the node object
7150Sstevel@tonic-gate  * and the property object.
7160Sstevel@tonic-gate  */
7170Sstevel@tonic-gate static int
lookup_and_lock_propnode(int rw,picl_prophdl_t proph,picl_obj_t ** nodep,picl_obj_t ** propp)7180Sstevel@tonic-gate lookup_and_lock_propnode(int rw, picl_prophdl_t proph, picl_obj_t **nodep,
7190Sstevel@tonic-gate     picl_obj_t **propp)
7200Sstevel@tonic-gate {
7210Sstevel@tonic-gate 	picl_obj_t	*pobj;
7220Sstevel@tonic-gate 	picl_obj_t	*nobj;
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	pobj = hash_lookup_obj(&ptreetbl, proph);
7250Sstevel@tonic-gate 	if (pobj == NULL)
7260Sstevel@tonic-gate 		return (ptree_hdl_error(proph));
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	/*
7290Sstevel@tonic-gate 	 * Get the property's or table entry's node object
7300Sstevel@tonic-gate 	 */
7310Sstevel@tonic-gate 	nobj = NULL;
7320Sstevel@tonic-gate 	if (pobj->obj_type == PICL_OBJ_PROP)
7330Sstevel@tonic-gate 		nobj = pobj->prop_node;
7340Sstevel@tonic-gate 	else if (pobj->obj_type == (PICL_OBJ_PROP|PICL_OBJ_TABLEENTRY))
7350Sstevel@tonic-gate 		nobj = pobj->prop_table->prop_node;
7360Sstevel@tonic-gate 	else {
7370Sstevel@tonic-gate 		*propp = pobj;	/* return the prop */
7380Sstevel@tonic-gate 		return (PICL_NOTPROP);
7390Sstevel@tonic-gate 	}
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	if (nobj && (lock_obj(rw, nobj) < 0))			/* Lock node */
7420Sstevel@tonic-gate 		return (PICL_FAILURE);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	*nodep = nobj;
7450Sstevel@tonic-gate 	*propp = pobj;
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 	return (PICL_SUCCESS);
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate /*
7510Sstevel@tonic-gate  * This function locks the node of a table and returns the node object
7520Sstevel@tonic-gate  * and the table object.
7530Sstevel@tonic-gate  */
7540Sstevel@tonic-gate static int
lookup_and_lock_tablenode(int rw,picl_prophdl_t tblh,picl_obj_t ** nodep,picl_obj_t ** tblobj)7550Sstevel@tonic-gate lookup_and_lock_tablenode(int rw, picl_prophdl_t tblh, picl_obj_t **nodep,
7560Sstevel@tonic-gate     picl_obj_t **tblobj)
7570Sstevel@tonic-gate {
7580Sstevel@tonic-gate 	picl_obj_t	*pobj;
7590Sstevel@tonic-gate 	picl_obj_t	*nobj;
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 	pobj = hash_lookup_obj(&ptreetbl, tblh);
7620Sstevel@tonic-gate 	if (pobj == NULL)
7630Sstevel@tonic-gate 		return (ptree_hdl_error(tblh));
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	/*
7660Sstevel@tonic-gate 	 * Get the property's or table entry's node object
7670Sstevel@tonic-gate 	 */
7680Sstevel@tonic-gate 	nobj = NULL;
7690Sstevel@tonic-gate 	if (pobj->obj_type != PICL_OBJ_TABLE)
7700Sstevel@tonic-gate 		return (PICL_NOTTABLE);
7710Sstevel@tonic-gate 	nobj = pobj->prop_node;
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	if (nobj && (lock_obj(rw, nobj) < 0))			/* Lock node */
7740Sstevel@tonic-gate 		return (PICL_FAILURE);
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	*nodep = nobj;
7770Sstevel@tonic-gate 	*tblobj = pobj;
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	return (PICL_SUCCESS);
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate /*
7830Sstevel@tonic-gate  * This locks the node of a table or a table entry and returns the
7840Sstevel@tonic-gate  * node object and the table or table entry object
7850Sstevel@tonic-gate  */
7860Sstevel@tonic-gate static int
lookup_and_lock_tableprop_node(int rw,picl_prophdl_t tblproph,picl_obj_t ** nodep,picl_obj_t ** tblpropp)7870Sstevel@tonic-gate lookup_and_lock_tableprop_node(int rw, picl_prophdl_t tblproph,
7880Sstevel@tonic-gate     picl_obj_t **nodep, picl_obj_t **tblpropp)
7890Sstevel@tonic-gate {
7900Sstevel@tonic-gate 	picl_obj_t	*pobj;
7910Sstevel@tonic-gate 	picl_obj_t	*nobj;
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	pobj = hash_lookup_obj(&ptreetbl, tblproph);
7940Sstevel@tonic-gate 	if (pobj == NULL)
7950Sstevel@tonic-gate 		return (ptree_hdl_error(tblproph));
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 	/*
7980Sstevel@tonic-gate 	 * Get the property's or table entry's node object
7990Sstevel@tonic-gate 	 */
8000Sstevel@tonic-gate 	nobj = NULL;
8010Sstevel@tonic-gate 	if ((pobj->obj_type != PICL_OBJ_TABLE) &&	/* not a table */
8020Sstevel@tonic-gate 	    !(pobj->obj_type & PICL_OBJ_TABLEENTRY))	/* or an entry */
8030Sstevel@tonic-gate 		return (PICL_NOTTABLE);
8040Sstevel@tonic-gate 	if (pobj->obj_type == PICL_OBJ_TABLE)
8050Sstevel@tonic-gate 		nobj = pobj->prop_node;
8060Sstevel@tonic-gate 	else
8070Sstevel@tonic-gate 		nobj = pobj->prop_table->prop_node;
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	if (nobj && (lock_obj(rw, nobj) < 0))			/* Lock node */
8100Sstevel@tonic-gate 		return (PICL_FAILURE);
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 	*tblpropp = pobj;
8130Sstevel@tonic-gate 	*nodep = nobj;
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	return (PICL_SUCCESS);
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate /*
8190Sstevel@tonic-gate  * Lock the node corresponding to the given handle and return its object
8200Sstevel@tonic-gate  */
8210Sstevel@tonic-gate static int
lookup_and_lock_node(int rw,picl_nodehdl_t nodeh,picl_obj_t ** nodep)8220Sstevel@tonic-gate lookup_and_lock_node(int rw, picl_nodehdl_t nodeh, picl_obj_t **nodep)
8230Sstevel@tonic-gate {
8240Sstevel@tonic-gate 	picl_obj_t	*nobj;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	nobj = hash_lookup_obj(&ptreetbl, nodeh);
8270Sstevel@tonic-gate 	if (nobj == NULL)
8280Sstevel@tonic-gate 		return (ptree_hdl_error(nodeh));
8290Sstevel@tonic-gate 	else if (nobj->obj_type != PICL_OBJ_NODE)
8300Sstevel@tonic-gate 		return (PICL_NOTNODE);
8310Sstevel@tonic-gate 	if (lock_obj(rw, nobj) < 0)			/* Lock node */
8320Sstevel@tonic-gate 		return (PICL_FAILURE);
8330Sstevel@tonic-gate 	*nodep = nobj;
8340Sstevel@tonic-gate 	return (PICL_SUCCESS);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate /*
8380Sstevel@tonic-gate  * Is the property name a restricted property name?
8390Sstevel@tonic-gate  */
8400Sstevel@tonic-gate static int
picl_restricted(const char * name)8410Sstevel@tonic-gate picl_restricted(const char *name)
8420Sstevel@tonic-gate {
8430Sstevel@tonic-gate 	if (strcmp(name, PICL_PROP_CLASSNAME) == 0)
8440Sstevel@tonic-gate 		return (0);		/* not restricted */
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	if ((name[0] == '_') && (strchr(&name[1], '_') == NULL))
8470Sstevel@tonic-gate 		return (1);
8480Sstevel@tonic-gate 	return (0);
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate /*
8520Sstevel@tonic-gate  * Check the value size with the property size
8530Sstevel@tonic-gate  * Return PICL_INVALIDARG if the size does not match exactly for strongly
8540Sstevel@tonic-gate  * typed properties.
8550Sstevel@tonic-gate  * For charstring reads allow sizes that match the value size
8560Sstevel@tonic-gate  * For bytearray return PICL_VALUETOOBIG
8570Sstevel@tonic-gate  * if the size is greater than the buffer size.
8580Sstevel@tonic-gate  */
8590Sstevel@tonic-gate static int
check_propsize(int op,picl_obj_t * propp,size_t sz)8600Sstevel@tonic-gate check_propsize(int op, picl_obj_t *propp, size_t sz)
8610Sstevel@tonic-gate {
8620Sstevel@tonic-gate 	if (propp->prop_mode & PICL_VOLATILE) {
8630Sstevel@tonic-gate 		if (sz != propp->prop_size)
8640Sstevel@tonic-gate 			return (PICL_INVALIDARG);
8650Sstevel@tonic-gate 		else
8660Sstevel@tonic-gate 			return (PICL_SUCCESS);
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate 	/*
8700Sstevel@tonic-gate 	 * check size for non-volatile properties
8710Sstevel@tonic-gate 	 */
8720Sstevel@tonic-gate 	switch (propp->prop_type) {
8730Sstevel@tonic-gate 	case PICL_PTYPE_CHARSTRING:
8740Sstevel@tonic-gate 		if ((op == PROP_READ) &&
8750Sstevel@tonic-gate 		    (strlen(propp->prop_val) >= sz))
8760Sstevel@tonic-gate 			return (PICL_VALUETOOBIG);
8770Sstevel@tonic-gate 		if ((op == PROP_WRITE) && (sz > propp->prop_size))
8780Sstevel@tonic-gate 			return (PICL_VALUETOOBIG);
8790Sstevel@tonic-gate 		break;
8800Sstevel@tonic-gate 	case PICL_PTYPE_BYTEARRAY:
8810Sstevel@tonic-gate 		if (op == PROP_WRITE) {
8820Sstevel@tonic-gate 			if (sz > propp->prop_size)
8830Sstevel@tonic-gate 				return (PICL_VALUETOOBIG);
8840Sstevel@tonic-gate 			return (PICL_SUCCESS);	/* allow small writes */
8850Sstevel@tonic-gate 		}
8860Sstevel@tonic-gate 		/* fall through for reads */
8870Sstevel@tonic-gate 	default:
8880Sstevel@tonic-gate 		if (propp->prop_size != sz)
8890Sstevel@tonic-gate 			return (PICL_INVALIDARG);
8900Sstevel@tonic-gate 		break;
8910Sstevel@tonic-gate 	}
8920Sstevel@tonic-gate 	return (PICL_SUCCESS);
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate void
cvt_ptree2picl(picl_hdl_t * handlep)8960Sstevel@tonic-gate cvt_ptree2picl(picl_hdl_t *handlep)
8970Sstevel@tonic-gate {
8980Sstevel@tonic-gate 	picl_obj_t	*pobj;
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);
9010Sstevel@tonic-gate 	pobj = hash_lookup_obj(&ptreetbl, *handlep);
9020Sstevel@tonic-gate 	if (pobj == NULL)
9030Sstevel@tonic-gate 		*handlep = PICL_INVALID_PICLHDL;
9040Sstevel@tonic-gate 	else
9050Sstevel@tonic-gate 		(void) memcpy(handlep, &pobj->picl_hdl, sizeof (*handlep));
9060Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate /*
9100Sstevel@tonic-gate  * The caller of the piclize() set of functions is assumed to hold
9110Sstevel@tonic-gate  * the ptree_rwlock().
9120Sstevel@tonic-gate  */
9130Sstevel@tonic-gate static void
piclize_obj(picl_obj_t * pobj)9140Sstevel@tonic-gate piclize_obj(picl_obj_t *pobj)
9150Sstevel@tonic-gate {
9160Sstevel@tonic-gate 	(void) rw_wrlock(&picltbl_rwlock);
9170Sstevel@tonic-gate 	pobj->picl_hdl = alloc_piclhdl();
9180Sstevel@tonic-gate 	(void) hash_add_newhdl(&picltbl, pobj->picl_hdl, pobj->ptree_hdl);
9190Sstevel@tonic-gate 	(void) rw_unlock(&picltbl_rwlock);
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate static void
piclize_table(picl_obj_t * tbl_obj)9230Sstevel@tonic-gate piclize_table(picl_obj_t  *tbl_obj)
9240Sstevel@tonic-gate {
9250Sstevel@tonic-gate 	picl_obj_t	*rowp;
9260Sstevel@tonic-gate 	picl_obj_t	*colp;
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	for (rowp = tbl_obj->next_row; rowp != NULL; rowp = rowp->next_col)
9290Sstevel@tonic-gate 		for (colp = rowp; colp != NULL; colp = colp->next_row)
9300Sstevel@tonic-gate 			piclize_obj(colp);
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate static void
piclize_prop(picl_obj_t * propp)9340Sstevel@tonic-gate piclize_prop(picl_obj_t *propp)
9350Sstevel@tonic-gate {
9360Sstevel@tonic-gate 	picl_obj_t	*tbl_obj;
9370Sstevel@tonic-gate 	picl_prophdl_t	tblh;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	piclize_obj(propp);
9400Sstevel@tonic-gate 	if (!(propp->prop_mode & PICL_VOLATILE) &&
9410Sstevel@tonic-gate 	    (propp->prop_type == PICL_PTYPE_TABLE)) {
9420Sstevel@tonic-gate 		tblh = *(picl_prophdl_t *)propp->prop_val;
9430Sstevel@tonic-gate 		tbl_obj = hash_lookup_obj(&ptreetbl, tblh);
9440Sstevel@tonic-gate 		if (tbl_obj == NULL)
9450Sstevel@tonic-gate 			return;
9460Sstevel@tonic-gate 		piclize_obj(tbl_obj);
9470Sstevel@tonic-gate 		piclize_table(tbl_obj);
9480Sstevel@tonic-gate 	}
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate /*
9520Sstevel@tonic-gate  * Function to create PICL handles for a subtree and add them to
9530Sstevel@tonic-gate  * the table
9540Sstevel@tonic-gate  */
9550Sstevel@tonic-gate static void
piclize_node(picl_obj_t * nodep)9560Sstevel@tonic-gate piclize_node(picl_obj_t  *nodep)
9570Sstevel@tonic-gate {
9580Sstevel@tonic-gate 	picl_obj_t	*propp;
9590Sstevel@tonic-gate 	picl_obj_t	*chdp;
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 	piclize_obj(nodep);
9620Sstevel@tonic-gate 	propp = nodep->first_prop;
9630Sstevel@tonic-gate 	while (propp != NULL) {
9640Sstevel@tonic-gate 		piclize_prop(propp);
9650Sstevel@tonic-gate 		propp = propp->next_prop;
9660Sstevel@tonic-gate 	}
9670Sstevel@tonic-gate 
9680Sstevel@tonic-gate 	/* go through the children */
9690Sstevel@tonic-gate 	for (chdp = nodep->child_node; chdp != NULL; chdp = chdp->sibling_node)
9700Sstevel@tonic-gate 		piclize_node(chdp);
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate /*
9740Sstevel@tonic-gate  * Function to remove PICL handles
9750Sstevel@tonic-gate  */
9760Sstevel@tonic-gate static void
unpiclize_obj(picl_obj_t * pobj)9770Sstevel@tonic-gate unpiclize_obj(picl_obj_t *pobj)
9780Sstevel@tonic-gate {
9790Sstevel@tonic-gate 	(void) rw_wrlock(&picltbl_rwlock);
9800Sstevel@tonic-gate 	(void) hash_remove(&picltbl, pobj->picl_hdl);
9810Sstevel@tonic-gate 	pobj->picl_hdl = PICL_INVALID_PICLHDL;
9820Sstevel@tonic-gate 	(void) rw_unlock(&picltbl_rwlock);
9830Sstevel@tonic-gate }
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate static void
unpiclize_table(picl_obj_t * tbl_obj)9860Sstevel@tonic-gate unpiclize_table(picl_obj_t  *tbl_obj)
9870Sstevel@tonic-gate {
9880Sstevel@tonic-gate 	picl_obj_t	*rowp;
9890Sstevel@tonic-gate 	picl_obj_t	*colp;
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	for (rowp = tbl_obj->next_row; rowp != NULL; rowp = rowp->next_col)
9920Sstevel@tonic-gate 		for (colp = rowp; colp != NULL; colp = colp->next_row)
9930Sstevel@tonic-gate 			unpiclize_obj(colp);
9940Sstevel@tonic-gate 	unpiclize_obj(tbl_obj);
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate static void
unpiclize_prop(picl_obj_t * propp)9980Sstevel@tonic-gate unpiclize_prop(picl_obj_t *propp)
9990Sstevel@tonic-gate {
10000Sstevel@tonic-gate 	picl_obj_t	*tbl_obj;
10010Sstevel@tonic-gate 	picl_prophdl_t	tblh;
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 	if (!IS_PICLIZED(propp))
10040Sstevel@tonic-gate 		return;
10050Sstevel@tonic-gate 	unpiclize_obj(propp);
10060Sstevel@tonic-gate 	if (!(propp->prop_mode & PICL_VOLATILE) &&
10070Sstevel@tonic-gate 	    (propp->prop_type == PICL_PTYPE_TABLE)) {
10080Sstevel@tonic-gate 		tblh = *(picl_prophdl_t *)propp->prop_val;
10090Sstevel@tonic-gate 		tbl_obj = hash_lookup_obj(&ptreetbl, tblh);
10100Sstevel@tonic-gate 		unpiclize_table(tbl_obj);
10110Sstevel@tonic-gate 	}
10120Sstevel@tonic-gate }
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate /*
10150Sstevel@tonic-gate  * Function to remove PICL handles for a subtree and its
10160Sstevel@tonic-gate  * properties
10170Sstevel@tonic-gate  */
10180Sstevel@tonic-gate static void
unpiclize_node(picl_obj_t * nodep)10190Sstevel@tonic-gate unpiclize_node(picl_obj_t  *nodep)
10200Sstevel@tonic-gate {
10210Sstevel@tonic-gate 	picl_obj_t	*propp;
10220Sstevel@tonic-gate 	picl_obj_t	*chdp;
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 	if (!IS_PICLIZED(nodep))
10260Sstevel@tonic-gate 		return;
10270Sstevel@tonic-gate 
10280Sstevel@tonic-gate 	unpiclize_obj(nodep);
10290Sstevel@tonic-gate 	propp = nodep->first_prop;
10300Sstevel@tonic-gate 	while (propp != NULL) {
10310Sstevel@tonic-gate 		unpiclize_prop(propp);
10320Sstevel@tonic-gate 		propp = propp->next_prop;
10330Sstevel@tonic-gate 	}
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 	/* go through the children */
10360Sstevel@tonic-gate 	for (chdp = nodep->child_node; chdp != NULL; chdp = chdp->sibling_node)
10370Sstevel@tonic-gate 		unpiclize_node(chdp);
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate /*
10420Sstevel@tonic-gate  * The caller holds the lock on the ptree_lock when calling this.
10430Sstevel@tonic-gate  * If ret is not NULL then this function returns the referenced object.
10440Sstevel@tonic-gate  */
10450Sstevel@tonic-gate static int
lookup_verify_ref_prop(picl_obj_t * propp,picl_obj_t ** ret)10460Sstevel@tonic-gate lookup_verify_ref_prop(picl_obj_t *propp, picl_obj_t **ret)
10470Sstevel@tonic-gate {
10480Sstevel@tonic-gate 	picl_nodehdl_t	refh;
10490Sstevel@tonic-gate 	picl_obj_t	*refobj;
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 	refh = *(picl_nodehdl_t *)propp->prop_val;
10520Sstevel@tonic-gate 	refobj = hash_lookup_obj(&ptreetbl, refh);
10530Sstevel@tonic-gate 	if (refobj == NULL)
10540Sstevel@tonic-gate 		return (ptree_hdl_error(refh));
10550Sstevel@tonic-gate 	else if (refobj->obj_type != PICL_OBJ_NODE)
10560Sstevel@tonic-gate 		return (PICL_INVREFERENCE);
10570Sstevel@tonic-gate 	if (ret)
10580Sstevel@tonic-gate 		*ret = refobj;
10590Sstevel@tonic-gate 	return (PICL_SUCCESS);
10600Sstevel@tonic-gate }
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate /*
10630Sstevel@tonic-gate  * The caller holds the lock on ptree_lock when calling this.
10640Sstevel@tonic-gate  * If ret is not NULL, then this function returns the table object
10650Sstevel@tonic-gate  */
10660Sstevel@tonic-gate static int
lookup_verify_table_prop(picl_obj_t * propp,picl_obj_t ** ret)10670Sstevel@tonic-gate lookup_verify_table_prop(picl_obj_t *propp, picl_obj_t **ret)
10680Sstevel@tonic-gate {
10690Sstevel@tonic-gate 	picl_prophdl_t	tblh;
10700Sstevel@tonic-gate 	picl_obj_t	*tbl_obj;
10710Sstevel@tonic-gate 
10720Sstevel@tonic-gate 	tblh = *(picl_prophdl_t *)propp->prop_val;
10730Sstevel@tonic-gate 	tbl_obj = hash_lookup_obj(&ptreetbl, tblh);
10740Sstevel@tonic-gate 	if (tbl_obj == NULL)
10750Sstevel@tonic-gate 		return (ptree_hdl_error(tblh));
10760Sstevel@tonic-gate 	else if (!(tbl_obj->obj_type & PICL_OBJ_TABLE))
10770Sstevel@tonic-gate 		return (PICL_NOTTABLE);
10780Sstevel@tonic-gate 	if (ret)
10790Sstevel@tonic-gate 		*ret = tbl_obj;
10800Sstevel@tonic-gate 	return (PICL_SUCCESS);
10810Sstevel@tonic-gate }
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate static int
lookup_verify_prop_handle(picl_prophdl_t proph,picl_obj_t ** ret)10840Sstevel@tonic-gate lookup_verify_prop_handle(picl_prophdl_t proph, picl_obj_t **ret)
10850Sstevel@tonic-gate {
10860Sstevel@tonic-gate 	picl_obj_t	*propp;
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 	propp = hash_lookup_obj(&ptreetbl, proph);
10890Sstevel@tonic-gate 	if (propp == NULL)
10900Sstevel@tonic-gate 		return (ptree_hdl_error(proph));
10910Sstevel@tonic-gate 	else if (!(propp->obj_type & PICL_OBJ_PROP))
10920Sstevel@tonic-gate 		return (PICL_NOTPROP);
10930Sstevel@tonic-gate 	if (ret)
10940Sstevel@tonic-gate 		*ret = propp;
10950Sstevel@tonic-gate 	return (PICL_SUCCESS);
10960Sstevel@tonic-gate }
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate static int
lookup_verify_node_handle(picl_nodehdl_t nodeh,picl_obj_t ** ret)10990Sstevel@tonic-gate lookup_verify_node_handle(picl_nodehdl_t nodeh, picl_obj_t **ret)
11000Sstevel@tonic-gate {
11010Sstevel@tonic-gate 	picl_obj_t	*nodep;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	nodep = hash_lookup_obj(&ptreetbl, nodeh);
11040Sstevel@tonic-gate 	if (nodep == NULL)
11050Sstevel@tonic-gate 		return (ptree_hdl_error(nodeh));
11060Sstevel@tonic-gate 	else if (nodep->obj_type != PICL_OBJ_NODE)
11070Sstevel@tonic-gate 		return (PICL_NOTNODE);
11080Sstevel@tonic-gate 	if (ret)
11090Sstevel@tonic-gate 		*ret = nodep;
11100Sstevel@tonic-gate 	return (PICL_SUCCESS);
11110Sstevel@tonic-gate }
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate static int
lookup_prop_by_name(picl_obj_t * nodep,const char * pname,picl_obj_t ** ret)11140Sstevel@tonic-gate lookup_prop_by_name(picl_obj_t *nodep, const char *pname, picl_obj_t **ret)
11150Sstevel@tonic-gate {
11160Sstevel@tonic-gate 	picl_obj_t	*propp;
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate 	if (strcmp(pname, PICL_PROP_PARENT) == 0) {
11190Sstevel@tonic-gate 		if (nodep->parent_node == NULL)
11200Sstevel@tonic-gate 			return (PICL_PROPNOTFOUND);
11210Sstevel@tonic-gate 		else
11220Sstevel@tonic-gate 			return (PICL_SUCCESS);
11230Sstevel@tonic-gate 	}
11240Sstevel@tonic-gate 	if (strcmp(pname, PICL_PROP_CHILD) == 0) {
11250Sstevel@tonic-gate 		if (nodep->child_node == NULL)
11260Sstevel@tonic-gate 			return (PICL_PROPNOTFOUND);
11270Sstevel@tonic-gate 		else
11280Sstevel@tonic-gate 			return (PICL_SUCCESS);
11290Sstevel@tonic-gate 	}
11300Sstevel@tonic-gate 	if (strcmp(pname, PICL_PROP_PEER) == 0) {
11310Sstevel@tonic-gate 		if (nodep->sibling_node == NULL)
11320Sstevel@tonic-gate 			return (PICL_PROPNOTFOUND);
11330Sstevel@tonic-gate 		else
11340Sstevel@tonic-gate 			return (PICL_SUCCESS);
11350Sstevel@tonic-gate 	}
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	propp = nodep->first_prop;
11380Sstevel@tonic-gate 	while (propp != NULL) {
11390Sstevel@tonic-gate 		if (strcmp(propp->prop_name, pname) == 0) {
11400Sstevel@tonic-gate 			if (ret)
11410Sstevel@tonic-gate 				*ret = propp;
11420Sstevel@tonic-gate 			return (PICL_SUCCESS);
11430Sstevel@tonic-gate 		}
11440Sstevel@tonic-gate 		propp = propp->next_prop;
11450Sstevel@tonic-gate 	}
11460Sstevel@tonic-gate 	return (PICL_PROPNOTFOUND);
11470Sstevel@tonic-gate }
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate /*
11500Sstevel@tonic-gate  * This function locks the ptree, verifies that the handle is a reference
11510Sstevel@tonic-gate  * to a node of specified class name, releases the lock
11520Sstevel@tonic-gate  */
11530Sstevel@tonic-gate static int
check_ref_handle(picl_nodehdl_t refh,char * clname)11540Sstevel@tonic-gate check_ref_handle(picl_nodehdl_t refh, char *clname)
11550Sstevel@tonic-gate {
11560Sstevel@tonic-gate 	picl_obj_t	*refobj;
11570Sstevel@tonic-gate 	picl_obj_t	*propp;
11580Sstevel@tonic-gate 	int		err;
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);	/* Lock ptree */
11610Sstevel@tonic-gate 	refobj = hash_lookup_obj(&ptreetbl, refh);
11620Sstevel@tonic-gate 	if ((refobj == NULL) || !(refobj->obj_type & PICL_OBJ_NODE)) {
11630Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
11640Sstevel@tonic-gate 		return (PICL_INVREFERENCE);
11650Sstevel@tonic-gate 	}
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 	err = lookup_prop_by_name(refobj, PICL_PROP_CLASSNAME, &propp);
11680Sstevel@tonic-gate 	if ((err != PICL_SUCCESS) || (propp->prop_val == NULL) ||
11690Sstevel@tonic-gate 	    (strcmp(propp->prop_val, clname) != 0))
11700Sstevel@tonic-gate 		err = PICL_INVREFERENCE;
11710Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
11720Sstevel@tonic-gate 	return (err);
11730Sstevel@tonic-gate }
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate static int
check_table_handle(picl_prophdl_t tblh)11760Sstevel@tonic-gate check_table_handle(picl_prophdl_t tblh)
11770Sstevel@tonic-gate {
11780Sstevel@tonic-gate 	picl_obj_t	*tbl_obj;
11790Sstevel@tonic-gate 	int		err;
11800Sstevel@tonic-gate 
11810Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);
11820Sstevel@tonic-gate 	err = PICL_SUCCESS;
11830Sstevel@tonic-gate 	tbl_obj = hash_lookup_obj(&ptreetbl, tblh);
11840Sstevel@tonic-gate 	if ((tbl_obj == NULL) || !(tbl_obj->obj_type & PICL_OBJ_TABLE))
11850Sstevel@tonic-gate 		err = PICL_NOTTABLE;
11860Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);
11870Sstevel@tonic-gate 	return (err);
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate /*
11910Sstevel@tonic-gate  * PICLTree Interface routines for plug-in modules
11920Sstevel@tonic-gate  */
11930Sstevel@tonic-gate int
ptree_get_root(picl_nodehdl_t * rooth)11940Sstevel@tonic-gate ptree_get_root(picl_nodehdl_t *rooth)
11950Sstevel@tonic-gate {
11960Sstevel@tonic-gate 	*rooth = ptree_root_hdl;
11970Sstevel@tonic-gate 	return (PICL_SUCCESS);
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate /*
12010Sstevel@tonic-gate  * Lock free create a property object
12020Sstevel@tonic-gate  */
12030Sstevel@tonic-gate static int
create_propobj(const ptree_propinfo_t * pinfo,const void * valbuf,picl_obj_t ** pobjp)12040Sstevel@tonic-gate create_propobj(const ptree_propinfo_t *pinfo, const void *valbuf,
12050Sstevel@tonic-gate     picl_obj_t **pobjp)
12060Sstevel@tonic-gate {
12070Sstevel@tonic-gate 	picl_obj_t	*pobj;
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate 	if (pinfo->version != PTREE_PROPINFO_VERSION_1)
12100Sstevel@tonic-gate 		return (PICL_NOTSUPPORTED);
12110Sstevel@tonic-gate 
12120Sstevel@tonic-gate 	if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE) &&
12130Sstevel@tonic-gate 	    (pinfo->piclinfo.type != PICL_PTYPE_VOID) &&
12140Sstevel@tonic-gate 	    (valbuf == NULL))
12150Sstevel@tonic-gate 		return (PICL_INVALIDARG);
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 	pobj = malloc(sizeof (picl_obj_t));
12180Sstevel@tonic-gate 	if (pobj == NULL)
12190Sstevel@tonic-gate 		return (PICL_FAILURE);
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate 	pobj->obj_type = PICL_OBJ_PROP;
12220Sstevel@tonic-gate 	pobj->pinfo_ver = pinfo->version;
12230Sstevel@tonic-gate 	pobj->prop_type = pinfo->piclinfo.type;
12240Sstevel@tonic-gate 	pobj->prop_mode = pinfo->piclinfo.accessmode;
12250Sstevel@tonic-gate 	pobj->prop_size = pinfo->piclinfo.size;
12260Sstevel@tonic-gate 	(void) strcpy(pobj->prop_name, pinfo->piclinfo.name);
12270Sstevel@tonic-gate 	pobj->read_func = pinfo->read;
12280Sstevel@tonic-gate 	pobj->write_func = pinfo->write;
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 	pobj->prop_val = NULL;
12310Sstevel@tonic-gate 	if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE)) {
12320Sstevel@tonic-gate 		pobj->prop_val = malloc(pinfo->piclinfo.size);
12330Sstevel@tonic-gate 		if (pobj->prop_val == NULL) {
12340Sstevel@tonic-gate 			free(pobj);
12350Sstevel@tonic-gate 			return (PICL_FAILURE);
12360Sstevel@tonic-gate 		}
12370Sstevel@tonic-gate 		if (pobj->prop_type == PICL_PTYPE_CHARSTRING)
12380Sstevel@tonic-gate 			(void) strlcpy(pobj->prop_val, valbuf,
12390Sstevel@tonic-gate 			    pinfo->piclinfo.size);
12400Sstevel@tonic-gate 		else
12410Sstevel@tonic-gate 			(void) memcpy(pobj->prop_val, valbuf,
12420Sstevel@tonic-gate 			    pinfo->piclinfo.size);
12430Sstevel@tonic-gate 	}
12440Sstevel@tonic-gate 	pobj->prop_node = NULL;
12450Sstevel@tonic-gate 	pobj->ptree_hdl = PICL_INVALID_PICLHDL;
12460Sstevel@tonic-gate 	pobj->picl_hdl = PICL_INVALID_PICLHDL;
12470Sstevel@tonic-gate 	pobj->next_prop = NULL;
12480Sstevel@tonic-gate 	pobj->next_row = NULL;
12490Sstevel@tonic-gate 	pobj->next_col = NULL;
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 	*pobjp = pobj;
12520Sstevel@tonic-gate 	return (PICL_SUCCESS);
12530Sstevel@tonic-gate }
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate /*
12560Sstevel@tonic-gate  * Check for valid arguments, create a property object,
12570Sstevel@tonic-gate  * Lock ptree_rwlock, add the new property handle, release the lock
12580Sstevel@tonic-gate  * For reference properties and table properties, the handles are verified
12590Sstevel@tonic-gate  * before creating the property.
12600Sstevel@tonic-gate  */
12610Sstevel@tonic-gate int
ptree_create_prop(const ptree_propinfo_t * pinfo,const void * valbuf,picl_prophdl_t * proph)12620Sstevel@tonic-gate ptree_create_prop(const ptree_propinfo_t *pinfo, const void *valbuf,
12630Sstevel@tonic-gate     picl_prophdl_t *proph)
12640Sstevel@tonic-gate {
12650Sstevel@tonic-gate 	picl_obj_t	*pobj;
12660Sstevel@tonic-gate 	picl_nodehdl_t	refh;
12670Sstevel@tonic-gate 	picl_prophdl_t	tblh;
12680Sstevel@tonic-gate 	int		err;
12690Sstevel@tonic-gate 	char		*ptr;
12700Sstevel@tonic-gate 	int		refflag;
12710Sstevel@tonic-gate 	char		classname[PICL_PROPNAMELEN_MAX];
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate 	if (pinfo == NULL)
12740Sstevel@tonic-gate 		return (PICL_INVALIDARG);
12750Sstevel@tonic-gate 	if (pinfo->version != PTREE_PROPINFO_VERSION_1)
12760Sstevel@tonic-gate 		return (PICL_NOTSUPPORTED);
12770Sstevel@tonic-gate 	if (pinfo->piclinfo.size >= PICL_PROPSIZE_MAX)
12780Sstevel@tonic-gate 		return (PICL_VALUETOOBIG);
12790Sstevel@tonic-gate 	if (picl_restricted(pinfo->piclinfo.name))
12800Sstevel@tonic-gate 		return (PICL_RESERVEDNAME);
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	refflag = 0;
12830Sstevel@tonic-gate 	if ((pinfo->piclinfo.name[0] == '_') &&
12840Sstevel@tonic-gate 	    (strchr(&pinfo->piclinfo.name[1], '_') != NULL))
12850Sstevel@tonic-gate 		refflag = 1;
12860Sstevel@tonic-gate 
12870Sstevel@tonic-gate 	if (pinfo->piclinfo.type == PICL_PTYPE_REFERENCE) {
12880Sstevel@tonic-gate 		if (refflag == 0)
12890Sstevel@tonic-gate 			return (PICL_INVREFERENCE);
12900Sstevel@tonic-gate 		/*
12910Sstevel@tonic-gate 		 * check valid reference handle for non-volatiles
12920Sstevel@tonic-gate 		 */
12930Sstevel@tonic-gate 		if (!(pinfo->piclinfo.accessmode & PICL_VOLATILE)) {
12940Sstevel@tonic-gate 			if (valbuf == NULL)
12950Sstevel@tonic-gate 				return (PICL_INVREFERENCE);
12960Sstevel@tonic-gate 			if (pinfo->piclinfo.size != sizeof (picl_nodehdl_t))
12970Sstevel@tonic-gate 				return (PICL_INVREFERENCE);
12980Sstevel@tonic-gate 			(void) strcpy(classname, pinfo->piclinfo.name);
12990Sstevel@tonic-gate 			ptr = strchr(&classname[1], '_');
13000Sstevel@tonic-gate 			*ptr = '\0';
13010Sstevel@tonic-gate 			refh = *(picl_hdl_t *)valbuf;
13020Sstevel@tonic-gate 			err = check_ref_handle(refh, &classname[1]);
13030Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
13040Sstevel@tonic-gate 				return (err);
13050Sstevel@tonic-gate 		}
13060Sstevel@tonic-gate 	} else if (refflag == 1)
13070Sstevel@tonic-gate 		return (PICL_INVREFERENCE);
13080Sstevel@tonic-gate 	else if ((pinfo->piclinfo.type == PICL_PTYPE_TABLE) &&
13090Sstevel@tonic-gate 	    (!(pinfo->piclinfo.accessmode & PICL_VOLATILE))) {
13100Sstevel@tonic-gate 		if (pinfo->piclinfo.size != sizeof (picl_prophdl_t))
13110Sstevel@tonic-gate 			return (PICL_INVALIDARG);
13120Sstevel@tonic-gate 		tblh = *(picl_prophdl_t *)valbuf;
13130Sstevel@tonic-gate 		err = check_table_handle(tblh);
13140Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
13150Sstevel@tonic-gate 			return (err);
13160Sstevel@tonic-gate 	} else if ((strcmp(pinfo->piclinfo.name, PICL_PROP_CLASSNAME) == 0) &&
13170Sstevel@tonic-gate 	    ((pinfo->piclinfo.type != PICL_PTYPE_CHARSTRING) ||
13185672Sanbui 	    (strlen(valbuf) >= PICL_CLASSNAMELEN_MAX)))
13190Sstevel@tonic-gate 		return (PICL_RESERVEDNAME);
13200Sstevel@tonic-gate 	else if ((strcmp(pinfo->piclinfo.name, PICL_PROP_NAME) == 0) &&
13210Sstevel@tonic-gate 	    (pinfo->piclinfo.type != PICL_PTYPE_CHARSTRING))
13220Sstevel@tonic-gate 		return (PICL_RESERVEDNAME);
13230Sstevel@tonic-gate 	/*
13240Sstevel@tonic-gate 	 * No locks held when you get here
13250Sstevel@tonic-gate 	 */
13260Sstevel@tonic-gate 	err = create_propobj(pinfo, valbuf, &pobj);
13270Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
13280Sstevel@tonic-gate 		return (err);
13290Sstevel@tonic-gate 
13300Sstevel@tonic-gate 	alloc_and_add_to_ptree(pobj);
13310Sstevel@tonic-gate 	*proph = pobj->ptree_hdl;
13320Sstevel@tonic-gate 	return (PICL_SUCCESS);
13330Sstevel@tonic-gate }
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate /*
13360Sstevel@tonic-gate  * Lock free routine to destroy table entries
13370Sstevel@tonic-gate  * This function removes the destroyed handles from the hash table
13380Sstevel@tonic-gate  * Uses lock free routines: hash_lookup() and hash_remove()
13390Sstevel@tonic-gate  */
13400Sstevel@tonic-gate static void
destroy_table(picl_obj_t * pobj)13410Sstevel@tonic-gate destroy_table(picl_obj_t *pobj)
13420Sstevel@tonic-gate {
13430Sstevel@tonic-gate 	picl_prophdl_t  tblh;
13440Sstevel@tonic-gate 	picl_obj_t	*tbl_obj;
13450Sstevel@tonic-gate 	picl_obj_t	*rowp;
13460Sstevel@tonic-gate 	picl_obj_t	*colp;
13470Sstevel@tonic-gate 	picl_obj_t	*freep;
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 	tblh = *(picl_prophdl_t *)pobj->prop_val;
13500Sstevel@tonic-gate 	tbl_obj = hash_lookup_obj(&ptreetbl, tblh);
13510Sstevel@tonic-gate 	if (tbl_obj == NULL)
13520Sstevel@tonic-gate 		return;
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 	assert(tbl_obj->obj_type & PICL_OBJ_TABLE);
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 	/* Delete all entries */
13570Sstevel@tonic-gate 	rowp = tbl_obj->next_row;
13580Sstevel@tonic-gate 	while (rowp != NULL) {
13590Sstevel@tonic-gate 		colp = rowp;
13600Sstevel@tonic-gate 		rowp = rowp->next_col;
13610Sstevel@tonic-gate 		while (colp != NULL) {
13620Sstevel@tonic-gate 			freep = colp;
13630Sstevel@tonic-gate 			colp = colp->next_row;
13640Sstevel@tonic-gate 			(void) hash_remove(&ptreetbl, freep->ptree_hdl);
13650Sstevel@tonic-gate 			if (freep->prop_val)
13660Sstevel@tonic-gate 				free(freep->prop_val);
13670Sstevel@tonic-gate 			free(freep);
13680Sstevel@tonic-gate 		}
13690Sstevel@tonic-gate 	}
13700Sstevel@tonic-gate 
13710Sstevel@tonic-gate 	(void) hash_remove(&ptreetbl, tbl_obj->ptree_hdl);
13720Sstevel@tonic-gate 	free(tbl_obj);
13730Sstevel@tonic-gate }
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate /*
13770Sstevel@tonic-gate  * Lock free function that frees up a property object and removes the
13780Sstevel@tonic-gate  * handles from Ptree table
13790Sstevel@tonic-gate  */
13800Sstevel@tonic-gate static void
destroy_propobj(picl_obj_t * propp)13810Sstevel@tonic-gate destroy_propobj(picl_obj_t *propp)
13820Sstevel@tonic-gate {
13830Sstevel@tonic-gate 	if (propp->prop_type == PICL_PTYPE_TABLE)
13840Sstevel@tonic-gate 		destroy_table(propp);
13850Sstevel@tonic-gate 
13860Sstevel@tonic-gate 	(void) hash_remove(&ptreetbl, propp->ptree_hdl);
13870Sstevel@tonic-gate 	if (propp->prop_val)
13880Sstevel@tonic-gate 		free(propp->prop_val);
13890Sstevel@tonic-gate 	free(propp);
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate /*
13930Sstevel@tonic-gate  * This function destroys a previously deleted property.
13940Sstevel@tonic-gate  * A deleted property does not have an associated node.
13950Sstevel@tonic-gate  * All memory allocated for this property are freed
13960Sstevel@tonic-gate  */
13970Sstevel@tonic-gate int
ptree_destroy_prop(picl_prophdl_t proph)13980Sstevel@tonic-gate ptree_destroy_prop(picl_prophdl_t proph)
13990Sstevel@tonic-gate {
14000Sstevel@tonic-gate 	picl_obj_t	*propp;
14010Sstevel@tonic-gate 
14020Sstevel@tonic-gate 	(void) rw_wrlock(&ptree_rwlock);	/* Exclusive Lock ptree */
14030Sstevel@tonic-gate 
14040Sstevel@tonic-gate 	propp = hash_lookup_obj(&ptreetbl, proph);
14050Sstevel@tonic-gate 	if (propp == NULL) {
14060Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* Unlock ptree */
14070Sstevel@tonic-gate 		return (ptree_hdl_error(proph));
14080Sstevel@tonic-gate 	}
14090Sstevel@tonic-gate 
14100Sstevel@tonic-gate 	/* Is the prop still attached to a node? */
14110Sstevel@tonic-gate 	if (propp->prop_node != NULL) {
14120Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* Unlock ptree */
14130Sstevel@tonic-gate 		return (PICL_CANTDESTROY);
14140Sstevel@tonic-gate 	}
14150Sstevel@tonic-gate 
14160Sstevel@tonic-gate 	destroy_propobj(propp);
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* Unlock ptree */
14190Sstevel@tonic-gate 	return (PICL_SUCCESS);
14200Sstevel@tonic-gate }
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate /*
14230Sstevel@tonic-gate  * This function adds a property to the property list of a node and adds
14240Sstevel@tonic-gate  * it to the PICL table if the node has a PICL handle.
14250Sstevel@tonic-gate  * This function locks the picl_rwlock and ptree_rwlock.
14260Sstevel@tonic-gate  */
14270Sstevel@tonic-gate int
ptree_add_prop(picl_nodehdl_t nodeh,picl_prophdl_t proph)14280Sstevel@tonic-gate ptree_add_prop(picl_nodehdl_t nodeh, picl_prophdl_t proph)
14290Sstevel@tonic-gate {
14300Sstevel@tonic-gate 	int		err;
14310Sstevel@tonic-gate 	picl_obj_t	*nodep;
14320Sstevel@tonic-gate 	picl_obj_t	*propp;
14330Sstevel@tonic-gate 	picl_obj_t  	*tbl_obj;
14340Sstevel@tonic-gate 	picl_obj_t	*refobj;
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* RDLock ptree */
14370Sstevel@tonic-gate 
14380Sstevel@tonic-gate 	/*
14390Sstevel@tonic-gate 	 * Verify property handle
14400Sstevel@tonic-gate 	 */
14410Sstevel@tonic-gate 	err = lookup_verify_prop_handle(proph, &propp);
14420Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
14430Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* Unlock ptree */
14440Sstevel@tonic-gate 		return (err);
14450Sstevel@tonic-gate 	}
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 	if (propp->prop_node != NULL) {
14480Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
14490Sstevel@tonic-gate 		return (PICL_INVALIDARG);
14500Sstevel@tonic-gate 	}
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate 	nodep = NULL;
14530Sstevel@tonic-gate 	/*
14540Sstevel@tonic-gate 	 * Exclusive Lock the node's properties
14550Sstevel@tonic-gate 	 */
14560Sstevel@tonic-gate 	err = lookup_and_lock_node(WRLOCK_NODE, nodeh, &nodep);
14570Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
14580Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* Unlock ptree */
14590Sstevel@tonic-gate 		return (err);
14600Sstevel@tonic-gate 	}
14610Sstevel@tonic-gate 
14620Sstevel@tonic-gate 	/*
14630Sstevel@tonic-gate 	 * check if prop already exists
14640Sstevel@tonic-gate 	 */
14650Sstevel@tonic-gate 	err = lookup_prop_by_name(nodep, propp->prop_name, NULL);
14660Sstevel@tonic-gate 	if (err == PICL_SUCCESS) {
14670Sstevel@tonic-gate 		unlock_node(nodep);			/* Unlock node */
14680Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* Unlock table */
14690Sstevel@tonic-gate 		return (PICL_PROPEXISTS);
14700Sstevel@tonic-gate 	}
14710Sstevel@tonic-gate 
14720Sstevel@tonic-gate 	/*
14730Sstevel@tonic-gate 	 * Verify property's value
14740Sstevel@tonic-gate 	 */
14750Sstevel@tonic-gate 	tbl_obj = NULL;
14760Sstevel@tonic-gate 	switch (propp->prop_type) {
14770Sstevel@tonic-gate 	case PICL_PTYPE_TABLE:
14780Sstevel@tonic-gate 		if (propp->prop_mode & PICL_VOLATILE)
14790Sstevel@tonic-gate 			break;
14800Sstevel@tonic-gate 		err = lookup_verify_table_prop(propp, &tbl_obj);
14810Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
14820Sstevel@tonic-gate 			unlock_node(nodep);
14830Sstevel@tonic-gate 			(void) rw_unlock(&ptree_rwlock);
14840Sstevel@tonic-gate 			return (err);
14850Sstevel@tonic-gate 		}
14860Sstevel@tonic-gate 		tbl_obj->prop_node = nodep;	/* set table's nodep */
14870Sstevel@tonic-gate 		tbl_obj->table_prop = propp;	/* set table prop */
14880Sstevel@tonic-gate 		break;
14890Sstevel@tonic-gate 	case PICL_PTYPE_REFERENCE:
14900Sstevel@tonic-gate 		if (propp->prop_mode & PICL_VOLATILE)
14910Sstevel@tonic-gate 			break;
14920Sstevel@tonic-gate 		err = lookup_verify_ref_prop(propp, &refobj);
14930Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
14940Sstevel@tonic-gate 			unlock_node(nodep);
14950Sstevel@tonic-gate 			(void) rw_unlock(&ptree_rwlock);
14960Sstevel@tonic-gate 			return (err);
14970Sstevel@tonic-gate 		}
14980Sstevel@tonic-gate 		if (IS_PICLIZED(nodep) && !IS_PICLIZED(refobj)) {
14990Sstevel@tonic-gate 			unlock_node(nodep);
15000Sstevel@tonic-gate 			(void) rw_unlock(&ptree_rwlock);
15010Sstevel@tonic-gate 			return (err);
15020Sstevel@tonic-gate 		}
15030Sstevel@tonic-gate 		break;
15040Sstevel@tonic-gate 	default:
15050Sstevel@tonic-gate 		break;
15060Sstevel@tonic-gate 	}
15070Sstevel@tonic-gate 
15080Sstevel@tonic-gate 	if (IS_PICLIZED(nodep))
15090Sstevel@tonic-gate 		piclize_prop(propp);
15100Sstevel@tonic-gate 	/*
15110Sstevel@tonic-gate 	 * Add prop to beginning of list
15120Sstevel@tonic-gate 	 */
15130Sstevel@tonic-gate 	propp->prop_node = nodep;		/* set prop's nodep */
15140Sstevel@tonic-gate 	propp->next_prop = nodep->first_prop;
15150Sstevel@tonic-gate 	nodep->first_prop = propp;
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 	unlock_node(nodep);				/* Unlock node */
15180Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* Unlock table */
15190Sstevel@tonic-gate 	return (PICL_SUCCESS);
15200Sstevel@tonic-gate }
15210Sstevel@tonic-gate 
15220Sstevel@tonic-gate /*
15230Sstevel@tonic-gate  * Lock free function that unlinks a property from its node
15240Sstevel@tonic-gate  */
15250Sstevel@tonic-gate static int
unlink_prop(picl_obj_t * nodep,picl_obj_t * propp)15260Sstevel@tonic-gate unlink_prop(picl_obj_t *nodep, picl_obj_t *propp)
15270Sstevel@tonic-gate {
15280Sstevel@tonic-gate 	picl_obj_t	*iterp;
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	iterp = nodep->first_prop;
15310Sstevel@tonic-gate 	if (iterp == propp) {	/* first property */
15320Sstevel@tonic-gate 		nodep->first_prop = iterp->next_prop;
15330Sstevel@tonic-gate 		return (PICL_SUCCESS);
15340Sstevel@tonic-gate 	}
15350Sstevel@tonic-gate 	while ((iterp != NULL) && (iterp->next_prop != propp))
15360Sstevel@tonic-gate 		iterp = iterp->next_prop;
15370Sstevel@tonic-gate 	if (iterp == NULL)
15380Sstevel@tonic-gate 		return (PICL_PROPNOTFOUND);
15390Sstevel@tonic-gate 	iterp->next_prop = propp->next_prop;
15400Sstevel@tonic-gate 	return (PICL_SUCCESS);
15410Sstevel@tonic-gate }
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate /*
15440Sstevel@tonic-gate  * This function deletes the specified property from the property list
15450Sstevel@tonic-gate  * of its node and removes the handle from PICL table, if the node
15460Sstevel@tonic-gate  * was piclized.
15470Sstevel@tonic-gate  */
15480Sstevel@tonic-gate int
ptree_delete_prop(picl_prophdl_t proph)15490Sstevel@tonic-gate ptree_delete_prop(picl_prophdl_t proph)
15500Sstevel@tonic-gate {
15510Sstevel@tonic-gate 	int		err;
15520Sstevel@tonic-gate 	picl_obj_t	*nodep;
15530Sstevel@tonic-gate 	picl_obj_t	*propp;
15540Sstevel@tonic-gate 
15550Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
15560Sstevel@tonic-gate 	/*
15570Sstevel@tonic-gate 	 * Lookup the property's node and lock it if there is one
15580Sstevel@tonic-gate 	 * return the objects for the property and the node
15590Sstevel@tonic-gate 	 */
15600Sstevel@tonic-gate 	nodep = propp = NULL;
15610Sstevel@tonic-gate 	err = lookup_and_lock_propnode(WRLOCK_NODE, proph, &nodep, &propp);
15620Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
15630Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
15640Sstevel@tonic-gate 		return (err);
15650Sstevel@tonic-gate 	} else if (nodep == NULL) {
15660Sstevel@tonic-gate 		/* Nothing to do - already deleted! */
15670Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
15680Sstevel@tonic-gate 		return (PICL_SUCCESS);
15690Sstevel@tonic-gate 	}
15700Sstevel@tonic-gate 
15710Sstevel@tonic-gate 	if (propp->obj_type & PICL_OBJ_TABLEENTRY) {
15720Sstevel@tonic-gate 		unlock_node(nodep);			/* Unlock node */
15730Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
15740Sstevel@tonic-gate 		return (PICL_NOTPROP);
15750Sstevel@tonic-gate 	}
15760Sstevel@tonic-gate 
15770Sstevel@tonic-gate 	err = unlink_prop(nodep, propp);
15780Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
15790Sstevel@tonic-gate 		unlock_node(nodep);			/* Unlock node */
15800Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
15810Sstevel@tonic-gate 		return (err);
15820Sstevel@tonic-gate 	}
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	propp->prop_node = NULL;	/* reset prop's nodep */
15850Sstevel@tonic-gate 	propp->next_prop = NULL;
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate 	unpiclize_prop(propp);
15880Sstevel@tonic-gate 
15890Sstevel@tonic-gate 	unlock_node(nodep);				/* Unlock node */
15900Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
15910Sstevel@tonic-gate 	return (PICL_SUCCESS);
15920Sstevel@tonic-gate }
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate /*
15950Sstevel@tonic-gate  * Create a table object and return its handle
15960Sstevel@tonic-gate  */
15970Sstevel@tonic-gate int
ptree_create_table(picl_prophdl_t * tblh)15980Sstevel@tonic-gate ptree_create_table(picl_prophdl_t *tblh)
15990Sstevel@tonic-gate {
16000Sstevel@tonic-gate 	picl_obj_t	*pobj;
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 	pobj = malloc(sizeof (picl_obj_t));
16030Sstevel@tonic-gate 	if (pobj == NULL)
16040Sstevel@tonic-gate 		return (PICL_FAILURE);
16050Sstevel@tonic-gate 	pobj->obj_type = PICL_OBJ_TABLE;
16060Sstevel@tonic-gate 	pobj->prop_val = NULL;
16070Sstevel@tonic-gate 	pobj->prop_node = NULL;
16080Sstevel@tonic-gate 	pobj->ptree_hdl = PICL_INVALID_PICLHDL;
16090Sstevel@tonic-gate 	pobj->picl_hdl = PICL_INVALID_PICLHDL;
16100Sstevel@tonic-gate 	pobj->table_prop = NULL;
16110Sstevel@tonic-gate 	pobj->next_row = NULL;
16120Sstevel@tonic-gate 	pobj->next_col = NULL;
16130Sstevel@tonic-gate 
16140Sstevel@tonic-gate 	alloc_and_add_to_ptree(pobj);
16150Sstevel@tonic-gate 	*tblh = pobj->ptree_hdl;
16160Sstevel@tonic-gate 	return (PICL_SUCCESS);
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate 
16190Sstevel@tonic-gate /*
16200Sstevel@tonic-gate  * Add the properties in <props> array as a row in the table
16210Sstevel@tonic-gate  * Add PICL handles if the table has a valid PICL handle
16220Sstevel@tonic-gate  */
16230Sstevel@tonic-gate int
ptree_add_row_to_table(picl_prophdl_t tblh,int nprops,const picl_prophdl_t * props)16240Sstevel@tonic-gate ptree_add_row_to_table(picl_prophdl_t tblh, int nprops,
16250Sstevel@tonic-gate     const picl_prophdl_t *props)
16260Sstevel@tonic-gate {
16270Sstevel@tonic-gate 	picl_obj_t	*tbl_obj;
16280Sstevel@tonic-gate 	picl_obj_t	*nodep;
16290Sstevel@tonic-gate 	picl_obj_t	*lastrow;
16300Sstevel@tonic-gate 	picl_obj_t	**newrow;
16310Sstevel@tonic-gate 	int		i;
16320Sstevel@tonic-gate 	int		err;
16330Sstevel@tonic-gate 	picl_obj_t	*pobj;
16340Sstevel@tonic-gate 	int		picl_it;
16350Sstevel@tonic-gate 
16360Sstevel@tonic-gate 	if (nprops < 1)
16370Sstevel@tonic-gate 		return (PICL_INVALIDARG);
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 	newrow = malloc(sizeof (picl_obj_t *) * nprops);
16400Sstevel@tonic-gate 	if (newrow == NULL)
16410Sstevel@tonic-gate 		return (PICL_FAILURE);
16420Sstevel@tonic-gate 
16430Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* Lock ptree */
16440Sstevel@tonic-gate 
16450Sstevel@tonic-gate 	err = lookup_and_lock_tablenode(WRLOCK_NODE, tblh, &nodep, &tbl_obj);
16460Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
16470Sstevel@tonic-gate 		free(newrow);
16480Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* Unlock table */
16490Sstevel@tonic-gate 		return (err);
16500Sstevel@tonic-gate 	}
16510Sstevel@tonic-gate 
16520Sstevel@tonic-gate 	/*
16530Sstevel@tonic-gate 	 * make sure all are either props or table handles
16540Sstevel@tonic-gate 	 */
16550Sstevel@tonic-gate 	for (i = 0; i < nprops; ++i) {
16560Sstevel@tonic-gate 		pobj = newrow[i] = hash_lookup_obj(&ptreetbl, props[i]);
16570Sstevel@tonic-gate 		if (pobj == NULL) {	/* no object */
16580Sstevel@tonic-gate 			err = ptree_hdl_error(props[i]);
16590Sstevel@tonic-gate 			break;
16600Sstevel@tonic-gate 		}
16610Sstevel@tonic-gate 		if ((!(pobj->obj_type & PICL_OBJ_PROP)) &&
16620Sstevel@tonic-gate 		    (!(pobj->obj_type & PICL_OBJ_TABLE))) {
16630Sstevel@tonic-gate 			err = PICL_NOTPROP;
16640Sstevel@tonic-gate 			break;
16650Sstevel@tonic-gate 		}
16660Sstevel@tonic-gate 		if (IS_PICLIZED(pobj) || (pobj->prop_table != NULL) ||
16670Sstevel@tonic-gate 		    (pobj->prop_node != NULL)) {
16680Sstevel@tonic-gate 			err = PICL_INVALIDARG;
16690Sstevel@tonic-gate 			break;
16700Sstevel@tonic-gate 		}
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 	}
16730Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
16740Sstevel@tonic-gate 		free(newrow);
16750Sstevel@tonic-gate 		unlock_node(nodep);
16760Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* Unlock table */
16770Sstevel@tonic-gate 		return (err);
16780Sstevel@tonic-gate 	}
16790Sstevel@tonic-gate 
16800Sstevel@tonic-gate 	/*
16810Sstevel@tonic-gate 	 * Mark all props as table entries, set up row linkages
16820Sstevel@tonic-gate 	 */
16830Sstevel@tonic-gate 	picl_it = 0;
16840Sstevel@tonic-gate 	if (IS_PICLIZED(tbl_obj))
16850Sstevel@tonic-gate 		picl_it = 1;
16860Sstevel@tonic-gate 	for (i = 0; i < nprops; ++i) {
16870Sstevel@tonic-gate 		newrow[i]->obj_type |= PICL_OBJ_TABLEENTRY;
16880Sstevel@tonic-gate 		newrow[i]->prop_table = tbl_obj;
16890Sstevel@tonic-gate 		newrow[i]->next_prop = NULL;
16900Sstevel@tonic-gate 		newrow[i]->next_col =  NULL;
16910Sstevel@tonic-gate 		if (picl_it)
16920Sstevel@tonic-gate 			piclize_obj(newrow[i]);
16930Sstevel@tonic-gate 		if (i != nprops - 1)
16940Sstevel@tonic-gate 			newrow[i]->next_row = newrow[i+1];
16950Sstevel@tonic-gate 	}
16960Sstevel@tonic-gate 	newrow[nprops - 1]->next_row = NULL;
16970Sstevel@tonic-gate 
16980Sstevel@tonic-gate 	if (tbl_obj->next_row == NULL) {	/* add first row */
16990Sstevel@tonic-gate 		tbl_obj->next_row = newrow[0];
17000Sstevel@tonic-gate 		tbl_obj->next_col = newrow[0];
17010Sstevel@tonic-gate 	} else {
17020Sstevel@tonic-gate 		lastrow = tbl_obj->next_row;
17030Sstevel@tonic-gate 		while (lastrow->next_col != NULL)
17040Sstevel@tonic-gate 			lastrow = lastrow->next_col;
17050Sstevel@tonic-gate 		i = 0;
17060Sstevel@tonic-gate 		while (lastrow != NULL) {
17070Sstevel@tonic-gate 			lastrow->next_col = newrow[i];
17080Sstevel@tonic-gate 			lastrow = lastrow->next_row;
17090Sstevel@tonic-gate 			++i;
17100Sstevel@tonic-gate 		}
17110Sstevel@tonic-gate 	}
17120Sstevel@tonic-gate 
17130Sstevel@tonic-gate 	unlock_node(nodep);			/* unlock node */
17140Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);	/* Unlock ptree */
17150Sstevel@tonic-gate 	free(newrow);
17160Sstevel@tonic-gate 	return (PICL_SUCCESS);
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate /*
17200Sstevel@tonic-gate  * This function returns the handle of the next property in the row
17210Sstevel@tonic-gate  */
17220Sstevel@tonic-gate int
ptree_get_next_by_row(picl_prophdl_t proph,picl_prophdl_t * nextrowh)17230Sstevel@tonic-gate ptree_get_next_by_row(picl_prophdl_t proph, picl_prophdl_t *nextrowh)
17240Sstevel@tonic-gate {
17250Sstevel@tonic-gate 	int		err;
17260Sstevel@tonic-gate 	picl_obj_t	*nodep;
17270Sstevel@tonic-gate 	picl_obj_t	*propp;
17280Sstevel@tonic-gate 
17290Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 	nodep = propp = NULL;
17320Sstevel@tonic-gate 	/*
17330Sstevel@tonic-gate 	 * proph could be a table handle or a table entry handle
17340Sstevel@tonic-gate 	 * Look it up as a table entry handle first, check error code
17350Sstevel@tonic-gate 	 * to see if it is a table handle
17360Sstevel@tonic-gate 	 */
17370Sstevel@tonic-gate 	err = lookup_and_lock_tableprop_node(RDLOCK_NODE, proph, &nodep,
17380Sstevel@tonic-gate 	    &propp);
17390Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
17400Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
17410Sstevel@tonic-gate 		return (err);
17420Sstevel@tonic-gate 	}
17430Sstevel@tonic-gate 
17440Sstevel@tonic-gate 	if (propp->next_row)
17450Sstevel@tonic-gate 		*nextrowh = propp->next_row->ptree_hdl;
17460Sstevel@tonic-gate 	else
17470Sstevel@tonic-gate 		err = PICL_ENDOFLIST;
17480Sstevel@tonic-gate 
17490Sstevel@tonic-gate 	unlock_node(nodep);			/* unlock node */
17500Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
17510Sstevel@tonic-gate 	return (err);
17520Sstevel@tonic-gate }
17530Sstevel@tonic-gate 
17540Sstevel@tonic-gate int
ptree_get_next_by_col(picl_prophdl_t proph,picl_prophdl_t * nextcolh)17550Sstevel@tonic-gate ptree_get_next_by_col(picl_prophdl_t proph, picl_prophdl_t *nextcolh)
17560Sstevel@tonic-gate {
17570Sstevel@tonic-gate 	int		err;
17580Sstevel@tonic-gate 	picl_obj_t	*propp;
17590Sstevel@tonic-gate 	picl_obj_t	*nodep;
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
17620Sstevel@tonic-gate 	nodep = propp = NULL;
17630Sstevel@tonic-gate 	/*
17640Sstevel@tonic-gate 	 * proph could be a table handle or a table entry handle
17650Sstevel@tonic-gate 	 * Look it up as a table entry handle first, check error code
17660Sstevel@tonic-gate 	 * to see if it is a table handle
17670Sstevel@tonic-gate 	 */
17680Sstevel@tonic-gate 	err = lookup_and_lock_tableprop_node(RDLOCK_NODE, proph, &nodep,
17690Sstevel@tonic-gate 	    &propp);
17700Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
17710Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
17720Sstevel@tonic-gate 		return (err);
17730Sstevel@tonic-gate 	}
17740Sstevel@tonic-gate 
17750Sstevel@tonic-gate 	if (propp->next_col)
17760Sstevel@tonic-gate 		*nextcolh = propp->next_col->ptree_hdl;
17770Sstevel@tonic-gate 	else
17780Sstevel@tonic-gate 		err = PICL_ENDOFLIST;
17790Sstevel@tonic-gate 
17800Sstevel@tonic-gate 	unlock_node(nodep);			/* unlock node */
17810Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
17820Sstevel@tonic-gate 	return (err);
17830Sstevel@tonic-gate }
17840Sstevel@tonic-gate 
17850Sstevel@tonic-gate /*
17860Sstevel@tonic-gate  * This function creates node object and adds its handle to the Ptree
17870Sstevel@tonic-gate  */
17880Sstevel@tonic-gate int
ptree_create_node(const char * name,const char * clname,picl_nodehdl_t * nodeh)17890Sstevel@tonic-gate ptree_create_node(const char *name, const char *clname, picl_nodehdl_t *nodeh)
17900Sstevel@tonic-gate {
17910Sstevel@tonic-gate 	picl_obj_t 		*pobj;
17920Sstevel@tonic-gate 	ptree_propinfo_t 	propinfo;
17930Sstevel@tonic-gate 	picl_prophdl_t		phdl;
17940Sstevel@tonic-gate 	picl_prophdl_t		cphdl;
17950Sstevel@tonic-gate 	int			err;
17960Sstevel@tonic-gate 
17970Sstevel@tonic-gate 	if ((name == NULL) || (*name == '\0') ||
17980Sstevel@tonic-gate 	    (clname == NULL) || (*clname == '\0'))
17990Sstevel@tonic-gate 		return (PICL_INVALIDARG);
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate 	if ((strlen(name) >= PICL_PROPNAMELEN_MAX) ||
18020Sstevel@tonic-gate 	    (strlen(clname) >= PICL_CLASSNAMELEN_MAX))
18030Sstevel@tonic-gate 		return (PICL_VALUETOOBIG);
18040Sstevel@tonic-gate 
18050Sstevel@tonic-gate 	/*
18060Sstevel@tonic-gate 	 * Create the picl object for node
18070Sstevel@tonic-gate 	 */
18080Sstevel@tonic-gate 	pobj = malloc(sizeof (picl_obj_t));
18090Sstevel@tonic-gate 	if (pobj == NULL)
18100Sstevel@tonic-gate 		return (PICL_FAILURE);
18110Sstevel@tonic-gate 	pobj->obj_type = PICL_OBJ_NODE;
18120Sstevel@tonic-gate 	pobj->first_prop = NULL;
18130Sstevel@tonic-gate 	pobj->ptree_hdl = PICL_INVALID_PICLHDL;
18140Sstevel@tonic-gate 	pobj->picl_hdl = PICL_INVALID_PICLHDL;
18150Sstevel@tonic-gate 	pobj->parent_node = NULL;
18160Sstevel@tonic-gate 	pobj->sibling_node = NULL;
18170Sstevel@tonic-gate 	pobj->child_node = NULL;
18180Sstevel@tonic-gate 	pobj->node_classname = strdup(clname);
18190Sstevel@tonic-gate 	if (pobj->node_classname == NULL) {
18200Sstevel@tonic-gate 		free(pobj);
18210Sstevel@tonic-gate 		return (PICL_FAILURE);
18220Sstevel@tonic-gate 	}
18230Sstevel@tonic-gate 	(void) rwlock_init(&pobj->node_lock, USYNC_THREAD, NULL);
18240Sstevel@tonic-gate 
18250Sstevel@tonic-gate 	alloc_and_add_to_ptree(pobj);	/* commit the node */
18260Sstevel@tonic-gate 
18270Sstevel@tonic-gate 	/*
18280Sstevel@tonic-gate 	 * create name property
18290Sstevel@tonic-gate 	 */
18300Sstevel@tonic-gate 	propinfo.version = PTREE_PROPINFO_VERSION_1;
18310Sstevel@tonic-gate 	propinfo.piclinfo.type = PICL_PTYPE_CHARSTRING;
18320Sstevel@tonic-gate 	propinfo.piclinfo.accessmode = PICL_READ;
18330Sstevel@tonic-gate 	propinfo.piclinfo.size = strlen(name) + 1;
18340Sstevel@tonic-gate 	(void) strcpy(propinfo.piclinfo.name, PICL_PROP_NAME);
18350Sstevel@tonic-gate 	propinfo.read = NULL;
18360Sstevel@tonic-gate 	propinfo.write = NULL;
18370Sstevel@tonic-gate 	err = ptree_create_prop(&propinfo, (const void *)name, &phdl);
18380Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
18390Sstevel@tonic-gate 		(void) ptree_destroy_node(pobj->ptree_hdl);
18400Sstevel@tonic-gate 		return (err);
18410Sstevel@tonic-gate 	}
18420Sstevel@tonic-gate 	err = ptree_add_prop(pobj->ptree_hdl, phdl);
18430Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
18440Sstevel@tonic-gate 		(void) ptree_destroy_prop(phdl);
18450Sstevel@tonic-gate 		(void) ptree_destroy_node(pobj->ptree_hdl);
18460Sstevel@tonic-gate 		return (err);
18470Sstevel@tonic-gate 	}
18480Sstevel@tonic-gate 
18490Sstevel@tonic-gate 	/*
18500Sstevel@tonic-gate 	 * create picl classname property
18510Sstevel@tonic-gate 	 */
18520Sstevel@tonic-gate 	propinfo.piclinfo.size = strlen(clname) + 1;
18530Sstevel@tonic-gate 	(void) strcpy(propinfo.piclinfo.name, PICL_PROP_CLASSNAME);
18540Sstevel@tonic-gate 	propinfo.read = NULL;
18550Sstevel@tonic-gate 	propinfo.write = NULL;
18560Sstevel@tonic-gate 	err = ptree_create_prop(&propinfo, (const void *)clname, &cphdl);
18570Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
18580Sstevel@tonic-gate 		(void) ptree_destroy_node(pobj->ptree_hdl);
18590Sstevel@tonic-gate 		return (err);
18600Sstevel@tonic-gate 	}
18610Sstevel@tonic-gate 	err = ptree_add_prop(pobj->ptree_hdl, cphdl);
18620Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
18630Sstevel@tonic-gate 		(void) ptree_destroy_prop(cphdl);
18640Sstevel@tonic-gate 		(void) ptree_destroy_node(pobj->ptree_hdl);
18650Sstevel@tonic-gate 		return (err);
18660Sstevel@tonic-gate 	}
18670Sstevel@tonic-gate 
18680Sstevel@tonic-gate 	*nodeh = pobj->ptree_hdl;
18690Sstevel@tonic-gate 	return (PICL_SUCCESS);
18700Sstevel@tonic-gate }
18710Sstevel@tonic-gate 
18720Sstevel@tonic-gate /*
18730Sstevel@tonic-gate  * Destroy a node/subtree freeing up space
18740Sstevel@tonic-gate  * Removed destroyed objects' handles from PTree table
18750Sstevel@tonic-gate  */
18760Sstevel@tonic-gate static void
destroy_subtree(picl_obj_t * nodep)18770Sstevel@tonic-gate destroy_subtree(picl_obj_t *nodep)
18780Sstevel@tonic-gate {
18790Sstevel@tonic-gate 	picl_obj_t	*iterp;
18800Sstevel@tonic-gate 	picl_obj_t	*freep;
18810Sstevel@tonic-gate 	picl_obj_t	*chdp;
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate 	if (nodep == NULL)
18840Sstevel@tonic-gate 		return;
18850Sstevel@tonic-gate 
18860Sstevel@tonic-gate 	chdp = nodep->child_node;
18870Sstevel@tonic-gate 	while (chdp != NULL) {
18880Sstevel@tonic-gate 		freep = chdp;
18890Sstevel@tonic-gate 		chdp = chdp->sibling_node;
18900Sstevel@tonic-gate 		destroy_subtree(freep);
18910Sstevel@tonic-gate 	}
18920Sstevel@tonic-gate 
18930Sstevel@tonic-gate 	/*
18940Sstevel@tonic-gate 	 * Lock the node
18950Sstevel@tonic-gate 	 */
18960Sstevel@tonic-gate 	(void) lock_obj(WRLOCK_NODE, nodep);
18970Sstevel@tonic-gate 
18980Sstevel@tonic-gate 	/*
18990Sstevel@tonic-gate 	 * destroy all properties associated with this node
19000Sstevel@tonic-gate 	 */
19010Sstevel@tonic-gate 	iterp = nodep->first_prop;
19020Sstevel@tonic-gate 	while (iterp != NULL) {
19030Sstevel@tonic-gate 		freep = iterp;
19040Sstevel@tonic-gate 		iterp = iterp->next_prop;
19050Sstevel@tonic-gate 		destroy_propobj(freep);
19060Sstevel@tonic-gate 	}
19070Sstevel@tonic-gate 
19080Sstevel@tonic-gate 	(void) hash_remove(&ptreetbl, nodep->ptree_hdl);
19090Sstevel@tonic-gate 	(void) rwlock_destroy(&nodep->node_lock);
19100Sstevel@tonic-gate 	free(nodep->node_classname);
19110Sstevel@tonic-gate 	free(nodep);
19120Sstevel@tonic-gate }
19130Sstevel@tonic-gate 
19140Sstevel@tonic-gate /*
19150Sstevel@tonic-gate  * This function destroys a previously deleted node/subtree. All the properties
19160Sstevel@tonic-gate  * are freed and removed from the PTree table.
19170Sstevel@tonic-gate  * Only one destroy is in progress at any time.
19180Sstevel@tonic-gate  */
19190Sstevel@tonic-gate int
ptree_destroy_node(picl_nodehdl_t nodeh)19200Sstevel@tonic-gate ptree_destroy_node(picl_nodehdl_t nodeh)
19210Sstevel@tonic-gate {
19220Sstevel@tonic-gate 	picl_obj_t	*nodep;
19230Sstevel@tonic-gate 	picl_obj_t	*parp;
19240Sstevel@tonic-gate 	picl_obj_t	*np;
19250Sstevel@tonic-gate 	int		err;
19260Sstevel@tonic-gate 
19270Sstevel@tonic-gate 	(void) rw_wrlock(&ptree_rwlock);	/* exclusive wrlock ptree */
19280Sstevel@tonic-gate 	nodep = NULL;
19290Sstevel@tonic-gate 	err = lookup_verify_node_handle(nodeh, &nodep);
19300Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
19310Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
19320Sstevel@tonic-gate 		return (err);
19330Sstevel@tonic-gate 	}
19340Sstevel@tonic-gate 
19350Sstevel@tonic-gate 	/*
19360Sstevel@tonic-gate 	 * Has this node/subtree been deleted?
19370Sstevel@tonic-gate 	 */
19380Sstevel@tonic-gate 	if (IS_PICLIZED(nodep)) {
19390Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
19400Sstevel@tonic-gate 		return (PICL_CANTDESTROY);
19410Sstevel@tonic-gate 	}
19420Sstevel@tonic-gate 
19430Sstevel@tonic-gate 	/*
19440Sstevel@tonic-gate 	 * update parent's child list to repair the tree when
19450Sstevel@tonic-gate 	 * parent is not null
19460Sstevel@tonic-gate 	 */
19470Sstevel@tonic-gate 	parp = nodep->parent_node;
19480Sstevel@tonic-gate 	if (parp == NULL) {			/* root */
19490Sstevel@tonic-gate 		destroy_subtree(nodep);
19500Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
19510Sstevel@tonic-gate 		return (PICL_SUCCESS);
19520Sstevel@tonic-gate 	}
19530Sstevel@tonic-gate 
19540Sstevel@tonic-gate 	np = parp->child_node;
19550Sstevel@tonic-gate 	if (np == nodep) {  /* first child */
19560Sstevel@tonic-gate 		parp->child_node = nodep->sibling_node;
19570Sstevel@tonic-gate 	} else {
19580Sstevel@tonic-gate 		while ((np != NULL) && (np->sibling_node != nodep))
19590Sstevel@tonic-gate 			np = np->sibling_node;
19600Sstevel@tonic-gate 		if (np != NULL)
19610Sstevel@tonic-gate 			np->sibling_node = nodep->sibling_node;
19620Sstevel@tonic-gate 	}
19630Sstevel@tonic-gate 
19640Sstevel@tonic-gate 	destroy_subtree(nodep);
19650Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
19660Sstevel@tonic-gate 	return (PICL_SUCCESS);
19670Sstevel@tonic-gate }
19680Sstevel@tonic-gate 
19690Sstevel@tonic-gate /*
19700Sstevel@tonic-gate  * This function deletes a node/subtree from the tree and removes the handles
19710Sstevel@tonic-gate  * from PICL table
19720Sstevel@tonic-gate  */
19730Sstevel@tonic-gate int
ptree_delete_node(picl_nodehdl_t nodeh)19740Sstevel@tonic-gate ptree_delete_node(picl_nodehdl_t nodeh)
19750Sstevel@tonic-gate {
19760Sstevel@tonic-gate 	picl_obj_t	*nodep;
19770Sstevel@tonic-gate 	picl_obj_t	*parp;
19780Sstevel@tonic-gate 	picl_obj_t	*np;
19790Sstevel@tonic-gate 	int		err;
19800Sstevel@tonic-gate 
19810Sstevel@tonic-gate 	(void) rw_wrlock(&ptree_rwlock);	/* exclusive wrlock ptree */
19820Sstevel@tonic-gate 
19830Sstevel@tonic-gate 	nodep = NULL;
19840Sstevel@tonic-gate 	err = lookup_verify_node_handle(nodeh, &nodep);
19850Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
19860Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
19870Sstevel@tonic-gate 		return (err);
19880Sstevel@tonic-gate 	}
19890Sstevel@tonic-gate 
19900Sstevel@tonic-gate 	/*
19910Sstevel@tonic-gate 	 * unparent it
19920Sstevel@tonic-gate 	 */
19930Sstevel@tonic-gate 	parp = nodep->parent_node;
19940Sstevel@tonic-gate 	if (parp != NULL) {
19950Sstevel@tonic-gate 		np = parp->child_node;
19960Sstevel@tonic-gate 		if (np == nodep)	/* first child */
19970Sstevel@tonic-gate 			parp->child_node = nodep->sibling_node;
19980Sstevel@tonic-gate 		else {
19990Sstevel@tonic-gate 			while ((np != NULL) && (np->sibling_node != nodep))
20000Sstevel@tonic-gate 				np = np->sibling_node;
20010Sstevel@tonic-gate 			if (np != NULL)
20020Sstevel@tonic-gate 				np->sibling_node = nodep->sibling_node;
20030Sstevel@tonic-gate 		}
20040Sstevel@tonic-gate 	}
20050Sstevel@tonic-gate 
20060Sstevel@tonic-gate 	nodep->parent_node = NULL;
20070Sstevel@tonic-gate 	nodep->sibling_node = NULL;
20080Sstevel@tonic-gate 
20090Sstevel@tonic-gate 	unpiclize_node(nodep);
20100Sstevel@tonic-gate 
20110Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
20120Sstevel@tonic-gate 	return (PICL_SUCCESS);
20130Sstevel@tonic-gate }
20140Sstevel@tonic-gate 
20150Sstevel@tonic-gate /*
20160Sstevel@tonic-gate  * This function adds a node as a child of another node
20170Sstevel@tonic-gate  */
20180Sstevel@tonic-gate int
ptree_add_node(picl_nodehdl_t parh,picl_nodehdl_t chdh)20190Sstevel@tonic-gate ptree_add_node(picl_nodehdl_t parh, picl_nodehdl_t chdh)
20200Sstevel@tonic-gate {
20210Sstevel@tonic-gate 	picl_obj_t	*pnodep;
20220Sstevel@tonic-gate 	picl_obj_t	*cnodep;
20230Sstevel@tonic-gate 	picl_obj_t	*nodep;
20240Sstevel@tonic-gate 	int		err;
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate 	(void) rw_wrlock(&ptree_rwlock);	/* exclusive lock ptree */
20270Sstevel@tonic-gate 
20280Sstevel@tonic-gate 	pnodep = cnodep = NULL;
20290Sstevel@tonic-gate 	err = lookup_verify_node_handle(parh, &pnodep);
20300Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
20310Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
20320Sstevel@tonic-gate 		return (err);
20330Sstevel@tonic-gate 	}
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate 	err = lookup_verify_node_handle(chdh, &cnodep);
20360Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
20370Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
20380Sstevel@tonic-gate 		return (err);
20390Sstevel@tonic-gate 	}
20400Sstevel@tonic-gate 
20410Sstevel@tonic-gate 	/* is chdh already a child? */
20420Sstevel@tonic-gate 	if (cnodep->parent_node != NULL) {
20430Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
20440Sstevel@tonic-gate 		return (PICL_CANTPARENT);
20450Sstevel@tonic-gate 	}
20460Sstevel@tonic-gate 
20470Sstevel@tonic-gate 	/*
20480Sstevel@tonic-gate 	 * append child to children list
20490Sstevel@tonic-gate 	 */
20500Sstevel@tonic-gate 	cnodep->parent_node = pnodep;
20510Sstevel@tonic-gate 	if (pnodep->child_node == NULL)
20520Sstevel@tonic-gate 		pnodep->child_node = cnodep;
20530Sstevel@tonic-gate 	else {
20540Sstevel@tonic-gate 		for (nodep = pnodep->child_node; nodep->sibling_node != NULL;
20550Sstevel@tonic-gate 		    nodep = nodep->sibling_node)
20560Sstevel@tonic-gate 			continue;
20570Sstevel@tonic-gate 		nodep->sibling_node = cnodep;
20580Sstevel@tonic-gate 
20590Sstevel@tonic-gate 	}
20600Sstevel@tonic-gate 
20610Sstevel@tonic-gate 	/* piclize */
20620Sstevel@tonic-gate 	if (IS_PICLIZED(pnodep))
20630Sstevel@tonic-gate 		piclize_node(cnodep);
20640Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
20650Sstevel@tonic-gate 	return (PICL_SUCCESS);
20660Sstevel@tonic-gate }
20670Sstevel@tonic-gate 
20680Sstevel@tonic-gate static void
copy_propinfo_ver_1(ptree_propinfo_t * pinfo,picl_obj_t * propp)20690Sstevel@tonic-gate copy_propinfo_ver_1(ptree_propinfo_t *pinfo, picl_obj_t *propp)
20700Sstevel@tonic-gate {
20710Sstevel@tonic-gate 	pinfo->version = propp->pinfo_ver;
20720Sstevel@tonic-gate 	pinfo->piclinfo.type = propp->prop_type;
20730Sstevel@tonic-gate 	pinfo->piclinfo.accessmode = propp->prop_mode;
20740Sstevel@tonic-gate 	pinfo->piclinfo.size = propp->prop_size;
20750Sstevel@tonic-gate 	(void) strcpy(pinfo->piclinfo.name, propp->prop_name);
20760Sstevel@tonic-gate 	pinfo->read = propp->read_func;
20770Sstevel@tonic-gate 	pinfo->write = propp->write_func;
20780Sstevel@tonic-gate }
20790Sstevel@tonic-gate 
20800Sstevel@tonic-gate static void
copy_reserved_propinfo_ver_1(ptree_propinfo_t * pinfo,const char * pname)20810Sstevel@tonic-gate copy_reserved_propinfo_ver_1(ptree_propinfo_t *pinfo, const char *pname)
20820Sstevel@tonic-gate {
20830Sstevel@tonic-gate 	pinfo->version = PTREE_PROPINFO_VERSION_1;
20840Sstevel@tonic-gate 	pinfo->piclinfo.type = PICL_PTYPE_REFERENCE;
20850Sstevel@tonic-gate 	pinfo->piclinfo.accessmode = PICL_READ;
20860Sstevel@tonic-gate 	pinfo->piclinfo.size = sizeof (picl_nodehdl_t);
20870Sstevel@tonic-gate 	(void) strcpy(pinfo->piclinfo.name, pname);
20880Sstevel@tonic-gate 	pinfo->read = NULL;
20890Sstevel@tonic-gate 	pinfo->write = NULL;
20900Sstevel@tonic-gate }
20910Sstevel@tonic-gate 
20920Sstevel@tonic-gate /*
20930Sstevel@tonic-gate  * This function returns the property information to a plug-in
20940Sstevel@tonic-gate  */
20950Sstevel@tonic-gate int
ptree_get_propinfo(picl_prophdl_t proph,ptree_propinfo_t * pinfo)20960Sstevel@tonic-gate ptree_get_propinfo(picl_prophdl_t proph, ptree_propinfo_t *pinfo)
20970Sstevel@tonic-gate {
20980Sstevel@tonic-gate 	int		err;
20990Sstevel@tonic-gate 	picl_obj_t	*nodep;
21000Sstevel@tonic-gate 	picl_obj_t  	*propp;
21010Sstevel@tonic-gate 
21020Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
21030Sstevel@tonic-gate 	nodep = propp = NULL;
21040Sstevel@tonic-gate 	err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp);
21050Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
21060Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
21070Sstevel@tonic-gate 		return (err);
21080Sstevel@tonic-gate 	}
21090Sstevel@tonic-gate 
21100Sstevel@tonic-gate 	if (propp->pinfo_ver == PTREE_PROPINFO_VERSION_1)
21110Sstevel@tonic-gate 		copy_propinfo_ver_1(pinfo, propp);
21120Sstevel@tonic-gate 	else
21130Sstevel@tonic-gate 		err = PICL_FAILURE;
21140Sstevel@tonic-gate 
21150Sstevel@tonic-gate 	unlock_node(nodep);			/* unlock node */
21160Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
21170Sstevel@tonic-gate 	return (err);
21180Sstevel@tonic-gate }
21190Sstevel@tonic-gate 
21200Sstevel@tonic-gate /*
21210Sstevel@tonic-gate  * This function returns the property information to a plug-in
21220Sstevel@tonic-gate  */
21230Sstevel@tonic-gate int
xptree_get_propinfo_by_name(picl_nodehdl_t nodeh,const char * pname,ptree_propinfo_t * pinfo)21240Sstevel@tonic-gate xptree_get_propinfo_by_name(picl_nodehdl_t nodeh, const char *pname,
21250Sstevel@tonic-gate     ptree_propinfo_t *pinfo)
21260Sstevel@tonic-gate {
21270Sstevel@tonic-gate 	int		err;
21280Sstevel@tonic-gate 	picl_obj_t	*nodep;
21290Sstevel@tonic-gate 	picl_obj_t  	*propp;
21300Sstevel@tonic-gate 
21310Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
21320Sstevel@tonic-gate 	nodep = propp = NULL;
21330Sstevel@tonic-gate 	err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep); /* lock node */
21340Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
21350Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
21360Sstevel@tonic-gate 		return (err);
21370Sstevel@tonic-gate 	}
21380Sstevel@tonic-gate 
21390Sstevel@tonic-gate 	err = lookup_prop_by_name(nodep, pname, &propp);
21400Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
21410Sstevel@tonic-gate 		unlock_node(nodep);
21420Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
21430Sstevel@tonic-gate 		return (err);
21440Sstevel@tonic-gate 	}
21450Sstevel@tonic-gate 
21460Sstevel@tonic-gate 	if (picl_restricted(pname))
21470Sstevel@tonic-gate 		copy_reserved_propinfo_ver_1(pinfo, pname);
21480Sstevel@tonic-gate 	else if (propp->pinfo_ver == PTREE_PROPINFO_VERSION_1)
21490Sstevel@tonic-gate 		copy_propinfo_ver_1(pinfo, propp);
21500Sstevel@tonic-gate 	else
21510Sstevel@tonic-gate 		err = PICL_FAILURE;
21520Sstevel@tonic-gate 
21530Sstevel@tonic-gate 	unlock_node(nodep);			/* unlock node */
21540Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
21550Sstevel@tonic-gate 	return (err);
21560Sstevel@tonic-gate }
21570Sstevel@tonic-gate 
21580Sstevel@tonic-gate /*
21590Sstevel@tonic-gate  * This function must be called only after a lookup_prop_by_name() returns
21600Sstevel@tonic-gate  * success and only if picl_restricted() returns true.
21610Sstevel@tonic-gate  */
21620Sstevel@tonic-gate static int
read_reserved_propval_and_unlock(picl_obj_t * nodep,const char * pname,void * vbuf,size_t size)21630Sstevel@tonic-gate read_reserved_propval_and_unlock(picl_obj_t *nodep, const char *pname,
21640Sstevel@tonic-gate     void *vbuf, size_t size)
21650Sstevel@tonic-gate {
21660Sstevel@tonic-gate 	void		*srcp;
21670Sstevel@tonic-gate 
21680Sstevel@tonic-gate 	if (size != sizeof (picl_nodehdl_t))
21690Sstevel@tonic-gate 		return (PICL_VALUETOOBIG);
21700Sstevel@tonic-gate 
21710Sstevel@tonic-gate 	if (strcmp(pname, PICL_PROP_PARENT) == 0)
21720Sstevel@tonic-gate 		srcp = &nodep->parent_node->ptree_hdl;
21730Sstevel@tonic-gate 	else if (strcmp(pname, PICL_PROP_CHILD) == 0)
21740Sstevel@tonic-gate 		srcp = &nodep->child_node->ptree_hdl;
21750Sstevel@tonic-gate 	else if (strcmp(pname, PICL_PROP_PEER) == 0)
21760Sstevel@tonic-gate 		srcp = &nodep->sibling_node->ptree_hdl;
21770Sstevel@tonic-gate 	else
21780Sstevel@tonic-gate 		return (PICL_FAILURE);
21790Sstevel@tonic-gate 
21800Sstevel@tonic-gate 	(void) memcpy(vbuf, srcp, sizeof (picl_nodehdl_t));
21810Sstevel@tonic-gate 	unlock_node(nodep);
21820Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);
21830Sstevel@tonic-gate 	return (PICL_SUCCESS);
21840Sstevel@tonic-gate }
21850Sstevel@tonic-gate 
21860Sstevel@tonic-gate /*
21870Sstevel@tonic-gate  * Returns the property value in the buffer and releases the node and
21880Sstevel@tonic-gate  * ptree locks.
21890Sstevel@tonic-gate  * For volatile properties, this function releases the locks on ptree
21900Sstevel@tonic-gate  * table and the node before calling the plug-in provided access function
21910Sstevel@tonic-gate  */
21920Sstevel@tonic-gate static int
read_propval_and_unlock(picl_obj_t * nodep,picl_obj_t * propp,void * vbuf,door_cred_t cred)21930Sstevel@tonic-gate read_propval_and_unlock(picl_obj_t *nodep, picl_obj_t *propp, void *vbuf,
21940Sstevel@tonic-gate     door_cred_t cred)
21950Sstevel@tonic-gate {
21960Sstevel@tonic-gate 	int		err;
21970Sstevel@tonic-gate 	int		(*volrd)(ptree_rarg_t *arg, void *buf);
21980Sstevel@tonic-gate 
21990Sstevel@tonic-gate 	err = PICL_SUCCESS;
22000Sstevel@tonic-gate 	if (propp->prop_mode & PICL_VOLATILE) {
22010Sstevel@tonic-gate 		ptree_rarg_t  rarg;
22020Sstevel@tonic-gate 
22030Sstevel@tonic-gate 		if (nodep)
22040Sstevel@tonic-gate 			rarg.nodeh = nodep->ptree_hdl;
22050Sstevel@tonic-gate 		else
22060Sstevel@tonic-gate 			rarg.nodeh = PICL_INVALID_PICLHDL;
22070Sstevel@tonic-gate 		rarg.proph = propp->ptree_hdl;
22080Sstevel@tonic-gate 		rarg.cred = cred;
22090Sstevel@tonic-gate 		volrd = propp->read_func;
22100Sstevel@tonic-gate 
22110Sstevel@tonic-gate 		unlock_node(nodep);		/* unlock node */
22120Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
22130Sstevel@tonic-gate 
22140Sstevel@tonic-gate 		if (volrd == NULL)
22150Sstevel@tonic-gate 			err = PICL_FAILURE;
22160Sstevel@tonic-gate 		else
22170Sstevel@tonic-gate 			err = (volrd)(&rarg, vbuf);
22180Sstevel@tonic-gate 		return (err);
22190Sstevel@tonic-gate 	} else if (propp->prop_type == PICL_PTYPE_CHARSTRING)
22200Sstevel@tonic-gate 		(void) strlcpy(vbuf, propp->prop_val, propp->prop_size);
22210Sstevel@tonic-gate 	else
22220Sstevel@tonic-gate 		(void) memcpy(vbuf, propp->prop_val, propp->prop_size);
22230Sstevel@tonic-gate 
22240Sstevel@tonic-gate 	unlock_node(nodep);
22250Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);
22260Sstevel@tonic-gate 	return (err);
22270Sstevel@tonic-gate }
22280Sstevel@tonic-gate 
22290Sstevel@tonic-gate int
xptree_get_propval_with_cred(picl_prophdl_t proph,void * vbuf,size_t size,door_cred_t cred)22300Sstevel@tonic-gate xptree_get_propval_with_cred(picl_prophdl_t proph, void *vbuf, size_t size,
22310Sstevel@tonic-gate     door_cred_t cred)
22320Sstevel@tonic-gate {
22330Sstevel@tonic-gate 	picl_obj_t	*propp;
22340Sstevel@tonic-gate 	picl_obj_t	*nodep;
22350Sstevel@tonic-gate 	int		err;
22360Sstevel@tonic-gate 
22370Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
22380Sstevel@tonic-gate 	nodep = propp = NULL;
22390Sstevel@tonic-gate 	err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp);
22400Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
22410Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
22420Sstevel@tonic-gate 		return (err);
22430Sstevel@tonic-gate 	}
22440Sstevel@tonic-gate 
22450Sstevel@tonic-gate 	err = check_propsize(PROP_READ, propp, size);
22460Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
22470Sstevel@tonic-gate 		unlock_node(nodep);		/* unlock node */
22480Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
22490Sstevel@tonic-gate 		return (err);
22500Sstevel@tonic-gate 	}
22510Sstevel@tonic-gate 
22520Sstevel@tonic-gate 	return (read_propval_and_unlock(nodep, propp, vbuf, cred));
22530Sstevel@tonic-gate }
22540Sstevel@tonic-gate 
22550Sstevel@tonic-gate /*
22560Sstevel@tonic-gate  * This function gets the credentials and  calls get_propval_with_cred.
22570Sstevel@tonic-gate  */
22580Sstevel@tonic-gate int
ptree_get_propval(picl_prophdl_t proph,void * vbuf,size_t size)22590Sstevel@tonic-gate ptree_get_propval(picl_prophdl_t proph, void *vbuf, size_t size)
22600Sstevel@tonic-gate {
22610Sstevel@tonic-gate 	return (xptree_get_propval_with_cred(proph, vbuf, size, picld_cred));
22620Sstevel@tonic-gate }
22630Sstevel@tonic-gate 
22640Sstevel@tonic-gate /*
22650Sstevel@tonic-gate  * This function retrieves a property's value by by its name
22660Sstevel@tonic-gate  * For volatile properties, the locks on ptree and node are released
22670Sstevel@tonic-gate  * before calling the plug-in provided access function
22680Sstevel@tonic-gate  */
22690Sstevel@tonic-gate int
xptree_get_propval_by_name_with_cred(picl_nodehdl_t nodeh,const char * pname,void * vbuf,size_t size,door_cred_t cred)22700Sstevel@tonic-gate xptree_get_propval_by_name_with_cred(picl_nodehdl_t nodeh, const char *pname,
22710Sstevel@tonic-gate     void *vbuf, size_t size, door_cred_t cred)
22720Sstevel@tonic-gate {
22730Sstevel@tonic-gate 	picl_obj_t	*nodep;
22740Sstevel@tonic-gate 	picl_obj_t	*propp;
22750Sstevel@tonic-gate 	int		err;
22760Sstevel@tonic-gate 
22770Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
22780Sstevel@tonic-gate 
22790Sstevel@tonic-gate 	nodep = NULL;
22800Sstevel@tonic-gate 	err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep);	/* lock node */
22810Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
22820Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
22830Sstevel@tonic-gate 		return (err);
22840Sstevel@tonic-gate 	}
22850Sstevel@tonic-gate 
22860Sstevel@tonic-gate 	err = lookup_prop_by_name(nodep, pname, &propp);
22870Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
22880Sstevel@tonic-gate 		unlock_node(nodep);
22890Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
22900Sstevel@tonic-gate 		return (err);
22910Sstevel@tonic-gate 	}
22920Sstevel@tonic-gate 
22930Sstevel@tonic-gate 	if (picl_restricted(pname))
22940Sstevel@tonic-gate 		return (read_reserved_propval_and_unlock(nodep, pname, vbuf,
22950Sstevel@tonic-gate 		    size));
22960Sstevel@tonic-gate 
22970Sstevel@tonic-gate 	err = check_propsize(PROP_READ, propp, size);
22980Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
22990Sstevel@tonic-gate 		unlock_node(nodep);
23000Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
23010Sstevel@tonic-gate 		return (err);
23020Sstevel@tonic-gate 	}
23030Sstevel@tonic-gate 
23040Sstevel@tonic-gate 	return (read_propval_and_unlock(nodep, propp, vbuf, cred));
23050Sstevel@tonic-gate }
23060Sstevel@tonic-gate 
23070Sstevel@tonic-gate /*
23080Sstevel@tonic-gate  * This function is used by plugins to get a value of a property
23090Sstevel@tonic-gate  * looking it up by its name.
23100Sstevel@tonic-gate  */
23110Sstevel@tonic-gate int
ptree_get_propval_by_name(picl_nodehdl_t nodeh,const char * pname,void * vbuf,size_t size)23120Sstevel@tonic-gate ptree_get_propval_by_name(picl_nodehdl_t nodeh, const char *pname, void *vbuf,
23130Sstevel@tonic-gate     size_t size)
23140Sstevel@tonic-gate {
23150Sstevel@tonic-gate 	return (xptree_get_propval_by_name_with_cred(nodeh, pname, vbuf, size,
23160Sstevel@tonic-gate 	    picld_cred));
23170Sstevel@tonic-gate }
23180Sstevel@tonic-gate 
23190Sstevel@tonic-gate /*
23200Sstevel@tonic-gate  * This function updates a property's value.
23210Sstevel@tonic-gate  * For volatile properties, the locks on the node and the ptree table
23220Sstevel@tonic-gate  * are released before calling the plug-in provided access function.
23230Sstevel@tonic-gate  */
23240Sstevel@tonic-gate static int
write_propval_and_unlock(picl_obj_t * nodep,picl_obj_t * propp,const void * vbuf,size_t size,door_cred_t cred)23250Sstevel@tonic-gate write_propval_and_unlock(picl_obj_t *nodep, picl_obj_t *propp, const void *vbuf,
23260Sstevel@tonic-gate     size_t size, door_cred_t cred)
23270Sstevel@tonic-gate {
23280Sstevel@tonic-gate 	int		err;
23290Sstevel@tonic-gate 	int		(*volwr)(ptree_warg_t *arg, const void *buf);
23300Sstevel@tonic-gate 
23310Sstevel@tonic-gate 	err = PICL_SUCCESS;
23320Sstevel@tonic-gate 	if (propp->prop_mode & PICL_VOLATILE) {
23330Sstevel@tonic-gate 		ptree_warg_t  warg;
23340Sstevel@tonic-gate 
23350Sstevel@tonic-gate 		if (nodep)
23360Sstevel@tonic-gate 			warg.nodeh = nodep->ptree_hdl;
23370Sstevel@tonic-gate 		else
23380Sstevel@tonic-gate 			warg.nodeh = PICL_INVALID_PICLHDL;
23390Sstevel@tonic-gate 		warg.proph = propp->ptree_hdl;
23400Sstevel@tonic-gate 		warg.cred = cred;
23410Sstevel@tonic-gate 		volwr = propp->write_func;
23420Sstevel@tonic-gate 
23430Sstevel@tonic-gate 		unlock_node(nodep);		/* unlock node */
23440Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
23450Sstevel@tonic-gate 
23460Sstevel@tonic-gate 		if (volwr == NULL)
23470Sstevel@tonic-gate 			err = PICL_FAILURE;
23480Sstevel@tonic-gate 		else
23490Sstevel@tonic-gate 			err = (volwr)(&warg, vbuf);
23500Sstevel@tonic-gate 		return (err);
23510Sstevel@tonic-gate 	} else
23520Sstevel@tonic-gate 		(void) memcpy(propp->prop_val, vbuf, size);
23530Sstevel@tonic-gate 
23540Sstevel@tonic-gate 	unlock_node(nodep);		/* unlock node */
23550Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
23560Sstevel@tonic-gate 	return (err);
23570Sstevel@tonic-gate }
23580Sstevel@tonic-gate 
23590Sstevel@tonic-gate int
xptree_update_propval_with_cred(picl_prophdl_t proph,const void * vbuf,size_t size,door_cred_t cred)23600Sstevel@tonic-gate xptree_update_propval_with_cred(picl_prophdl_t proph, const void *vbuf,
23610Sstevel@tonic-gate     size_t size, door_cred_t cred)
23620Sstevel@tonic-gate {
23630Sstevel@tonic-gate 	picl_obj_t	*nodep;
23640Sstevel@tonic-gate 	picl_obj_t	*propp;
23650Sstevel@tonic-gate 	int		err;
23660Sstevel@tonic-gate 
23670Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
23680Sstevel@tonic-gate 	nodep = propp = NULL;
23690Sstevel@tonic-gate 	err = lookup_and_lock_propnode(WRLOCK_NODE, proph, &nodep, &propp);
23700Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
23710Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
23720Sstevel@tonic-gate 		return (err);
23730Sstevel@tonic-gate 	}
23740Sstevel@tonic-gate 
23750Sstevel@tonic-gate 	err = check_propsize(PROP_WRITE, propp, size);
23760Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
23770Sstevel@tonic-gate 		unlock_node(nodep);		/* unlock node */
23780Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
23790Sstevel@tonic-gate 		return (err);
23800Sstevel@tonic-gate 	}
23810Sstevel@tonic-gate 
23820Sstevel@tonic-gate 	return (write_propval_and_unlock(nodep, propp, vbuf, size, cred));
23830Sstevel@tonic-gate }
23840Sstevel@tonic-gate 
23850Sstevel@tonic-gate /*
23860Sstevel@tonic-gate  * Ptree function used by plug-ins to update a property's value
23870Sstevel@tonic-gate  * calls update_propval_with_cred(), which releases locks for volatile props
23880Sstevel@tonic-gate  */
23890Sstevel@tonic-gate int
ptree_update_propval(picl_prophdl_t proph,const void * vbuf,size_t size)23900Sstevel@tonic-gate ptree_update_propval(picl_prophdl_t proph, const void *vbuf, size_t size)
23910Sstevel@tonic-gate {
23920Sstevel@tonic-gate 	return (xptree_update_propval_with_cred(proph, vbuf, size, picld_cred));
23930Sstevel@tonic-gate }
23940Sstevel@tonic-gate 
23950Sstevel@tonic-gate /*
23960Sstevel@tonic-gate  * This function writes/updates a property's value by looking it up
23970Sstevel@tonic-gate  * by its name.
23980Sstevel@tonic-gate  * For volatile properties this function releases the locks on the
23990Sstevel@tonic-gate  * node and the ptree table.
24000Sstevel@tonic-gate  */
24010Sstevel@tonic-gate int
xptree_update_propval_by_name_with_cred(picl_nodehdl_t nodeh,const char * pname,const void * vbuf,size_t size,door_cred_t cred)24020Sstevel@tonic-gate xptree_update_propval_by_name_with_cred(picl_nodehdl_t nodeh, const char *pname,
24030Sstevel@tonic-gate     const void *vbuf, size_t size, door_cred_t cred)
24040Sstevel@tonic-gate {
24050Sstevel@tonic-gate 	picl_obj_t	*nodep;
24060Sstevel@tonic-gate 	picl_obj_t	*propp;
24070Sstevel@tonic-gate 	int		err;
24080Sstevel@tonic-gate 
24090Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
24100Sstevel@tonic-gate 	nodep = NULL;
24110Sstevel@tonic-gate 	err = lookup_and_lock_node(WRLOCK_NODE, nodeh, &nodep);	/* lock node */
24120Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
24130Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
24140Sstevel@tonic-gate 		return (err);
24150Sstevel@tonic-gate 	}
24160Sstevel@tonic-gate 
24170Sstevel@tonic-gate 	if (picl_restricted(pname)) {
24180Sstevel@tonic-gate 		unlock_node(nodep);
24190Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
24200Sstevel@tonic-gate 		return (PICL_RESERVEDNAME);
24210Sstevel@tonic-gate 	}
24220Sstevel@tonic-gate 
24230Sstevel@tonic-gate 	err = lookup_prop_by_name(nodep, pname, &propp);
24240Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
24250Sstevel@tonic-gate 		unlock_node(nodep);
24260Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
24270Sstevel@tonic-gate 		return (err);
24280Sstevel@tonic-gate 	}
24290Sstevel@tonic-gate 
24300Sstevel@tonic-gate 	err = check_propsize(PROP_WRITE, propp, size);
24310Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
24320Sstevel@tonic-gate 		unlock_node(nodep);
24330Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
24340Sstevel@tonic-gate 		return (err);
24350Sstevel@tonic-gate 	}
24360Sstevel@tonic-gate 
24370Sstevel@tonic-gate 	return (write_propval_and_unlock(nodep, propp, vbuf, size, cred));
24380Sstevel@tonic-gate }
24390Sstevel@tonic-gate 
24400Sstevel@tonic-gate /*
24410Sstevel@tonic-gate  * This function updates the value of a property specified by its name
24420Sstevel@tonic-gate  */
24430Sstevel@tonic-gate int
ptree_update_propval_by_name(picl_nodehdl_t nodeh,const char * pname,const void * vbuf,size_t size)24440Sstevel@tonic-gate ptree_update_propval_by_name(picl_nodehdl_t nodeh, const char *pname,
24450Sstevel@tonic-gate     const void *vbuf, size_t size)
24460Sstevel@tonic-gate {
24470Sstevel@tonic-gate 	return (xptree_update_propval_by_name_with_cred(nodeh, pname, vbuf,
24480Sstevel@tonic-gate 	    size, picld_cred));
24490Sstevel@tonic-gate }
24500Sstevel@tonic-gate 
24510Sstevel@tonic-gate /*
24520Sstevel@tonic-gate  * This function retrieves the handle of a property by its name
24530Sstevel@tonic-gate  */
24540Sstevel@tonic-gate int
ptree_get_prop_by_name(picl_nodehdl_t nodeh,const char * pname,picl_prophdl_t * proph)24550Sstevel@tonic-gate ptree_get_prop_by_name(picl_nodehdl_t nodeh, const char *pname,
24560Sstevel@tonic-gate     picl_prophdl_t *proph)
24570Sstevel@tonic-gate {
24580Sstevel@tonic-gate 	picl_obj_t	*nodep;
24590Sstevel@tonic-gate 	picl_obj_t	*propp;
24600Sstevel@tonic-gate 	int		err;
24610Sstevel@tonic-gate 
24620Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
24630Sstevel@tonic-gate 	nodep = NULL;
24640Sstevel@tonic-gate 	err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &nodep);	/* lock node */
24650Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
24660Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
24670Sstevel@tonic-gate 		return (err);
24680Sstevel@tonic-gate 	}
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate 	if (picl_restricted(pname)) {
24710Sstevel@tonic-gate 		err = PICL_RESERVEDNAME;
24720Sstevel@tonic-gate 		unlock_node(nodep);			/* unlock node */
24730Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
24740Sstevel@tonic-gate 		return (err);
24750Sstevel@tonic-gate 	}
24760Sstevel@tonic-gate 
24770Sstevel@tonic-gate 	err = lookup_prop_by_name(nodep, pname, &propp);
24780Sstevel@tonic-gate 	if (err == PICL_SUCCESS)
24790Sstevel@tonic-gate 		*proph = propp->ptree_hdl;
24800Sstevel@tonic-gate 
24810Sstevel@tonic-gate 	unlock_node(nodep);			/* unlock node */
24820Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
24830Sstevel@tonic-gate 	return (err);
24840Sstevel@tonic-gate }
24850Sstevel@tonic-gate 
24860Sstevel@tonic-gate /*
24870Sstevel@tonic-gate  * This function returns the handle of the first property
24880Sstevel@tonic-gate  */
24890Sstevel@tonic-gate int
ptree_get_first_prop(picl_nodehdl_t nodeh,picl_prophdl_t * proph)24900Sstevel@tonic-gate ptree_get_first_prop(picl_nodehdl_t nodeh, picl_prophdl_t *proph)
24910Sstevel@tonic-gate {
24920Sstevel@tonic-gate 	picl_obj_t	*pobj;
24930Sstevel@tonic-gate 	int		err;
24940Sstevel@tonic-gate 
24950Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
24960Sstevel@tonic-gate 	pobj = NULL;
24970Sstevel@tonic-gate 	err = lookup_and_lock_node(RDLOCK_NODE, nodeh, &pobj);	/* lock node */
24980Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
24990Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
25000Sstevel@tonic-gate 		return (err);
25010Sstevel@tonic-gate 	}
25020Sstevel@tonic-gate 
25030Sstevel@tonic-gate 	if (pobj->first_prop)
25040Sstevel@tonic-gate 		*proph = pobj->first_prop->ptree_hdl;
25050Sstevel@tonic-gate 	else
25060Sstevel@tonic-gate 		err = PICL_ENDOFLIST;
25070Sstevel@tonic-gate 
25080Sstevel@tonic-gate 	unlock_node(pobj);			/* unlock node */
25090Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
25100Sstevel@tonic-gate 	return (err);
25110Sstevel@tonic-gate }
25120Sstevel@tonic-gate 
25130Sstevel@tonic-gate /*
25140Sstevel@tonic-gate  * This function returns the handle of next property in the list
25150Sstevel@tonic-gate  */
25160Sstevel@tonic-gate int
ptree_get_next_prop(picl_prophdl_t proph,picl_prophdl_t * nextproph)25170Sstevel@tonic-gate ptree_get_next_prop(picl_prophdl_t proph, picl_prophdl_t *nextproph)
25180Sstevel@tonic-gate {
25190Sstevel@tonic-gate 	picl_obj_t	*nodep;
25200Sstevel@tonic-gate 	picl_obj_t	*propp;
25210Sstevel@tonic-gate 	int		err;
25220Sstevel@tonic-gate 
25230Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
25240Sstevel@tonic-gate 	nodep = propp = NULL;
25250Sstevel@tonic-gate 	err = lookup_and_lock_propnode(RDLOCK_NODE, proph, &nodep, &propp);
25260Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
25270Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);	/* unlock ptree */
25280Sstevel@tonic-gate 		return (err);
25290Sstevel@tonic-gate 	}
25300Sstevel@tonic-gate 
25310Sstevel@tonic-gate 	if (propp->next_prop) {
25320Sstevel@tonic-gate 		*nextproph = propp->next_prop->ptree_hdl;
25330Sstevel@tonic-gate 	} else
25340Sstevel@tonic-gate 		err = PICL_ENDOFLIST;
25350Sstevel@tonic-gate 
25360Sstevel@tonic-gate 	unlock_node(nodep);				/* unlock node */
25370Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
25380Sstevel@tonic-gate 	return (err);
25390Sstevel@tonic-gate }
25400Sstevel@tonic-gate 
25410Sstevel@tonic-gate /*
25420Sstevel@tonic-gate  * These functions are called by ptree_get_node_by_path()
25430Sstevel@tonic-gate  * Append a prop expression entry to the list
25440Sstevel@tonic-gate  */
25450Sstevel@tonic-gate static prop_list_t *
append_entry_to_list(prop_list_t * el,prop_list_t * list)25460Sstevel@tonic-gate append_entry_to_list(prop_list_t *el, prop_list_t *list)
25470Sstevel@tonic-gate {
25480Sstevel@tonic-gate 	prop_list_t	*ptr;
25490Sstevel@tonic-gate 
25500Sstevel@tonic-gate 	if (el == NULL)
25510Sstevel@tonic-gate 		return (list);
25520Sstevel@tonic-gate 
25530Sstevel@tonic-gate 	if (list == NULL) {
25540Sstevel@tonic-gate 		list = el;
25550Sstevel@tonic-gate 		return (list);
25560Sstevel@tonic-gate 	}
25570Sstevel@tonic-gate 
25580Sstevel@tonic-gate 	/*
25590Sstevel@tonic-gate 	 * Add it to the end of list
25600Sstevel@tonic-gate 	 */
25610Sstevel@tonic-gate 	ptr = list;
25620Sstevel@tonic-gate 
25630Sstevel@tonic-gate 	while (ptr->next != NULL)
25640Sstevel@tonic-gate 		ptr = ptr->next;
25650Sstevel@tonic-gate 
25660Sstevel@tonic-gate 	ptr->next = el;
25670Sstevel@tonic-gate 
25680Sstevel@tonic-gate 	return (list);
25690Sstevel@tonic-gate }
25700Sstevel@tonic-gate 
25710Sstevel@tonic-gate /*
25720Sstevel@tonic-gate  * Free the property expression list
25730Sstevel@tonic-gate  */
25740Sstevel@tonic-gate static void
free_list(prop_list_t * list)25750Sstevel@tonic-gate free_list(prop_list_t *list)
25760Sstevel@tonic-gate {
25770Sstevel@tonic-gate 	prop_list_t	*ptr;
25780Sstevel@tonic-gate 	prop_list_t	*tmp;
25790Sstevel@tonic-gate 
25800Sstevel@tonic-gate 	for (ptr = list; ptr != NULL; ptr = tmp) {
25810Sstevel@tonic-gate 		tmp = ptr->next;
25820Sstevel@tonic-gate 		free(ptr);
25830Sstevel@tonic-gate 	}
25840Sstevel@tonic-gate }
25850Sstevel@tonic-gate 
25860Sstevel@tonic-gate static int
parse_prl(char * prl,char ** name,char ** baddr,prop_list_t ** plist)25870Sstevel@tonic-gate parse_prl(char *prl, char **name, char **baddr, prop_list_t **plist)
25880Sstevel@tonic-gate {
25890Sstevel@tonic-gate 	char		*propptr;
25900Sstevel@tonic-gate 	char		*ptr;
25910Sstevel@tonic-gate 	char		*pname;
25920Sstevel@tonic-gate 	char		*pval;
25930Sstevel@tonic-gate 	prop_list_t	*el;
25940Sstevel@tonic-gate 
25950Sstevel@tonic-gate 	if (prl == NULL)
25960Sstevel@tonic-gate 		return (PICL_FAILURE);
25970Sstevel@tonic-gate 
25980Sstevel@tonic-gate 	if ((prl[0] == '@') || (prl[0] == '?'))
25990Sstevel@tonic-gate 		return (PICL_FAILURE);
26000Sstevel@tonic-gate 
26010Sstevel@tonic-gate 	*name = prl;
26020Sstevel@tonic-gate 
26030Sstevel@tonic-gate 	/*
26040Sstevel@tonic-gate 	 * get property expression
26050Sstevel@tonic-gate 	 */
26060Sstevel@tonic-gate 	ptr = strchr(prl, '?');
26070Sstevel@tonic-gate 
26080Sstevel@tonic-gate 	if (ptr != NULL) {
26090Sstevel@tonic-gate 		*ptr = '\0';
26100Sstevel@tonic-gate 		propptr = ptr + 1;
26110Sstevel@tonic-gate 	} else
26120Sstevel@tonic-gate 		propptr = NULL;
26130Sstevel@tonic-gate 
26140Sstevel@tonic-gate 	/*
26150Sstevel@tonic-gate 	 * get bus value
26160Sstevel@tonic-gate 	 */
26170Sstevel@tonic-gate 	ptr = strchr(prl, '@');
26180Sstevel@tonic-gate 
26190Sstevel@tonic-gate 	if (ptr != NULL) {
26200Sstevel@tonic-gate 		*ptr = '\0';
26210Sstevel@tonic-gate 		*baddr = ptr + 1;
26220Sstevel@tonic-gate 		if (strlen(*baddr) == 0)	/* no bus value after @ */
26230Sstevel@tonic-gate 			return (PICL_FAILURE);
26240Sstevel@tonic-gate 	}
26250Sstevel@tonic-gate 
26260Sstevel@tonic-gate 	/*
26270Sstevel@tonic-gate 	 * create the prop list
26280Sstevel@tonic-gate 	 */
26290Sstevel@tonic-gate 	while (propptr != NULL) {
26300Sstevel@tonic-gate 		pname = propptr;
26310Sstevel@tonic-gate 		pval = NULL;
26320Sstevel@tonic-gate 
26330Sstevel@tonic-gate 		ptr = strchr(propptr, '?');
26340Sstevel@tonic-gate 
26350Sstevel@tonic-gate 		if (ptr != NULL) {  /* more ?<prop>=<propval> */
26360Sstevel@tonic-gate 			*ptr = '\0';
26370Sstevel@tonic-gate 			propptr = ptr + 1;
26380Sstevel@tonic-gate 		} else
26390Sstevel@tonic-gate 			propptr = NULL;
26400Sstevel@tonic-gate 
26410Sstevel@tonic-gate 		if (strlen(pname) == 0)	/* no prop exp after ? */
26420Sstevel@tonic-gate 			return (PICL_FAILURE);
26430Sstevel@tonic-gate 
26440Sstevel@tonic-gate 		ptr = strchr(pname, '=');
26450Sstevel@tonic-gate 		if (ptr != NULL) { /* not void prop */
26460Sstevel@tonic-gate 			*ptr = '\0';
26470Sstevel@tonic-gate 			pval = ptr + 1;
26480Sstevel@tonic-gate 			/*
26490Sstevel@tonic-gate 			 * <prop>= is treated as void property
26500Sstevel@tonic-gate 			 */
26510Sstevel@tonic-gate 			if (strlen(pval) == 0)
26520Sstevel@tonic-gate 				pval = NULL;
26530Sstevel@tonic-gate 		}
26540Sstevel@tonic-gate 
26550Sstevel@tonic-gate 		el = (prop_list_t *)malloc(sizeof (prop_list_t));
26560Sstevel@tonic-gate 		el->pname = pname;
26570Sstevel@tonic-gate 		el->pval = pval;
26580Sstevel@tonic-gate 		el->next = NULL;
26590Sstevel@tonic-gate 		*plist = append_entry_to_list(el, *plist);
26600Sstevel@tonic-gate 	}
26610Sstevel@tonic-gate 
26620Sstevel@tonic-gate 	return (PICL_SUCCESS);
26630Sstevel@tonic-gate }
26640Sstevel@tonic-gate 
26650Sstevel@tonic-gate static int
prop_match(ptree_propinfo_t pinfo,void * vbuf,char * val)26660Sstevel@tonic-gate prop_match(ptree_propinfo_t pinfo, void *vbuf, char *val)
26670Sstevel@tonic-gate {
26680Sstevel@tonic-gate 	int8_t		cval;
26690Sstevel@tonic-gate 	uint8_t		ucval;
26700Sstevel@tonic-gate 	int16_t		sval;
26710Sstevel@tonic-gate 	uint16_t	usval;
26720Sstevel@tonic-gate 	int32_t		intval;
26730Sstevel@tonic-gate 	uint32_t	uintval;
26740Sstevel@tonic-gate 	int64_t		llval;
26750Sstevel@tonic-gate 	uint64_t	ullval;
26760Sstevel@tonic-gate 	float		fval;
26770Sstevel@tonic-gate 	double		dval;
26780Sstevel@tonic-gate 
26790Sstevel@tonic-gate 	switch (pinfo.piclinfo.type) {
26800Sstevel@tonic-gate 	case PICL_PTYPE_CHARSTRING:
26810Sstevel@tonic-gate 		if (strcasecmp(pinfo.piclinfo.name, PICL_PROP_CLASSNAME) == 0) {
26820Sstevel@tonic-gate 			if (strcmp(val, PICL_CLASS_PICL) == 0)
26830Sstevel@tonic-gate 				return (1);
26840Sstevel@tonic-gate 		}
26850Sstevel@tonic-gate 		if (strcmp(val, (char *)vbuf) == 0)
26860Sstevel@tonic-gate 			return (1);
26870Sstevel@tonic-gate 		else
26880Sstevel@tonic-gate 			return (0);
26890Sstevel@tonic-gate 	case PICL_PTYPE_INT:
26900Sstevel@tonic-gate 		switch (pinfo.piclinfo.size) {
26910Sstevel@tonic-gate 		case sizeof (int8_t):
26920Sstevel@tonic-gate 			cval = (int8_t)strtol(val, (char **)NULL, 0);
26930Sstevel@tonic-gate 			return (cval == *(char *)vbuf);
26940Sstevel@tonic-gate 		case sizeof (int16_t):
26950Sstevel@tonic-gate 			sval = (int16_t)strtol(val, (char **)NULL, 0);
26960Sstevel@tonic-gate 			return (sval == *(int16_t *)vbuf);
26970Sstevel@tonic-gate 		case sizeof (int32_t):
26980Sstevel@tonic-gate 			intval = (int32_t)strtol(val, (char **)NULL, 0);
26990Sstevel@tonic-gate 			return (intval == *(int32_t *)vbuf);
27000Sstevel@tonic-gate 		case sizeof (int64_t):
27010Sstevel@tonic-gate 			llval = strtoll(val, (char **)NULL, 0);
27020Sstevel@tonic-gate 			return (llval == *(int64_t *)vbuf);
27030Sstevel@tonic-gate 		default:
27040Sstevel@tonic-gate 			return (0);
27050Sstevel@tonic-gate 		}
27060Sstevel@tonic-gate 	case PICL_PTYPE_UNSIGNED_INT:
27070Sstevel@tonic-gate 		switch (pinfo.piclinfo.size) {
27080Sstevel@tonic-gate 		case sizeof (uint8_t):
27090Sstevel@tonic-gate 			ucval = (uint8_t)strtoul(val, (char **)NULL, 0);
27100Sstevel@tonic-gate 			return (ucval == *(uint8_t *)vbuf);
27110Sstevel@tonic-gate 		case sizeof (uint16_t):
27120Sstevel@tonic-gate 			usval = (uint16_t)strtoul(val, (char **)NULL, 0);
27130Sstevel@tonic-gate 			return (usval == *(uint16_t *)vbuf);
27140Sstevel@tonic-gate 		case sizeof (uint32_t):
27150Sstevel@tonic-gate 			uintval = (uint32_t)strtoul(val, (char **)NULL, 0);
27160Sstevel@tonic-gate 			return (uintval == *(uint32_t *)vbuf);
27170Sstevel@tonic-gate 		case sizeof (uint64_t):
27180Sstevel@tonic-gate 			ullval = strtoull(val, (char **)NULL, 0);
27190Sstevel@tonic-gate 			return (ullval == *(uint64_t *)vbuf);
27200Sstevel@tonic-gate 		default:
27210Sstevel@tonic-gate 			return (0);
27220Sstevel@tonic-gate 		}
27230Sstevel@tonic-gate 	case PICL_PTYPE_FLOAT:
27240Sstevel@tonic-gate 		switch (pinfo.piclinfo.size) {
27250Sstevel@tonic-gate 		case sizeof (float):
27260Sstevel@tonic-gate 			fval = (float)strtod(val, (char **)NULL);
27270Sstevel@tonic-gate 			return (fval == *(float *)vbuf);
27280Sstevel@tonic-gate 		case sizeof (double):
27290Sstevel@tonic-gate 			dval = strtod(val, (char **)NULL);
27300Sstevel@tonic-gate 			return (dval == *(double *)vbuf);
27310Sstevel@tonic-gate 		default:
27320Sstevel@tonic-gate 			return (0);
27330Sstevel@tonic-gate 		}
27340Sstevel@tonic-gate 	case PICL_PTYPE_VOID:
27350Sstevel@tonic-gate 	case PICL_PTYPE_TIMESTAMP:
27360Sstevel@tonic-gate 	case PICL_PTYPE_TABLE:
27370Sstevel@tonic-gate 	case PICL_PTYPE_REFERENCE:
27380Sstevel@tonic-gate 	case PICL_PTYPE_BYTEARRAY:
27390Sstevel@tonic-gate 	case PICL_PTYPE_UNKNOWN:
27400Sstevel@tonic-gate 	default:
27410Sstevel@tonic-gate 		return (0);
27420Sstevel@tonic-gate 	}
27430Sstevel@tonic-gate }
27440Sstevel@tonic-gate 
27450Sstevel@tonic-gate static int
check_propval(picl_nodehdl_t nodeh,char * pname,char * pval)27460Sstevel@tonic-gate check_propval(picl_nodehdl_t nodeh, char *pname, char *pval)
27470Sstevel@tonic-gate {
27480Sstevel@tonic-gate 	int			err;
27490Sstevel@tonic-gate 	picl_prophdl_t		proph;
27500Sstevel@tonic-gate 	ptree_propinfo_t 	pinfo;
27510Sstevel@tonic-gate 	void			*vbuf;
27520Sstevel@tonic-gate 
27530Sstevel@tonic-gate 	err = ptree_get_prop_by_name(nodeh, pname, &proph);
27540Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
27550Sstevel@tonic-gate 		return (err);
27560Sstevel@tonic-gate 
27570Sstevel@tonic-gate 	err = ptree_get_propinfo(proph, &pinfo);
27580Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
27590Sstevel@tonic-gate 		return (err);
27600Sstevel@tonic-gate 
27610Sstevel@tonic-gate 	if (pval == NULL) {	/* void type */
27620Sstevel@tonic-gate 		if (pinfo.piclinfo.type != PICL_PTYPE_VOID)
27630Sstevel@tonic-gate 			return (PICL_FAILURE);
27640Sstevel@tonic-gate 	} else {
27650Sstevel@tonic-gate 		vbuf = alloca(pinfo.piclinfo.size);
27660Sstevel@tonic-gate 		if (vbuf == NULL)
27670Sstevel@tonic-gate 			return (PICL_FAILURE);
27680Sstevel@tonic-gate 		err = ptree_get_propval(proph, vbuf,
27690Sstevel@tonic-gate 		    pinfo.piclinfo.size);
27700Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
27710Sstevel@tonic-gate 			return (err);
27720Sstevel@tonic-gate 
27730Sstevel@tonic-gate 		if (!prop_match(pinfo, vbuf, pval))
27740Sstevel@tonic-gate 			return (PICL_FAILURE);
27750Sstevel@tonic-gate 	}
27760Sstevel@tonic-gate 	return (PICL_SUCCESS);
27770Sstevel@tonic-gate }
27780Sstevel@tonic-gate 
27790Sstevel@tonic-gate static int
get_child_by_path(picl_nodehdl_t rooth,char * prl,picl_nodehdl_t * nodeh,char * pname)27800Sstevel@tonic-gate get_child_by_path(picl_nodehdl_t rooth, char *prl,
27810Sstevel@tonic-gate     picl_nodehdl_t *nodeh, char *pname)
27820Sstevel@tonic-gate {
27830Sstevel@tonic-gate 	picl_nodehdl_t		chdh;
27840Sstevel@tonic-gate 	int			err;
27850Sstevel@tonic-gate 	char			*nameval;
27860Sstevel@tonic-gate 	char			*nodename;
27870Sstevel@tonic-gate 	char			*path;
27880Sstevel@tonic-gate 	char			*baddr;
27890Sstevel@tonic-gate 	char			*busval;
27900Sstevel@tonic-gate 	prop_list_t		*plist;
27910Sstevel@tonic-gate 	prop_list_t		*ptr;
27920Sstevel@tonic-gate 
27930Sstevel@tonic-gate 	if (prl == NULL)
27940Sstevel@tonic-gate 		return (PICL_FAILURE);
27950Sstevel@tonic-gate 
2796*13093SRoger.Faulkner@Oracle.COM 	path = strdupa(prl);
27970Sstevel@tonic-gate 	if (path == NULL)
27980Sstevel@tonic-gate 		return (PICL_FAILURE);
27990Sstevel@tonic-gate 
28000Sstevel@tonic-gate 	plist = NULL;
28010Sstevel@tonic-gate 	nodename = NULL;
28020Sstevel@tonic-gate 	baddr = NULL;
28030Sstevel@tonic-gate 
28040Sstevel@tonic-gate 	err = parse_prl(path, &nodename, &baddr, &plist);
28050Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
28060Sstevel@tonic-gate 		free_list(plist);
28070Sstevel@tonic-gate 		return (err);
28080Sstevel@tonic-gate 	}
28090Sstevel@tonic-gate 
28100Sstevel@tonic-gate 	if (nodename == NULL)
28110Sstevel@tonic-gate 		return (PICL_FAILURE);
28120Sstevel@tonic-gate 
28130Sstevel@tonic-gate 	nameval = alloca(strlen(nodename) + 1);
28140Sstevel@tonic-gate 	if (nameval == NULL) {
28150Sstevel@tonic-gate 		free_list(plist);
28160Sstevel@tonic-gate 		return (PICL_FAILURE);
28170Sstevel@tonic-gate 	}
28180Sstevel@tonic-gate 
28190Sstevel@tonic-gate 	if (baddr != NULL) {
28200Sstevel@tonic-gate 		busval = alloca(strlen(baddr) + 1);
28210Sstevel@tonic-gate 		if (busval == NULL) {
28220Sstevel@tonic-gate 			free_list(plist);
28230Sstevel@tonic-gate 			return (PICL_FAILURE);
28240Sstevel@tonic-gate 		}
28250Sstevel@tonic-gate 	}
28260Sstevel@tonic-gate 
28270Sstevel@tonic-gate 	for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
28280Sstevel@tonic-gate 	    sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
28295672Sanbui 	    err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
28305672Sanbui 	    sizeof (picl_nodehdl_t))) {
28310Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
28320Sstevel@tonic-gate 			free_list(plist);
28330Sstevel@tonic-gate 			return (PICL_FAILURE);
28340Sstevel@tonic-gate 		}
28350Sstevel@tonic-gate 
28360Sstevel@tonic-gate 		/*
28370Sstevel@tonic-gate 		 * compare name
28380Sstevel@tonic-gate 		 */
28390Sstevel@tonic-gate 		if ((strcmp(pname, PICL_PROP_CLASSNAME) != 0) ||
28400Sstevel@tonic-gate 		    (strcmp(nodename, PICL_CLASS_PICL) != 0)) {
28410Sstevel@tonic-gate 			err = ptree_get_propval_by_name(chdh, pname,
28420Sstevel@tonic-gate 			    nameval, (strlen(nodename) + 1));
28430Sstevel@tonic-gate 
28440Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
28450Sstevel@tonic-gate 				continue;
28460Sstevel@tonic-gate 			if (strcmp(nameval, nodename) != 0)
28470Sstevel@tonic-gate 				continue;
28480Sstevel@tonic-gate 		}
28490Sstevel@tonic-gate 
28500Sstevel@tonic-gate 		/*
28510Sstevel@tonic-gate 		 * compare device address with bus-addr prop first
28520Sstevel@tonic-gate 		 * then with UnitAddress property
28530Sstevel@tonic-gate 		 */
28540Sstevel@tonic-gate 		if (baddr != NULL) { /* compare bus-addr prop */
28550Sstevel@tonic-gate 			if ((ptree_get_propval_by_name(chdh, PICL_PROP_BUS_ADDR,
28560Sstevel@tonic-gate 			    busval, (strlen(baddr) + 1)) != PICL_SUCCESS) &&
28570Sstevel@tonic-gate 			    (ptree_get_propval_by_name(chdh,
28585672Sanbui 			    PICL_PROP_UNIT_ADDRESS, busval,
28595672Sanbui 			    (strlen(baddr) + 1)) != PICL_SUCCESS))
28600Sstevel@tonic-gate 				continue;
28610Sstevel@tonic-gate 
28620Sstevel@tonic-gate 			if (strcmp(busval, baddr) != 0)
28630Sstevel@tonic-gate 				continue; /* not match */
28640Sstevel@tonic-gate 		}
28650Sstevel@tonic-gate 
28660Sstevel@tonic-gate 		if (plist == NULL) { /* no prop expression */
28670Sstevel@tonic-gate 			*nodeh = chdh;
28680Sstevel@tonic-gate 			return (PICL_SUCCESS);
28690Sstevel@tonic-gate 		}
28700Sstevel@tonic-gate 
28710Sstevel@tonic-gate 		/*
28720Sstevel@tonic-gate 		 * compare the property expression list
28730Sstevel@tonic-gate 		 */
28740Sstevel@tonic-gate 		ptr = plist;
28750Sstevel@tonic-gate 
28760Sstevel@tonic-gate 		while (ptr != NULL) {
28770Sstevel@tonic-gate 			err = check_propval(chdh, ptr->pname, ptr->pval);
28780Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
28790Sstevel@tonic-gate 				break;
28800Sstevel@tonic-gate 
28810Sstevel@tonic-gate 			ptr = ptr->next;
28820Sstevel@tonic-gate 		}
28830Sstevel@tonic-gate 		if (ptr == NULL) {
28840Sstevel@tonic-gate 			*nodeh = chdh;
28850Sstevel@tonic-gate 			free_list(plist);
28860Sstevel@tonic-gate 			return (PICL_SUCCESS);
28870Sstevel@tonic-gate 		}
28880Sstevel@tonic-gate 	}
28890Sstevel@tonic-gate 	free_list(plist);
28900Sstevel@tonic-gate 	return (PICL_NOTNODE);
28910Sstevel@tonic-gate }
28920Sstevel@tonic-gate 
28930Sstevel@tonic-gate /*
28940Sstevel@tonic-gate  * This functions returns the handle of node specified by its path
28950Sstevel@tonic-gate  */
28960Sstevel@tonic-gate int
ptree_get_node_by_path(const char * piclprl,picl_nodehdl_t * handle)28970Sstevel@tonic-gate ptree_get_node_by_path(const char *piclprl, picl_nodehdl_t *handle)
28980Sstevel@tonic-gate {
28990Sstevel@tonic-gate 	picl_nodehdl_t	rooth;
29000Sstevel@tonic-gate 	picl_nodehdl_t	chdh;
29010Sstevel@tonic-gate 	char		*path;
29020Sstevel@tonic-gate 	char		*ptr;
29030Sstevel@tonic-gate 	char		*defprop;
29040Sstevel@tonic-gate 	char		*tokindex;
29050Sstevel@tonic-gate 	int 		err;
29060Sstevel@tonic-gate 	int		len;
29070Sstevel@tonic-gate 	int		npflg;	/* namepath flag */
29080Sstevel@tonic-gate 
29090Sstevel@tonic-gate 
2910*13093SRoger.Faulkner@Oracle.COM 	path = strdupa(piclprl);
29110Sstevel@tonic-gate 	if (path == NULL)
29120Sstevel@tonic-gate 		return (PICL_FAILURE);
29130Sstevel@tonic-gate 
29140Sstevel@tonic-gate 	npflg = 1;	/* default */
29150Sstevel@tonic-gate 	defprop = path;
29160Sstevel@tonic-gate 	if (path[0] == '/') {
29170Sstevel@tonic-gate 		ptr = &path[1];
29180Sstevel@tonic-gate 	} else if ((tokindex = strchr(path, ':')) != NULL) {
29190Sstevel@tonic-gate 		*tokindex = '\0';
29200Sstevel@tonic-gate 		++tokindex;
29210Sstevel@tonic-gate 		if (*tokindex == '/')
29220Sstevel@tonic-gate 			ptr = tokindex + 1;
29230Sstevel@tonic-gate 		else
29240Sstevel@tonic-gate 			return (PICL_NOTNODE);
29250Sstevel@tonic-gate 		npflg = 0;
29260Sstevel@tonic-gate 	} else
29270Sstevel@tonic-gate 		return (PICL_NOTNODE);
29280Sstevel@tonic-gate 
29290Sstevel@tonic-gate 	err = ptree_get_root(&rooth);
29300Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
29310Sstevel@tonic-gate 		return (err);
29320Sstevel@tonic-gate 
29330Sstevel@tonic-gate 	for (chdh = rooth, tokindex = strchr(ptr, '/');
29340Sstevel@tonic-gate 	    tokindex != NULL;
29350Sstevel@tonic-gate 	    ptr = tokindex + 1, tokindex = strchr(ptr, '/')) {
29360Sstevel@tonic-gate 		*tokindex = '\0';
29370Sstevel@tonic-gate 		if (npflg)
29380Sstevel@tonic-gate 			err = get_child_by_path(chdh, ptr, &chdh,
29390Sstevel@tonic-gate 			    PICL_PROP_NAME);
29400Sstevel@tonic-gate 		else
29410Sstevel@tonic-gate 			err = get_child_by_path(chdh, ptr, &chdh,
29420Sstevel@tonic-gate 			    defprop);
29430Sstevel@tonic-gate 
29440Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
29450Sstevel@tonic-gate 			return (err);
29460Sstevel@tonic-gate 	}
29470Sstevel@tonic-gate 
29480Sstevel@tonic-gate 	/*
29490Sstevel@tonic-gate 	 * check if last token is empty or not
29500Sstevel@tonic-gate 	 * eg. /a/b/c/ or /a/b/c
29510Sstevel@tonic-gate 	 */
29520Sstevel@tonic-gate 	if (*ptr == '\0') {
29530Sstevel@tonic-gate 		*handle = chdh;
29540Sstevel@tonic-gate 		return (PICL_SUCCESS);
29550Sstevel@tonic-gate 	}
29560Sstevel@tonic-gate 
29570Sstevel@tonic-gate 	len = strcspn(ptr, " \t\n");
29580Sstevel@tonic-gate 	if (len == 0) {
29590Sstevel@tonic-gate 		*handle = chdh;
29600Sstevel@tonic-gate 		return (PICL_SUCCESS);
29610Sstevel@tonic-gate 	}
29620Sstevel@tonic-gate 
29630Sstevel@tonic-gate 	ptr[len] = '\0';
29640Sstevel@tonic-gate 	if (npflg)
29650Sstevel@tonic-gate 		err = get_child_by_path(chdh, ptr, &chdh, PICL_PROP_NAME);
29660Sstevel@tonic-gate 	else
29670Sstevel@tonic-gate 		err = get_child_by_path(chdh, ptr, &chdh, defprop);
29680Sstevel@tonic-gate 
29690Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
29700Sstevel@tonic-gate 		return (err);
29710Sstevel@tonic-gate 
29720Sstevel@tonic-gate 	*handle = chdh;
29730Sstevel@tonic-gate 	return (PICL_SUCCESS);
29740Sstevel@tonic-gate }
29750Sstevel@tonic-gate 
29760Sstevel@tonic-gate /*
29770Sstevel@tonic-gate  * Initialize propinfo
29780Sstevel@tonic-gate  */
29790Sstevel@tonic-gate int
ptree_init_propinfo(ptree_propinfo_t * infop,int version,int ptype,int pmode,size_t psize,char * pname,int (* readfn)(ptree_rarg_t *,void *),int (* writefn)(ptree_warg_t *,const void *))29800Sstevel@tonic-gate ptree_init_propinfo(ptree_propinfo_t *infop, int version, int ptype, int pmode,
29810Sstevel@tonic-gate     size_t psize, char *pname, int (*readfn)(ptree_rarg_t *, void *),
29820Sstevel@tonic-gate     int (*writefn)(ptree_warg_t *, const void *))
29830Sstevel@tonic-gate {
29840Sstevel@tonic-gate 	if (version != PTREE_PROPINFO_VERSION_1)
29850Sstevel@tonic-gate 		return (PICL_NOTSUPPORTED);
29860Sstevel@tonic-gate 	if ((infop == NULL) || (pname == NULL))
29870Sstevel@tonic-gate 		return (PICL_INVALIDARG);
29880Sstevel@tonic-gate 	infop->version = version;
29890Sstevel@tonic-gate 	infop->piclinfo.type = ptype;
29900Sstevel@tonic-gate 	infop->piclinfo.accessmode = pmode;
29910Sstevel@tonic-gate 	infop->piclinfo.size = psize;
29920Sstevel@tonic-gate 	infop->read = readfn;
29930Sstevel@tonic-gate 	infop->write = writefn;
29940Sstevel@tonic-gate 	(void) strlcpy(infop->piclinfo.name, pname, PICL_PROPNAMELEN_MAX);
29950Sstevel@tonic-gate 	return (PICL_SUCCESS);
29960Sstevel@tonic-gate }
29970Sstevel@tonic-gate 
29980Sstevel@tonic-gate /*
29990Sstevel@tonic-gate  * Creates a property, adds it to the node, and returns the property
30000Sstevel@tonic-gate  * handle to the caller if successful and proph is not NULL
30010Sstevel@tonic-gate  */
30020Sstevel@tonic-gate int
ptree_create_and_add_prop(picl_nodehdl_t nodeh,ptree_propinfo_t * infop,void * vbuf,picl_prophdl_t * proph)30030Sstevel@tonic-gate ptree_create_and_add_prop(picl_nodehdl_t nodeh, ptree_propinfo_t *infop,
30040Sstevel@tonic-gate     void *vbuf, picl_prophdl_t *proph)
30050Sstevel@tonic-gate {
30060Sstevel@tonic-gate 	int		err;
30070Sstevel@tonic-gate 	picl_prophdl_t	tmph;
30080Sstevel@tonic-gate 
30090Sstevel@tonic-gate 	err = ptree_create_prop(infop, vbuf, &tmph);
30100Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
30110Sstevel@tonic-gate 		return (err);
30120Sstevel@tonic-gate 	err = ptree_add_prop(nodeh, tmph);
30130Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
30140Sstevel@tonic-gate 		(void) ptree_destroy_prop(tmph);
30150Sstevel@tonic-gate 		return (err);
30160Sstevel@tonic-gate 	}
30170Sstevel@tonic-gate 	if (proph)
30180Sstevel@tonic-gate 		*proph = tmph;
30190Sstevel@tonic-gate 	return (PICL_SUCCESS);
30200Sstevel@tonic-gate }
30210Sstevel@tonic-gate 
30220Sstevel@tonic-gate /*
30230Sstevel@tonic-gate  * Creates a node, adds it to its parent node, and returns the node
30240Sstevel@tonic-gate  * handle to the caller if successful
30250Sstevel@tonic-gate  */
30260Sstevel@tonic-gate int
ptree_create_and_add_node(picl_nodehdl_t rooth,const char * name,const char * classname,picl_nodehdl_t * nodeh)30270Sstevel@tonic-gate ptree_create_and_add_node(picl_nodehdl_t rooth, const char *name,
30280Sstevel@tonic-gate     const char *classname, picl_nodehdl_t *nodeh)
30290Sstevel@tonic-gate {
30300Sstevel@tonic-gate 	picl_nodehdl_t	tmph;
30310Sstevel@tonic-gate 	int		err;
30320Sstevel@tonic-gate 
30330Sstevel@tonic-gate 	err = ptree_create_node(name, classname, &tmph);
30340Sstevel@tonic-gate 
30350Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
30360Sstevel@tonic-gate 		return (err);
30370Sstevel@tonic-gate 
30380Sstevel@tonic-gate 	err = ptree_add_node(rooth, tmph);
30390Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
30400Sstevel@tonic-gate 		(void) ptree_destroy_node(tmph);
30410Sstevel@tonic-gate 		return (err);
30420Sstevel@tonic-gate 	}
30430Sstevel@tonic-gate 
30440Sstevel@tonic-gate 	*nodeh = tmph;
30450Sstevel@tonic-gate 	return (PICL_SUCCESS);
30460Sstevel@tonic-gate }
30470Sstevel@tonic-gate 
30480Sstevel@tonic-gate 
30490Sstevel@tonic-gate /*
30500Sstevel@tonic-gate  * recursively visit all nodes
30510Sstevel@tonic-gate  */
30520Sstevel@tonic-gate static int
do_walk(picl_nodehdl_t rooth,const char * classname,void * c_args,int (* callback_fn)(picl_nodehdl_t hdl,void * args))30530Sstevel@tonic-gate do_walk(picl_nodehdl_t rooth, const char *classname,
30540Sstevel@tonic-gate     void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args))
30550Sstevel@tonic-gate {
30560Sstevel@tonic-gate 	int		err;
30570Sstevel@tonic-gate 	picl_nodehdl_t	chdh;
30580Sstevel@tonic-gate 	char		classval[PICL_CLASSNAMELEN_MAX];
30590Sstevel@tonic-gate 
30600Sstevel@tonic-gate 	err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
30610Sstevel@tonic-gate 	    sizeof (chdh));
30620Sstevel@tonic-gate 	while (err == PICL_SUCCESS) {
30630Sstevel@tonic-gate 		err = ptree_get_propval_by_name(chdh, PICL_PROP_CLASSNAME,
30640Sstevel@tonic-gate 		    classval, sizeof (classval));
30650Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
30660Sstevel@tonic-gate 			return (err);
30670Sstevel@tonic-gate 
30680Sstevel@tonic-gate 		if ((classname == NULL) || (strcmp(classname, classval) == 0)) {
30690Sstevel@tonic-gate 			err = callback_fn(chdh, c_args);
30700Sstevel@tonic-gate 			if (err != PICL_WALK_CONTINUE)
30710Sstevel@tonic-gate 				return (err);
30720Sstevel@tonic-gate 		}
30730Sstevel@tonic-gate 
30740Sstevel@tonic-gate 		if ((err = do_walk(chdh, classname, c_args, callback_fn)) !=
30750Sstevel@tonic-gate 		    PICL_WALK_CONTINUE)
30760Sstevel@tonic-gate 			return (err);
30770Sstevel@tonic-gate 
30780Sstevel@tonic-gate 		err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
30790Sstevel@tonic-gate 		    sizeof (chdh));
30800Sstevel@tonic-gate 	}
30810Sstevel@tonic-gate 	if (err == PICL_PROPNOTFOUND)	/* end of a branch */
30820Sstevel@tonic-gate 		return (PICL_WALK_CONTINUE);
30830Sstevel@tonic-gate 	return (err);
30840Sstevel@tonic-gate 
30850Sstevel@tonic-gate }
30860Sstevel@tonic-gate 
30870Sstevel@tonic-gate /*
30880Sstevel@tonic-gate  * This function visits all the nodes in the subtree rooted at <rooth>.
30890Sstevel@tonic-gate  * For each node that matches the class name specified, the callback
30900Sstevel@tonic-gate  * function is invoked.
30910Sstevel@tonic-gate  */
30920Sstevel@tonic-gate int
ptree_walk_tree_by_class(picl_nodehdl_t rooth,const char * classname,void * c_args,int (* callback_fn)(picl_nodehdl_t hdl,void * args))30930Sstevel@tonic-gate ptree_walk_tree_by_class(picl_nodehdl_t rooth, const char *classname,
30940Sstevel@tonic-gate     void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args))
30950Sstevel@tonic-gate {
30960Sstevel@tonic-gate 	int		err;
30970Sstevel@tonic-gate 
30980Sstevel@tonic-gate 	if (callback_fn == NULL)
30990Sstevel@tonic-gate 		return (PICL_INVALIDARG);
31000Sstevel@tonic-gate 	err = do_walk(rooth, classname, c_args, callback_fn);
31010Sstevel@tonic-gate 	if ((err == PICL_WALK_CONTINUE) || (err == PICL_WALK_TERMINATE))
31020Sstevel@tonic-gate 		return (PICL_SUCCESS);
31030Sstevel@tonic-gate 	return (err);
31040Sstevel@tonic-gate }
31050Sstevel@tonic-gate 
31060Sstevel@tonic-gate static int
compare_propval(picl_nodehdl_t nodeh,char * pname,picl_prop_type_t ptype,void * pval,size_t valsize)31070Sstevel@tonic-gate compare_propval(picl_nodehdl_t nodeh, char *pname, picl_prop_type_t ptype,
31080Sstevel@tonic-gate     void *pval, size_t valsize)
31090Sstevel@tonic-gate {
31100Sstevel@tonic-gate 	int			err;
31110Sstevel@tonic-gate 	picl_prophdl_t		proph;
31120Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
31130Sstevel@tonic-gate 	void			*vbuf;
31140Sstevel@tonic-gate 
31150Sstevel@tonic-gate 	err = ptree_get_prop_by_name(nodeh, pname, &proph);
31160Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
31170Sstevel@tonic-gate 		return (0);
31180Sstevel@tonic-gate 	err = ptree_get_propinfo(proph, &propinfo);
31190Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
31200Sstevel@tonic-gate 		return (0);
31210Sstevel@tonic-gate 	if (propinfo.piclinfo.type != ptype)
31220Sstevel@tonic-gate 		return (0);
31230Sstevel@tonic-gate 	if (propinfo.piclinfo.type == PICL_PTYPE_VOID)
31240Sstevel@tonic-gate 		return (1);
31250Sstevel@tonic-gate 	if (pval == NULL)
31260Sstevel@tonic-gate 		return (0);
31270Sstevel@tonic-gate 	if (valsize > propinfo.piclinfo.size)
31280Sstevel@tonic-gate 		return (0);
31290Sstevel@tonic-gate 	vbuf = alloca(propinfo.piclinfo.size);
31300Sstevel@tonic-gate 	if (vbuf == NULL)
31310Sstevel@tonic-gate 		return (0);
31320Sstevel@tonic-gate 	err = ptree_get_propval(proph, vbuf, propinfo.piclinfo.size);
31330Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
31340Sstevel@tonic-gate 		return (0);
31350Sstevel@tonic-gate 	if (memcmp(vbuf, pval, valsize) == 0)
31360Sstevel@tonic-gate 		return (1);
31370Sstevel@tonic-gate 	return (0);
31380Sstevel@tonic-gate }
31390Sstevel@tonic-gate 
31400Sstevel@tonic-gate 
31410Sstevel@tonic-gate /*
31420Sstevel@tonic-gate  * This function traverses the subtree and finds a node that has a property
31430Sstevel@tonic-gate  * of the specified name and type with the specified value.
31440Sstevel@tonic-gate  * The matched node in the tree is returned in retnodeh. If there is
31450Sstevel@tonic-gate  * no node with that property, then PICL_NODENOTFOUND is returned.
31460Sstevel@tonic-gate  */
31470Sstevel@tonic-gate int
ptree_find_node(picl_nodehdl_t rooth,char * pname,picl_prop_type_t ptype,void * pval,size_t valsize,picl_nodehdl_t * retnodeh)31480Sstevel@tonic-gate ptree_find_node(picl_nodehdl_t rooth, char *pname, picl_prop_type_t ptype,
31490Sstevel@tonic-gate     void *pval, size_t valsize, picl_nodehdl_t *retnodeh)
31500Sstevel@tonic-gate {
31510Sstevel@tonic-gate 	int			err;
31520Sstevel@tonic-gate 	picl_nodehdl_t		chdh;
31530Sstevel@tonic-gate 
31540Sstevel@tonic-gate 	if (pname == NULL)
31550Sstevel@tonic-gate 		return (PICL_INVALIDARG);
31560Sstevel@tonic-gate 	err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
31570Sstevel@tonic-gate 	    sizeof (chdh));
31580Sstevel@tonic-gate 
31590Sstevel@tonic-gate 	while (err == PICL_SUCCESS) {
31600Sstevel@tonic-gate 		if (compare_propval(chdh, pname, ptype, pval, valsize)) {
31610Sstevel@tonic-gate 			if (retnodeh)
31620Sstevel@tonic-gate 				*retnodeh = chdh;
31630Sstevel@tonic-gate 			return (PICL_SUCCESS);
31640Sstevel@tonic-gate 		}
31650Sstevel@tonic-gate 
31660Sstevel@tonic-gate 		err = ptree_find_node(chdh, pname, ptype, pval, valsize,
31670Sstevel@tonic-gate 		    retnodeh);
31680Sstevel@tonic-gate 		if (err != PICL_NODENOTFOUND)
31690Sstevel@tonic-gate 			return (err);
31700Sstevel@tonic-gate 
31710Sstevel@tonic-gate 		err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
31720Sstevel@tonic-gate 		    sizeof (chdh));
31730Sstevel@tonic-gate 	}
31740Sstevel@tonic-gate 	if (err == PICL_PROPNOTFOUND)
31750Sstevel@tonic-gate 		return (PICL_NODENOTFOUND);
31760Sstevel@tonic-gate 	return (err);
31770Sstevel@tonic-gate }
31780Sstevel@tonic-gate 
31790Sstevel@tonic-gate /*
31800Sstevel@tonic-gate  * This function gets the frutree parent for a given node.
31810Sstevel@tonic-gate  * Traverse up the tree and look for the following properties:
31820Sstevel@tonic-gate  * Frutree parent reference properties:
31830Sstevel@tonic-gate  *  _fru_parent
31840Sstevel@tonic-gate  *  _location_parent
31850Sstevel@tonic-gate  *  _port_parent
31860Sstevel@tonic-gate  * If the frutree reference property is found, return its value.
31870Sstevel@tonic-gate  * Else, return the handle of /frutree/chassis.
31880Sstevel@tonic-gate  */
31890Sstevel@tonic-gate int
ptree_get_frutree_parent(picl_nodehdl_t nodeh,picl_nodehdl_t * fruh)31900Sstevel@tonic-gate ptree_get_frutree_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruh)
31910Sstevel@tonic-gate {
31920Sstevel@tonic-gate 	int		err;
31930Sstevel@tonic-gate 	picl_nodehdl_t	nparh;
31940Sstevel@tonic-gate 	picl_nodehdl_t	fruparh;
31950Sstevel@tonic-gate 
31960Sstevel@tonic-gate 	err = PICL_SUCCESS;
31970Sstevel@tonic-gate 	nparh = nodeh;
31980Sstevel@tonic-gate 	while (err == PICL_SUCCESS) {
31990Sstevel@tonic-gate 		err = ptree_get_propval_by_name(nparh, PICL_REFPROP_FRU_PARENT,
32000Sstevel@tonic-gate 		    &fruparh, sizeof (fruparh));
32010Sstevel@tonic-gate 		if (err == PICL_SUCCESS) {
32020Sstevel@tonic-gate 			*fruh = fruparh;
32030Sstevel@tonic-gate 			return (PICL_SUCCESS);
32040Sstevel@tonic-gate 		}
32050Sstevel@tonic-gate 		err = ptree_get_propval_by_name(nparh,
32060Sstevel@tonic-gate 		    PICL_REFPROP_LOC_PARENT, &fruparh, sizeof (fruparh));
32070Sstevel@tonic-gate 		if (err == PICL_SUCCESS) {
32080Sstevel@tonic-gate 			*fruh = fruparh;
32090Sstevel@tonic-gate 			return (PICL_SUCCESS);
32100Sstevel@tonic-gate 		}
32110Sstevel@tonic-gate 		err = ptree_get_propval_by_name(nparh, PICL_REFPROP_PORT_PARENT,
32120Sstevel@tonic-gate 		    &fruparh, sizeof (fruparh));
32130Sstevel@tonic-gate 		if (err == PICL_SUCCESS) {
32140Sstevel@tonic-gate 			*fruh = fruparh;
32150Sstevel@tonic-gate 			return (PICL_SUCCESS);
32160Sstevel@tonic-gate 		}
32170Sstevel@tonic-gate 
32180Sstevel@tonic-gate 		err = ptree_get_propval_by_name(nparh, PICL_PROP_PARENT, &nparh,
32190Sstevel@tonic-gate 		    sizeof (nparh));
32200Sstevel@tonic-gate 	}
32210Sstevel@tonic-gate 
32220Sstevel@tonic-gate 	if (err == PICL_PROPNOTFOUND) {	/* return /frutree/chassis handle */
32230Sstevel@tonic-gate 		err = ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, &fruparh);
32240Sstevel@tonic-gate 		if (err == PICL_SUCCESS) {
32250Sstevel@tonic-gate 			*fruh = fruparh;
32260Sstevel@tonic-gate 			return (PICL_SUCCESS);
32270Sstevel@tonic-gate 		}
32280Sstevel@tonic-gate 	}
32290Sstevel@tonic-gate 	return (err);
32300Sstevel@tonic-gate }
32310Sstevel@tonic-gate 
32320Sstevel@tonic-gate /*
32330Sstevel@tonic-gate  * This function is called by plug-ins to register with the daemon
32340Sstevel@tonic-gate  */
32350Sstevel@tonic-gate int
picld_plugin_register(picld_plugin_reg_t * regp)32360Sstevel@tonic-gate picld_plugin_register(picld_plugin_reg_t *regp)
32370Sstevel@tonic-gate {
32380Sstevel@tonic-gate 	picld_plugin_reg_list_t	*el;
32390Sstevel@tonic-gate 	picld_plugin_reg_list_t	*tmp;
32400Sstevel@tonic-gate 
32410Sstevel@tonic-gate 	if (regp == NULL)
32420Sstevel@tonic-gate 		return (PICL_FAILURE);
32430Sstevel@tonic-gate 
32440Sstevel@tonic-gate 	if (regp->version != PICLD_PLUGIN_VERSION_1)
32450Sstevel@tonic-gate 		return (PICL_NOTSUPPORTED);
32460Sstevel@tonic-gate 
32470Sstevel@tonic-gate 	el = malloc(sizeof (picld_plugin_reg_list_t));
32480Sstevel@tonic-gate 	if (el == NULL)
32490Sstevel@tonic-gate 		return (PICL_FAILURE);
32500Sstevel@tonic-gate 	el->reg.version = regp->version;
32510Sstevel@tonic-gate 	el->reg.critical = regp->critical;
32520Sstevel@tonic-gate 	if (regp->name)
32530Sstevel@tonic-gate 		el->reg.name = strdup(regp->name);
32540Sstevel@tonic-gate 	if (el->reg.name == NULL)
32550Sstevel@tonic-gate 		return (PICL_FAILURE);
32560Sstevel@tonic-gate 
32570Sstevel@tonic-gate 	el->reg.plugin_init = regp->plugin_init;
32580Sstevel@tonic-gate 	el->reg.plugin_fini = regp->plugin_fini;
32590Sstevel@tonic-gate 	el->next = NULL;
32600Sstevel@tonic-gate 
32610Sstevel@tonic-gate 	if (plugin_reg_list == NULL) {
32620Sstevel@tonic-gate 		plugin_reg_list = el;
32630Sstevel@tonic-gate 	} else {	/* add to end */
32640Sstevel@tonic-gate 		tmp = plugin_reg_list;
32650Sstevel@tonic-gate 		while (tmp->next != NULL)
32660Sstevel@tonic-gate 			tmp = tmp->next;
32670Sstevel@tonic-gate 		tmp->next = el;
32680Sstevel@tonic-gate 	}
32690Sstevel@tonic-gate 
32700Sstevel@tonic-gate 	return (PICL_SUCCESS);
32710Sstevel@tonic-gate }
32720Sstevel@tonic-gate 
32730Sstevel@tonic-gate /*
32740Sstevel@tonic-gate  * Call fini routines of the registered plugins
32750Sstevel@tonic-gate  */
32760Sstevel@tonic-gate static void
plugin_fini(picld_plugin_reg_list_t * p)32770Sstevel@tonic-gate plugin_fini(picld_plugin_reg_list_t *p)
32780Sstevel@tonic-gate {
32790Sstevel@tonic-gate 	if (p == NULL)
32800Sstevel@tonic-gate 		return;
32810Sstevel@tonic-gate 
32820Sstevel@tonic-gate 	plugin_fini(p->next);
32830Sstevel@tonic-gate 	if (p->reg.plugin_fini)
32840Sstevel@tonic-gate 		(p->reg.plugin_fini)();
32850Sstevel@tonic-gate }
32860Sstevel@tonic-gate 
32870Sstevel@tonic-gate /*
32880Sstevel@tonic-gate  * Create PICL Tree
32890Sstevel@tonic-gate  */
32900Sstevel@tonic-gate 
32910Sstevel@tonic-gate static void
init_plugin_reg_list(void)32920Sstevel@tonic-gate init_plugin_reg_list(void)
32930Sstevel@tonic-gate {
32940Sstevel@tonic-gate 	plugin_reg_list = NULL;
32950Sstevel@tonic-gate }
32960Sstevel@tonic-gate 
32970Sstevel@tonic-gate static int
picltree_set_root(picl_nodehdl_t rooth)32980Sstevel@tonic-gate picltree_set_root(picl_nodehdl_t rooth)
32990Sstevel@tonic-gate {
33000Sstevel@tonic-gate 	picl_obj_t 	*pobj;
33010Sstevel@tonic-gate 	int		err;
33020Sstevel@tonic-gate 
33030Sstevel@tonic-gate 	(void) rw_rdlock(&ptree_rwlock);		/* lock ptree */
33040Sstevel@tonic-gate 	pobj = NULL;
33050Sstevel@tonic-gate 	err = lookup_and_lock_node(RDLOCK_NODE, rooth, &pobj); /* lock node */
33060Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
33070Sstevel@tonic-gate 		(void) rw_unlock(&ptree_rwlock);
33080Sstevel@tonic-gate 		return (PICL_FAILURE);
33090Sstevel@tonic-gate 	}
33100Sstevel@tonic-gate 	piclize_node(pobj);
33110Sstevel@tonic-gate 	picl_root_obj = pobj;
33120Sstevel@tonic-gate 	ptree_root_hdl = pobj->ptree_hdl;
33130Sstevel@tonic-gate 	unlock_node(pobj);			/* unlock node */
33140Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);		/* unlock ptree */
33150Sstevel@tonic-gate 	return (PICL_SUCCESS);
33160Sstevel@tonic-gate }
33170Sstevel@tonic-gate 
33180Sstevel@tonic-gate static int
picltree_init(void)33190Sstevel@tonic-gate picltree_init(void)
33200Sstevel@tonic-gate {
33210Sstevel@tonic-gate 	(void) rwlock_init(&ptree_rwlock, USYNC_THREAD, NULL);
33220Sstevel@tonic-gate 	(void) rwlock_init(&picltbl_rwlock, USYNC_THREAD, NULL);
33230Sstevel@tonic-gate 
33240Sstevel@tonic-gate 	if (hash_init(&picltbl) < 0)
33250Sstevel@tonic-gate 		return (PICL_FAILURE);
33260Sstevel@tonic-gate 	if (hash_init(&ptreetbl) < 0)
33270Sstevel@tonic-gate 		return (PICL_FAILURE);
33280Sstevel@tonic-gate 
33290Sstevel@tonic-gate 	if (pthread_mutex_init(&ptreehdl_lock, NULL) != 0)
33300Sstevel@tonic-gate 		return (PICL_FAILURE);
33310Sstevel@tonic-gate 
33320Sstevel@tonic-gate 	if (pthread_mutex_init(&piclhdl_lock, NULL) != 0)
33330Sstevel@tonic-gate 		return (PICL_FAILURE);
33340Sstevel@tonic-gate 
33350Sstevel@tonic-gate 	if (pthread_mutex_init(&evtq_lock, NULL) != 0)
33360Sstevel@tonic-gate 		return (PICL_FAILURE);
33370Sstevel@tonic-gate 	if (pthread_cond_init(&evtq_cv, NULL) != 0)
33380Sstevel@tonic-gate 		return (PICL_FAILURE);
33390Sstevel@tonic-gate 	if (pthread_mutex_init(&evthandler_lock, NULL) != 0)
33400Sstevel@tonic-gate 		return (PICL_FAILURE);
33410Sstevel@tonic-gate 
33420Sstevel@tonic-gate 	picl_root_obj = NULL;
33430Sstevel@tonic-gate 	eventqp = NULL;
33440Sstevel@tonic-gate 	evt_handlers = NULL;
33450Sstevel@tonic-gate 	ptree_root_hdl = PICL_INVALID_PICLHDL;
33460Sstevel@tonic-gate 
33470Sstevel@tonic-gate 	return (PICL_SUCCESS);
33480Sstevel@tonic-gate }
33490Sstevel@tonic-gate 
33500Sstevel@tonic-gate static void
add_unique_plugin_to_list(char * path,char * name)33510Sstevel@tonic-gate add_unique_plugin_to_list(char *path, char *name)
33520Sstevel@tonic-gate {
33530Sstevel@tonic-gate 	char	*buf;
33540Sstevel@tonic-gate 	picld_plugin_desc_t	*pl;
33550Sstevel@tonic-gate 	picld_plugin_desc_t	*tmp;
33560Sstevel@tonic-gate 
33570Sstevel@tonic-gate 	pl = plugin_desc;
33580Sstevel@tonic-gate 	while (pl != NULL) {
33590Sstevel@tonic-gate 		if (strcmp(pl->libname, name) == 0)
33600Sstevel@tonic-gate 			return;
33610Sstevel@tonic-gate 		else
33620Sstevel@tonic-gate 			pl = pl->next;
33630Sstevel@tonic-gate 	}
33640Sstevel@tonic-gate 
33650Sstevel@tonic-gate 	pl = malloc(sizeof (picld_plugin_desc_t));
33660Sstevel@tonic-gate 	if (pl == NULL)
33670Sstevel@tonic-gate 		return;
33680Sstevel@tonic-gate 
33690Sstevel@tonic-gate 	pl->libname = strdup(name);
33700Sstevel@tonic-gate 	if (pl->libname == NULL)
33710Sstevel@tonic-gate 		return;
33720Sstevel@tonic-gate 	buf = alloca(strlen(name) + strlen(path) + 2);
33730Sstevel@tonic-gate 	if (buf == NULL)
33740Sstevel@tonic-gate 		return;
33750Sstevel@tonic-gate 	(void) strcpy(buf, path);
33760Sstevel@tonic-gate 	(void) strcat(buf, name);
33770Sstevel@tonic-gate 	pl->pathname = strdup(buf);
33780Sstevel@tonic-gate 	if (pl->pathname == NULL)
33790Sstevel@tonic-gate 		return;
33800Sstevel@tonic-gate 
33810Sstevel@tonic-gate 	pl->next = NULL;
33820Sstevel@tonic-gate 
33830Sstevel@tonic-gate 	if (plugin_desc == NULL)
33840Sstevel@tonic-gate 		plugin_desc = pl;
33850Sstevel@tonic-gate 	else {
33860Sstevel@tonic-gate 		tmp = plugin_desc;
33870Sstevel@tonic-gate 		while (tmp->next != NULL)
33880Sstevel@tonic-gate 			tmp = tmp->next;
33890Sstevel@tonic-gate 		tmp->next = pl;
33900Sstevel@tonic-gate 	}
33910Sstevel@tonic-gate }
33920Sstevel@tonic-gate 
33930Sstevel@tonic-gate static void
get_plugins_from_dir(char * dirname)33940Sstevel@tonic-gate get_plugins_from_dir(char *dirname)
33950Sstevel@tonic-gate {
33960Sstevel@tonic-gate 	struct dirent	*ent;
33970Sstevel@tonic-gate 	DIR	*dir;
33980Sstevel@tonic-gate 	int	len;
33990Sstevel@tonic-gate 	int	solen = strlen(SO_VERS) + 1;
34000Sstevel@tonic-gate 
34010Sstevel@tonic-gate 	if ((dir = opendir(dirname)) == NULL)
34020Sstevel@tonic-gate 		return;
34030Sstevel@tonic-gate 
34040Sstevel@tonic-gate 	while ((ent = readdir(dir)) != NULL) {
34050Sstevel@tonic-gate 		if ((strcmp(ent->d_name, ".") == 0) ||
34060Sstevel@tonic-gate 		    (strcmp(ent->d_name, "..") == 0))
34070Sstevel@tonic-gate 			continue;
34080Sstevel@tonic-gate 
34090Sstevel@tonic-gate 		len = strlen(ent->d_name) + 1;
34100Sstevel@tonic-gate 		if (len < solen)
34110Sstevel@tonic-gate 			continue;
34120Sstevel@tonic-gate 
34130Sstevel@tonic-gate 		if (strcmp(ent->d_name + (len - solen), SO_VERS) == 0)
34140Sstevel@tonic-gate 			add_unique_plugin_to_list(dirname, ent->d_name);
34150Sstevel@tonic-gate 	}
34160Sstevel@tonic-gate 
34170Sstevel@tonic-gate 	(void) closedir(dir);
34180Sstevel@tonic-gate }
34190Sstevel@tonic-gate 
34200Sstevel@tonic-gate 
34210Sstevel@tonic-gate static void
init_plugin_list(void)34220Sstevel@tonic-gate init_plugin_list(void)
34230Sstevel@tonic-gate {
34240Sstevel@tonic-gate 	char	nmbuf[SYS_NMLN];
34250Sstevel@tonic-gate 	char	pname[PATH_MAX];
34260Sstevel@tonic-gate 
34270Sstevel@tonic-gate 	plugin_desc = NULL;
34280Sstevel@tonic-gate 	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
34290Sstevel@tonic-gate 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
34300Sstevel@tonic-gate 		if (access(pname, R_OK) == 0)
34310Sstevel@tonic-gate 			get_plugins_from_dir(pname);
34320Sstevel@tonic-gate 	}
34330Sstevel@tonic-gate 
34340Sstevel@tonic-gate 	if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
34350Sstevel@tonic-gate 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
34360Sstevel@tonic-gate 		if (access(pname, R_OK) == 0)
34370Sstevel@tonic-gate 			get_plugins_from_dir(pname);
34380Sstevel@tonic-gate 	}
34390Sstevel@tonic-gate 
34400Sstevel@tonic-gate 	(void) snprintf(pname, PATH_MAX, "%s/", PICLD_COMMON_PLUGIN_DIR);
34410Sstevel@tonic-gate 	if (access(pname, R_OK) == 0)
34420Sstevel@tonic-gate 		get_plugins_from_dir(pname);
34430Sstevel@tonic-gate }
34440Sstevel@tonic-gate 
34450Sstevel@tonic-gate static void
load_plugins(void)34460Sstevel@tonic-gate load_plugins(void)
34470Sstevel@tonic-gate {
34480Sstevel@tonic-gate 	picld_plugin_desc_t	*pl;
34490Sstevel@tonic-gate 
34500Sstevel@tonic-gate 	pl = plugin_desc;
34510Sstevel@tonic-gate 	while (pl != NULL) {
34520Sstevel@tonic-gate 		pl->dlh = dlopen(pl->pathname, RTLD_LAZY|RTLD_LOCAL);
34530Sstevel@tonic-gate 		if (pl->dlh == NULL) {
34540Sstevel@tonic-gate 			syslog(LOG_CRIT, dlerror());
34550Sstevel@tonic-gate 			return;
34560Sstevel@tonic-gate 		}
34570Sstevel@tonic-gate 		pl = pl->next;
34580Sstevel@tonic-gate 	}
34590Sstevel@tonic-gate }
34600Sstevel@tonic-gate 
34610Sstevel@tonic-gate 
34620Sstevel@tonic-gate 
34630Sstevel@tonic-gate static int
add_root_props(picl_nodehdl_t rooth)34640Sstevel@tonic-gate add_root_props(picl_nodehdl_t rooth)
34650Sstevel@tonic-gate {
34660Sstevel@tonic-gate 	int			err;
34670Sstevel@tonic-gate 	picl_prophdl_t		proph;
34680Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
34690Sstevel@tonic-gate 	float			picl_vers;
34700Sstevel@tonic-gate 
34710Sstevel@tonic-gate #define	PICL_PROP_PICL_VERSION		"PICLVersion"
34720Sstevel@tonic-gate #define	PICL_VERSION			1.1
34730Sstevel@tonic-gate 
34740Sstevel@tonic-gate 	err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION_1,
34750Sstevel@tonic-gate 	    PICL_PTYPE_FLOAT, PICL_READ, sizeof (picl_vers),
34760Sstevel@tonic-gate 	    PICL_PROP_PICL_VERSION, NULL, NULL);
34770Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
34780Sstevel@tonic-gate 		return (err);
34790Sstevel@tonic-gate 
34800Sstevel@tonic-gate 	picl_vers = PICL_VERSION;
34810Sstevel@tonic-gate 	err = ptree_create_and_add_prop(rooth, &pinfo, &picl_vers, &proph);
34820Sstevel@tonic-gate 	return (err);
34830Sstevel@tonic-gate }
34840Sstevel@tonic-gate 
34850Sstevel@tonic-gate static int
construct_picltree(void)34860Sstevel@tonic-gate construct_picltree(void)
34870Sstevel@tonic-gate {
34880Sstevel@tonic-gate 	int			err;
34890Sstevel@tonic-gate 	picld_plugin_reg_list_t	*iter;
34900Sstevel@tonic-gate 	picl_nodehdl_t		rhdl;
34910Sstevel@tonic-gate 
34920Sstevel@tonic-gate 	/*
34930Sstevel@tonic-gate 	 * Create "/" node
34940Sstevel@tonic-gate 	 */
34950Sstevel@tonic-gate 	if ((err = ptree_create_node(PICL_NODE_ROOT, PICL_CLASS_PICL,
34960Sstevel@tonic-gate 	    &rhdl)) != PICL_SUCCESS) {
34970Sstevel@tonic-gate 		return (err);
34980Sstevel@tonic-gate 	}
34990Sstevel@tonic-gate 
35000Sstevel@tonic-gate 	if (picltree_set_root(rhdl) != PICL_SUCCESS) {
35010Sstevel@tonic-gate 		return (PICL_FAILURE);
35020Sstevel@tonic-gate 	}
35030Sstevel@tonic-gate 
35040Sstevel@tonic-gate 	err = add_root_props(rhdl);
35050Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
35060Sstevel@tonic-gate 		return (err);
35070Sstevel@tonic-gate 
35080Sstevel@tonic-gate 	/*
35090Sstevel@tonic-gate 	 * Initialize the registered plug-in modules
35100Sstevel@tonic-gate 	 */
35110Sstevel@tonic-gate 	iter = plugin_reg_list;
35120Sstevel@tonic-gate 	while (iter != NULL) {
35130Sstevel@tonic-gate 		if (iter->reg.plugin_init)
35140Sstevel@tonic-gate 			(iter->reg.plugin_init)();
35150Sstevel@tonic-gate 		iter = iter->next;
35160Sstevel@tonic-gate 	}
35170Sstevel@tonic-gate 	return (PICL_SUCCESS);
35180Sstevel@tonic-gate }
35190Sstevel@tonic-gate 
35200Sstevel@tonic-gate void
xptree_destroy(void)35210Sstevel@tonic-gate xptree_destroy(void)
35220Sstevel@tonic-gate {
35230Sstevel@tonic-gate 	dbg_print(1, "xptree_destroy: picl_root_obj = %s\n",
35240Sstevel@tonic-gate 	    (picl_root_obj == NULL ? "NULL" : "not-NULL"));
35250Sstevel@tonic-gate 
35260Sstevel@tonic-gate 	if (picl_root_obj == NULL)
35270Sstevel@tonic-gate 		return;
35280Sstevel@tonic-gate 
35290Sstevel@tonic-gate 	dbg_print(1, "xptree_destroy: call plugin_fini\n");
35300Sstevel@tonic-gate 	plugin_fini(plugin_reg_list);
35310Sstevel@tonic-gate 	dbg_print(1, "xptree_destroy: plugin_fini DONE\n");
35320Sstevel@tonic-gate 
35330Sstevel@tonic-gate 	(void) ptree_delete_node(picl_root_obj->ptree_hdl);
35340Sstevel@tonic-gate 	(void) ptree_destroy_node(picl_root_obj->ptree_hdl);
35350Sstevel@tonic-gate 
35360Sstevel@tonic-gate 	(void) rw_wrlock(&ptree_rwlock);
35370Sstevel@tonic-gate 	picl_root_obj = NULL;
35380Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);
35390Sstevel@tonic-gate }
35400Sstevel@tonic-gate 
35410Sstevel@tonic-gate /*ARGSUSED*/
35420Sstevel@tonic-gate int
xptree_initialize(int flg)35430Sstevel@tonic-gate xptree_initialize(int flg)
35440Sstevel@tonic-gate {
35450Sstevel@tonic-gate 	int		err;
35460Sstevel@tonic-gate 	pthread_attr_t	attr;
35470Sstevel@tonic-gate 	pthread_t	tid;
35480Sstevel@tonic-gate 
35490Sstevel@tonic-gate 	picld_pid = getpid();
35500Sstevel@tonic-gate 	picld_cred.dc_euid = geteuid();
35510Sstevel@tonic-gate 	picld_cred.dc_egid = getegid();
35520Sstevel@tonic-gate 	picld_cred.dc_ruid = getuid();
35530Sstevel@tonic-gate 	picld_cred.dc_rgid = getgid();
35540Sstevel@tonic-gate 	picld_cred.dc_pid = getpid();
35550Sstevel@tonic-gate 
35560Sstevel@tonic-gate 	picl_hdl_hi = 1;
35570Sstevel@tonic-gate 	ptree_hdl_hi = 1;
35580Sstevel@tonic-gate 	ptree_generation = 1;
35590Sstevel@tonic-gate 	qempty_wait = 0;
35600Sstevel@tonic-gate 
35610Sstevel@tonic-gate 	if (pthread_mutex_init(&ptree_refresh_mutex, NULL) != 0)
35620Sstevel@tonic-gate 		return (PICL_FAILURE);
35630Sstevel@tonic-gate 
35640Sstevel@tonic-gate 	if (picltree_init() != PICL_SUCCESS)
35650Sstevel@tonic-gate 		return (PICL_FAILURE);
35660Sstevel@tonic-gate 
35670Sstevel@tonic-gate 	init_plugin_reg_list();
35680Sstevel@tonic-gate 	init_plugin_list();
35690Sstevel@tonic-gate 	load_plugins();
35700Sstevel@tonic-gate 
35710Sstevel@tonic-gate 	err = construct_picltree();
35720Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
35730Sstevel@tonic-gate 		return (err);
35740Sstevel@tonic-gate 
35750Sstevel@tonic-gate 	/*
35760Sstevel@tonic-gate 	 * Dispatch events after all plug-ins have initialized
35770Sstevel@tonic-gate 	 */
35780Sstevel@tonic-gate 	if (pthread_attr_init(&attr) != 0)
35790Sstevel@tonic-gate 		return (PICL_FAILURE);
35800Sstevel@tonic-gate 
35810Sstevel@tonic-gate 	(void) pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
35820Sstevel@tonic-gate 	if (pthread_create(&tid, &attr, ptree_event_thread, NULL))
35830Sstevel@tonic-gate 		return (PICL_FAILURE);
35840Sstevel@tonic-gate 
35850Sstevel@tonic-gate 	return (PICL_SUCCESS);
35860Sstevel@tonic-gate }
35870Sstevel@tonic-gate 
35880Sstevel@tonic-gate int
xptree_reinitialize(void)35890Sstevel@tonic-gate xptree_reinitialize(void)
35900Sstevel@tonic-gate {
35910Sstevel@tonic-gate 	int	err;
35920Sstevel@tonic-gate 
35930Sstevel@tonic-gate 	/*
35940Sstevel@tonic-gate 	 * Wait for eventq to become empty
35950Sstevel@tonic-gate 	 */
35960Sstevel@tonic-gate 	dbg_print(1, "xptree_reinitialize: wait for evtq empty\n");
35970Sstevel@tonic-gate 	(void) pthread_mutex_lock(&evtq_lock);
35980Sstevel@tonic-gate 	qempty_wait = 1;
35990Sstevel@tonic-gate 	while (eventqp != NULL)
36000Sstevel@tonic-gate 		(void) pthread_cond_wait(&evtq_empty, &evtq_lock);
36010Sstevel@tonic-gate 	qempty_wait = 0;
36020Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&evtq_lock);
36030Sstevel@tonic-gate 	dbg_print(1, "xptree_reinitialize: evtq empty is EMPTY\n");
36040Sstevel@tonic-gate 
36050Sstevel@tonic-gate 	(void) rw_wrlock(&ptree_rwlock);
36060Sstevel@tonic-gate 	picl_root_obj = NULL;
36070Sstevel@tonic-gate 	ptree_root_hdl = PICL_INVALID_PICLHDL;
36080Sstevel@tonic-gate 	(void) rw_unlock(&ptree_rwlock);
36090Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ptree_refresh_mutex);
36100Sstevel@tonic-gate 	++ptree_generation;
36110Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ptree_refresh_mutex);
36120Sstevel@tonic-gate 
36130Sstevel@tonic-gate 	err = construct_picltree();
36140Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ptree_refresh_mutex);
36150Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&ptree_refresh_cond);
36160Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ptree_refresh_mutex);
36170Sstevel@tonic-gate 
36180Sstevel@tonic-gate 	(void) pthread_mutex_lock(&evtq_lock);
36190Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&evtq_cv);
36200Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&evtq_lock);
36210Sstevel@tonic-gate 
36220Sstevel@tonic-gate 	return (err);
36230Sstevel@tonic-gate }
36240Sstevel@tonic-gate 
36250Sstevel@tonic-gate /*
36260Sstevel@tonic-gate  * This function is called by the PICL daemon on behalf of clients to
36270Sstevel@tonic-gate  * wait for a tree refresh
36280Sstevel@tonic-gate  */
36290Sstevel@tonic-gate int
xptree_refresh_notify(uint32_t secs)36300Sstevel@tonic-gate xptree_refresh_notify(uint32_t secs)
36310Sstevel@tonic-gate {
36320Sstevel@tonic-gate 	int	curgen;
36330Sstevel@tonic-gate 	int	ret;
36340Sstevel@tonic-gate 	timespec_t	to;
36350Sstevel@tonic-gate 
36365672Sanbui 	if (secs != 0) {
36375672Sanbui 		if (pthread_mutex_lock(&ptree_refresh_mutex) != 0)
36385672Sanbui 			return (PICL_FAILURE);
36395672Sanbui 
36405672Sanbui 		curgen = ptree_generation;
36415672Sanbui 
36425672Sanbui 		while (curgen == ptree_generation) {
36435698Sanbui 			if (secs == UINT32_MAX)	/* wait forever */
36445672Sanbui 				(void) pthread_cond_wait(&ptree_refresh_cond,
36455672Sanbui 				    &ptree_refresh_mutex);
36465672Sanbui 			else {
36475672Sanbui 				to.tv_sec = secs;
36485672Sanbui 				to.tv_nsec = 0;
36495672Sanbui 				ret = pthread_cond_reltimedwait_np(
36505672Sanbui 				    &ptree_refresh_cond,
36515672Sanbui 				    &ptree_refresh_mutex, &to);
36525672Sanbui 				if (ret == ETIMEDOUT)
36535672Sanbui 					break;
36545672Sanbui 			}
36550Sstevel@tonic-gate 		}
36565672Sanbui 
36575672Sanbui 		(void) pthread_mutex_unlock(&ptree_refresh_mutex);
36580Sstevel@tonic-gate 	}
36590Sstevel@tonic-gate 
36600Sstevel@tonic-gate 	return (PICL_SUCCESS);
36610Sstevel@tonic-gate }
36620Sstevel@tonic-gate 
36630Sstevel@tonic-gate /*VARARGS2*/
36640Sstevel@tonic-gate void
dbg_print(int level,const char * fmt,...)36650Sstevel@tonic-gate dbg_print(int level, const char *fmt, ...)
36660Sstevel@tonic-gate {
36670Sstevel@tonic-gate 	if (verbose_level >= level) {
36680Sstevel@tonic-gate 		va_list	ap;
36690Sstevel@tonic-gate 
36700Sstevel@tonic-gate 		va_start(ap, fmt);
36710Sstevel@tonic-gate 		(void) vprintf(fmt, ap);
36720Sstevel@tonic-gate 		va_end(ap);
36730Sstevel@tonic-gate 	}
36740Sstevel@tonic-gate }
36750Sstevel@tonic-gate 
36760Sstevel@tonic-gate /*ARGSUSED*/
36770Sstevel@tonic-gate void
dbg_exec(int level,void (* fn)(void * args),void * args)36780Sstevel@tonic-gate dbg_exec(int level, void (*fn)(void *args), void *args)
36790Sstevel@tonic-gate {
36800Sstevel@tonic-gate 	if (verbose_level > level)
36810Sstevel@tonic-gate 		(*fn)(args);
36820Sstevel@tonic-gate }
3683