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