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