4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
27 * This module implements the PTree interface and the PICL to PTree calls
32 * PICL Node and Property Handles Table:
33 * A node or property in PICL tree has two handles: a ptree handle, which is
34 * used by plug-ins and the libpicltree interface, and a picl handle
35 * which is used by clients and the libpicl interface.
36 * The mapping of ptree handles to the internal PICL object (picl_obj_t) is
37 * kept in a ptree hash table (ptreetbl), and the mapping of a picl handle
38 * to its ptree handle is kept in the picl hash table (picltbl).
39 * The reader/writer lock, ptree_rwlock, is held when reading or modifying ptree
40 * hash table (ptreetbl) and/or the PICL tree structure (nodes and linkages
41 * between them). The reader/writer lock, picltbl_rwlock, is held when reading
42 * or modifying picl hash table (picltbl).
44 * The mutex, ptreehdl_lock, is used to control allocation of ptree handles.
45 * The mutex, piclhdl_lock, is used to control allocation of picl handles.
47 * The mutex, ptree_refresh_mutex, and the condition, ptree_refresh_cond,
48 * are used to synchronize PICL refreshes (ptree_refresh) and to wait/signal
49 * change in PICL tree structure.
51 * The counter, picl_hdl_hi, is the hi water mark for allocated picl handles.
52 * The counter, ptree_hdl_hi, is the hi water mark for allocated ptree handles.
53 * A stale handle error is returned for handle values below the hi water
54 * mark, and invalid handles are returned for handle values above the hi water
55 * mark or when the process id field of the handle does not match.
58 * The structure of the PICL tree is controlled by the ptree_rwlock. The
59 * properties of a node are controlled by individual node locks. The
60 * piclize-ing or unpiclize-ing of a node is controlled by picltbl_rwlock.
62 * Two-Phase Locking scheme: lock acquire phase and lock release phase.
65 * The ptree_rwlock and node locks are always acquired in the following order:
70 * There are three locks:
71 * ptree_rwlock: a reader lock is obtained to do ptree hash table
72 * lookups and traverse tree. A writer lock is obtained
73 * when creating or destroying nodes from the ptree,
74 * or when modifying node linkages: parent, peer, child.
75 * picltbl_rwlock: a reader lock is obtained for picl hash table lookups.
76 * A writer lock is obtained when piclize-ing or
77 * unpiclize-ing nodes or properties.
78 * node_lock: This is a reader/writer lock for properties of a node.
79 * A reader lock is obtained before reading property
80 * values. A writer lock is obtained when adding or
81 * removing properties and when modifying a property value.
83 * Never hold more than one node lock at a time.
86 * There are two locks:
87 * evtq_lock: this lock protects the event queue. It is obtained
88 * to queue events that are posted and to unqueue
89 * events to be dispatched.
90 * evtq_cv: condition variable is protected by evtq_lock. It is
91 * used by the ptree event thread to wait for events
92 * until eventqp is not NULL.
93 * evtq_empty: condition variable protected by evtq_lock. It is
94 * used to signal when the eventq becomes empty. The
95 * reinitialization process waits on this condition.
96 * evthandler_lock: this protects the event handler list. It is obtained
97 * to add event handlers on registration and to remove
98 * event handlers on unregistration.
99 * (handler)->cv: condition variable per handler protected by
100 * evthandler_lock. It is used to wait until the
101 * event handler completes execution (execflg == 0)
102 * before unregistering the handler.
125 #include <inttypes.h>
126 #include <sys/systeminfo.h>
127 #include <sys/utsname.h>
129 #include <picltree.h>
130 #include "picldefs.h"
131 #include "ptree_impl.h"
133 #define SO_VERS ".so.1"
135 static hash_t picltbl
; /* client handles to picl obj */
136 static hash_t ptreetbl
; /* ptree handles to picl obj */
137 static pthread_mutex_t ptreehdl_lock
;
138 static pthread_mutex_t piclhdl_lock
;
139 static pthread_mutex_t ptree_refresh_mutex
;
140 static rwlock_t picltbl_rwlock
; /* PICL handle table lock */
141 static rwlock_t ptree_rwlock
; /* PICL tree lock */
142 static pthread_cond_t ptree_refresh_cond
= PTHREAD_COND_INITIALIZER
;
143 static uint32_t ptree_hdl_hi
= 1;
144 static uint32_t picl_hdl_hi
= 1;
145 static picl_obj_t
*picl_root_obj
= NULL
;
146 static picl_nodehdl_t ptree_root_hdl
= PICL_INVALID_PICLHDL
;
147 static int ptree_generation
= 0;
148 static pid_t picld_pid
;
149 static door_cred_t picld_cred
;
150 static int qempty_wait
; /* evtq_empty condition waiter flag */
152 static picld_plugin_reg_list_t
*plugin_reg_list
= NULL
;
153 static picld_plugin_desc_t
*plugin_desc
;
155 static eventq_t
*eventqp
; /* PICL events queue */
156 static pthread_mutex_t evtq_lock
= PTHREAD_MUTEX_INITIALIZER
;
157 static pthread_cond_t evtq_cv
= PTHREAD_COND_INITIALIZER
;
158 static pthread_cond_t evtq_empty
= PTHREAD_COND_INITIALIZER
;
159 static evt_handler_t
*evt_handlers
; /* Event handler list */
160 static pthread_mutex_t evthandler_lock
= PTHREAD_MUTEX_INITIALIZER
;
163 * PICL daemon verbose level
169 * Event handler free functions
172 free_handler(evt_handler_t
*evhp
)
175 (void) pthread_cond_broadcast(&evhp
->cv
);
176 (void) pthread_cond_destroy(&evhp
->cv
);
182 * queue_event to events queue
185 queue_event(eventq_t
*evt
)
194 while (tmpp
->next
!= NULL
)
201 * unqueue_event from the specified eventq
204 unqueue_event(eventq_t
**qp
)
215 * register an event handler by adding it to the list
218 ptree_register_handler(const char *ename
,
219 void (*evt_handler
)(const char *ename
, const void *earg
, size_t size
,
220 void *cookie
), void *cookie
)
226 return (PICL_INVALIDARG
);
229 * Initialize event handler entry
231 ent
= malloc(sizeof (*ent
));
233 return (PICL_FAILURE
);
234 ent
->ename
= strdup(ename
);
235 if (ent
->ename
== NULL
) {
237 return (PICL_FAILURE
);
239 ent
->cookie
= cookie
;
240 ent
->evt_handler
= evt_handler
;
243 (void) pthread_cond_init(&ent
->cv
, NULL
);
247 * add handler to the handler list
249 (void) pthread_mutex_lock(&evthandler_lock
);
250 if (evt_handlers
== NULL
) {
252 (void) pthread_mutex_unlock(&evthandler_lock
);
253 return (PICL_SUCCESS
);
256 while (iter
->next
!= NULL
)
259 (void) pthread_mutex_unlock(&evthandler_lock
);
261 return (PICL_SUCCESS
);
268 ptree_unregister_handler(const char *ename
,
269 void (*evt_handler
)(const char *ename
, const void *earg
, size_t size
,
270 void *cookie
), void *cookie
)
272 evt_handler_t
*evhdlrp
, **evhdlrpp
;
278 * unlink handler from handler list
280 (void) pthread_mutex_lock(&evthandler_lock
);
283 for (evhdlrpp
= &evt_handlers
; (evhdlrp
= *evhdlrpp
) != NULL
;
284 evhdlrpp
= &evhdlrp
->next
) {
285 if ((evhdlrp
->cookie
!= cookie
) ||
286 (strcmp(evhdlrp
->ename
, ename
) != 0) ||
287 (evhdlrp
->evt_handler
!= evt_handler
))
291 * If the handler is in execution, release the lock
292 * and wait for it to complete and retry.
294 if (evhdlrp
->execflg
) {
295 evhdlrp
->wakeupflg
= 1;
296 (void) pthread_cond_wait(&evhdlrp
->cv
,
302 * Unlink this handler from the linked list
304 *evhdlrpp
= evhdlrp
->next
;
305 free_handler(evhdlrp
);
309 (void) pthread_mutex_unlock(&evthandler_lock
);
313 * Call all registered handlers for the event
316 call_event_handlers(eventq_t
*ev
)
319 void (*evhandler
)(const char *, const void *, size_t, void *);
320 void (*completion_handler
)(char *ename
, void *earg
, size_t size
);
322 (void) pthread_mutex_lock(&evthandler_lock
);
324 while (iter
!= NULL
) {
325 if (strcmp(iter
->ename
, ev
->ename
) == 0) {
326 evhandler
= iter
->evt_handler
;
328 (void) pthread_mutex_unlock(&evthandler_lock
);
330 dbg_print(2, "ptree_evthr: Invoking evthdlr:%p"
331 " ename:%s\n", evhandler
, ev
->ename
);
332 (*evhandler
)(ev
->ename
, ev
->earg
, ev
->size
,
334 dbg_print(2, "ptree_evthr: done evthdlr:%p "
335 "ename:%s\n", evhandler
, ev
->ename
);
337 (void) pthread_mutex_lock(&evthandler_lock
);
339 if (iter
->wakeupflg
) {
341 (void) pthread_cond_broadcast(&iter
->cv
);
346 (void) pthread_mutex_unlock(&evthandler_lock
);
347 if ((completion_handler
= ev
->completion_handler
) != NULL
) {
349 "ptree_evthr: Invoking completion hdlr:%p ename:%s\n",
350 completion_handler
, ev
->ename
);
351 (*completion_handler
)((char *)ev
->ename
, (void *)ev
->earg
,
353 dbg_print(2, "ptree_evthr: done completion hdlr:%p ename:%s\n",
354 completion_handler
, ev
->ename
);
356 (void) pthread_mutex_lock(&ptree_refresh_mutex
);
358 (void) pthread_cond_broadcast(&ptree_refresh_cond
);
359 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
363 * This function is called by a plug-in to post an event
366 ptree_post_event(const char *ename
, const void *earg
, size_t size
,
367 void (*completion_handler
)(char *ename
, void *earg
, size_t size
))
372 return (PICL_INVALIDARG
);
374 evt
= malloc(sizeof (*evt
));
376 return (PICL_FAILURE
);
380 evt
->completion_handler
= completion_handler
;
382 (void) pthread_mutex_lock(&evtq_lock
);
384 (void) pthread_cond_broadcast(&evtq_cv
);
385 (void) pthread_mutex_unlock(&evtq_lock
);
386 return (PICL_SUCCESS
);
390 * PICLTREE event thread
394 ptree_event_thread(void *argp
)
399 (void) pthread_mutex_lock(&evtq_lock
);
400 while (eventqp
== NULL
) {
405 (void) pthread_cond_broadcast(&evtq_empty
);
406 (void) pthread_cond_wait(&evtq_cv
, &evtq_lock
);
408 if ((evt
= unqueue_event(&eventqp
)) != NULL
) {
409 (void) pthread_mutex_unlock(&evtq_lock
);
410 call_event_handlers(evt
);
413 (void) pthread_mutex_unlock(&evtq_lock
);
421 * Create a new element
424 hash_newobj(uint32_t hdl_val
, void *obj_val
)
428 n
= malloc(sizeof (*n
));
432 n
->hash_obj
= obj_val
;
438 hash_newhdl(uint32_t picl_hdl
, uint32_t ptreeh
)
442 n
= malloc(sizeof (*n
));
446 n
->hash_hdl
= ptreeh
;
452 * Initialize a hash table by setting all entries to NULL
455 hash_init(hash_t
*htbl
)
459 htbl
->hash_size
= HASH_TBL_SIZE
;
460 htbl
->tbl
= malloc(sizeof (hash_elem_t
*) * HASH_TBL_SIZE
);
461 if (htbl
->tbl
== NULL
)
463 for (i
= 0; i
< htbl
->hash_size
; ++i
)
469 * Lock free function to add an entry in the hash table
472 hash_add_newobj(hash_t
*htbl
, picl_hdl_t hdl
, void *pobj
)
476 uint32_t hash_val
= HASH_VAL(hdl
);
478 n
= hash_newobj(hash_val
, pobj
);
481 indx
= HASH_INDEX(htbl
->hash_size
, hash_val
);
482 n
->next
= htbl
->tbl
[indx
];
488 hash_add_newhdl(hash_t
*htbl
, picl_hdl_t piclh
, picl_hdl_t ptreeh
)
492 uint32_t picl_val
= HASH_VAL(piclh
);
493 uint32_t ptree_val
= HASH_VAL(ptreeh
);
495 n
= hash_newhdl(picl_val
, ptree_val
);
499 indx
= HASH_INDEX(htbl
->hash_size
, picl_val
);
500 n
->next
= htbl
->tbl
[indx
];
506 * Lock free function to remove the handle from the hash table
507 * Returns -1 if element not found, 0 if successful
510 hash_remove(hash_t
*htbl
, picl_hdl_t hdl
)
515 uint32_t hash_val
= HASH_VAL(hdl
);
517 i
= HASH_INDEX(htbl
->hash_size
, hash_val
);
518 if (htbl
->tbl
[i
] == NULL
)
522 if (cur
->hdl
== hash_val
) {
523 htbl
->tbl
[i
] = cur
->next
;
528 while (nxt
!= NULL
) {
529 if (nxt
->hdl
== hash_val
) {
530 cur
->next
= nxt
->next
;
541 * Lock free function to lookup the hash table for a given handle
542 * Returns NULL if not found
545 hash_lookup_obj(hash_t
*htbl
, picl_hdl_t hdl
)
551 hash_val
= HASH_VAL(hdl
);
552 i
= HASH_INDEX(htbl
->hash_size
, hash_val
);
554 while (tmp
!= NULL
) {
555 if (tmp
->hdl
== hash_val
)
556 return (tmp
->hash_obj
);
563 hash_lookup_hdl(hash_t
*htbl
, picl_hdl_t hdl
)
569 hash_val
= HASH_VAL(hdl
);
570 i
= HASH_INDEX(htbl
->hash_size
, hash_val
);
572 while (tmp
!= NULL
) {
573 if (tmp
->hdl
== hash_val
)
574 return (MAKE_HANDLE(picld_pid
, tmp
->hash_hdl
));
577 return (PICL_INVALID_PICLHDL
);
581 * Is the PICL handle stale or invalid handle?
584 picl_hdl_error(picl_hdl_t hdl
)
586 uint32_t hash_val
= HASH_VAL(hdl
);
587 pid_t pid
= GET_PID(hdl
);
590 (void) pthread_mutex_lock(&piclhdl_lock
);
591 err
= PICL_STALEHANDLE
;
592 if ((pid
!= picld_pid
) || (hash_val
>= picl_hdl_hi
) ||
594 err
= PICL_INVALIDHANDLE
;
595 (void) pthread_mutex_unlock(&piclhdl_lock
);
600 * Is the Ptree handle stale or invalid handle?
603 ptree_hdl_error(picl_hdl_t hdl
)
605 uint32_t hash_val
= HASH_VAL(hdl
);
606 pid_t pid
= GET_PID(hdl
);
609 (void) pthread_mutex_lock(&ptreehdl_lock
);
610 err
= PICL_STALEHANDLE
;
611 if ((pid
!= picld_pid
) || (hash_val
>= ptree_hdl_hi
) ||
613 err
= PICL_INVALIDHANDLE
;
614 (void) pthread_mutex_unlock(&ptreehdl_lock
);
619 * For a PICL handle, return the PTree handle and the PICL object
620 * Locks and releases the PICL table.
623 cvt_picl2ptree(picl_hdl_t hdl
, picl_hdl_t
*ptree_hdl
)
628 (void) rw_rdlock(&picltbl_rwlock
); /* lock picl */
629 tmph
= hash_lookup_hdl(&picltbl
, hdl
);
630 if (tmph
== PICL_INVALID_PICLHDL
) {
631 err
= picl_hdl_error(hdl
);
632 (void) rw_unlock(&picltbl_rwlock
); /* unlock picl */
636 (void) rw_unlock(&picltbl_rwlock
); /* unlock picl */
637 return (PICL_SUCCESS
);
641 * Allocate a ptree handle
648 (void) pthread_mutex_lock(&ptreehdl_lock
); /* lock ptreehdl */
649 hdl
= MAKE_HANDLE(picld_pid
, ptree_hdl_hi
);
651 (void) pthread_mutex_unlock(&ptreehdl_lock
); /* unlock ptreehdl */
656 * Allocate a picl handle
657 * A PICL handle is ptree_hdl value with 1 in MSB of handle value.
658 * If a ptree handle already has 1 in MSB, then it cannot be piclized
659 * and the daemon must be restarted.
666 (void) pthread_mutex_lock(&piclhdl_lock
); /* lock piclhdl */
667 hdl
= MAKE_HANDLE(picld_pid
, picl_hdl_hi
);
669 (void) pthread_mutex_unlock(&piclhdl_lock
); /* unlock piclhdl */
674 * Allocate and add handle to PTree hash table
677 alloc_and_add_to_ptree(picl_obj_t
*pobj
)
679 pobj
->ptree_hdl
= alloc_ptreehdl();
680 (void) rw_wrlock(&ptree_rwlock
);
681 (void) hash_add_newobj(&ptreetbl
, pobj
->ptree_hdl
, pobj
);
682 (void) rw_unlock(&ptree_rwlock
);
686 * Lock a picl node object
689 lock_obj(int rw
, picl_obj_t
*nodep
)
691 if (rw
== RDLOCK_NODE
)
692 (void) rw_rdlock(&nodep
->node_lock
);
693 else if (rw
== WRLOCK_NODE
)
694 (void) rw_wrlock(&nodep
->node_lock
);
701 * Release the picl node object.
702 * This function may be called with a NULL object pointer.
705 unlock_node(picl_obj_t
*nodep
)
709 (void) rw_unlock(&nodep
->node_lock
);
713 * This function locks the node of a property and returns the node object
714 * and the property object.
717 lookup_and_lock_propnode(int rw
, picl_prophdl_t proph
, picl_obj_t
**nodep
,
723 pobj
= hash_lookup_obj(&ptreetbl
, proph
);
725 return (ptree_hdl_error(proph
));
728 * Get the property's or table entry's node object
731 if (pobj
->obj_type
== PICL_OBJ_PROP
)
732 nobj
= pobj
->prop_node
;
733 else if (pobj
->obj_type
== (PICL_OBJ_PROP
|PICL_OBJ_TABLEENTRY
))
734 nobj
= pobj
->prop_table
->prop_node
;
736 *propp
= pobj
; /* return the prop */
737 return (PICL_NOTPROP
);
740 if (nobj
&& (lock_obj(rw
, nobj
) < 0)) /* Lock node */
741 return (PICL_FAILURE
);
746 return (PICL_SUCCESS
);
750 * This function locks the node of a table and returns the node object
751 * and the table object.
754 lookup_and_lock_tablenode(int rw
, picl_prophdl_t tblh
, picl_obj_t
**nodep
,
760 pobj
= hash_lookup_obj(&ptreetbl
, tblh
);
762 return (ptree_hdl_error(tblh
));
765 * Get the property's or table entry's node object
768 if (pobj
->obj_type
!= PICL_OBJ_TABLE
)
769 return (PICL_NOTTABLE
);
770 nobj
= pobj
->prop_node
;
772 if (nobj
&& (lock_obj(rw
, nobj
) < 0)) /* Lock node */
773 return (PICL_FAILURE
);
778 return (PICL_SUCCESS
);
782 * This locks the node of a table or a table entry and returns the
783 * node object and the table or table entry object
786 lookup_and_lock_tableprop_node(int rw
, picl_prophdl_t tblproph
,
787 picl_obj_t
**nodep
, picl_obj_t
**tblpropp
)
792 pobj
= hash_lookup_obj(&ptreetbl
, tblproph
);
794 return (ptree_hdl_error(tblproph
));
797 * Get the property's or table entry's node object
800 if ((pobj
->obj_type
!= PICL_OBJ_TABLE
) && /* not a table */
801 !(pobj
->obj_type
& PICL_OBJ_TABLEENTRY
)) /* or an entry */
802 return (PICL_NOTTABLE
);
803 if (pobj
->obj_type
== PICL_OBJ_TABLE
)
804 nobj
= pobj
->prop_node
;
806 nobj
= pobj
->prop_table
->prop_node
;
808 if (nobj
&& (lock_obj(rw
, nobj
) < 0)) /* Lock node */
809 return (PICL_FAILURE
);
814 return (PICL_SUCCESS
);
818 * Lock the node corresponding to the given handle and return its object
821 lookup_and_lock_node(int rw
, picl_nodehdl_t nodeh
, picl_obj_t
**nodep
)
825 nobj
= hash_lookup_obj(&ptreetbl
, nodeh
);
827 return (ptree_hdl_error(nodeh
));
828 else if (nobj
->obj_type
!= PICL_OBJ_NODE
)
829 return (PICL_NOTNODE
);
830 if (lock_obj(rw
, nobj
) < 0) /* Lock node */
831 return (PICL_FAILURE
);
833 return (PICL_SUCCESS
);
837 * Is the property name a restricted property name?
840 picl_restricted(const char *name
)
842 if (strcmp(name
, PICL_PROP_CLASSNAME
) == 0)
843 return (0); /* not restricted */
845 if ((name
[0] == '_') && (strchr(&name
[1], '_') == NULL
))
851 * Check the value size with the property size
852 * Return PICL_INVALIDARG if the size does not match exactly for strongly
854 * For charstring reads allow sizes that match the value size
855 * For bytearray return PICL_VALUETOOBIG
856 * if the size is greater than the buffer size.
859 check_propsize(int op
, picl_obj_t
*propp
, size_t sz
)
861 if (propp
->prop_mode
& PICL_VOLATILE
) {
862 if (sz
!= propp
->prop_size
)
863 return (PICL_INVALIDARG
);
865 return (PICL_SUCCESS
);
869 * check size for non-volatile properties
871 switch (propp
->prop_type
) {
872 case PICL_PTYPE_CHARSTRING
:
873 if ((op
== PROP_READ
) &&
874 (strlen(propp
->prop_val
) >= sz
))
875 return (PICL_VALUETOOBIG
);
876 if ((op
== PROP_WRITE
) && (sz
> propp
->prop_size
))
877 return (PICL_VALUETOOBIG
);
879 case PICL_PTYPE_BYTEARRAY
:
880 if (op
== PROP_WRITE
) {
881 if (sz
> propp
->prop_size
)
882 return (PICL_VALUETOOBIG
);
883 return (PICL_SUCCESS
); /* allow small writes */
885 /* fall through for reads */
887 if (propp
->prop_size
!= sz
)
888 return (PICL_INVALIDARG
);
891 return (PICL_SUCCESS
);
895 cvt_ptree2picl(picl_hdl_t
*handlep
)
899 (void) rw_rdlock(&ptree_rwlock
);
900 pobj
= hash_lookup_obj(&ptreetbl
, *handlep
);
902 *handlep
= PICL_INVALID_PICLHDL
;
904 (void) memcpy(handlep
, &pobj
->picl_hdl
, sizeof (*handlep
));
905 (void) rw_unlock(&ptree_rwlock
);
909 * The caller of the piclize() set of functions is assumed to hold
910 * the ptree_rwlock().
913 piclize_obj(picl_obj_t
*pobj
)
915 (void) rw_wrlock(&picltbl_rwlock
);
916 pobj
->picl_hdl
= alloc_piclhdl();
917 (void) hash_add_newhdl(&picltbl
, pobj
->picl_hdl
, pobj
->ptree_hdl
);
918 (void) rw_unlock(&picltbl_rwlock
);
922 piclize_table(picl_obj_t
*tbl_obj
)
927 for (rowp
= tbl_obj
->next_row
; rowp
!= NULL
; rowp
= rowp
->next_col
)
928 for (colp
= rowp
; colp
!= NULL
; colp
= colp
->next_row
)
933 piclize_prop(picl_obj_t
*propp
)
939 if (!(propp
->prop_mode
& PICL_VOLATILE
) &&
940 (propp
->prop_type
== PICL_PTYPE_TABLE
)) {
941 tblh
= *(picl_prophdl_t
*)propp
->prop_val
;
942 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
945 piclize_obj(tbl_obj
);
946 piclize_table(tbl_obj
);
951 * Function to create PICL handles for a subtree and add them to
955 piclize_node(picl_obj_t
*nodep
)
961 propp
= nodep
->first_prop
;
962 while (propp
!= NULL
) {
964 propp
= propp
->next_prop
;
967 /* go through the children */
968 for (chdp
= nodep
->child_node
; chdp
!= NULL
; chdp
= chdp
->sibling_node
)
973 * Function to remove PICL handles
976 unpiclize_obj(picl_obj_t
*pobj
)
978 (void) rw_wrlock(&picltbl_rwlock
);
979 (void) hash_remove(&picltbl
, pobj
->picl_hdl
);
980 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
981 (void) rw_unlock(&picltbl_rwlock
);
985 unpiclize_table(picl_obj_t
*tbl_obj
)
990 for (rowp
= tbl_obj
->next_row
; rowp
!= NULL
; rowp
= rowp
->next_col
)
991 for (colp
= rowp
; colp
!= NULL
; colp
= colp
->next_row
)
993 unpiclize_obj(tbl_obj
);
997 unpiclize_prop(picl_obj_t
*propp
)
1000 picl_prophdl_t tblh
;
1002 if (!IS_PICLIZED(propp
))
1004 unpiclize_obj(propp
);
1005 if (!(propp
->prop_mode
& PICL_VOLATILE
) &&
1006 (propp
->prop_type
== PICL_PTYPE_TABLE
)) {
1007 tblh
= *(picl_prophdl_t
*)propp
->prop_val
;
1008 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1009 unpiclize_table(tbl_obj
);
1014 * Function to remove PICL handles for a subtree and its
1018 unpiclize_node(picl_obj_t
*nodep
)
1024 if (!IS_PICLIZED(nodep
))
1027 unpiclize_obj(nodep
);
1028 propp
= nodep
->first_prop
;
1029 while (propp
!= NULL
) {
1030 unpiclize_prop(propp
);
1031 propp
= propp
->next_prop
;
1034 /* go through the children */
1035 for (chdp
= nodep
->child_node
; chdp
!= NULL
; chdp
= chdp
->sibling_node
)
1036 unpiclize_node(chdp
);
1041 * The caller holds the lock on the ptree_lock when calling this.
1042 * If ret is not NULL then this function returns the referenced object.
1045 lookup_verify_ref_prop(picl_obj_t
*propp
, picl_obj_t
**ret
)
1047 picl_nodehdl_t refh
;
1050 refh
= *(picl_nodehdl_t
*)propp
->prop_val
;
1051 refobj
= hash_lookup_obj(&ptreetbl
, refh
);
1053 return (ptree_hdl_error(refh
));
1054 else if (refobj
->obj_type
!= PICL_OBJ_NODE
)
1055 return (PICL_INVREFERENCE
);
1058 return (PICL_SUCCESS
);
1062 * The caller holds the lock on ptree_lock when calling this.
1063 * If ret is not NULL, then this function returns the table object
1066 lookup_verify_table_prop(picl_obj_t
*propp
, picl_obj_t
**ret
)
1068 picl_prophdl_t tblh
;
1069 picl_obj_t
*tbl_obj
;
1071 tblh
= *(picl_prophdl_t
*)propp
->prop_val
;
1072 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1073 if (tbl_obj
== NULL
)
1074 return (ptree_hdl_error(tblh
));
1075 else if (!(tbl_obj
->obj_type
& PICL_OBJ_TABLE
))
1076 return (PICL_NOTTABLE
);
1079 return (PICL_SUCCESS
);
1083 lookup_verify_prop_handle(picl_prophdl_t proph
, picl_obj_t
**ret
)
1087 propp
= hash_lookup_obj(&ptreetbl
, proph
);
1089 return (ptree_hdl_error(proph
));
1090 else if (!(propp
->obj_type
& PICL_OBJ_PROP
))
1091 return (PICL_NOTPROP
);
1094 return (PICL_SUCCESS
);
1098 lookup_verify_node_handle(picl_nodehdl_t nodeh
, picl_obj_t
**ret
)
1102 nodep
= hash_lookup_obj(&ptreetbl
, nodeh
);
1104 return (ptree_hdl_error(nodeh
));
1105 else if (nodep
->obj_type
!= PICL_OBJ_NODE
)
1106 return (PICL_NOTNODE
);
1109 return (PICL_SUCCESS
);
1113 lookup_prop_by_name(picl_obj_t
*nodep
, const char *pname
, picl_obj_t
**ret
)
1117 if (strcmp(pname
, PICL_PROP_PARENT
) == 0) {
1118 if (nodep
->parent_node
== NULL
)
1119 return (PICL_PROPNOTFOUND
);
1121 return (PICL_SUCCESS
);
1123 if (strcmp(pname
, PICL_PROP_CHILD
) == 0) {
1124 if (nodep
->child_node
== NULL
)
1125 return (PICL_PROPNOTFOUND
);
1127 return (PICL_SUCCESS
);
1129 if (strcmp(pname
, PICL_PROP_PEER
) == 0) {
1130 if (nodep
->sibling_node
== NULL
)
1131 return (PICL_PROPNOTFOUND
);
1133 return (PICL_SUCCESS
);
1136 propp
= nodep
->first_prop
;
1137 while (propp
!= NULL
) {
1138 if (strcmp(propp
->prop_name
, pname
) == 0) {
1141 return (PICL_SUCCESS
);
1143 propp
= propp
->next_prop
;
1145 return (PICL_PROPNOTFOUND
);
1149 * This function locks the ptree, verifies that the handle is a reference
1150 * to a node of specified class name, releases the lock
1153 check_ref_handle(picl_nodehdl_t refh
, char *clname
)
1159 (void) rw_rdlock(&ptree_rwlock
); /* Lock ptree */
1160 refobj
= hash_lookup_obj(&ptreetbl
, refh
);
1161 if ((refobj
== NULL
) || !(refobj
->obj_type
& PICL_OBJ_NODE
)) {
1162 (void) rw_unlock(&ptree_rwlock
);
1163 return (PICL_INVREFERENCE
);
1166 err
= lookup_prop_by_name(refobj
, PICL_PROP_CLASSNAME
, &propp
);
1167 if ((err
!= PICL_SUCCESS
) || (propp
->prop_val
== NULL
) ||
1168 (strcmp(propp
->prop_val
, clname
) != 0))
1169 err
= PICL_INVREFERENCE
;
1170 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1175 check_table_handle(picl_prophdl_t tblh
)
1177 picl_obj_t
*tbl_obj
;
1180 (void) rw_rdlock(&ptree_rwlock
);
1182 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1183 if ((tbl_obj
== NULL
) || !(tbl_obj
->obj_type
& PICL_OBJ_TABLE
))
1184 err
= PICL_NOTTABLE
;
1185 (void) rw_unlock(&ptree_rwlock
);
1190 * PICLTree Interface routines for plug-in modules
1193 ptree_get_root(picl_nodehdl_t
*rooth
)
1195 *rooth
= ptree_root_hdl
;
1196 return (PICL_SUCCESS
);
1200 * Lock free create a property object
1203 create_propobj(const ptree_propinfo_t
*pinfo
, const void *valbuf
,
1208 if (pinfo
->version
!= PTREE_PROPINFO_VERSION_1
)
1209 return (PICL_NOTSUPPORTED
);
1211 if (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
) &&
1212 (pinfo
->piclinfo
.type
!= PICL_PTYPE_VOID
) &&
1214 return (PICL_INVALIDARG
);
1216 pobj
= malloc(sizeof (picl_obj_t
));
1218 return (PICL_FAILURE
);
1220 pobj
->obj_type
= PICL_OBJ_PROP
;
1221 pobj
->pinfo_ver
= pinfo
->version
;
1222 pobj
->prop_type
= pinfo
->piclinfo
.type
;
1223 pobj
->prop_mode
= pinfo
->piclinfo
.accessmode
;
1224 pobj
->prop_size
= pinfo
->piclinfo
.size
;
1225 (void) strcpy(pobj
->prop_name
, pinfo
->piclinfo
.name
);
1226 pobj
->read_func
= pinfo
->read
;
1227 pobj
->write_func
= pinfo
->write
;
1229 pobj
->prop_val
= NULL
;
1230 if (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
)) {
1231 pobj
->prop_val
= malloc(pinfo
->piclinfo
.size
);
1232 if (pobj
->prop_val
== NULL
) {
1234 return (PICL_FAILURE
);
1236 if (pobj
->prop_type
== PICL_PTYPE_CHARSTRING
)
1237 (void) strlcpy(pobj
->prop_val
, valbuf
,
1238 pinfo
->piclinfo
.size
);
1240 (void) memcpy(pobj
->prop_val
, valbuf
,
1241 pinfo
->piclinfo
.size
);
1243 pobj
->prop_node
= NULL
;
1244 pobj
->ptree_hdl
= PICL_INVALID_PICLHDL
;
1245 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
1246 pobj
->next_prop
= NULL
;
1247 pobj
->next_row
= NULL
;
1248 pobj
->next_col
= NULL
;
1251 return (PICL_SUCCESS
);
1255 * Check for valid arguments, create a property object,
1256 * Lock ptree_rwlock, add the new property handle, release the lock
1257 * For reference properties and table properties, the handles are verified
1258 * before creating the property.
1261 ptree_create_prop(const ptree_propinfo_t
*pinfo
, const void *valbuf
,
1262 picl_prophdl_t
*proph
)
1265 picl_nodehdl_t refh
;
1266 picl_prophdl_t tblh
;
1270 char classname
[PICL_PROPNAMELEN_MAX
];
1273 return (PICL_INVALIDARG
);
1274 if (pinfo
->version
!= PTREE_PROPINFO_VERSION_1
)
1275 return (PICL_NOTSUPPORTED
);
1276 if (pinfo
->piclinfo
.size
>= PICL_PROPSIZE_MAX
)
1277 return (PICL_VALUETOOBIG
);
1278 if (picl_restricted(pinfo
->piclinfo
.name
))
1279 return (PICL_RESERVEDNAME
);
1282 if ((pinfo
->piclinfo
.name
[0] == '_') &&
1283 (strchr(&pinfo
->piclinfo
.name
[1], '_') != NULL
))
1286 if (pinfo
->piclinfo
.type
== PICL_PTYPE_REFERENCE
) {
1288 return (PICL_INVREFERENCE
);
1290 * check valid reference handle for non-volatiles
1292 if (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
)) {
1294 return (PICL_INVREFERENCE
);
1295 if (pinfo
->piclinfo
.size
!= sizeof (picl_nodehdl_t
))
1296 return (PICL_INVREFERENCE
);
1297 (void) strcpy(classname
, pinfo
->piclinfo
.name
);
1298 ptr
= strchr(&classname
[1], '_');
1300 refh
= *(picl_hdl_t
*)valbuf
;
1301 err
= check_ref_handle(refh
, &classname
[1]);
1302 if (err
!= PICL_SUCCESS
)
1305 } else if (refflag
== 1)
1306 return (PICL_INVREFERENCE
);
1307 else if ((pinfo
->piclinfo
.type
== PICL_PTYPE_TABLE
) &&
1308 (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
))) {
1309 if (pinfo
->piclinfo
.size
!= sizeof (picl_prophdl_t
))
1310 return (PICL_INVALIDARG
);
1311 tblh
= *(picl_prophdl_t
*)valbuf
;
1312 err
= check_table_handle(tblh
);
1313 if (err
!= PICL_SUCCESS
)
1315 } else if ((strcmp(pinfo
->piclinfo
.name
, PICL_PROP_CLASSNAME
) == 0) &&
1316 ((pinfo
->piclinfo
.type
!= PICL_PTYPE_CHARSTRING
) ||
1317 (strlen(valbuf
) >= PICL_CLASSNAMELEN_MAX
)))
1318 return (PICL_RESERVEDNAME
);
1319 else if ((strcmp(pinfo
->piclinfo
.name
, PICL_PROP_NAME
) == 0) &&
1320 (pinfo
->piclinfo
.type
!= PICL_PTYPE_CHARSTRING
))
1321 return (PICL_RESERVEDNAME
);
1323 * No locks held when you get here
1325 err
= create_propobj(pinfo
, valbuf
, &pobj
);
1326 if (err
!= PICL_SUCCESS
)
1329 alloc_and_add_to_ptree(pobj
);
1330 *proph
= pobj
->ptree_hdl
;
1331 return (PICL_SUCCESS
);
1335 * Lock free routine to destroy table entries
1336 * This function removes the destroyed handles from the hash table
1337 * Uses lock free routines: hash_lookup() and hash_remove()
1340 destroy_table(picl_obj_t
*pobj
)
1342 picl_prophdl_t tblh
;
1343 picl_obj_t
*tbl_obj
;
1348 tblh
= *(picl_prophdl_t
*)pobj
->prop_val
;
1349 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1350 if (tbl_obj
== NULL
)
1353 assert(tbl_obj
->obj_type
& PICL_OBJ_TABLE
);
1355 /* Delete all entries */
1356 rowp
= tbl_obj
->next_row
;
1357 while (rowp
!= NULL
) {
1359 rowp
= rowp
->next_col
;
1360 while (colp
!= NULL
) {
1362 colp
= colp
->next_row
;
1363 (void) hash_remove(&ptreetbl
, freep
->ptree_hdl
);
1364 free(freep
->prop_val
);
1369 (void) hash_remove(&ptreetbl
, tbl_obj
->ptree_hdl
);
1375 * Lock free function that frees up a property object and removes the
1376 * handles from Ptree table
1379 destroy_propobj(picl_obj_t
*propp
)
1381 if (propp
->prop_type
== PICL_PTYPE_TABLE
)
1382 destroy_table(propp
);
1384 (void) hash_remove(&ptreetbl
, propp
->ptree_hdl
);
1385 free(propp
->prop_val
);
1390 * This function destroys a previously deleted property.
1391 * A deleted property does not have an associated node.
1392 * All memory allocated for this property are freed
1395 ptree_destroy_prop(picl_prophdl_t proph
)
1399 (void) rw_wrlock(&ptree_rwlock
); /* Exclusive Lock ptree */
1401 propp
= hash_lookup_obj(&ptreetbl
, proph
);
1402 if (propp
== NULL
) {
1403 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1404 return (ptree_hdl_error(proph
));
1407 /* Is the prop still attached to a node? */
1408 if (propp
->prop_node
!= NULL
) {
1409 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1410 return (PICL_CANTDESTROY
);
1413 destroy_propobj(propp
);
1415 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1416 return (PICL_SUCCESS
);
1420 * This function adds a property to the property list of a node and adds
1421 * it to the PICL table if the node has a PICL handle.
1422 * This function locks the picl_rwlock and ptree_rwlock.
1425 ptree_add_prop(picl_nodehdl_t nodeh
, picl_prophdl_t proph
)
1430 picl_obj_t
*tbl_obj
;
1433 (void) rw_rdlock(&ptree_rwlock
); /* RDLock ptree */
1436 * Verify property handle
1438 err
= lookup_verify_prop_handle(proph
, &propp
);
1439 if (err
!= PICL_SUCCESS
) {
1440 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1444 if (propp
->prop_node
!= NULL
) {
1445 (void) rw_unlock(&ptree_rwlock
);
1446 return (PICL_INVALIDARG
);
1451 * Exclusive Lock the node's properties
1453 err
= lookup_and_lock_node(WRLOCK_NODE
, nodeh
, &nodep
);
1454 if (err
!= PICL_SUCCESS
) {
1455 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1460 * check if prop already exists
1462 err
= lookup_prop_by_name(nodep
, propp
->prop_name
, NULL
);
1463 if (err
== PICL_SUCCESS
) {
1464 unlock_node(nodep
); /* Unlock node */
1465 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1466 return (PICL_PROPEXISTS
);
1470 * Verify property's value
1473 switch (propp
->prop_type
) {
1474 case PICL_PTYPE_TABLE
:
1475 if (propp
->prop_mode
& PICL_VOLATILE
)
1477 err
= lookup_verify_table_prop(propp
, &tbl_obj
);
1478 if (err
!= PICL_SUCCESS
) {
1480 (void) rw_unlock(&ptree_rwlock
);
1483 tbl_obj
->prop_node
= nodep
; /* set table's nodep */
1484 tbl_obj
->table_prop
= propp
; /* set table prop */
1486 case PICL_PTYPE_REFERENCE
:
1487 if (propp
->prop_mode
& PICL_VOLATILE
)
1489 err
= lookup_verify_ref_prop(propp
, &refobj
);
1490 if (err
!= PICL_SUCCESS
) {
1492 (void) rw_unlock(&ptree_rwlock
);
1495 if (IS_PICLIZED(nodep
) && !IS_PICLIZED(refobj
)) {
1497 (void) rw_unlock(&ptree_rwlock
);
1505 if (IS_PICLIZED(nodep
))
1506 piclize_prop(propp
);
1508 * Add prop to beginning of list
1510 propp
->prop_node
= nodep
; /* set prop's nodep */
1511 propp
->next_prop
= nodep
->first_prop
;
1512 nodep
->first_prop
= propp
;
1514 unlock_node(nodep
); /* Unlock node */
1515 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1516 return (PICL_SUCCESS
);
1520 * Lock free function that unlinks a property from its node
1523 unlink_prop(picl_obj_t
*nodep
, picl_obj_t
*propp
)
1527 iterp
= nodep
->first_prop
;
1528 if (iterp
== propp
) { /* first property */
1529 nodep
->first_prop
= iterp
->next_prop
;
1530 return (PICL_SUCCESS
);
1532 while ((iterp
!= NULL
) && (iterp
->next_prop
!= propp
))
1533 iterp
= iterp
->next_prop
;
1535 return (PICL_PROPNOTFOUND
);
1536 iterp
->next_prop
= propp
->next_prop
;
1537 return (PICL_SUCCESS
);
1541 * This function deletes the specified property from the property list
1542 * of its node and removes the handle from PICL table, if the node
1546 ptree_delete_prop(picl_prophdl_t proph
)
1552 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
1554 * Lookup the property's node and lock it if there is one
1555 * return the objects for the property and the node
1557 nodep
= propp
= NULL
;
1558 err
= lookup_and_lock_propnode(WRLOCK_NODE
, proph
, &nodep
, &propp
);
1559 if (err
!= PICL_SUCCESS
) {
1560 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1562 } else if (nodep
== NULL
) {
1563 /* Nothing to do - already deleted! */
1564 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1565 return (PICL_SUCCESS
);
1568 if (propp
->obj_type
& PICL_OBJ_TABLEENTRY
) {
1569 unlock_node(nodep
); /* Unlock node */
1570 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1571 return (PICL_NOTPROP
);
1574 err
= unlink_prop(nodep
, propp
);
1575 if (err
!= PICL_SUCCESS
) {
1576 unlock_node(nodep
); /* Unlock node */
1577 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1581 propp
->prop_node
= NULL
; /* reset prop's nodep */
1582 propp
->next_prop
= NULL
;
1584 unpiclize_prop(propp
);
1586 unlock_node(nodep
); /* Unlock node */
1587 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1588 return (PICL_SUCCESS
);
1592 * Create a table object and return its handle
1595 ptree_create_table(picl_prophdl_t
*tblh
)
1599 pobj
= malloc(sizeof (picl_obj_t
));
1601 return (PICL_FAILURE
);
1602 pobj
->obj_type
= PICL_OBJ_TABLE
;
1603 pobj
->prop_val
= NULL
;
1604 pobj
->prop_node
= NULL
;
1605 pobj
->ptree_hdl
= PICL_INVALID_PICLHDL
;
1606 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
1607 pobj
->table_prop
= NULL
;
1608 pobj
->next_row
= NULL
;
1609 pobj
->next_col
= NULL
;
1611 alloc_and_add_to_ptree(pobj
);
1612 *tblh
= pobj
->ptree_hdl
;
1613 return (PICL_SUCCESS
);
1617 * Add the properties in <props> array as a row in the table
1618 * Add PICL handles if the table has a valid PICL handle
1621 ptree_add_row_to_table(picl_prophdl_t tblh
, int nprops
,
1622 const picl_prophdl_t
*props
)
1624 picl_obj_t
*tbl_obj
;
1626 picl_obj_t
*lastrow
;
1627 picl_obj_t
**newrow
;
1634 return (PICL_INVALIDARG
);
1636 newrow
= malloc(sizeof (picl_obj_t
*) * nprops
);
1638 return (PICL_FAILURE
);
1640 (void) rw_rdlock(&ptree_rwlock
); /* Lock ptree */
1642 err
= lookup_and_lock_tablenode(WRLOCK_NODE
, tblh
, &nodep
, &tbl_obj
);
1643 if (err
!= PICL_SUCCESS
) {
1645 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1650 * make sure all are either props or table handles
1652 for (i
= 0; i
< nprops
; ++i
) {
1653 pobj
= newrow
[i
] = hash_lookup_obj(&ptreetbl
, props
[i
]);
1654 if (pobj
== NULL
) { /* no object */
1655 err
= ptree_hdl_error(props
[i
]);
1658 if ((!(pobj
->obj_type
& PICL_OBJ_PROP
)) &&
1659 (!(pobj
->obj_type
& PICL_OBJ_TABLE
))) {
1663 if (IS_PICLIZED(pobj
) || (pobj
->prop_table
!= NULL
) ||
1664 (pobj
->prop_node
!= NULL
)) {
1665 err
= PICL_INVALIDARG
;
1670 if (err
!= PICL_SUCCESS
) {
1673 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1678 * Mark all props as table entries, set up row linkages
1681 if (IS_PICLIZED(tbl_obj
))
1683 for (i
= 0; i
< nprops
; ++i
) {
1684 newrow
[i
]->obj_type
|= PICL_OBJ_TABLEENTRY
;
1685 newrow
[i
]->prop_table
= tbl_obj
;
1686 newrow
[i
]->next_prop
= NULL
;
1687 newrow
[i
]->next_col
= NULL
;
1689 piclize_obj(newrow
[i
]);
1690 if (i
!= nprops
- 1)
1691 newrow
[i
]->next_row
= newrow
[i
+1];
1693 newrow
[nprops
- 1]->next_row
= NULL
;
1695 if (tbl_obj
->next_row
== NULL
) { /* add first row */
1696 tbl_obj
->next_row
= newrow
[0];
1697 tbl_obj
->next_col
= newrow
[0];
1699 lastrow
= tbl_obj
->next_row
;
1700 while (lastrow
->next_col
!= NULL
)
1701 lastrow
= lastrow
->next_col
;
1703 while (lastrow
!= NULL
) {
1704 lastrow
->next_col
= newrow
[i
];
1705 lastrow
= lastrow
->next_row
;
1710 unlock_node(nodep
); /* unlock node */
1711 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1713 return (PICL_SUCCESS
);
1717 * This function returns the handle of the next property in the row
1720 ptree_get_next_by_row(picl_prophdl_t proph
, picl_prophdl_t
*nextrowh
)
1726 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
1728 nodep
= propp
= NULL
;
1730 * proph could be a table handle or a table entry handle
1731 * Look it up as a table entry handle first, check error code
1732 * to see if it is a table handle
1734 err
= lookup_and_lock_tableprop_node(RDLOCK_NODE
, proph
, &nodep
,
1736 if (err
!= PICL_SUCCESS
) {
1737 (void) rw_unlock(&ptree_rwlock
);
1741 if (propp
->next_row
)
1742 *nextrowh
= propp
->next_row
->ptree_hdl
;
1744 err
= PICL_ENDOFLIST
;
1746 unlock_node(nodep
); /* unlock node */
1747 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1752 ptree_get_next_by_col(picl_prophdl_t proph
, picl_prophdl_t
*nextcolh
)
1758 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
1759 nodep
= propp
= NULL
;
1761 * proph could be a table handle or a table entry handle
1762 * Look it up as a table entry handle first, check error code
1763 * to see if it is a table handle
1765 err
= lookup_and_lock_tableprop_node(RDLOCK_NODE
, proph
, &nodep
,
1767 if (err
!= PICL_SUCCESS
) {
1768 (void) rw_unlock(&ptree_rwlock
);
1772 if (propp
->next_col
)
1773 *nextcolh
= propp
->next_col
->ptree_hdl
;
1775 err
= PICL_ENDOFLIST
;
1777 unlock_node(nodep
); /* unlock node */
1778 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1783 * This function creates node object and adds its handle to the Ptree
1786 ptree_create_node(const char *name
, const char *clname
, picl_nodehdl_t
*nodeh
)
1789 ptree_propinfo_t propinfo
;
1790 picl_prophdl_t phdl
;
1791 picl_prophdl_t cphdl
;
1794 if ((name
== NULL
) || (*name
== '\0') ||
1795 (clname
== NULL
) || (*clname
== '\0'))
1796 return (PICL_INVALIDARG
);
1798 if ((strlen(name
) >= PICL_PROPNAMELEN_MAX
) ||
1799 (strlen(clname
) >= PICL_CLASSNAMELEN_MAX
))
1800 return (PICL_VALUETOOBIG
);
1803 * Create the picl object for node
1805 pobj
= malloc(sizeof (picl_obj_t
));
1807 return (PICL_FAILURE
);
1808 pobj
->obj_type
= PICL_OBJ_NODE
;
1809 pobj
->first_prop
= NULL
;
1810 pobj
->ptree_hdl
= PICL_INVALID_PICLHDL
;
1811 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
1812 pobj
->parent_node
= NULL
;
1813 pobj
->sibling_node
= NULL
;
1814 pobj
->child_node
= NULL
;
1815 pobj
->node_classname
= strdup(clname
);
1816 if (pobj
->node_classname
== NULL
) {
1818 return (PICL_FAILURE
);
1820 (void) rwlock_init(&pobj
->node_lock
, USYNC_THREAD
, NULL
);
1822 alloc_and_add_to_ptree(pobj
); /* commit the node */
1825 * create name property
1827 propinfo
.version
= PTREE_PROPINFO_VERSION_1
;
1828 propinfo
.piclinfo
.type
= PICL_PTYPE_CHARSTRING
;
1829 propinfo
.piclinfo
.accessmode
= PICL_READ
;
1830 propinfo
.piclinfo
.size
= strlen(name
) + 1;
1831 (void) strcpy(propinfo
.piclinfo
.name
, PICL_PROP_NAME
);
1832 propinfo
.read
= NULL
;
1833 propinfo
.write
= NULL
;
1834 err
= ptree_create_prop(&propinfo
, (const void *)name
, &phdl
);
1835 if (err
!= PICL_SUCCESS
) {
1836 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1839 err
= ptree_add_prop(pobj
->ptree_hdl
, phdl
);
1840 if (err
!= PICL_SUCCESS
) {
1841 (void) ptree_destroy_prop(phdl
);
1842 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1847 * create picl classname property
1849 propinfo
.piclinfo
.size
= strlen(clname
) + 1;
1850 (void) strcpy(propinfo
.piclinfo
.name
, PICL_PROP_CLASSNAME
);
1851 propinfo
.read
= NULL
;
1852 propinfo
.write
= NULL
;
1853 err
= ptree_create_prop(&propinfo
, (const void *)clname
, &cphdl
);
1854 if (err
!= PICL_SUCCESS
) {
1855 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1858 err
= ptree_add_prop(pobj
->ptree_hdl
, cphdl
);
1859 if (err
!= PICL_SUCCESS
) {
1860 (void) ptree_destroy_prop(cphdl
);
1861 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1865 *nodeh
= pobj
->ptree_hdl
;
1866 return (PICL_SUCCESS
);
1870 * Destroy a node/subtree freeing up space
1871 * Removed destroyed objects' handles from PTree table
1874 destroy_subtree(picl_obj_t
*nodep
)
1883 chdp
= nodep
->child_node
;
1884 while (chdp
!= NULL
) {
1886 chdp
= chdp
->sibling_node
;
1887 destroy_subtree(freep
);
1893 (void) lock_obj(WRLOCK_NODE
, nodep
);
1896 * destroy all properties associated with this node
1898 iterp
= nodep
->first_prop
;
1899 while (iterp
!= NULL
) {
1901 iterp
= iterp
->next_prop
;
1902 destroy_propobj(freep
);
1905 (void) hash_remove(&ptreetbl
, nodep
->ptree_hdl
);
1906 (void) rwlock_destroy(&nodep
->node_lock
);
1907 free(nodep
->node_classname
);
1912 * This function destroys a previously deleted node/subtree. All the properties
1913 * are freed and removed from the PTree table.
1914 * Only one destroy is in progress at any time.
1917 ptree_destroy_node(picl_nodehdl_t nodeh
)
1924 (void) rw_wrlock(&ptree_rwlock
); /* exclusive wrlock ptree */
1926 err
= lookup_verify_node_handle(nodeh
, &nodep
);
1927 if (err
!= PICL_SUCCESS
) {
1928 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1933 * Has this node/subtree been deleted?
1935 if (IS_PICLIZED(nodep
)) {
1936 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1937 return (PICL_CANTDESTROY
);
1941 * update parent's child list to repair the tree when
1942 * parent is not null
1944 parp
= nodep
->parent_node
;
1945 if (parp
== NULL
) { /* root */
1946 destroy_subtree(nodep
);
1947 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1948 return (PICL_SUCCESS
);
1951 np
= parp
->child_node
;
1952 if (np
== nodep
) { /* first child */
1953 parp
->child_node
= nodep
->sibling_node
;
1955 while ((np
!= NULL
) && (np
->sibling_node
!= nodep
))
1956 np
= np
->sibling_node
;
1958 np
->sibling_node
= nodep
->sibling_node
;
1961 destroy_subtree(nodep
);
1962 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1963 return (PICL_SUCCESS
);
1967 * This function deletes a node/subtree from the tree and removes the handles
1971 ptree_delete_node(picl_nodehdl_t nodeh
)
1978 (void) rw_wrlock(&ptree_rwlock
); /* exclusive wrlock ptree */
1981 err
= lookup_verify_node_handle(nodeh
, &nodep
);
1982 if (err
!= PICL_SUCCESS
) {
1983 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1990 parp
= nodep
->parent_node
;
1992 np
= parp
->child_node
;
1993 if (np
== nodep
) /* first child */
1994 parp
->child_node
= nodep
->sibling_node
;
1996 while ((np
!= NULL
) && (np
->sibling_node
!= nodep
))
1997 np
= np
->sibling_node
;
1999 np
->sibling_node
= nodep
->sibling_node
;
2003 nodep
->parent_node
= NULL
;
2004 nodep
->sibling_node
= NULL
;
2006 unpiclize_node(nodep
);
2008 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2009 return (PICL_SUCCESS
);
2013 * This function adds a node as a child of another node
2016 ptree_add_node(picl_nodehdl_t parh
, picl_nodehdl_t chdh
)
2023 (void) rw_wrlock(&ptree_rwlock
); /* exclusive lock ptree */
2025 pnodep
= cnodep
= NULL
;
2026 err
= lookup_verify_node_handle(parh
, &pnodep
);
2027 if (err
!= PICL_SUCCESS
) {
2028 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2032 err
= lookup_verify_node_handle(chdh
, &cnodep
);
2033 if (err
!= PICL_SUCCESS
) {
2034 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2038 /* is chdh already a child? */
2039 if (cnodep
->parent_node
!= NULL
) {
2040 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2041 return (PICL_CANTPARENT
);
2045 * append child to children list
2047 cnodep
->parent_node
= pnodep
;
2048 if (pnodep
->child_node
== NULL
)
2049 pnodep
->child_node
= cnodep
;
2051 for (nodep
= pnodep
->child_node
; nodep
->sibling_node
!= NULL
;
2052 nodep
= nodep
->sibling_node
)
2054 nodep
->sibling_node
= cnodep
;
2059 if (IS_PICLIZED(pnodep
))
2060 piclize_node(cnodep
);
2061 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2062 return (PICL_SUCCESS
);
2066 copy_propinfo_ver_1(ptree_propinfo_t
*pinfo
, picl_obj_t
*propp
)
2068 pinfo
->version
= propp
->pinfo_ver
;
2069 pinfo
->piclinfo
.type
= propp
->prop_type
;
2070 pinfo
->piclinfo
.accessmode
= propp
->prop_mode
;
2071 pinfo
->piclinfo
.size
= propp
->prop_size
;
2072 (void) strcpy(pinfo
->piclinfo
.name
, propp
->prop_name
);
2073 pinfo
->read
= propp
->read_func
;
2074 pinfo
->write
= propp
->write_func
;
2078 copy_reserved_propinfo_ver_1(ptree_propinfo_t
*pinfo
, const char *pname
)
2080 pinfo
->version
= PTREE_PROPINFO_VERSION_1
;
2081 pinfo
->piclinfo
.type
= PICL_PTYPE_REFERENCE
;
2082 pinfo
->piclinfo
.accessmode
= PICL_READ
;
2083 pinfo
->piclinfo
.size
= sizeof (picl_nodehdl_t
);
2084 (void) strcpy(pinfo
->piclinfo
.name
, pname
);
2086 pinfo
->write
= NULL
;
2090 * This function returns the property information to a plug-in
2093 ptree_get_propinfo(picl_prophdl_t proph
, ptree_propinfo_t
*pinfo
)
2099 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2100 nodep
= propp
= NULL
;
2101 err
= lookup_and_lock_propnode(RDLOCK_NODE
, proph
, &nodep
, &propp
);
2102 if (err
!= PICL_SUCCESS
) {
2103 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2107 if (propp
->pinfo_ver
== PTREE_PROPINFO_VERSION_1
)
2108 copy_propinfo_ver_1(pinfo
, propp
);
2112 unlock_node(nodep
); /* unlock node */
2113 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2118 * This function returns the property information to a plug-in
2121 xptree_get_propinfo_by_name(picl_nodehdl_t nodeh
, const char *pname
,
2122 ptree_propinfo_t
*pinfo
)
2128 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2129 nodep
= propp
= NULL
;
2130 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2131 if (err
!= PICL_SUCCESS
) {
2132 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2136 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2137 if (err
!= PICL_SUCCESS
) {
2139 (void) rw_unlock(&ptree_rwlock
);
2143 if (picl_restricted(pname
))
2144 copy_reserved_propinfo_ver_1(pinfo
, pname
);
2145 else if (propp
->pinfo_ver
== PTREE_PROPINFO_VERSION_1
)
2146 copy_propinfo_ver_1(pinfo
, propp
);
2150 unlock_node(nodep
); /* unlock node */
2151 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2156 * This function must be called only after a lookup_prop_by_name() returns
2157 * success and only if picl_restricted() returns true.
2160 read_reserved_propval_and_unlock(picl_obj_t
*nodep
, const char *pname
,
2161 void *vbuf
, size_t size
)
2165 if (size
!= sizeof (picl_nodehdl_t
))
2166 return (PICL_VALUETOOBIG
);
2168 if (strcmp(pname
, PICL_PROP_PARENT
) == 0)
2169 srcp
= &nodep
->parent_node
->ptree_hdl
;
2170 else if (strcmp(pname
, PICL_PROP_CHILD
) == 0)
2171 srcp
= &nodep
->child_node
->ptree_hdl
;
2172 else if (strcmp(pname
, PICL_PROP_PEER
) == 0)
2173 srcp
= &nodep
->sibling_node
->ptree_hdl
;
2175 return (PICL_FAILURE
);
2177 (void) memcpy(vbuf
, srcp
, sizeof (picl_nodehdl_t
));
2179 (void) rw_unlock(&ptree_rwlock
);
2180 return (PICL_SUCCESS
);
2184 * Returns the property value in the buffer and releases the node and
2186 * For volatile properties, this function releases the locks on ptree
2187 * table and the node before calling the plug-in provided access function
2190 read_propval_and_unlock(picl_obj_t
*nodep
, picl_obj_t
*propp
, void *vbuf
,
2194 int (*volrd
)(ptree_rarg_t
*arg
, void *buf
);
2197 if (propp
->prop_mode
& PICL_VOLATILE
) {
2201 rarg
.nodeh
= nodep
->ptree_hdl
;
2203 rarg
.nodeh
= PICL_INVALID_PICLHDL
;
2204 rarg
.proph
= propp
->ptree_hdl
;
2206 volrd
= propp
->read_func
;
2208 unlock_node(nodep
); /* unlock node */
2209 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2214 err
= (volrd
)(&rarg
, vbuf
);
2216 } else if (propp
->prop_type
== PICL_PTYPE_CHARSTRING
)
2217 (void) strlcpy(vbuf
, propp
->prop_val
, propp
->prop_size
);
2219 (void) memcpy(vbuf
, propp
->prop_val
, propp
->prop_size
);
2222 (void) rw_unlock(&ptree_rwlock
);
2227 xptree_get_propval_with_cred(picl_prophdl_t proph
, void *vbuf
, size_t size
,
2234 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2235 nodep
= propp
= NULL
;
2236 err
= lookup_and_lock_propnode(RDLOCK_NODE
, proph
, &nodep
, &propp
);
2237 if (err
!= PICL_SUCCESS
) {
2238 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2242 err
= check_propsize(PROP_READ
, propp
, size
);
2243 if (err
!= PICL_SUCCESS
) {
2244 unlock_node(nodep
); /* unlock node */
2245 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2249 return (read_propval_and_unlock(nodep
, propp
, vbuf
, cred
));
2253 * This function gets the credentials and calls get_propval_with_cred.
2256 ptree_get_propval(picl_prophdl_t proph
, void *vbuf
, size_t size
)
2258 return (xptree_get_propval_with_cred(proph
, vbuf
, size
, picld_cred
));
2262 * This function retrieves a property's value by by its name
2263 * For volatile properties, the locks on ptree and node are released
2264 * before calling the plug-in provided access function
2267 xptree_get_propval_by_name_with_cred(picl_nodehdl_t nodeh
, const char *pname
,
2268 void *vbuf
, size_t size
, door_cred_t cred
)
2274 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2277 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2278 if (err
!= PICL_SUCCESS
) {
2279 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2283 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2284 if (err
!= PICL_SUCCESS
) {
2286 (void) rw_unlock(&ptree_rwlock
);
2290 if (picl_restricted(pname
))
2291 return (read_reserved_propval_and_unlock(nodep
, pname
, vbuf
,
2294 err
= check_propsize(PROP_READ
, propp
, size
);
2295 if (err
!= PICL_SUCCESS
) {
2297 (void) rw_unlock(&ptree_rwlock
);
2301 return (read_propval_and_unlock(nodep
, propp
, vbuf
, cred
));
2305 * This function is used by plugins to get a value of a property
2306 * looking it up by its name.
2309 ptree_get_propval_by_name(picl_nodehdl_t nodeh
, const char *pname
, void *vbuf
,
2312 return (xptree_get_propval_by_name_with_cred(nodeh
, pname
, vbuf
, size
,
2317 * This function updates a property's value.
2318 * For volatile properties, the locks on the node and the ptree table
2319 * are released before calling the plug-in provided access function.
2322 write_propval_and_unlock(picl_obj_t
*nodep
, picl_obj_t
*propp
, const void *vbuf
,
2323 size_t size
, door_cred_t cred
)
2326 int (*volwr
)(ptree_warg_t
*arg
, const void *buf
);
2329 if (propp
->prop_mode
& PICL_VOLATILE
) {
2333 warg
.nodeh
= nodep
->ptree_hdl
;
2335 warg
.nodeh
= PICL_INVALID_PICLHDL
;
2336 warg
.proph
= propp
->ptree_hdl
;
2338 volwr
= propp
->write_func
;
2340 unlock_node(nodep
); /* unlock node */
2341 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2346 err
= (volwr
)(&warg
, vbuf
);
2349 (void) memcpy(propp
->prop_val
, vbuf
, size
);
2351 unlock_node(nodep
); /* unlock node */
2352 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2357 xptree_update_propval_with_cred(picl_prophdl_t proph
, const void *vbuf
,
2358 size_t size
, door_cred_t cred
)
2364 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2365 nodep
= propp
= NULL
;
2366 err
= lookup_and_lock_propnode(WRLOCK_NODE
, proph
, &nodep
, &propp
);
2367 if (err
!= PICL_SUCCESS
) {
2368 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2372 err
= check_propsize(PROP_WRITE
, propp
, size
);
2373 if (err
!= PICL_SUCCESS
) {
2374 unlock_node(nodep
); /* unlock node */
2375 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2379 return (write_propval_and_unlock(nodep
, propp
, vbuf
, size
, cred
));
2383 * Ptree function used by plug-ins to update a property's value
2384 * calls update_propval_with_cred(), which releases locks for volatile props
2387 ptree_update_propval(picl_prophdl_t proph
, const void *vbuf
, size_t size
)
2389 return (xptree_update_propval_with_cred(proph
, vbuf
, size
, picld_cred
));
2393 * This function writes/updates a property's value by looking it up
2395 * For volatile properties this function releases the locks on the
2396 * node and the ptree table.
2399 xptree_update_propval_by_name_with_cred(picl_nodehdl_t nodeh
, const char *pname
,
2400 const void *vbuf
, size_t size
, door_cred_t cred
)
2406 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2408 err
= lookup_and_lock_node(WRLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2409 if (err
!= PICL_SUCCESS
) {
2410 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2414 if (picl_restricted(pname
)) {
2416 (void) rw_unlock(&ptree_rwlock
);
2417 return (PICL_RESERVEDNAME
);
2420 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2421 if (err
!= PICL_SUCCESS
) {
2423 (void) rw_unlock(&ptree_rwlock
);
2427 err
= check_propsize(PROP_WRITE
, propp
, size
);
2428 if (err
!= PICL_SUCCESS
) {
2430 (void) rw_unlock(&ptree_rwlock
);
2434 return (write_propval_and_unlock(nodep
, propp
, vbuf
, size
, cred
));
2438 * This function updates the value of a property specified by its name
2441 ptree_update_propval_by_name(picl_nodehdl_t nodeh
, const char *pname
,
2442 const void *vbuf
, size_t size
)
2444 return (xptree_update_propval_by_name_with_cred(nodeh
, pname
, vbuf
,
2449 * This function retrieves the handle of a property by its name
2452 ptree_get_prop_by_name(picl_nodehdl_t nodeh
, const char *pname
,
2453 picl_prophdl_t
*proph
)
2459 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2461 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2462 if (err
!= PICL_SUCCESS
) {
2463 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2467 if (picl_restricted(pname
)) {
2468 err
= PICL_RESERVEDNAME
;
2469 unlock_node(nodep
); /* unlock node */
2470 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2474 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2475 if (err
== PICL_SUCCESS
)
2476 *proph
= propp
->ptree_hdl
;
2478 unlock_node(nodep
); /* unlock node */
2479 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2484 * This function returns the handle of the first property
2487 ptree_get_first_prop(picl_nodehdl_t nodeh
, picl_prophdl_t
*proph
)
2492 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2494 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &pobj
); /* lock node */
2495 if (err
!= PICL_SUCCESS
) {
2496 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2500 if (pobj
->first_prop
)
2501 *proph
= pobj
->first_prop
->ptree_hdl
;
2503 err
= PICL_ENDOFLIST
;
2505 unlock_node(pobj
); /* unlock node */
2506 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2511 * This function returns the handle of next property in the list
2514 ptree_get_next_prop(picl_prophdl_t proph
, picl_prophdl_t
*nextproph
)
2520 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2521 nodep
= propp
= NULL
;
2522 err
= lookup_and_lock_propnode(RDLOCK_NODE
, proph
, &nodep
, &propp
);
2523 if (err
!= PICL_SUCCESS
) {
2524 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2528 if (propp
->next_prop
) {
2529 *nextproph
= propp
->next_prop
->ptree_hdl
;
2531 err
= PICL_ENDOFLIST
;
2533 unlock_node(nodep
); /* unlock node */
2534 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2539 * These functions are called by ptree_get_node_by_path()
2540 * Append a prop expression entry to the list
2542 static prop_list_t
*
2543 append_entry_to_list(prop_list_t
*el
, prop_list_t
*list
)
2556 * Add it to the end of list
2560 while (ptr
->next
!= NULL
)
2569 * Free the property expression list
2572 free_list(prop_list_t
*list
)
2577 for (ptr
= list
; ptr
!= NULL
; ptr
= tmp
) {
2584 parse_prl(char *prl
, char **name
, char **baddr
, prop_list_t
**plist
)
2593 return (PICL_FAILURE
);
2595 if ((prl
[0] == '@') || (prl
[0] == '?'))
2596 return (PICL_FAILURE
);
2601 * get property expression
2603 ptr
= strchr(prl
, '?');
2614 ptr
= strchr(prl
, '@');
2619 if (strlen(*baddr
) == 0) /* no bus value after @ */
2620 return (PICL_FAILURE
);
2624 * create the prop list
2626 while (propptr
!= NULL
) {
2630 ptr
= strchr(propptr
, '?');
2632 if (ptr
!= NULL
) { /* more ?<prop>=<propval> */
2638 if (strlen(pname
) == 0) /* no prop exp after ? */
2639 return (PICL_FAILURE
);
2641 ptr
= strchr(pname
, '=');
2642 if (ptr
!= NULL
) { /* not void prop */
2646 * <prop>= is treated as void property
2648 if (strlen(pval
) == 0)
2652 el
= (prop_list_t
*)malloc(sizeof (prop_list_t
));
2656 *plist
= append_entry_to_list(el
, *plist
);
2659 return (PICL_SUCCESS
);
2663 prop_match(ptree_propinfo_t pinfo
, void *vbuf
, char *val
)
2676 switch (pinfo
.piclinfo
.type
) {
2677 case PICL_PTYPE_CHARSTRING
:
2678 if (strcasecmp(pinfo
.piclinfo
.name
, PICL_PROP_CLASSNAME
) == 0) {
2679 if (strcmp(val
, PICL_CLASS_PICL
) == 0)
2682 if (strcmp(val
, (char *)vbuf
) == 0)
2686 case PICL_PTYPE_INT
:
2687 switch (pinfo
.piclinfo
.size
) {
2688 case sizeof (int8_t):
2689 cval
= (int8_t)strtol(val
, (char **)NULL
, 0);
2690 return (cval
== *(char *)vbuf
);
2691 case sizeof (int16_t):
2692 sval
= (int16_t)strtol(val
, (char **)NULL
, 0);
2693 return (sval
== *(int16_t *)vbuf
);
2694 case sizeof (int32_t):
2695 intval
= (int32_t)strtol(val
, (char **)NULL
, 0);
2696 return (intval
== *(int32_t *)vbuf
);
2697 case sizeof (int64_t):
2698 llval
= strtoll(val
, (char **)NULL
, 0);
2699 return (llval
== *(int64_t *)vbuf
);
2703 case PICL_PTYPE_UNSIGNED_INT
:
2704 switch (pinfo
.piclinfo
.size
) {
2705 case sizeof (uint8_t):
2706 ucval
= (uint8_t)strtoul(val
, (char **)NULL
, 0);
2707 return (ucval
== *(uint8_t *)vbuf
);
2708 case sizeof (uint16_t):
2709 usval
= (uint16_t)strtoul(val
, (char **)NULL
, 0);
2710 return (usval
== *(uint16_t *)vbuf
);
2711 case sizeof (uint32_t):
2712 uintval
= (uint32_t)strtoul(val
, (char **)NULL
, 0);
2713 return (uintval
== *(uint32_t *)vbuf
);
2714 case sizeof (uint64_t):
2715 ullval
= strtoull(val
, (char **)NULL
, 0);
2716 return (ullval
== *(uint64_t *)vbuf
);
2720 case PICL_PTYPE_FLOAT
:
2721 switch (pinfo
.piclinfo
.size
) {
2722 case sizeof (float):
2723 fval
= (float)strtod(val
, (char **)NULL
);
2724 return (fval
== *(float *)vbuf
);
2725 case sizeof (double):
2726 dval
= strtod(val
, (char **)NULL
);
2727 return (dval
== *(double *)vbuf
);
2731 case PICL_PTYPE_VOID
:
2732 case PICL_PTYPE_TIMESTAMP
:
2733 case PICL_PTYPE_TABLE
:
2734 case PICL_PTYPE_REFERENCE
:
2735 case PICL_PTYPE_BYTEARRAY
:
2736 case PICL_PTYPE_UNKNOWN
:
2743 check_propval(picl_nodehdl_t nodeh
, char *pname
, char *pval
)
2746 picl_prophdl_t proph
;
2747 ptree_propinfo_t pinfo
;
2750 err
= ptree_get_prop_by_name(nodeh
, pname
, &proph
);
2751 if (err
!= PICL_SUCCESS
)
2754 err
= ptree_get_propinfo(proph
, &pinfo
);
2755 if (err
!= PICL_SUCCESS
)
2758 if (pval
== NULL
) { /* void type */
2759 if (pinfo
.piclinfo
.type
!= PICL_PTYPE_VOID
)
2760 return (PICL_FAILURE
);
2762 vbuf
= alloca(pinfo
.piclinfo
.size
);
2764 return (PICL_FAILURE
);
2765 err
= ptree_get_propval(proph
, vbuf
,
2766 pinfo
.piclinfo
.size
);
2767 if (err
!= PICL_SUCCESS
)
2770 if (!prop_match(pinfo
, vbuf
, pval
))
2771 return (PICL_FAILURE
);
2773 return (PICL_SUCCESS
);
2777 get_child_by_path(picl_nodehdl_t rooth
, char *prl
,
2778 picl_nodehdl_t
*nodeh
, char *pname
)
2780 picl_nodehdl_t chdh
;
2791 return (PICL_FAILURE
);
2793 path
= strdupa(prl
);
2795 return (PICL_FAILURE
);
2801 err
= parse_prl(path
, &nodename
, &baddr
, &plist
);
2802 if (err
!= PICL_SUCCESS
) {
2807 if (nodename
== NULL
)
2808 return (PICL_FAILURE
);
2810 nameval
= alloca(strlen(nodename
) + 1);
2811 if (nameval
== NULL
) {
2813 return (PICL_FAILURE
);
2816 if (baddr
!= NULL
) {
2817 busval
= alloca(strlen(baddr
) + 1);
2818 if (busval
== NULL
) {
2820 return (PICL_FAILURE
);
2824 for (err
= ptree_get_propval_by_name(rooth
, PICL_PROP_CHILD
, &chdh
,
2825 sizeof (picl_nodehdl_t
)); err
!= PICL_PROPNOTFOUND
;
2826 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
2827 sizeof (picl_nodehdl_t
))) {
2828 if (err
!= PICL_SUCCESS
) {
2830 return (PICL_FAILURE
);
2836 if ((strcmp(pname
, PICL_PROP_CLASSNAME
) != 0) ||
2837 (strcmp(nodename
, PICL_CLASS_PICL
) != 0)) {
2838 err
= ptree_get_propval_by_name(chdh
, pname
,
2839 nameval
, (strlen(nodename
) + 1));
2841 if (err
!= PICL_SUCCESS
)
2843 if (strcmp(nameval
, nodename
) != 0)
2848 * compare device address with bus-addr prop first
2849 * then with UnitAddress property
2851 if (baddr
!= NULL
) { /* compare bus-addr prop */
2852 if ((ptree_get_propval_by_name(chdh
, PICL_PROP_BUS_ADDR
,
2853 busval
, (strlen(baddr
) + 1)) != PICL_SUCCESS
) &&
2854 (ptree_get_propval_by_name(chdh
,
2855 PICL_PROP_UNIT_ADDRESS
, busval
,
2856 (strlen(baddr
) + 1)) != PICL_SUCCESS
))
2859 if (strcmp(busval
, baddr
) != 0)
2860 continue; /* not match */
2863 if (plist
== NULL
) { /* no prop expression */
2865 return (PICL_SUCCESS
);
2869 * compare the property expression list
2873 while (ptr
!= NULL
) {
2874 err
= check_propval(chdh
, ptr
->pname
, ptr
->pval
);
2875 if (err
!= PICL_SUCCESS
)
2883 return (PICL_SUCCESS
);
2887 return (PICL_NOTNODE
);
2891 * This functions returns the handle of node specified by its path
2894 ptree_get_node_by_path(const char *piclprl
, picl_nodehdl_t
*handle
)
2896 picl_nodehdl_t rooth
;
2897 picl_nodehdl_t chdh
;
2904 int npflg
; /* namepath flag */
2907 path
= strdupa(piclprl
);
2909 return (PICL_FAILURE
);
2911 npflg
= 1; /* default */
2913 if (path
[0] == '/') {
2915 } else if ((tokindex
= strchr(path
, ':')) != NULL
) {
2918 if (*tokindex
== '/')
2921 return (PICL_NOTNODE
);
2924 return (PICL_NOTNODE
);
2926 err
= ptree_get_root(&rooth
);
2927 if (err
!= PICL_SUCCESS
)
2930 for (chdh
= rooth
, tokindex
= strchr(ptr
, '/');
2932 ptr
= tokindex
+ 1, tokindex
= strchr(ptr
, '/')) {
2935 err
= get_child_by_path(chdh
, ptr
, &chdh
,
2938 err
= get_child_by_path(chdh
, ptr
, &chdh
,
2941 if (err
!= PICL_SUCCESS
)
2946 * check if last token is empty or not
2947 * eg. /a/b/c/ or /a/b/c
2951 return (PICL_SUCCESS
);
2954 len
= strcspn(ptr
, " \t\n");
2957 return (PICL_SUCCESS
);
2962 err
= get_child_by_path(chdh
, ptr
, &chdh
, PICL_PROP_NAME
);
2964 err
= get_child_by_path(chdh
, ptr
, &chdh
, defprop
);
2966 if (err
!= PICL_SUCCESS
)
2970 return (PICL_SUCCESS
);
2974 * Initialize propinfo
2977 ptree_init_propinfo(ptree_propinfo_t
*infop
, int version
, int ptype
, int pmode
,
2978 size_t psize
, char *pname
, int (*readfn
)(ptree_rarg_t
*, void *),
2979 int (*writefn
)(ptree_warg_t
*, const void *))
2981 if (version
!= PTREE_PROPINFO_VERSION_1
)
2982 return (PICL_NOTSUPPORTED
);
2983 if ((infop
== NULL
) || (pname
== NULL
))
2984 return (PICL_INVALIDARG
);
2985 infop
->version
= version
;
2986 infop
->piclinfo
.type
= ptype
;
2987 infop
->piclinfo
.accessmode
= pmode
;
2988 infop
->piclinfo
.size
= psize
;
2989 infop
->read
= readfn
;
2990 infop
->write
= writefn
;
2991 (void) strlcpy(infop
->piclinfo
.name
, pname
, PICL_PROPNAMELEN_MAX
);
2992 return (PICL_SUCCESS
);
2996 * Creates a property, adds it to the node, and returns the property
2997 * handle to the caller if successful and proph is not NULL
3000 ptree_create_and_add_prop(picl_nodehdl_t nodeh
, ptree_propinfo_t
*infop
,
3001 void *vbuf
, picl_prophdl_t
*proph
)
3004 picl_prophdl_t tmph
;
3006 err
= ptree_create_prop(infop
, vbuf
, &tmph
);
3007 if (err
!= PICL_SUCCESS
)
3009 err
= ptree_add_prop(nodeh
, tmph
);
3010 if (err
!= PICL_SUCCESS
) {
3011 (void) ptree_destroy_prop(tmph
);
3016 return (PICL_SUCCESS
);
3020 * Creates a node, adds it to its parent node, and returns the node
3021 * handle to the caller if successful
3024 ptree_create_and_add_node(picl_nodehdl_t rooth
, const char *name
,
3025 const char *classname
, picl_nodehdl_t
*nodeh
)
3027 picl_nodehdl_t tmph
;
3030 err
= ptree_create_node(name
, classname
, &tmph
);
3032 if (err
!= PICL_SUCCESS
)
3035 err
= ptree_add_node(rooth
, tmph
);
3036 if (err
!= PICL_SUCCESS
) {
3037 (void) ptree_destroy_node(tmph
);
3042 return (PICL_SUCCESS
);
3047 * recursively visit all nodes
3050 do_walk(picl_nodehdl_t rooth
, const char *classname
,
3051 void *c_args
, int (*callback_fn
)(picl_nodehdl_t hdl
, void *args
))
3054 picl_nodehdl_t chdh
;
3055 char classval
[PICL_CLASSNAMELEN_MAX
];
3057 err
= ptree_get_propval_by_name(rooth
, PICL_PROP_CHILD
, &chdh
,
3059 while (err
== PICL_SUCCESS
) {
3060 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_CLASSNAME
,
3061 classval
, sizeof (classval
));
3062 if (err
!= PICL_SUCCESS
)
3065 if ((classname
== NULL
) || (strcmp(classname
, classval
) == 0)) {
3066 err
= callback_fn(chdh
, c_args
);
3067 if (err
!= PICL_WALK_CONTINUE
)
3071 if ((err
= do_walk(chdh
, classname
, c_args
, callback_fn
)) !=
3075 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
3078 if (err
== PICL_PROPNOTFOUND
) /* end of a branch */
3079 return (PICL_WALK_CONTINUE
);
3085 * This function visits all the nodes in the subtree rooted at <rooth>.
3086 * For each node that matches the class name specified, the callback
3087 * function is invoked.
3090 ptree_walk_tree_by_class(picl_nodehdl_t rooth
, const char *classname
,
3091 void *c_args
, int (*callback_fn
)(picl_nodehdl_t hdl
, void *args
))
3095 if (callback_fn
== NULL
)
3096 return (PICL_INVALIDARG
);
3097 err
= do_walk(rooth
, classname
, c_args
, callback_fn
);
3098 if ((err
== PICL_WALK_CONTINUE
) || (err
== PICL_WALK_TERMINATE
))
3099 return (PICL_SUCCESS
);
3104 compare_propval(picl_nodehdl_t nodeh
, char *pname
, picl_prop_type_t ptype
,
3105 void *pval
, size_t valsize
)
3108 picl_prophdl_t proph
;
3109 ptree_propinfo_t propinfo
;
3112 err
= ptree_get_prop_by_name(nodeh
, pname
, &proph
);
3113 if (err
!= PICL_SUCCESS
)
3115 err
= ptree_get_propinfo(proph
, &propinfo
);
3116 if (err
!= PICL_SUCCESS
)
3118 if (propinfo
.piclinfo
.type
!= ptype
)
3120 if (propinfo
.piclinfo
.type
== PICL_PTYPE_VOID
)
3124 if (valsize
> propinfo
.piclinfo
.size
)
3126 vbuf
= alloca(propinfo
.piclinfo
.size
);
3129 err
= ptree_get_propval(proph
, vbuf
, propinfo
.piclinfo
.size
);
3130 if (err
!= PICL_SUCCESS
)
3132 if (memcmp(vbuf
, pval
, valsize
) == 0)
3139 * This function traverses the subtree and finds a node that has a property
3140 * of the specified name and type with the specified value.
3141 * The matched node in the tree is returned in retnodeh. If there is
3142 * no node with that property, then PICL_NODENOTFOUND is returned.
3145 ptree_find_node(picl_nodehdl_t rooth
, char *pname
, picl_prop_type_t ptype
,
3146 void *pval
, size_t valsize
, picl_nodehdl_t
*retnodeh
)
3149 picl_nodehdl_t chdh
;
3152 return (PICL_INVALIDARG
);
3153 err
= ptree_get_propval_by_name(rooth
, PICL_PROP_CHILD
, &chdh
,
3156 while (err
== PICL_SUCCESS
) {
3157 if (compare_propval(chdh
, pname
, ptype
, pval
, valsize
)) {
3160 return (PICL_SUCCESS
);
3163 err
= ptree_find_node(chdh
, pname
, ptype
, pval
, valsize
,
3165 if (err
!= PICL_NODENOTFOUND
)
3168 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
3171 if (err
== PICL_PROPNOTFOUND
)
3172 return (PICL_NODENOTFOUND
);
3177 * This function gets the frutree parent for a given node.
3178 * Traverse up the tree and look for the following properties:
3179 * Frutree parent reference properties:
3183 * If the frutree reference property is found, return its value.
3184 * Else, return the handle of /frutree/chassis.
3187 ptree_get_frutree_parent(picl_nodehdl_t nodeh
, picl_nodehdl_t
*fruh
)
3190 picl_nodehdl_t nparh
;
3191 picl_nodehdl_t fruparh
;
3195 while (err
== PICL_SUCCESS
) {
3196 err
= ptree_get_propval_by_name(nparh
, PICL_REFPROP_FRU_PARENT
,
3197 &fruparh
, sizeof (fruparh
));
3198 if (err
== PICL_SUCCESS
) {
3200 return (PICL_SUCCESS
);
3202 err
= ptree_get_propval_by_name(nparh
,
3203 PICL_REFPROP_LOC_PARENT
, &fruparh
, sizeof (fruparh
));
3204 if (err
== PICL_SUCCESS
) {
3206 return (PICL_SUCCESS
);
3208 err
= ptree_get_propval_by_name(nparh
, PICL_REFPROP_PORT_PARENT
,
3209 &fruparh
, sizeof (fruparh
));
3210 if (err
== PICL_SUCCESS
) {
3212 return (PICL_SUCCESS
);
3215 err
= ptree_get_propval_by_name(nparh
, PICL_PROP_PARENT
, &nparh
,
3219 if (err
== PICL_PROPNOTFOUND
) { /* return /frutree/chassis handle */
3220 err
= ptree_get_node_by_path(PICL_FRUTREE_CHASSIS
, &fruparh
);
3221 if (err
== PICL_SUCCESS
) {
3223 return (PICL_SUCCESS
);
3230 * This function is called by plug-ins to register with the daemon
3233 picld_plugin_register(picld_plugin_reg_t
*regp
)
3235 picld_plugin_reg_list_t
*el
;
3236 picld_plugin_reg_list_t
*tmp
;
3239 return (PICL_FAILURE
);
3241 if (regp
->version
!= PICLD_PLUGIN_VERSION_1
)
3242 return (PICL_NOTSUPPORTED
);
3244 el
= malloc(sizeof (picld_plugin_reg_list_t
));
3246 return (PICL_FAILURE
);
3247 el
->reg
.version
= regp
->version
;
3248 el
->reg
.critical
= regp
->critical
;
3250 el
->reg
.name
= strdup(regp
->name
);
3251 if (el
->reg
.name
== NULL
)
3252 return (PICL_FAILURE
);
3254 el
->reg
.plugin_init
= regp
->plugin_init
;
3255 el
->reg
.plugin_fini
= regp
->plugin_fini
;
3258 if (plugin_reg_list
== NULL
) {
3259 plugin_reg_list
= el
;
3260 } else { /* add to end */
3261 tmp
= plugin_reg_list
;
3262 while (tmp
->next
!= NULL
)
3267 return (PICL_SUCCESS
);
3271 * Call fini routines of the registered plugins
3274 plugin_fini(picld_plugin_reg_list_t
*p
)
3279 plugin_fini(p
->next
);
3280 if (p
->reg
.plugin_fini
)
3281 (p
->reg
.plugin_fini
)();
3289 init_plugin_reg_list(void)
3291 plugin_reg_list
= NULL
;
3295 picltree_set_root(picl_nodehdl_t rooth
)
3300 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
3302 err
= lookup_and_lock_node(RDLOCK_NODE
, rooth
, &pobj
); /* lock node */
3303 if (err
!= PICL_SUCCESS
) {
3304 (void) rw_unlock(&ptree_rwlock
);
3305 return (PICL_FAILURE
);
3308 picl_root_obj
= pobj
;
3309 ptree_root_hdl
= pobj
->ptree_hdl
;
3310 unlock_node(pobj
); /* unlock node */
3311 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
3312 return (PICL_SUCCESS
);
3318 (void) rwlock_init(&ptree_rwlock
, USYNC_THREAD
, NULL
);
3319 (void) rwlock_init(&picltbl_rwlock
, USYNC_THREAD
, NULL
);
3321 if (hash_init(&picltbl
) < 0)
3322 return (PICL_FAILURE
);
3323 if (hash_init(&ptreetbl
) < 0)
3324 return (PICL_FAILURE
);
3326 if (pthread_mutex_init(&ptreehdl_lock
, NULL
) != 0)
3327 return (PICL_FAILURE
);
3329 if (pthread_mutex_init(&piclhdl_lock
, NULL
) != 0)
3330 return (PICL_FAILURE
);
3332 if (pthread_mutex_init(&evtq_lock
, NULL
) != 0)
3333 return (PICL_FAILURE
);
3334 if (pthread_cond_init(&evtq_cv
, NULL
) != 0)
3335 return (PICL_FAILURE
);
3336 if (pthread_mutex_init(&evthandler_lock
, NULL
) != 0)
3337 return (PICL_FAILURE
);
3339 picl_root_obj
= NULL
;
3341 evt_handlers
= NULL
;
3342 ptree_root_hdl
= PICL_INVALID_PICLHDL
;
3344 return (PICL_SUCCESS
);
3348 add_unique_plugin_to_list(char *path
, char *name
)
3351 picld_plugin_desc_t
*pl
;
3352 picld_plugin_desc_t
*tmp
;
3355 while (pl
!= NULL
) {
3356 if (strcmp(pl
->libname
, name
) == 0)
3362 pl
= malloc(sizeof (picld_plugin_desc_t
));
3366 pl
->libname
= strdup(name
);
3367 if (pl
->libname
== NULL
)
3369 buf
= alloca(strlen(name
) + strlen(path
) + 2);
3372 (void) strcpy(buf
, path
);
3373 (void) strcat(buf
, name
);
3374 pl
->pathname
= strdup(buf
);
3375 if (pl
->pathname
== NULL
)
3380 if (plugin_desc
== NULL
)
3384 while (tmp
->next
!= NULL
)
3391 get_plugins_from_dir(char *dirname
)
3396 int solen
= strlen(SO_VERS
) + 1;
3398 if ((dir
= opendir(dirname
)) == NULL
)
3401 while ((ent
= readdir(dir
)) != NULL
) {
3402 if ((strcmp(ent
->d_name
, ".") == 0) ||
3403 (strcmp(ent
->d_name
, "..") == 0))
3406 len
= strlen(ent
->d_name
) + 1;
3410 if (strcmp(ent
->d_name
+ (len
- solen
), SO_VERS
) == 0)
3411 add_unique_plugin_to_list(dirname
, ent
->d_name
);
3414 (void) closedir(dir
);
3419 init_plugin_list(void)
3421 char nmbuf
[SYS_NMLN
];
3422 char pname
[PATH_MAX
];
3425 if (sysinfo(SI_PLATFORM
, nmbuf
, sizeof (nmbuf
)) != -1) {
3426 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
3427 if (access(pname
, R_OK
) == 0)
3428 get_plugins_from_dir(pname
);
3431 if (sysinfo(SI_MACHINE
, nmbuf
, sizeof (nmbuf
)) != -1) {
3432 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
3433 if (access(pname
, R_OK
) == 0)
3434 get_plugins_from_dir(pname
);
3437 (void) snprintf(pname
, PATH_MAX
, "%s/", PICLD_COMMON_PLUGIN_DIR
);
3438 if (access(pname
, R_OK
) == 0)
3439 get_plugins_from_dir(pname
);
3445 picld_plugin_desc_t
*pl
;
3448 while (pl
!= NULL
) {
3449 pl
->dlh
= dlopen(pl
->pathname
, RTLD_LAZY
|RTLD_LOCAL
);
3450 if (pl
->dlh
== NULL
) {
3451 syslog(LOG_CRIT
, dlerror());
3461 add_root_props(picl_nodehdl_t rooth
)
3464 picl_prophdl_t proph
;
3465 ptree_propinfo_t pinfo
;
3468 #define PICL_PROP_PICL_VERSION "PICLVersion"
3469 #define PICL_VERSION 1.1
3471 err
= ptree_init_propinfo(&pinfo
, PTREE_PROPINFO_VERSION_1
,
3472 PICL_PTYPE_FLOAT
, PICL_READ
, sizeof (picl_vers
),
3473 PICL_PROP_PICL_VERSION
, NULL
, NULL
);
3474 if (err
!= PICL_SUCCESS
)
3477 picl_vers
= PICL_VERSION
;
3478 err
= ptree_create_and_add_prop(rooth
, &pinfo
, &picl_vers
, &proph
);
3483 construct_picltree(void)
3486 picld_plugin_reg_list_t
*iter
;
3487 picl_nodehdl_t rhdl
;
3492 if ((err
= ptree_create_node(PICL_NODE_ROOT
, PICL_CLASS_PICL
,
3493 &rhdl
)) != PICL_SUCCESS
) {
3497 if (picltree_set_root(rhdl
) != PICL_SUCCESS
) {
3498 return (PICL_FAILURE
);
3501 err
= add_root_props(rhdl
);
3502 if (err
!= PICL_SUCCESS
)
3506 * Initialize the registered plug-in modules
3508 iter
= plugin_reg_list
;
3509 while (iter
!= NULL
) {
3510 if (iter
->reg
.plugin_init
)
3511 (iter
->reg
.plugin_init
)();
3514 return (PICL_SUCCESS
);
3518 xptree_destroy(void)
3520 dbg_print(1, "xptree_destroy: picl_root_obj = %s\n",
3521 (picl_root_obj
== NULL
? "NULL" : "not-NULL"));
3523 if (picl_root_obj
== NULL
)
3526 dbg_print(1, "xptree_destroy: call plugin_fini\n");
3527 plugin_fini(plugin_reg_list
);
3528 dbg_print(1, "xptree_destroy: plugin_fini DONE\n");
3530 (void) ptree_delete_node(picl_root_obj
->ptree_hdl
);
3531 (void) ptree_destroy_node(picl_root_obj
->ptree_hdl
);
3533 (void) rw_wrlock(&ptree_rwlock
);
3534 picl_root_obj
= NULL
;
3535 (void) rw_unlock(&ptree_rwlock
);
3540 xptree_initialize(int flg
)
3543 pthread_attr_t attr
;
3546 picld_pid
= getpid();
3547 picld_cred
.dc_euid
= geteuid();
3548 picld_cred
.dc_egid
= getegid();
3549 picld_cred
.dc_ruid
= getuid();
3550 picld_cred
.dc_rgid
= getgid();
3551 picld_cred
.dc_pid
= getpid();
3555 ptree_generation
= 1;
3558 if (pthread_mutex_init(&ptree_refresh_mutex
, NULL
) != 0)
3559 return (PICL_FAILURE
);
3561 if (picltree_init() != PICL_SUCCESS
)
3562 return (PICL_FAILURE
);
3564 init_plugin_reg_list();
3568 err
= construct_picltree();
3569 if (err
!= PICL_SUCCESS
)
3573 * Dispatch events after all plug-ins have initialized
3575 if (pthread_attr_init(&attr
) != 0)
3576 return (PICL_FAILURE
);
3578 (void) pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
);
3579 if (pthread_create(&tid
, &attr
, ptree_event_thread
, NULL
))
3580 return (PICL_FAILURE
);
3582 return (PICL_SUCCESS
);
3586 xptree_reinitialize(void)
3591 * Wait for eventq to become empty
3593 dbg_print(1, "xptree_reinitialize: wait for evtq empty\n");
3594 (void) pthread_mutex_lock(&evtq_lock
);
3596 while (eventqp
!= NULL
)
3597 (void) pthread_cond_wait(&evtq_empty
, &evtq_lock
);
3599 (void) pthread_mutex_unlock(&evtq_lock
);
3600 dbg_print(1, "xptree_reinitialize: evtq empty is EMPTY\n");
3602 (void) rw_wrlock(&ptree_rwlock
);
3603 picl_root_obj
= NULL
;
3604 ptree_root_hdl
= PICL_INVALID_PICLHDL
;
3605 (void) rw_unlock(&ptree_rwlock
);
3606 (void) pthread_mutex_lock(&ptree_refresh_mutex
);
3608 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
3610 err
= construct_picltree();
3611 (void) pthread_mutex_lock(&ptree_refresh_mutex
);
3612 (void) pthread_cond_broadcast(&ptree_refresh_cond
);
3613 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
3615 (void) pthread_mutex_lock(&evtq_lock
);
3616 (void) pthread_cond_broadcast(&evtq_cv
);
3617 (void) pthread_mutex_unlock(&evtq_lock
);
3623 * This function is called by the PICL daemon on behalf of clients to
3624 * wait for a tree refresh
3627 xptree_refresh_notify(uint32_t secs
)
3634 if (pthread_mutex_lock(&ptree_refresh_mutex
) != 0)
3635 return (PICL_FAILURE
);
3637 curgen
= ptree_generation
;
3639 while (curgen
== ptree_generation
) {
3640 if (secs
== UINT32_MAX
) /* wait forever */
3641 (void) pthread_cond_wait(&ptree_refresh_cond
,
3642 &ptree_refresh_mutex
);
3646 ret
= pthread_cond_reltimedwait_np(
3647 &ptree_refresh_cond
,
3648 &ptree_refresh_mutex
, &to
);
3649 if (ret
== ETIMEDOUT
)
3654 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
3657 return (PICL_SUCCESS
);
3662 dbg_print(int level
, const char *fmt
, ...)
3664 if (verbose_level
>= level
) {
3668 (void) vprintf(fmt
, ap
);
3675 dbg_exec(int level
, void (*fn
)(void *args
), void *args
)
3677 if (verbose_level
> level
)