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
)
176 (void) pthread_cond_broadcast(&evhp
->cv
);
177 (void) pthread_cond_destroy(&evhp
->cv
);
183 * queue_event to events queue
186 queue_event(eventq_t
*evt
)
195 while (tmpp
->next
!= NULL
)
202 * unqueue_event from the specified eventq
205 unqueue_event(eventq_t
**qp
)
216 * register an event handler by adding it to the list
219 ptree_register_handler(const char *ename
,
220 void (*evt_handler
)(const char *ename
, const void *earg
, size_t size
,
221 void *cookie
), void *cookie
)
227 return (PICL_INVALIDARG
);
230 * Initialize event handler entry
232 ent
= malloc(sizeof (*ent
));
234 return (PICL_FAILURE
);
235 ent
->ename
= strdup(ename
);
236 if (ent
->ename
== NULL
) {
238 return (PICL_FAILURE
);
240 ent
->cookie
= cookie
;
241 ent
->evt_handler
= evt_handler
;
244 (void) pthread_cond_init(&ent
->cv
, NULL
);
248 * add handler to the handler list
250 (void) pthread_mutex_lock(&evthandler_lock
);
251 if (evt_handlers
== NULL
) {
253 (void) pthread_mutex_unlock(&evthandler_lock
);
254 return (PICL_SUCCESS
);
257 while (iter
->next
!= NULL
)
260 (void) pthread_mutex_unlock(&evthandler_lock
);
262 return (PICL_SUCCESS
);
269 ptree_unregister_handler(const char *ename
,
270 void (*evt_handler
)(const char *ename
, const void *earg
, size_t size
,
271 void *cookie
), void *cookie
)
273 evt_handler_t
*evhdlrp
, **evhdlrpp
;
279 * unlink handler from handler list
281 (void) pthread_mutex_lock(&evthandler_lock
);
284 for (evhdlrpp
= &evt_handlers
; (evhdlrp
= *evhdlrpp
) != NULL
;
285 evhdlrpp
= &evhdlrp
->next
) {
286 if ((evhdlrp
->cookie
!= cookie
) ||
287 (strcmp(evhdlrp
->ename
, ename
) != 0) ||
288 (evhdlrp
->evt_handler
!= evt_handler
))
292 * If the handler is in execution, release the lock
293 * and wait for it to complete and retry.
295 if (evhdlrp
->execflg
) {
296 evhdlrp
->wakeupflg
= 1;
297 (void) pthread_cond_wait(&evhdlrp
->cv
,
303 * Unlink this handler from the linked list
305 *evhdlrpp
= evhdlrp
->next
;
306 free_handler(evhdlrp
);
310 (void) pthread_mutex_unlock(&evthandler_lock
);
314 * Call all registered handlers for the event
317 call_event_handlers(eventq_t
*ev
)
320 void (*evhandler
)(const char *, const void *, size_t, void *);
321 void (*completion_handler
)(char *ename
, void *earg
, size_t size
);
323 (void) pthread_mutex_lock(&evthandler_lock
);
325 while (iter
!= NULL
) {
326 if (strcmp(iter
->ename
, ev
->ename
) == 0) {
327 evhandler
= iter
->evt_handler
;
329 (void) pthread_mutex_unlock(&evthandler_lock
);
331 dbg_print(2, "ptree_evthr: Invoking evthdlr:%p"
332 " ename:%s\n", evhandler
, ev
->ename
);
333 (*evhandler
)(ev
->ename
, ev
->earg
, ev
->size
,
335 dbg_print(2, "ptree_evthr: done evthdlr:%p "
336 "ename:%s\n", evhandler
, ev
->ename
);
338 (void) pthread_mutex_lock(&evthandler_lock
);
340 if (iter
->wakeupflg
) {
342 (void) pthread_cond_broadcast(&iter
->cv
);
347 (void) pthread_mutex_unlock(&evthandler_lock
);
348 if ((completion_handler
= ev
->completion_handler
) != NULL
) {
350 "ptree_evthr: Invoking completion hdlr:%p ename:%s\n",
351 completion_handler
, ev
->ename
);
352 (*completion_handler
)((char *)ev
->ename
, (void *)ev
->earg
,
354 dbg_print(2, "ptree_evthr: done completion hdlr:%p ename:%s\n",
355 completion_handler
, ev
->ename
);
357 (void) pthread_mutex_lock(&ptree_refresh_mutex
);
359 (void) pthread_cond_broadcast(&ptree_refresh_cond
);
360 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
364 * This function is called by a plug-in to post an event
367 ptree_post_event(const char *ename
, const void *earg
, size_t size
,
368 void (*completion_handler
)(char *ename
, void *earg
, size_t size
))
373 return (PICL_INVALIDARG
);
375 evt
= malloc(sizeof (*evt
));
377 return (PICL_FAILURE
);
381 evt
->completion_handler
= completion_handler
;
383 (void) pthread_mutex_lock(&evtq_lock
);
385 (void) pthread_cond_broadcast(&evtq_cv
);
386 (void) pthread_mutex_unlock(&evtq_lock
);
387 return (PICL_SUCCESS
);
391 * PICLTREE event thread
395 ptree_event_thread(void *argp
)
400 (void) pthread_mutex_lock(&evtq_lock
);
401 while (eventqp
== NULL
) {
406 (void) pthread_cond_broadcast(&evtq_empty
);
407 (void) pthread_cond_wait(&evtq_cv
, &evtq_lock
);
409 if ((evt
= unqueue_event(&eventqp
)) != NULL
) {
410 (void) pthread_mutex_unlock(&evtq_lock
);
411 call_event_handlers(evt
);
414 (void) pthread_mutex_unlock(&evtq_lock
);
422 * Create a new element
425 hash_newobj(uint32_t hdl_val
, void *obj_val
)
429 n
= malloc(sizeof (*n
));
433 n
->hash_obj
= obj_val
;
439 hash_newhdl(uint32_t picl_hdl
, uint32_t ptreeh
)
443 n
= malloc(sizeof (*n
));
447 n
->hash_hdl
= ptreeh
;
453 * Initialize a hash table by setting all entries to NULL
456 hash_init(hash_t
*htbl
)
460 htbl
->hash_size
= HASH_TBL_SIZE
;
461 htbl
->tbl
= malloc(sizeof (hash_elem_t
*) * HASH_TBL_SIZE
);
462 if (htbl
->tbl
== NULL
)
464 for (i
= 0; i
< htbl
->hash_size
; ++i
)
470 * Lock free function to add an entry in the hash table
473 hash_add_newobj(hash_t
*htbl
, picl_hdl_t hdl
, void *pobj
)
477 uint32_t hash_val
= HASH_VAL(hdl
);
479 n
= hash_newobj(hash_val
, pobj
);
482 indx
= HASH_INDEX(htbl
->hash_size
, hash_val
);
483 n
->next
= htbl
->tbl
[indx
];
489 hash_add_newhdl(hash_t
*htbl
, picl_hdl_t piclh
, picl_hdl_t ptreeh
)
493 uint32_t picl_val
= HASH_VAL(piclh
);
494 uint32_t ptree_val
= HASH_VAL(ptreeh
);
496 n
= hash_newhdl(picl_val
, ptree_val
);
500 indx
= HASH_INDEX(htbl
->hash_size
, picl_val
);
501 n
->next
= htbl
->tbl
[indx
];
507 * Lock free function to remove the handle from the hash table
508 * Returns -1 if element not found, 0 if successful
511 hash_remove(hash_t
*htbl
, picl_hdl_t hdl
)
516 uint32_t hash_val
= HASH_VAL(hdl
);
518 i
= HASH_INDEX(htbl
->hash_size
, hash_val
);
519 if (htbl
->tbl
[i
] == NULL
)
523 if (cur
->hdl
== hash_val
) {
524 htbl
->tbl
[i
] = cur
->next
;
529 while (nxt
!= NULL
) {
530 if (nxt
->hdl
== hash_val
) {
531 cur
->next
= nxt
->next
;
542 * Lock free function to lookup the hash table for a given handle
543 * Returns NULL if not found
546 hash_lookup_obj(hash_t
*htbl
, picl_hdl_t hdl
)
552 hash_val
= HASH_VAL(hdl
);
553 i
= HASH_INDEX(htbl
->hash_size
, hash_val
);
555 while (tmp
!= NULL
) {
556 if (tmp
->hdl
== hash_val
)
557 return (tmp
->hash_obj
);
564 hash_lookup_hdl(hash_t
*htbl
, picl_hdl_t hdl
)
570 hash_val
= HASH_VAL(hdl
);
571 i
= HASH_INDEX(htbl
->hash_size
, hash_val
);
573 while (tmp
!= NULL
) {
574 if (tmp
->hdl
== hash_val
)
575 return (MAKE_HANDLE(picld_pid
, tmp
->hash_hdl
));
578 return (PICL_INVALID_PICLHDL
);
582 * Is the PICL handle stale or invalid handle?
585 picl_hdl_error(picl_hdl_t hdl
)
587 uint32_t hash_val
= HASH_VAL(hdl
);
588 pid_t pid
= GET_PID(hdl
);
591 (void) pthread_mutex_lock(&piclhdl_lock
);
592 err
= PICL_STALEHANDLE
;
593 if ((pid
!= picld_pid
) || (hash_val
>= picl_hdl_hi
) ||
595 err
= PICL_INVALIDHANDLE
;
596 (void) pthread_mutex_unlock(&piclhdl_lock
);
601 * Is the Ptree handle stale or invalid handle?
604 ptree_hdl_error(picl_hdl_t hdl
)
606 uint32_t hash_val
= HASH_VAL(hdl
);
607 pid_t pid
= GET_PID(hdl
);
610 (void) pthread_mutex_lock(&ptreehdl_lock
);
611 err
= PICL_STALEHANDLE
;
612 if ((pid
!= picld_pid
) || (hash_val
>= ptree_hdl_hi
) ||
614 err
= PICL_INVALIDHANDLE
;
615 (void) pthread_mutex_unlock(&ptreehdl_lock
);
620 * For a PICL handle, return the PTree handle and the PICL object
621 * Locks and releases the PICL table.
624 cvt_picl2ptree(picl_hdl_t hdl
, picl_hdl_t
*ptree_hdl
)
629 (void) rw_rdlock(&picltbl_rwlock
); /* lock picl */
630 tmph
= hash_lookup_hdl(&picltbl
, hdl
);
631 if (tmph
== PICL_INVALID_PICLHDL
) {
632 err
= picl_hdl_error(hdl
);
633 (void) rw_unlock(&picltbl_rwlock
); /* unlock picl */
637 (void) rw_unlock(&picltbl_rwlock
); /* unlock picl */
638 return (PICL_SUCCESS
);
642 * Allocate a ptree handle
649 (void) pthread_mutex_lock(&ptreehdl_lock
); /* lock ptreehdl */
650 hdl
= MAKE_HANDLE(picld_pid
, ptree_hdl_hi
);
652 (void) pthread_mutex_unlock(&ptreehdl_lock
); /* unlock ptreehdl */
657 * Allocate a picl handle
658 * A PICL handle is ptree_hdl value with 1 in MSB of handle value.
659 * If a ptree handle already has 1 in MSB, then it cannot be piclized
660 * and the daemon must be restarted.
667 (void) pthread_mutex_lock(&piclhdl_lock
); /* lock piclhdl */
668 hdl
= MAKE_HANDLE(picld_pid
, picl_hdl_hi
);
670 (void) pthread_mutex_unlock(&piclhdl_lock
); /* unlock piclhdl */
675 * Allocate and add handle to PTree hash table
678 alloc_and_add_to_ptree(picl_obj_t
*pobj
)
680 pobj
->ptree_hdl
= alloc_ptreehdl();
681 (void) rw_wrlock(&ptree_rwlock
);
682 (void) hash_add_newobj(&ptreetbl
, pobj
->ptree_hdl
, pobj
);
683 (void) rw_unlock(&ptree_rwlock
);
687 * Lock a picl node object
690 lock_obj(int rw
, picl_obj_t
*nodep
)
692 if (rw
== RDLOCK_NODE
)
693 (void) rw_rdlock(&nodep
->node_lock
);
694 else if (rw
== WRLOCK_NODE
)
695 (void) rw_wrlock(&nodep
->node_lock
);
702 * Release the picl node object.
703 * This function may be called with a NULL object pointer.
706 unlock_node(picl_obj_t
*nodep
)
710 (void) rw_unlock(&nodep
->node_lock
);
714 * This function locks the node of a property and returns the node object
715 * and the property object.
718 lookup_and_lock_propnode(int rw
, picl_prophdl_t proph
, picl_obj_t
**nodep
,
724 pobj
= hash_lookup_obj(&ptreetbl
, proph
);
726 return (ptree_hdl_error(proph
));
729 * Get the property's or table entry's node object
732 if (pobj
->obj_type
== PICL_OBJ_PROP
)
733 nobj
= pobj
->prop_node
;
734 else if (pobj
->obj_type
== (PICL_OBJ_PROP
|PICL_OBJ_TABLEENTRY
))
735 nobj
= pobj
->prop_table
->prop_node
;
737 *propp
= pobj
; /* return the prop */
738 return (PICL_NOTPROP
);
741 if (nobj
&& (lock_obj(rw
, nobj
) < 0)) /* Lock node */
742 return (PICL_FAILURE
);
747 return (PICL_SUCCESS
);
751 * This function locks the node of a table and returns the node object
752 * and the table object.
755 lookup_and_lock_tablenode(int rw
, picl_prophdl_t tblh
, picl_obj_t
**nodep
,
761 pobj
= hash_lookup_obj(&ptreetbl
, tblh
);
763 return (ptree_hdl_error(tblh
));
766 * Get the property's or table entry's node object
769 if (pobj
->obj_type
!= PICL_OBJ_TABLE
)
770 return (PICL_NOTTABLE
);
771 nobj
= pobj
->prop_node
;
773 if (nobj
&& (lock_obj(rw
, nobj
) < 0)) /* Lock node */
774 return (PICL_FAILURE
);
779 return (PICL_SUCCESS
);
783 * This locks the node of a table or a table entry and returns the
784 * node object and the table or table entry object
787 lookup_and_lock_tableprop_node(int rw
, picl_prophdl_t tblproph
,
788 picl_obj_t
**nodep
, picl_obj_t
**tblpropp
)
793 pobj
= hash_lookup_obj(&ptreetbl
, tblproph
);
795 return (ptree_hdl_error(tblproph
));
798 * Get the property's or table entry's node object
801 if ((pobj
->obj_type
!= PICL_OBJ_TABLE
) && /* not a table */
802 !(pobj
->obj_type
& PICL_OBJ_TABLEENTRY
)) /* or an entry */
803 return (PICL_NOTTABLE
);
804 if (pobj
->obj_type
== PICL_OBJ_TABLE
)
805 nobj
= pobj
->prop_node
;
807 nobj
= pobj
->prop_table
->prop_node
;
809 if (nobj
&& (lock_obj(rw
, nobj
) < 0)) /* Lock node */
810 return (PICL_FAILURE
);
815 return (PICL_SUCCESS
);
819 * Lock the node corresponding to the given handle and return its object
822 lookup_and_lock_node(int rw
, picl_nodehdl_t nodeh
, picl_obj_t
**nodep
)
826 nobj
= hash_lookup_obj(&ptreetbl
, nodeh
);
828 return (ptree_hdl_error(nodeh
));
829 else if (nobj
->obj_type
!= PICL_OBJ_NODE
)
830 return (PICL_NOTNODE
);
831 if (lock_obj(rw
, nobj
) < 0) /* Lock node */
832 return (PICL_FAILURE
);
834 return (PICL_SUCCESS
);
838 * Is the property name a restricted property name?
841 picl_restricted(const char *name
)
843 if (strcmp(name
, PICL_PROP_CLASSNAME
) == 0)
844 return (0); /* not restricted */
846 if ((name
[0] == '_') && (strchr(&name
[1], '_') == NULL
))
852 * Check the value size with the property size
853 * Return PICL_INVALIDARG if the size does not match exactly for strongly
855 * For charstring reads allow sizes that match the value size
856 * For bytearray return PICL_VALUETOOBIG
857 * if the size is greater than the buffer size.
860 check_propsize(int op
, picl_obj_t
*propp
, size_t sz
)
862 if (propp
->prop_mode
& PICL_VOLATILE
) {
863 if (sz
!= propp
->prop_size
)
864 return (PICL_INVALIDARG
);
866 return (PICL_SUCCESS
);
870 * check size for non-volatile properties
872 switch (propp
->prop_type
) {
873 case PICL_PTYPE_CHARSTRING
:
874 if ((op
== PROP_READ
) &&
875 (strlen(propp
->prop_val
) >= sz
))
876 return (PICL_VALUETOOBIG
);
877 if ((op
== PROP_WRITE
) && (sz
> propp
->prop_size
))
878 return (PICL_VALUETOOBIG
);
880 case PICL_PTYPE_BYTEARRAY
:
881 if (op
== PROP_WRITE
) {
882 if (sz
> propp
->prop_size
)
883 return (PICL_VALUETOOBIG
);
884 return (PICL_SUCCESS
); /* allow small writes */
886 /* fall through for reads */
888 if (propp
->prop_size
!= sz
)
889 return (PICL_INVALIDARG
);
892 return (PICL_SUCCESS
);
896 cvt_ptree2picl(picl_hdl_t
*handlep
)
900 (void) rw_rdlock(&ptree_rwlock
);
901 pobj
= hash_lookup_obj(&ptreetbl
, *handlep
);
903 *handlep
= PICL_INVALID_PICLHDL
;
905 (void) memcpy(handlep
, &pobj
->picl_hdl
, sizeof (*handlep
));
906 (void) rw_unlock(&ptree_rwlock
);
910 * The caller of the piclize() set of functions is assumed to hold
911 * the ptree_rwlock().
914 piclize_obj(picl_obj_t
*pobj
)
916 (void) rw_wrlock(&picltbl_rwlock
);
917 pobj
->picl_hdl
= alloc_piclhdl();
918 (void) hash_add_newhdl(&picltbl
, pobj
->picl_hdl
, pobj
->ptree_hdl
);
919 (void) rw_unlock(&picltbl_rwlock
);
923 piclize_table(picl_obj_t
*tbl_obj
)
928 for (rowp
= tbl_obj
->next_row
; rowp
!= NULL
; rowp
= rowp
->next_col
)
929 for (colp
= rowp
; colp
!= NULL
; colp
= colp
->next_row
)
934 piclize_prop(picl_obj_t
*propp
)
940 if (!(propp
->prop_mode
& PICL_VOLATILE
) &&
941 (propp
->prop_type
== PICL_PTYPE_TABLE
)) {
942 tblh
= *(picl_prophdl_t
*)propp
->prop_val
;
943 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
946 piclize_obj(tbl_obj
);
947 piclize_table(tbl_obj
);
952 * Function to create PICL handles for a subtree and add them to
956 piclize_node(picl_obj_t
*nodep
)
962 propp
= nodep
->first_prop
;
963 while (propp
!= NULL
) {
965 propp
= propp
->next_prop
;
968 /* go through the children */
969 for (chdp
= nodep
->child_node
; chdp
!= NULL
; chdp
= chdp
->sibling_node
)
974 * Function to remove PICL handles
977 unpiclize_obj(picl_obj_t
*pobj
)
979 (void) rw_wrlock(&picltbl_rwlock
);
980 (void) hash_remove(&picltbl
, pobj
->picl_hdl
);
981 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
982 (void) rw_unlock(&picltbl_rwlock
);
986 unpiclize_table(picl_obj_t
*tbl_obj
)
991 for (rowp
= tbl_obj
->next_row
; rowp
!= NULL
; rowp
= rowp
->next_col
)
992 for (colp
= rowp
; colp
!= NULL
; colp
= colp
->next_row
)
994 unpiclize_obj(tbl_obj
);
998 unpiclize_prop(picl_obj_t
*propp
)
1000 picl_obj_t
*tbl_obj
;
1001 picl_prophdl_t tblh
;
1003 if (!IS_PICLIZED(propp
))
1005 unpiclize_obj(propp
);
1006 if (!(propp
->prop_mode
& PICL_VOLATILE
) &&
1007 (propp
->prop_type
== PICL_PTYPE_TABLE
)) {
1008 tblh
= *(picl_prophdl_t
*)propp
->prop_val
;
1009 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1010 unpiclize_table(tbl_obj
);
1015 * Function to remove PICL handles for a subtree and its
1019 unpiclize_node(picl_obj_t
*nodep
)
1025 if (!IS_PICLIZED(nodep
))
1028 unpiclize_obj(nodep
);
1029 propp
= nodep
->first_prop
;
1030 while (propp
!= NULL
) {
1031 unpiclize_prop(propp
);
1032 propp
= propp
->next_prop
;
1035 /* go through the children */
1036 for (chdp
= nodep
->child_node
; chdp
!= NULL
; chdp
= chdp
->sibling_node
)
1037 unpiclize_node(chdp
);
1042 * The caller holds the lock on the ptree_lock when calling this.
1043 * If ret is not NULL then this function returns the referenced object.
1046 lookup_verify_ref_prop(picl_obj_t
*propp
, picl_obj_t
**ret
)
1048 picl_nodehdl_t refh
;
1051 refh
= *(picl_nodehdl_t
*)propp
->prop_val
;
1052 refobj
= hash_lookup_obj(&ptreetbl
, refh
);
1054 return (ptree_hdl_error(refh
));
1055 else if (refobj
->obj_type
!= PICL_OBJ_NODE
)
1056 return (PICL_INVREFERENCE
);
1059 return (PICL_SUCCESS
);
1063 * The caller holds the lock on ptree_lock when calling this.
1064 * If ret is not NULL, then this function returns the table object
1067 lookup_verify_table_prop(picl_obj_t
*propp
, picl_obj_t
**ret
)
1069 picl_prophdl_t tblh
;
1070 picl_obj_t
*tbl_obj
;
1072 tblh
= *(picl_prophdl_t
*)propp
->prop_val
;
1073 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1074 if (tbl_obj
== NULL
)
1075 return (ptree_hdl_error(tblh
));
1076 else if (!(tbl_obj
->obj_type
& PICL_OBJ_TABLE
))
1077 return (PICL_NOTTABLE
);
1080 return (PICL_SUCCESS
);
1084 lookup_verify_prop_handle(picl_prophdl_t proph
, picl_obj_t
**ret
)
1088 propp
= hash_lookup_obj(&ptreetbl
, proph
);
1090 return (ptree_hdl_error(proph
));
1091 else if (!(propp
->obj_type
& PICL_OBJ_PROP
))
1092 return (PICL_NOTPROP
);
1095 return (PICL_SUCCESS
);
1099 lookup_verify_node_handle(picl_nodehdl_t nodeh
, picl_obj_t
**ret
)
1103 nodep
= hash_lookup_obj(&ptreetbl
, nodeh
);
1105 return (ptree_hdl_error(nodeh
));
1106 else if (nodep
->obj_type
!= PICL_OBJ_NODE
)
1107 return (PICL_NOTNODE
);
1110 return (PICL_SUCCESS
);
1114 lookup_prop_by_name(picl_obj_t
*nodep
, const char *pname
, picl_obj_t
**ret
)
1118 if (strcmp(pname
, PICL_PROP_PARENT
) == 0) {
1119 if (nodep
->parent_node
== NULL
)
1120 return (PICL_PROPNOTFOUND
);
1122 return (PICL_SUCCESS
);
1124 if (strcmp(pname
, PICL_PROP_CHILD
) == 0) {
1125 if (nodep
->child_node
== NULL
)
1126 return (PICL_PROPNOTFOUND
);
1128 return (PICL_SUCCESS
);
1130 if (strcmp(pname
, PICL_PROP_PEER
) == 0) {
1131 if (nodep
->sibling_node
== NULL
)
1132 return (PICL_PROPNOTFOUND
);
1134 return (PICL_SUCCESS
);
1137 propp
= nodep
->first_prop
;
1138 while (propp
!= NULL
) {
1139 if (strcmp(propp
->prop_name
, pname
) == 0) {
1142 return (PICL_SUCCESS
);
1144 propp
= propp
->next_prop
;
1146 return (PICL_PROPNOTFOUND
);
1150 * This function locks the ptree, verifies that the handle is a reference
1151 * to a node of specified class name, releases the lock
1154 check_ref_handle(picl_nodehdl_t refh
, char *clname
)
1160 (void) rw_rdlock(&ptree_rwlock
); /* Lock ptree */
1161 refobj
= hash_lookup_obj(&ptreetbl
, refh
);
1162 if ((refobj
== NULL
) || !(refobj
->obj_type
& PICL_OBJ_NODE
)) {
1163 (void) rw_unlock(&ptree_rwlock
);
1164 return (PICL_INVREFERENCE
);
1167 err
= lookup_prop_by_name(refobj
, PICL_PROP_CLASSNAME
, &propp
);
1168 if ((err
!= PICL_SUCCESS
) || (propp
->prop_val
== NULL
) ||
1169 (strcmp(propp
->prop_val
, clname
) != 0))
1170 err
= PICL_INVREFERENCE
;
1171 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1176 check_table_handle(picl_prophdl_t tblh
)
1178 picl_obj_t
*tbl_obj
;
1181 (void) rw_rdlock(&ptree_rwlock
);
1183 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1184 if ((tbl_obj
== NULL
) || !(tbl_obj
->obj_type
& PICL_OBJ_TABLE
))
1185 err
= PICL_NOTTABLE
;
1186 (void) rw_unlock(&ptree_rwlock
);
1191 * PICLTree Interface routines for plug-in modules
1194 ptree_get_root(picl_nodehdl_t
*rooth
)
1196 *rooth
= ptree_root_hdl
;
1197 return (PICL_SUCCESS
);
1201 * Lock free create a property object
1204 create_propobj(const ptree_propinfo_t
*pinfo
, const void *valbuf
,
1209 if (pinfo
->version
!= PTREE_PROPINFO_VERSION_1
)
1210 return (PICL_NOTSUPPORTED
);
1212 if (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
) &&
1213 (pinfo
->piclinfo
.type
!= PICL_PTYPE_VOID
) &&
1215 return (PICL_INVALIDARG
);
1217 pobj
= malloc(sizeof (picl_obj_t
));
1219 return (PICL_FAILURE
);
1221 pobj
->obj_type
= PICL_OBJ_PROP
;
1222 pobj
->pinfo_ver
= pinfo
->version
;
1223 pobj
->prop_type
= pinfo
->piclinfo
.type
;
1224 pobj
->prop_mode
= pinfo
->piclinfo
.accessmode
;
1225 pobj
->prop_size
= pinfo
->piclinfo
.size
;
1226 (void) strcpy(pobj
->prop_name
, pinfo
->piclinfo
.name
);
1227 pobj
->read_func
= pinfo
->read
;
1228 pobj
->write_func
= pinfo
->write
;
1230 pobj
->prop_val
= NULL
;
1231 if (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
)) {
1232 pobj
->prop_val
= malloc(pinfo
->piclinfo
.size
);
1233 if (pobj
->prop_val
== NULL
) {
1235 return (PICL_FAILURE
);
1237 if (pobj
->prop_type
== PICL_PTYPE_CHARSTRING
)
1238 (void) strlcpy(pobj
->prop_val
, valbuf
,
1239 pinfo
->piclinfo
.size
);
1241 (void) memcpy(pobj
->prop_val
, valbuf
,
1242 pinfo
->piclinfo
.size
);
1244 pobj
->prop_node
= NULL
;
1245 pobj
->ptree_hdl
= PICL_INVALID_PICLHDL
;
1246 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
1247 pobj
->next_prop
= NULL
;
1248 pobj
->next_row
= NULL
;
1249 pobj
->next_col
= NULL
;
1252 return (PICL_SUCCESS
);
1256 * Check for valid arguments, create a property object,
1257 * Lock ptree_rwlock, add the new property handle, release the lock
1258 * For reference properties and table properties, the handles are verified
1259 * before creating the property.
1262 ptree_create_prop(const ptree_propinfo_t
*pinfo
, const void *valbuf
,
1263 picl_prophdl_t
*proph
)
1266 picl_nodehdl_t refh
;
1267 picl_prophdl_t tblh
;
1271 char classname
[PICL_PROPNAMELEN_MAX
];
1274 return (PICL_INVALIDARG
);
1275 if (pinfo
->version
!= PTREE_PROPINFO_VERSION_1
)
1276 return (PICL_NOTSUPPORTED
);
1277 if (pinfo
->piclinfo
.size
>= PICL_PROPSIZE_MAX
)
1278 return (PICL_VALUETOOBIG
);
1279 if (picl_restricted(pinfo
->piclinfo
.name
))
1280 return (PICL_RESERVEDNAME
);
1283 if ((pinfo
->piclinfo
.name
[0] == '_') &&
1284 (strchr(&pinfo
->piclinfo
.name
[1], '_') != NULL
))
1287 if (pinfo
->piclinfo
.type
== PICL_PTYPE_REFERENCE
) {
1289 return (PICL_INVREFERENCE
);
1291 * check valid reference handle for non-volatiles
1293 if (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
)) {
1295 return (PICL_INVREFERENCE
);
1296 if (pinfo
->piclinfo
.size
!= sizeof (picl_nodehdl_t
))
1297 return (PICL_INVREFERENCE
);
1298 (void) strcpy(classname
, pinfo
->piclinfo
.name
);
1299 ptr
= strchr(&classname
[1], '_');
1301 refh
= *(picl_hdl_t
*)valbuf
;
1302 err
= check_ref_handle(refh
, &classname
[1]);
1303 if (err
!= PICL_SUCCESS
)
1306 } else if (refflag
== 1)
1307 return (PICL_INVREFERENCE
);
1308 else if ((pinfo
->piclinfo
.type
== PICL_PTYPE_TABLE
) &&
1309 (!(pinfo
->piclinfo
.accessmode
& PICL_VOLATILE
))) {
1310 if (pinfo
->piclinfo
.size
!= sizeof (picl_prophdl_t
))
1311 return (PICL_INVALIDARG
);
1312 tblh
= *(picl_prophdl_t
*)valbuf
;
1313 err
= check_table_handle(tblh
);
1314 if (err
!= PICL_SUCCESS
)
1316 } else if ((strcmp(pinfo
->piclinfo
.name
, PICL_PROP_CLASSNAME
) == 0) &&
1317 ((pinfo
->piclinfo
.type
!= PICL_PTYPE_CHARSTRING
) ||
1318 (strlen(valbuf
) >= PICL_CLASSNAMELEN_MAX
)))
1319 return (PICL_RESERVEDNAME
);
1320 else if ((strcmp(pinfo
->piclinfo
.name
, PICL_PROP_NAME
) == 0) &&
1321 (pinfo
->piclinfo
.type
!= PICL_PTYPE_CHARSTRING
))
1322 return (PICL_RESERVEDNAME
);
1324 * No locks held when you get here
1326 err
= create_propobj(pinfo
, valbuf
, &pobj
);
1327 if (err
!= PICL_SUCCESS
)
1330 alloc_and_add_to_ptree(pobj
);
1331 *proph
= pobj
->ptree_hdl
;
1332 return (PICL_SUCCESS
);
1336 * Lock free routine to destroy table entries
1337 * This function removes the destroyed handles from the hash table
1338 * Uses lock free routines: hash_lookup() and hash_remove()
1341 destroy_table(picl_obj_t
*pobj
)
1343 picl_prophdl_t tblh
;
1344 picl_obj_t
*tbl_obj
;
1349 tblh
= *(picl_prophdl_t
*)pobj
->prop_val
;
1350 tbl_obj
= hash_lookup_obj(&ptreetbl
, tblh
);
1351 if (tbl_obj
== NULL
)
1354 assert(tbl_obj
->obj_type
& PICL_OBJ_TABLE
);
1356 /* Delete all entries */
1357 rowp
= tbl_obj
->next_row
;
1358 while (rowp
!= NULL
) {
1360 rowp
= rowp
->next_col
;
1361 while (colp
!= NULL
) {
1363 colp
= colp
->next_row
;
1364 (void) hash_remove(&ptreetbl
, freep
->ptree_hdl
);
1365 if (freep
->prop_val
)
1366 free(freep
->prop_val
);
1371 (void) hash_remove(&ptreetbl
, tbl_obj
->ptree_hdl
);
1377 * Lock free function that frees up a property object and removes the
1378 * handles from Ptree table
1381 destroy_propobj(picl_obj_t
*propp
)
1383 if (propp
->prop_type
== PICL_PTYPE_TABLE
)
1384 destroy_table(propp
);
1386 (void) hash_remove(&ptreetbl
, propp
->ptree_hdl
);
1387 if (propp
->prop_val
)
1388 free(propp
->prop_val
);
1393 * This function destroys a previously deleted property.
1394 * A deleted property does not have an associated node.
1395 * All memory allocated for this property are freed
1398 ptree_destroy_prop(picl_prophdl_t proph
)
1402 (void) rw_wrlock(&ptree_rwlock
); /* Exclusive Lock ptree */
1404 propp
= hash_lookup_obj(&ptreetbl
, proph
);
1405 if (propp
== NULL
) {
1406 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1407 return (ptree_hdl_error(proph
));
1410 /* Is the prop still attached to a node? */
1411 if (propp
->prop_node
!= NULL
) {
1412 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1413 return (PICL_CANTDESTROY
);
1416 destroy_propobj(propp
);
1418 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1419 return (PICL_SUCCESS
);
1423 * This function adds a property to the property list of a node and adds
1424 * it to the PICL table if the node has a PICL handle.
1425 * This function locks the picl_rwlock and ptree_rwlock.
1428 ptree_add_prop(picl_nodehdl_t nodeh
, picl_prophdl_t proph
)
1433 picl_obj_t
*tbl_obj
;
1436 (void) rw_rdlock(&ptree_rwlock
); /* RDLock ptree */
1439 * Verify property handle
1441 err
= lookup_verify_prop_handle(proph
, &propp
);
1442 if (err
!= PICL_SUCCESS
) {
1443 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1447 if (propp
->prop_node
!= NULL
) {
1448 (void) rw_unlock(&ptree_rwlock
);
1449 return (PICL_INVALIDARG
);
1454 * Exclusive Lock the node's properties
1456 err
= lookup_and_lock_node(WRLOCK_NODE
, nodeh
, &nodep
);
1457 if (err
!= PICL_SUCCESS
) {
1458 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1463 * check if prop already exists
1465 err
= lookup_prop_by_name(nodep
, propp
->prop_name
, NULL
);
1466 if (err
== PICL_SUCCESS
) {
1467 unlock_node(nodep
); /* Unlock node */
1468 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1469 return (PICL_PROPEXISTS
);
1473 * Verify property's value
1476 switch (propp
->prop_type
) {
1477 case PICL_PTYPE_TABLE
:
1478 if (propp
->prop_mode
& PICL_VOLATILE
)
1480 err
= lookup_verify_table_prop(propp
, &tbl_obj
);
1481 if (err
!= PICL_SUCCESS
) {
1483 (void) rw_unlock(&ptree_rwlock
);
1486 tbl_obj
->prop_node
= nodep
; /* set table's nodep */
1487 tbl_obj
->table_prop
= propp
; /* set table prop */
1489 case PICL_PTYPE_REFERENCE
:
1490 if (propp
->prop_mode
& PICL_VOLATILE
)
1492 err
= lookup_verify_ref_prop(propp
, &refobj
);
1493 if (err
!= PICL_SUCCESS
) {
1495 (void) rw_unlock(&ptree_rwlock
);
1498 if (IS_PICLIZED(nodep
) && !IS_PICLIZED(refobj
)) {
1500 (void) rw_unlock(&ptree_rwlock
);
1508 if (IS_PICLIZED(nodep
))
1509 piclize_prop(propp
);
1511 * Add prop to beginning of list
1513 propp
->prop_node
= nodep
; /* set prop's nodep */
1514 propp
->next_prop
= nodep
->first_prop
;
1515 nodep
->first_prop
= propp
;
1517 unlock_node(nodep
); /* Unlock node */
1518 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1519 return (PICL_SUCCESS
);
1523 * Lock free function that unlinks a property from its node
1526 unlink_prop(picl_obj_t
*nodep
, picl_obj_t
*propp
)
1530 iterp
= nodep
->first_prop
;
1531 if (iterp
== propp
) { /* first property */
1532 nodep
->first_prop
= iterp
->next_prop
;
1533 return (PICL_SUCCESS
);
1535 while ((iterp
!= NULL
) && (iterp
->next_prop
!= propp
))
1536 iterp
= iterp
->next_prop
;
1538 return (PICL_PROPNOTFOUND
);
1539 iterp
->next_prop
= propp
->next_prop
;
1540 return (PICL_SUCCESS
);
1544 * This function deletes the specified property from the property list
1545 * of its node and removes the handle from PICL table, if the node
1549 ptree_delete_prop(picl_prophdl_t proph
)
1555 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
1557 * Lookup the property's node and lock it if there is one
1558 * return the objects for the property and the node
1560 nodep
= propp
= NULL
;
1561 err
= lookup_and_lock_propnode(WRLOCK_NODE
, proph
, &nodep
, &propp
);
1562 if (err
!= PICL_SUCCESS
) {
1563 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1565 } else if (nodep
== NULL
) {
1566 /* Nothing to do - already deleted! */
1567 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1568 return (PICL_SUCCESS
);
1571 if (propp
->obj_type
& PICL_OBJ_TABLEENTRY
) {
1572 unlock_node(nodep
); /* Unlock node */
1573 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1574 return (PICL_NOTPROP
);
1577 err
= unlink_prop(nodep
, propp
);
1578 if (err
!= PICL_SUCCESS
) {
1579 unlock_node(nodep
); /* Unlock node */
1580 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1584 propp
->prop_node
= NULL
; /* reset prop's nodep */
1585 propp
->next_prop
= NULL
;
1587 unpiclize_prop(propp
);
1589 unlock_node(nodep
); /* Unlock node */
1590 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1591 return (PICL_SUCCESS
);
1595 * Create a table object and return its handle
1598 ptree_create_table(picl_prophdl_t
*tblh
)
1602 pobj
= malloc(sizeof (picl_obj_t
));
1604 return (PICL_FAILURE
);
1605 pobj
->obj_type
= PICL_OBJ_TABLE
;
1606 pobj
->prop_val
= NULL
;
1607 pobj
->prop_node
= NULL
;
1608 pobj
->ptree_hdl
= PICL_INVALID_PICLHDL
;
1609 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
1610 pobj
->table_prop
= NULL
;
1611 pobj
->next_row
= NULL
;
1612 pobj
->next_col
= NULL
;
1614 alloc_and_add_to_ptree(pobj
);
1615 *tblh
= pobj
->ptree_hdl
;
1616 return (PICL_SUCCESS
);
1620 * Add the properties in <props> array as a row in the table
1621 * Add PICL handles if the table has a valid PICL handle
1624 ptree_add_row_to_table(picl_prophdl_t tblh
, int nprops
,
1625 const picl_prophdl_t
*props
)
1627 picl_obj_t
*tbl_obj
;
1629 picl_obj_t
*lastrow
;
1630 picl_obj_t
**newrow
;
1637 return (PICL_INVALIDARG
);
1639 newrow
= malloc(sizeof (picl_obj_t
*) * nprops
);
1641 return (PICL_FAILURE
);
1643 (void) rw_rdlock(&ptree_rwlock
); /* Lock ptree */
1645 err
= lookup_and_lock_tablenode(WRLOCK_NODE
, tblh
, &nodep
, &tbl_obj
);
1646 if (err
!= PICL_SUCCESS
) {
1648 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1653 * make sure all are either props or table handles
1655 for (i
= 0; i
< nprops
; ++i
) {
1656 pobj
= newrow
[i
] = hash_lookup_obj(&ptreetbl
, props
[i
]);
1657 if (pobj
== NULL
) { /* no object */
1658 err
= ptree_hdl_error(props
[i
]);
1661 if ((!(pobj
->obj_type
& PICL_OBJ_PROP
)) &&
1662 (!(pobj
->obj_type
& PICL_OBJ_TABLE
))) {
1666 if (IS_PICLIZED(pobj
) || (pobj
->prop_table
!= NULL
) ||
1667 (pobj
->prop_node
!= NULL
)) {
1668 err
= PICL_INVALIDARG
;
1673 if (err
!= PICL_SUCCESS
) {
1676 (void) rw_unlock(&ptree_rwlock
); /* Unlock table */
1681 * Mark all props as table entries, set up row linkages
1684 if (IS_PICLIZED(tbl_obj
))
1686 for (i
= 0; i
< nprops
; ++i
) {
1687 newrow
[i
]->obj_type
|= PICL_OBJ_TABLEENTRY
;
1688 newrow
[i
]->prop_table
= tbl_obj
;
1689 newrow
[i
]->next_prop
= NULL
;
1690 newrow
[i
]->next_col
= NULL
;
1692 piclize_obj(newrow
[i
]);
1693 if (i
!= nprops
- 1)
1694 newrow
[i
]->next_row
= newrow
[i
+1];
1696 newrow
[nprops
- 1]->next_row
= NULL
;
1698 if (tbl_obj
->next_row
== NULL
) { /* add first row */
1699 tbl_obj
->next_row
= newrow
[0];
1700 tbl_obj
->next_col
= newrow
[0];
1702 lastrow
= tbl_obj
->next_row
;
1703 while (lastrow
->next_col
!= NULL
)
1704 lastrow
= lastrow
->next_col
;
1706 while (lastrow
!= NULL
) {
1707 lastrow
->next_col
= newrow
[i
];
1708 lastrow
= lastrow
->next_row
;
1713 unlock_node(nodep
); /* unlock node */
1714 (void) rw_unlock(&ptree_rwlock
); /* Unlock ptree */
1716 return (PICL_SUCCESS
);
1720 * This function returns the handle of the next property in the row
1723 ptree_get_next_by_row(picl_prophdl_t proph
, picl_prophdl_t
*nextrowh
)
1729 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
1731 nodep
= propp
= NULL
;
1733 * proph could be a table handle or a table entry handle
1734 * Look it up as a table entry handle first, check error code
1735 * to see if it is a table handle
1737 err
= lookup_and_lock_tableprop_node(RDLOCK_NODE
, proph
, &nodep
,
1739 if (err
!= PICL_SUCCESS
) {
1740 (void) rw_unlock(&ptree_rwlock
);
1744 if (propp
->next_row
)
1745 *nextrowh
= propp
->next_row
->ptree_hdl
;
1747 err
= PICL_ENDOFLIST
;
1749 unlock_node(nodep
); /* unlock node */
1750 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1755 ptree_get_next_by_col(picl_prophdl_t proph
, picl_prophdl_t
*nextcolh
)
1761 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
1762 nodep
= propp
= NULL
;
1764 * proph could be a table handle or a table entry handle
1765 * Look it up as a table entry handle first, check error code
1766 * to see if it is a table handle
1768 err
= lookup_and_lock_tableprop_node(RDLOCK_NODE
, proph
, &nodep
,
1770 if (err
!= PICL_SUCCESS
) {
1771 (void) rw_unlock(&ptree_rwlock
);
1775 if (propp
->next_col
)
1776 *nextcolh
= propp
->next_col
->ptree_hdl
;
1778 err
= PICL_ENDOFLIST
;
1780 unlock_node(nodep
); /* unlock node */
1781 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1786 * This function creates node object and adds its handle to the Ptree
1789 ptree_create_node(const char *name
, const char *clname
, picl_nodehdl_t
*nodeh
)
1792 ptree_propinfo_t propinfo
;
1793 picl_prophdl_t phdl
;
1794 picl_prophdl_t cphdl
;
1797 if ((name
== NULL
) || (*name
== '\0') ||
1798 (clname
== NULL
) || (*clname
== '\0'))
1799 return (PICL_INVALIDARG
);
1801 if ((strlen(name
) >= PICL_PROPNAMELEN_MAX
) ||
1802 (strlen(clname
) >= PICL_CLASSNAMELEN_MAX
))
1803 return (PICL_VALUETOOBIG
);
1806 * Create the picl object for node
1808 pobj
= malloc(sizeof (picl_obj_t
));
1810 return (PICL_FAILURE
);
1811 pobj
->obj_type
= PICL_OBJ_NODE
;
1812 pobj
->first_prop
= NULL
;
1813 pobj
->ptree_hdl
= PICL_INVALID_PICLHDL
;
1814 pobj
->picl_hdl
= PICL_INVALID_PICLHDL
;
1815 pobj
->parent_node
= NULL
;
1816 pobj
->sibling_node
= NULL
;
1817 pobj
->child_node
= NULL
;
1818 pobj
->node_classname
= strdup(clname
);
1819 if (pobj
->node_classname
== NULL
) {
1821 return (PICL_FAILURE
);
1823 (void) rwlock_init(&pobj
->node_lock
, USYNC_THREAD
, NULL
);
1825 alloc_and_add_to_ptree(pobj
); /* commit the node */
1828 * create name property
1830 propinfo
.version
= PTREE_PROPINFO_VERSION_1
;
1831 propinfo
.piclinfo
.type
= PICL_PTYPE_CHARSTRING
;
1832 propinfo
.piclinfo
.accessmode
= PICL_READ
;
1833 propinfo
.piclinfo
.size
= strlen(name
) + 1;
1834 (void) strcpy(propinfo
.piclinfo
.name
, PICL_PROP_NAME
);
1835 propinfo
.read
= NULL
;
1836 propinfo
.write
= NULL
;
1837 err
= ptree_create_prop(&propinfo
, (const void *)name
, &phdl
);
1838 if (err
!= PICL_SUCCESS
) {
1839 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1842 err
= ptree_add_prop(pobj
->ptree_hdl
, phdl
);
1843 if (err
!= PICL_SUCCESS
) {
1844 (void) ptree_destroy_prop(phdl
);
1845 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1850 * create picl classname property
1852 propinfo
.piclinfo
.size
= strlen(clname
) + 1;
1853 (void) strcpy(propinfo
.piclinfo
.name
, PICL_PROP_CLASSNAME
);
1854 propinfo
.read
= NULL
;
1855 propinfo
.write
= NULL
;
1856 err
= ptree_create_prop(&propinfo
, (const void *)clname
, &cphdl
);
1857 if (err
!= PICL_SUCCESS
) {
1858 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1861 err
= ptree_add_prop(pobj
->ptree_hdl
, cphdl
);
1862 if (err
!= PICL_SUCCESS
) {
1863 (void) ptree_destroy_prop(cphdl
);
1864 (void) ptree_destroy_node(pobj
->ptree_hdl
);
1868 *nodeh
= pobj
->ptree_hdl
;
1869 return (PICL_SUCCESS
);
1873 * Destroy a node/subtree freeing up space
1874 * Removed destroyed objects' handles from PTree table
1877 destroy_subtree(picl_obj_t
*nodep
)
1886 chdp
= nodep
->child_node
;
1887 while (chdp
!= NULL
) {
1889 chdp
= chdp
->sibling_node
;
1890 destroy_subtree(freep
);
1896 (void) lock_obj(WRLOCK_NODE
, nodep
);
1899 * destroy all properties associated with this node
1901 iterp
= nodep
->first_prop
;
1902 while (iterp
!= NULL
) {
1904 iterp
= iterp
->next_prop
;
1905 destroy_propobj(freep
);
1908 (void) hash_remove(&ptreetbl
, nodep
->ptree_hdl
);
1909 (void) rwlock_destroy(&nodep
->node_lock
);
1910 free(nodep
->node_classname
);
1915 * This function destroys a previously deleted node/subtree. All the properties
1916 * are freed and removed from the PTree table.
1917 * Only one destroy is in progress at any time.
1920 ptree_destroy_node(picl_nodehdl_t nodeh
)
1927 (void) rw_wrlock(&ptree_rwlock
); /* exclusive wrlock ptree */
1929 err
= lookup_verify_node_handle(nodeh
, &nodep
);
1930 if (err
!= PICL_SUCCESS
) {
1931 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1936 * Has this node/subtree been deleted?
1938 if (IS_PICLIZED(nodep
)) {
1939 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1940 return (PICL_CANTDESTROY
);
1944 * update parent's child list to repair the tree when
1945 * parent is not null
1947 parp
= nodep
->parent_node
;
1948 if (parp
== NULL
) { /* root */
1949 destroy_subtree(nodep
);
1950 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1951 return (PICL_SUCCESS
);
1954 np
= parp
->child_node
;
1955 if (np
== nodep
) { /* first child */
1956 parp
->child_node
= nodep
->sibling_node
;
1958 while ((np
!= NULL
) && (np
->sibling_node
!= nodep
))
1959 np
= np
->sibling_node
;
1961 np
->sibling_node
= nodep
->sibling_node
;
1964 destroy_subtree(nodep
);
1965 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1966 return (PICL_SUCCESS
);
1970 * This function deletes a node/subtree from the tree and removes the handles
1974 ptree_delete_node(picl_nodehdl_t nodeh
)
1981 (void) rw_wrlock(&ptree_rwlock
); /* exclusive wrlock ptree */
1984 err
= lookup_verify_node_handle(nodeh
, &nodep
);
1985 if (err
!= PICL_SUCCESS
) {
1986 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
1993 parp
= nodep
->parent_node
;
1995 np
= parp
->child_node
;
1996 if (np
== nodep
) /* first child */
1997 parp
->child_node
= nodep
->sibling_node
;
1999 while ((np
!= NULL
) && (np
->sibling_node
!= nodep
))
2000 np
= np
->sibling_node
;
2002 np
->sibling_node
= nodep
->sibling_node
;
2006 nodep
->parent_node
= NULL
;
2007 nodep
->sibling_node
= NULL
;
2009 unpiclize_node(nodep
);
2011 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2012 return (PICL_SUCCESS
);
2016 * This function adds a node as a child of another node
2019 ptree_add_node(picl_nodehdl_t parh
, picl_nodehdl_t chdh
)
2026 (void) rw_wrlock(&ptree_rwlock
); /* exclusive lock ptree */
2028 pnodep
= cnodep
= NULL
;
2029 err
= lookup_verify_node_handle(parh
, &pnodep
);
2030 if (err
!= PICL_SUCCESS
) {
2031 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2035 err
= lookup_verify_node_handle(chdh
, &cnodep
);
2036 if (err
!= PICL_SUCCESS
) {
2037 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2041 /* is chdh already a child? */
2042 if (cnodep
->parent_node
!= NULL
) {
2043 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2044 return (PICL_CANTPARENT
);
2048 * append child to children list
2050 cnodep
->parent_node
= pnodep
;
2051 if (pnodep
->child_node
== NULL
)
2052 pnodep
->child_node
= cnodep
;
2054 for (nodep
= pnodep
->child_node
; nodep
->sibling_node
!= NULL
;
2055 nodep
= nodep
->sibling_node
)
2057 nodep
->sibling_node
= cnodep
;
2062 if (IS_PICLIZED(pnodep
))
2063 piclize_node(cnodep
);
2064 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2065 return (PICL_SUCCESS
);
2069 copy_propinfo_ver_1(ptree_propinfo_t
*pinfo
, picl_obj_t
*propp
)
2071 pinfo
->version
= propp
->pinfo_ver
;
2072 pinfo
->piclinfo
.type
= propp
->prop_type
;
2073 pinfo
->piclinfo
.accessmode
= propp
->prop_mode
;
2074 pinfo
->piclinfo
.size
= propp
->prop_size
;
2075 (void) strcpy(pinfo
->piclinfo
.name
, propp
->prop_name
);
2076 pinfo
->read
= propp
->read_func
;
2077 pinfo
->write
= propp
->write_func
;
2081 copy_reserved_propinfo_ver_1(ptree_propinfo_t
*pinfo
, const char *pname
)
2083 pinfo
->version
= PTREE_PROPINFO_VERSION_1
;
2084 pinfo
->piclinfo
.type
= PICL_PTYPE_REFERENCE
;
2085 pinfo
->piclinfo
.accessmode
= PICL_READ
;
2086 pinfo
->piclinfo
.size
= sizeof (picl_nodehdl_t
);
2087 (void) strcpy(pinfo
->piclinfo
.name
, pname
);
2089 pinfo
->write
= NULL
;
2093 * This function returns the property information to a plug-in
2096 ptree_get_propinfo(picl_prophdl_t proph
, ptree_propinfo_t
*pinfo
)
2102 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2103 nodep
= propp
= NULL
;
2104 err
= lookup_and_lock_propnode(RDLOCK_NODE
, proph
, &nodep
, &propp
);
2105 if (err
!= PICL_SUCCESS
) {
2106 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2110 if (propp
->pinfo_ver
== PTREE_PROPINFO_VERSION_1
)
2111 copy_propinfo_ver_1(pinfo
, propp
);
2115 unlock_node(nodep
); /* unlock node */
2116 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2121 * This function returns the property information to a plug-in
2124 xptree_get_propinfo_by_name(picl_nodehdl_t nodeh
, const char *pname
,
2125 ptree_propinfo_t
*pinfo
)
2131 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2132 nodep
= propp
= NULL
;
2133 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2134 if (err
!= PICL_SUCCESS
) {
2135 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2139 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2140 if (err
!= PICL_SUCCESS
) {
2142 (void) rw_unlock(&ptree_rwlock
);
2146 if (picl_restricted(pname
))
2147 copy_reserved_propinfo_ver_1(pinfo
, pname
);
2148 else if (propp
->pinfo_ver
== PTREE_PROPINFO_VERSION_1
)
2149 copy_propinfo_ver_1(pinfo
, propp
);
2153 unlock_node(nodep
); /* unlock node */
2154 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2159 * This function must be called only after a lookup_prop_by_name() returns
2160 * success and only if picl_restricted() returns true.
2163 read_reserved_propval_and_unlock(picl_obj_t
*nodep
, const char *pname
,
2164 void *vbuf
, size_t size
)
2168 if (size
!= sizeof (picl_nodehdl_t
))
2169 return (PICL_VALUETOOBIG
);
2171 if (strcmp(pname
, PICL_PROP_PARENT
) == 0)
2172 srcp
= &nodep
->parent_node
->ptree_hdl
;
2173 else if (strcmp(pname
, PICL_PROP_CHILD
) == 0)
2174 srcp
= &nodep
->child_node
->ptree_hdl
;
2175 else if (strcmp(pname
, PICL_PROP_PEER
) == 0)
2176 srcp
= &nodep
->sibling_node
->ptree_hdl
;
2178 return (PICL_FAILURE
);
2180 (void) memcpy(vbuf
, srcp
, sizeof (picl_nodehdl_t
));
2182 (void) rw_unlock(&ptree_rwlock
);
2183 return (PICL_SUCCESS
);
2187 * Returns the property value in the buffer and releases the node and
2189 * For volatile properties, this function releases the locks on ptree
2190 * table and the node before calling the plug-in provided access function
2193 read_propval_and_unlock(picl_obj_t
*nodep
, picl_obj_t
*propp
, void *vbuf
,
2197 int (*volrd
)(ptree_rarg_t
*arg
, void *buf
);
2200 if (propp
->prop_mode
& PICL_VOLATILE
) {
2204 rarg
.nodeh
= nodep
->ptree_hdl
;
2206 rarg
.nodeh
= PICL_INVALID_PICLHDL
;
2207 rarg
.proph
= propp
->ptree_hdl
;
2209 volrd
= propp
->read_func
;
2211 unlock_node(nodep
); /* unlock node */
2212 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2217 err
= (volrd
)(&rarg
, vbuf
);
2219 } else if (propp
->prop_type
== PICL_PTYPE_CHARSTRING
)
2220 (void) strlcpy(vbuf
, propp
->prop_val
, propp
->prop_size
);
2222 (void) memcpy(vbuf
, propp
->prop_val
, propp
->prop_size
);
2225 (void) rw_unlock(&ptree_rwlock
);
2230 xptree_get_propval_with_cred(picl_prophdl_t proph
, void *vbuf
, size_t size
,
2237 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2238 nodep
= propp
= NULL
;
2239 err
= lookup_and_lock_propnode(RDLOCK_NODE
, proph
, &nodep
, &propp
);
2240 if (err
!= PICL_SUCCESS
) {
2241 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2245 err
= check_propsize(PROP_READ
, propp
, size
);
2246 if (err
!= PICL_SUCCESS
) {
2247 unlock_node(nodep
); /* unlock node */
2248 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2252 return (read_propval_and_unlock(nodep
, propp
, vbuf
, cred
));
2256 * This function gets the credentials and calls get_propval_with_cred.
2259 ptree_get_propval(picl_prophdl_t proph
, void *vbuf
, size_t size
)
2261 return (xptree_get_propval_with_cred(proph
, vbuf
, size
, picld_cred
));
2265 * This function retrieves a property's value by by its name
2266 * For volatile properties, the locks on ptree and node are released
2267 * before calling the plug-in provided access function
2270 xptree_get_propval_by_name_with_cred(picl_nodehdl_t nodeh
, const char *pname
,
2271 void *vbuf
, size_t size
, door_cred_t cred
)
2277 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2280 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2281 if (err
!= PICL_SUCCESS
) {
2282 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2286 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2287 if (err
!= PICL_SUCCESS
) {
2289 (void) rw_unlock(&ptree_rwlock
);
2293 if (picl_restricted(pname
))
2294 return (read_reserved_propval_and_unlock(nodep
, pname
, vbuf
,
2297 err
= check_propsize(PROP_READ
, propp
, size
);
2298 if (err
!= PICL_SUCCESS
) {
2300 (void) rw_unlock(&ptree_rwlock
);
2304 return (read_propval_and_unlock(nodep
, propp
, vbuf
, cred
));
2308 * This function is used by plugins to get a value of a property
2309 * looking it up by its name.
2312 ptree_get_propval_by_name(picl_nodehdl_t nodeh
, const char *pname
, void *vbuf
,
2315 return (xptree_get_propval_by_name_with_cred(nodeh
, pname
, vbuf
, size
,
2320 * This function updates a property's value.
2321 * For volatile properties, the locks on the node and the ptree table
2322 * are released before calling the plug-in provided access function.
2325 write_propval_and_unlock(picl_obj_t
*nodep
, picl_obj_t
*propp
, const void *vbuf
,
2326 size_t size
, door_cred_t cred
)
2329 int (*volwr
)(ptree_warg_t
*arg
, const void *buf
);
2332 if (propp
->prop_mode
& PICL_VOLATILE
) {
2336 warg
.nodeh
= nodep
->ptree_hdl
;
2338 warg
.nodeh
= PICL_INVALID_PICLHDL
;
2339 warg
.proph
= propp
->ptree_hdl
;
2341 volwr
= propp
->write_func
;
2343 unlock_node(nodep
); /* unlock node */
2344 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2349 err
= (volwr
)(&warg
, vbuf
);
2352 (void) memcpy(propp
->prop_val
, vbuf
, size
);
2354 unlock_node(nodep
); /* unlock node */
2355 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2360 xptree_update_propval_with_cred(picl_prophdl_t proph
, const void *vbuf
,
2361 size_t size
, door_cred_t cred
)
2367 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2368 nodep
= propp
= NULL
;
2369 err
= lookup_and_lock_propnode(WRLOCK_NODE
, proph
, &nodep
, &propp
);
2370 if (err
!= PICL_SUCCESS
) {
2371 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2375 err
= check_propsize(PROP_WRITE
, propp
, size
);
2376 if (err
!= PICL_SUCCESS
) {
2377 unlock_node(nodep
); /* unlock node */
2378 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2382 return (write_propval_and_unlock(nodep
, propp
, vbuf
, size
, cred
));
2386 * Ptree function used by plug-ins to update a property's value
2387 * calls update_propval_with_cred(), which releases locks for volatile props
2390 ptree_update_propval(picl_prophdl_t proph
, const void *vbuf
, size_t size
)
2392 return (xptree_update_propval_with_cred(proph
, vbuf
, size
, picld_cred
));
2396 * This function writes/updates a property's value by looking it up
2398 * For volatile properties this function releases the locks on the
2399 * node and the ptree table.
2402 xptree_update_propval_by_name_with_cred(picl_nodehdl_t nodeh
, const char *pname
,
2403 const void *vbuf
, size_t size
, door_cred_t cred
)
2409 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2411 err
= lookup_and_lock_node(WRLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2412 if (err
!= PICL_SUCCESS
) {
2413 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2417 if (picl_restricted(pname
)) {
2419 (void) rw_unlock(&ptree_rwlock
);
2420 return (PICL_RESERVEDNAME
);
2423 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2424 if (err
!= PICL_SUCCESS
) {
2426 (void) rw_unlock(&ptree_rwlock
);
2430 err
= check_propsize(PROP_WRITE
, propp
, size
);
2431 if (err
!= PICL_SUCCESS
) {
2433 (void) rw_unlock(&ptree_rwlock
);
2437 return (write_propval_and_unlock(nodep
, propp
, vbuf
, size
, cred
));
2441 * This function updates the value of a property specified by its name
2444 ptree_update_propval_by_name(picl_nodehdl_t nodeh
, const char *pname
,
2445 const void *vbuf
, size_t size
)
2447 return (xptree_update_propval_by_name_with_cred(nodeh
, pname
, vbuf
,
2452 * This function retrieves the handle of a property by its name
2455 ptree_get_prop_by_name(picl_nodehdl_t nodeh
, const char *pname
,
2456 picl_prophdl_t
*proph
)
2462 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2464 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &nodep
); /* lock node */
2465 if (err
!= PICL_SUCCESS
) {
2466 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2470 if (picl_restricted(pname
)) {
2471 err
= PICL_RESERVEDNAME
;
2472 unlock_node(nodep
); /* unlock node */
2473 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2477 err
= lookup_prop_by_name(nodep
, pname
, &propp
);
2478 if (err
== PICL_SUCCESS
)
2479 *proph
= propp
->ptree_hdl
;
2481 unlock_node(nodep
); /* unlock node */
2482 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2487 * This function returns the handle of the first property
2490 ptree_get_first_prop(picl_nodehdl_t nodeh
, picl_prophdl_t
*proph
)
2495 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2497 err
= lookup_and_lock_node(RDLOCK_NODE
, nodeh
, &pobj
); /* lock node */
2498 if (err
!= PICL_SUCCESS
) {
2499 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2503 if (pobj
->first_prop
)
2504 *proph
= pobj
->first_prop
->ptree_hdl
;
2506 err
= PICL_ENDOFLIST
;
2508 unlock_node(pobj
); /* unlock node */
2509 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2514 * This function returns the handle of next property in the list
2517 ptree_get_next_prop(picl_prophdl_t proph
, picl_prophdl_t
*nextproph
)
2523 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
2524 nodep
= propp
= NULL
;
2525 err
= lookup_and_lock_propnode(RDLOCK_NODE
, proph
, &nodep
, &propp
);
2526 if (err
!= PICL_SUCCESS
) {
2527 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2531 if (propp
->next_prop
) {
2532 *nextproph
= propp
->next_prop
->ptree_hdl
;
2534 err
= PICL_ENDOFLIST
;
2536 unlock_node(nodep
); /* unlock node */
2537 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
2542 * These functions are called by ptree_get_node_by_path()
2543 * Append a prop expression entry to the list
2545 static prop_list_t
*
2546 append_entry_to_list(prop_list_t
*el
, prop_list_t
*list
)
2559 * Add it to the end of list
2563 while (ptr
->next
!= NULL
)
2572 * Free the property expression list
2575 free_list(prop_list_t
*list
)
2580 for (ptr
= list
; ptr
!= NULL
; ptr
= tmp
) {
2587 parse_prl(char *prl
, char **name
, char **baddr
, prop_list_t
**plist
)
2596 return (PICL_FAILURE
);
2598 if ((prl
[0] == '@') || (prl
[0] == '?'))
2599 return (PICL_FAILURE
);
2604 * get property expression
2606 ptr
= strchr(prl
, '?');
2617 ptr
= strchr(prl
, '@');
2622 if (strlen(*baddr
) == 0) /* no bus value after @ */
2623 return (PICL_FAILURE
);
2627 * create the prop list
2629 while (propptr
!= NULL
) {
2633 ptr
= strchr(propptr
, '?');
2635 if (ptr
!= NULL
) { /* more ?<prop>=<propval> */
2641 if (strlen(pname
) == 0) /* no prop exp after ? */
2642 return (PICL_FAILURE
);
2644 ptr
= strchr(pname
, '=');
2645 if (ptr
!= NULL
) { /* not void prop */
2649 * <prop>= is treated as void property
2651 if (strlen(pval
) == 0)
2655 el
= (prop_list_t
*)malloc(sizeof (prop_list_t
));
2659 *plist
= append_entry_to_list(el
, *plist
);
2662 return (PICL_SUCCESS
);
2666 prop_match(ptree_propinfo_t pinfo
, void *vbuf
, char *val
)
2679 switch (pinfo
.piclinfo
.type
) {
2680 case PICL_PTYPE_CHARSTRING
:
2681 if (strcasecmp(pinfo
.piclinfo
.name
, PICL_PROP_CLASSNAME
) == 0) {
2682 if (strcmp(val
, PICL_CLASS_PICL
) == 0)
2685 if (strcmp(val
, (char *)vbuf
) == 0)
2689 case PICL_PTYPE_INT
:
2690 switch (pinfo
.piclinfo
.size
) {
2691 case sizeof (int8_t):
2692 cval
= (int8_t)strtol(val
, (char **)NULL
, 0);
2693 return (cval
== *(char *)vbuf
);
2694 case sizeof (int16_t):
2695 sval
= (int16_t)strtol(val
, (char **)NULL
, 0);
2696 return (sval
== *(int16_t *)vbuf
);
2697 case sizeof (int32_t):
2698 intval
= (int32_t)strtol(val
, (char **)NULL
, 0);
2699 return (intval
== *(int32_t *)vbuf
);
2700 case sizeof (int64_t):
2701 llval
= strtoll(val
, (char **)NULL
, 0);
2702 return (llval
== *(int64_t *)vbuf
);
2706 case PICL_PTYPE_UNSIGNED_INT
:
2707 switch (pinfo
.piclinfo
.size
) {
2708 case sizeof (uint8_t):
2709 ucval
= (uint8_t)strtoul(val
, (char **)NULL
, 0);
2710 return (ucval
== *(uint8_t *)vbuf
);
2711 case sizeof (uint16_t):
2712 usval
= (uint16_t)strtoul(val
, (char **)NULL
, 0);
2713 return (usval
== *(uint16_t *)vbuf
);
2714 case sizeof (uint32_t):
2715 uintval
= (uint32_t)strtoul(val
, (char **)NULL
, 0);
2716 return (uintval
== *(uint32_t *)vbuf
);
2717 case sizeof (uint64_t):
2718 ullval
= strtoull(val
, (char **)NULL
, 0);
2719 return (ullval
== *(uint64_t *)vbuf
);
2723 case PICL_PTYPE_FLOAT
:
2724 switch (pinfo
.piclinfo
.size
) {
2725 case sizeof (float):
2726 fval
= (float)strtod(val
, (char **)NULL
);
2727 return (fval
== *(float *)vbuf
);
2728 case sizeof (double):
2729 dval
= strtod(val
, (char **)NULL
);
2730 return (dval
== *(double *)vbuf
);
2734 case PICL_PTYPE_VOID
:
2735 case PICL_PTYPE_TIMESTAMP
:
2736 case PICL_PTYPE_TABLE
:
2737 case PICL_PTYPE_REFERENCE
:
2738 case PICL_PTYPE_BYTEARRAY
:
2739 case PICL_PTYPE_UNKNOWN
:
2746 check_propval(picl_nodehdl_t nodeh
, char *pname
, char *pval
)
2749 picl_prophdl_t proph
;
2750 ptree_propinfo_t pinfo
;
2753 err
= ptree_get_prop_by_name(nodeh
, pname
, &proph
);
2754 if (err
!= PICL_SUCCESS
)
2757 err
= ptree_get_propinfo(proph
, &pinfo
);
2758 if (err
!= PICL_SUCCESS
)
2761 if (pval
== NULL
) { /* void type */
2762 if (pinfo
.piclinfo
.type
!= PICL_PTYPE_VOID
)
2763 return (PICL_FAILURE
);
2765 vbuf
= alloca(pinfo
.piclinfo
.size
);
2767 return (PICL_FAILURE
);
2768 err
= ptree_get_propval(proph
, vbuf
,
2769 pinfo
.piclinfo
.size
);
2770 if (err
!= PICL_SUCCESS
)
2773 if (!prop_match(pinfo
, vbuf
, pval
))
2774 return (PICL_FAILURE
);
2776 return (PICL_SUCCESS
);
2780 get_child_by_path(picl_nodehdl_t rooth
, char *prl
,
2781 picl_nodehdl_t
*nodeh
, char *pname
)
2783 picl_nodehdl_t chdh
;
2794 return (PICL_FAILURE
);
2796 path
= strdupa(prl
);
2798 return (PICL_FAILURE
);
2804 err
= parse_prl(path
, &nodename
, &baddr
, &plist
);
2805 if (err
!= PICL_SUCCESS
) {
2810 if (nodename
== NULL
)
2811 return (PICL_FAILURE
);
2813 nameval
= alloca(strlen(nodename
) + 1);
2814 if (nameval
== NULL
) {
2816 return (PICL_FAILURE
);
2819 if (baddr
!= NULL
) {
2820 busval
= alloca(strlen(baddr
) + 1);
2821 if (busval
== NULL
) {
2823 return (PICL_FAILURE
);
2827 for (err
= ptree_get_propval_by_name(rooth
, PICL_PROP_CHILD
, &chdh
,
2828 sizeof (picl_nodehdl_t
)); err
!= PICL_PROPNOTFOUND
;
2829 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
2830 sizeof (picl_nodehdl_t
))) {
2831 if (err
!= PICL_SUCCESS
) {
2833 return (PICL_FAILURE
);
2839 if ((strcmp(pname
, PICL_PROP_CLASSNAME
) != 0) ||
2840 (strcmp(nodename
, PICL_CLASS_PICL
) != 0)) {
2841 err
= ptree_get_propval_by_name(chdh
, pname
,
2842 nameval
, (strlen(nodename
) + 1));
2844 if (err
!= PICL_SUCCESS
)
2846 if (strcmp(nameval
, nodename
) != 0)
2851 * compare device address with bus-addr prop first
2852 * then with UnitAddress property
2854 if (baddr
!= NULL
) { /* compare bus-addr prop */
2855 if ((ptree_get_propval_by_name(chdh
, PICL_PROP_BUS_ADDR
,
2856 busval
, (strlen(baddr
) + 1)) != PICL_SUCCESS
) &&
2857 (ptree_get_propval_by_name(chdh
,
2858 PICL_PROP_UNIT_ADDRESS
, busval
,
2859 (strlen(baddr
) + 1)) != PICL_SUCCESS
))
2862 if (strcmp(busval
, baddr
) != 0)
2863 continue; /* not match */
2866 if (plist
== NULL
) { /* no prop expression */
2868 return (PICL_SUCCESS
);
2872 * compare the property expression list
2876 while (ptr
!= NULL
) {
2877 err
= check_propval(chdh
, ptr
->pname
, ptr
->pval
);
2878 if (err
!= PICL_SUCCESS
)
2886 return (PICL_SUCCESS
);
2890 return (PICL_NOTNODE
);
2894 * This functions returns the handle of node specified by its path
2897 ptree_get_node_by_path(const char *piclprl
, picl_nodehdl_t
*handle
)
2899 picl_nodehdl_t rooth
;
2900 picl_nodehdl_t chdh
;
2907 int npflg
; /* namepath flag */
2910 path
= strdupa(piclprl
);
2912 return (PICL_FAILURE
);
2914 npflg
= 1; /* default */
2916 if (path
[0] == '/') {
2918 } else if ((tokindex
= strchr(path
, ':')) != NULL
) {
2921 if (*tokindex
== '/')
2924 return (PICL_NOTNODE
);
2927 return (PICL_NOTNODE
);
2929 err
= ptree_get_root(&rooth
);
2930 if (err
!= PICL_SUCCESS
)
2933 for (chdh
= rooth
, tokindex
= strchr(ptr
, '/');
2935 ptr
= tokindex
+ 1, tokindex
= strchr(ptr
, '/')) {
2938 err
= get_child_by_path(chdh
, ptr
, &chdh
,
2941 err
= get_child_by_path(chdh
, ptr
, &chdh
,
2944 if (err
!= PICL_SUCCESS
)
2949 * check if last token is empty or not
2950 * eg. /a/b/c/ or /a/b/c
2954 return (PICL_SUCCESS
);
2957 len
= strcspn(ptr
, " \t\n");
2960 return (PICL_SUCCESS
);
2965 err
= get_child_by_path(chdh
, ptr
, &chdh
, PICL_PROP_NAME
);
2967 err
= get_child_by_path(chdh
, ptr
, &chdh
, defprop
);
2969 if (err
!= PICL_SUCCESS
)
2973 return (PICL_SUCCESS
);
2977 * Initialize propinfo
2980 ptree_init_propinfo(ptree_propinfo_t
*infop
, int version
, int ptype
, int pmode
,
2981 size_t psize
, char *pname
, int (*readfn
)(ptree_rarg_t
*, void *),
2982 int (*writefn
)(ptree_warg_t
*, const void *))
2984 if (version
!= PTREE_PROPINFO_VERSION_1
)
2985 return (PICL_NOTSUPPORTED
);
2986 if ((infop
== NULL
) || (pname
== NULL
))
2987 return (PICL_INVALIDARG
);
2988 infop
->version
= version
;
2989 infop
->piclinfo
.type
= ptype
;
2990 infop
->piclinfo
.accessmode
= pmode
;
2991 infop
->piclinfo
.size
= psize
;
2992 infop
->read
= readfn
;
2993 infop
->write
= writefn
;
2994 (void) strlcpy(infop
->piclinfo
.name
, pname
, PICL_PROPNAMELEN_MAX
);
2995 return (PICL_SUCCESS
);
2999 * Creates a property, adds it to the node, and returns the property
3000 * handle to the caller if successful and proph is not NULL
3003 ptree_create_and_add_prop(picl_nodehdl_t nodeh
, ptree_propinfo_t
*infop
,
3004 void *vbuf
, picl_prophdl_t
*proph
)
3007 picl_prophdl_t tmph
;
3009 err
= ptree_create_prop(infop
, vbuf
, &tmph
);
3010 if (err
!= PICL_SUCCESS
)
3012 err
= ptree_add_prop(nodeh
, tmph
);
3013 if (err
!= PICL_SUCCESS
) {
3014 (void) ptree_destroy_prop(tmph
);
3019 return (PICL_SUCCESS
);
3023 * Creates a node, adds it to its parent node, and returns the node
3024 * handle to the caller if successful
3027 ptree_create_and_add_node(picl_nodehdl_t rooth
, const char *name
,
3028 const char *classname
, picl_nodehdl_t
*nodeh
)
3030 picl_nodehdl_t tmph
;
3033 err
= ptree_create_node(name
, classname
, &tmph
);
3035 if (err
!= PICL_SUCCESS
)
3038 err
= ptree_add_node(rooth
, tmph
);
3039 if (err
!= PICL_SUCCESS
) {
3040 (void) ptree_destroy_node(tmph
);
3045 return (PICL_SUCCESS
);
3050 * recursively visit all nodes
3053 do_walk(picl_nodehdl_t rooth
, const char *classname
,
3054 void *c_args
, int (*callback_fn
)(picl_nodehdl_t hdl
, void *args
))
3057 picl_nodehdl_t chdh
;
3058 char classval
[PICL_CLASSNAMELEN_MAX
];
3060 err
= ptree_get_propval_by_name(rooth
, PICL_PROP_CHILD
, &chdh
,
3062 while (err
== PICL_SUCCESS
) {
3063 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_CLASSNAME
,
3064 classval
, sizeof (classval
));
3065 if (err
!= PICL_SUCCESS
)
3068 if ((classname
== NULL
) || (strcmp(classname
, classval
) == 0)) {
3069 err
= callback_fn(chdh
, c_args
);
3070 if (err
!= PICL_WALK_CONTINUE
)
3074 if ((err
= do_walk(chdh
, classname
, c_args
, callback_fn
)) !=
3078 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
3081 if (err
== PICL_PROPNOTFOUND
) /* end of a branch */
3082 return (PICL_WALK_CONTINUE
);
3088 * This function visits all the nodes in the subtree rooted at <rooth>.
3089 * For each node that matches the class name specified, the callback
3090 * function is invoked.
3093 ptree_walk_tree_by_class(picl_nodehdl_t rooth
, const char *classname
,
3094 void *c_args
, int (*callback_fn
)(picl_nodehdl_t hdl
, void *args
))
3098 if (callback_fn
== NULL
)
3099 return (PICL_INVALIDARG
);
3100 err
= do_walk(rooth
, classname
, c_args
, callback_fn
);
3101 if ((err
== PICL_WALK_CONTINUE
) || (err
== PICL_WALK_TERMINATE
))
3102 return (PICL_SUCCESS
);
3107 compare_propval(picl_nodehdl_t nodeh
, char *pname
, picl_prop_type_t ptype
,
3108 void *pval
, size_t valsize
)
3111 picl_prophdl_t proph
;
3112 ptree_propinfo_t propinfo
;
3115 err
= ptree_get_prop_by_name(nodeh
, pname
, &proph
);
3116 if (err
!= PICL_SUCCESS
)
3118 err
= ptree_get_propinfo(proph
, &propinfo
);
3119 if (err
!= PICL_SUCCESS
)
3121 if (propinfo
.piclinfo
.type
!= ptype
)
3123 if (propinfo
.piclinfo
.type
== PICL_PTYPE_VOID
)
3127 if (valsize
> propinfo
.piclinfo
.size
)
3129 vbuf
= alloca(propinfo
.piclinfo
.size
);
3132 err
= ptree_get_propval(proph
, vbuf
, propinfo
.piclinfo
.size
);
3133 if (err
!= PICL_SUCCESS
)
3135 if (memcmp(vbuf
, pval
, valsize
) == 0)
3142 * This function traverses the subtree and finds a node that has a property
3143 * of the specified name and type with the specified value.
3144 * The matched node in the tree is returned in retnodeh. If there is
3145 * no node with that property, then PICL_NODENOTFOUND is returned.
3148 ptree_find_node(picl_nodehdl_t rooth
, char *pname
, picl_prop_type_t ptype
,
3149 void *pval
, size_t valsize
, picl_nodehdl_t
*retnodeh
)
3152 picl_nodehdl_t chdh
;
3155 return (PICL_INVALIDARG
);
3156 err
= ptree_get_propval_by_name(rooth
, PICL_PROP_CHILD
, &chdh
,
3159 while (err
== PICL_SUCCESS
) {
3160 if (compare_propval(chdh
, pname
, ptype
, pval
, valsize
)) {
3163 return (PICL_SUCCESS
);
3166 err
= ptree_find_node(chdh
, pname
, ptype
, pval
, valsize
,
3168 if (err
!= PICL_NODENOTFOUND
)
3171 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
3174 if (err
== PICL_PROPNOTFOUND
)
3175 return (PICL_NODENOTFOUND
);
3180 * This function gets the frutree parent for a given node.
3181 * Traverse up the tree and look for the following properties:
3182 * Frutree parent reference properties:
3186 * If the frutree reference property is found, return its value.
3187 * Else, return the handle of /frutree/chassis.
3190 ptree_get_frutree_parent(picl_nodehdl_t nodeh
, picl_nodehdl_t
*fruh
)
3193 picl_nodehdl_t nparh
;
3194 picl_nodehdl_t fruparh
;
3198 while (err
== PICL_SUCCESS
) {
3199 err
= ptree_get_propval_by_name(nparh
, PICL_REFPROP_FRU_PARENT
,
3200 &fruparh
, sizeof (fruparh
));
3201 if (err
== PICL_SUCCESS
) {
3203 return (PICL_SUCCESS
);
3205 err
= ptree_get_propval_by_name(nparh
,
3206 PICL_REFPROP_LOC_PARENT
, &fruparh
, sizeof (fruparh
));
3207 if (err
== PICL_SUCCESS
) {
3209 return (PICL_SUCCESS
);
3211 err
= ptree_get_propval_by_name(nparh
, PICL_REFPROP_PORT_PARENT
,
3212 &fruparh
, sizeof (fruparh
));
3213 if (err
== PICL_SUCCESS
) {
3215 return (PICL_SUCCESS
);
3218 err
= ptree_get_propval_by_name(nparh
, PICL_PROP_PARENT
, &nparh
,
3222 if (err
== PICL_PROPNOTFOUND
) { /* return /frutree/chassis handle */
3223 err
= ptree_get_node_by_path(PICL_FRUTREE_CHASSIS
, &fruparh
);
3224 if (err
== PICL_SUCCESS
) {
3226 return (PICL_SUCCESS
);
3233 * This function is called by plug-ins to register with the daemon
3236 picld_plugin_register(picld_plugin_reg_t
*regp
)
3238 picld_plugin_reg_list_t
*el
;
3239 picld_plugin_reg_list_t
*tmp
;
3242 return (PICL_FAILURE
);
3244 if (regp
->version
!= PICLD_PLUGIN_VERSION_1
)
3245 return (PICL_NOTSUPPORTED
);
3247 el
= malloc(sizeof (picld_plugin_reg_list_t
));
3249 return (PICL_FAILURE
);
3250 el
->reg
.version
= regp
->version
;
3251 el
->reg
.critical
= regp
->critical
;
3253 el
->reg
.name
= strdup(regp
->name
);
3254 if (el
->reg
.name
== NULL
)
3255 return (PICL_FAILURE
);
3257 el
->reg
.plugin_init
= regp
->plugin_init
;
3258 el
->reg
.plugin_fini
= regp
->plugin_fini
;
3261 if (plugin_reg_list
== NULL
) {
3262 plugin_reg_list
= el
;
3263 } else { /* add to end */
3264 tmp
= plugin_reg_list
;
3265 while (tmp
->next
!= NULL
)
3270 return (PICL_SUCCESS
);
3274 * Call fini routines of the registered plugins
3277 plugin_fini(picld_plugin_reg_list_t
*p
)
3282 plugin_fini(p
->next
);
3283 if (p
->reg
.plugin_fini
)
3284 (p
->reg
.plugin_fini
)();
3292 init_plugin_reg_list(void)
3294 plugin_reg_list
= NULL
;
3298 picltree_set_root(picl_nodehdl_t rooth
)
3303 (void) rw_rdlock(&ptree_rwlock
); /* lock ptree */
3305 err
= lookup_and_lock_node(RDLOCK_NODE
, rooth
, &pobj
); /* lock node */
3306 if (err
!= PICL_SUCCESS
) {
3307 (void) rw_unlock(&ptree_rwlock
);
3308 return (PICL_FAILURE
);
3311 picl_root_obj
= pobj
;
3312 ptree_root_hdl
= pobj
->ptree_hdl
;
3313 unlock_node(pobj
); /* unlock node */
3314 (void) rw_unlock(&ptree_rwlock
); /* unlock ptree */
3315 return (PICL_SUCCESS
);
3321 (void) rwlock_init(&ptree_rwlock
, USYNC_THREAD
, NULL
);
3322 (void) rwlock_init(&picltbl_rwlock
, USYNC_THREAD
, NULL
);
3324 if (hash_init(&picltbl
) < 0)
3325 return (PICL_FAILURE
);
3326 if (hash_init(&ptreetbl
) < 0)
3327 return (PICL_FAILURE
);
3329 if (pthread_mutex_init(&ptreehdl_lock
, NULL
) != 0)
3330 return (PICL_FAILURE
);
3332 if (pthread_mutex_init(&piclhdl_lock
, NULL
) != 0)
3333 return (PICL_FAILURE
);
3335 if (pthread_mutex_init(&evtq_lock
, NULL
) != 0)
3336 return (PICL_FAILURE
);
3337 if (pthread_cond_init(&evtq_cv
, NULL
) != 0)
3338 return (PICL_FAILURE
);
3339 if (pthread_mutex_init(&evthandler_lock
, NULL
) != 0)
3340 return (PICL_FAILURE
);
3342 picl_root_obj
= NULL
;
3344 evt_handlers
= NULL
;
3345 ptree_root_hdl
= PICL_INVALID_PICLHDL
;
3347 return (PICL_SUCCESS
);
3351 add_unique_plugin_to_list(char *path
, char *name
)
3354 picld_plugin_desc_t
*pl
;
3355 picld_plugin_desc_t
*tmp
;
3358 while (pl
!= NULL
) {
3359 if (strcmp(pl
->libname
, name
) == 0)
3365 pl
= malloc(sizeof (picld_plugin_desc_t
));
3369 pl
->libname
= strdup(name
);
3370 if (pl
->libname
== NULL
)
3372 buf
= alloca(strlen(name
) + strlen(path
) + 2);
3375 (void) strcpy(buf
, path
);
3376 (void) strcat(buf
, name
);
3377 pl
->pathname
= strdup(buf
);
3378 if (pl
->pathname
== NULL
)
3383 if (plugin_desc
== NULL
)
3387 while (tmp
->next
!= NULL
)
3394 get_plugins_from_dir(char *dirname
)
3399 int solen
= strlen(SO_VERS
) + 1;
3401 if ((dir
= opendir(dirname
)) == NULL
)
3404 while ((ent
= readdir(dir
)) != NULL
) {
3405 if ((strcmp(ent
->d_name
, ".") == 0) ||
3406 (strcmp(ent
->d_name
, "..") == 0))
3409 len
= strlen(ent
->d_name
) + 1;
3413 if (strcmp(ent
->d_name
+ (len
- solen
), SO_VERS
) == 0)
3414 add_unique_plugin_to_list(dirname
, ent
->d_name
);
3417 (void) closedir(dir
);
3422 init_plugin_list(void)
3424 char nmbuf
[SYS_NMLN
];
3425 char pname
[PATH_MAX
];
3428 if (sysinfo(SI_PLATFORM
, nmbuf
, sizeof (nmbuf
)) != -1) {
3429 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
3430 if (access(pname
, R_OK
) == 0)
3431 get_plugins_from_dir(pname
);
3434 if (sysinfo(SI_MACHINE
, nmbuf
, sizeof (nmbuf
)) != -1) {
3435 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
3436 if (access(pname
, R_OK
) == 0)
3437 get_plugins_from_dir(pname
);
3440 (void) snprintf(pname
, PATH_MAX
, "%s/", PICLD_COMMON_PLUGIN_DIR
);
3441 if (access(pname
, R_OK
) == 0)
3442 get_plugins_from_dir(pname
);
3448 picld_plugin_desc_t
*pl
;
3451 while (pl
!= NULL
) {
3452 pl
->dlh
= dlopen(pl
->pathname
, RTLD_LAZY
|RTLD_LOCAL
);
3453 if (pl
->dlh
== NULL
) {
3454 syslog(LOG_CRIT
, dlerror());
3464 add_root_props(picl_nodehdl_t rooth
)
3467 picl_prophdl_t proph
;
3468 ptree_propinfo_t pinfo
;
3471 #define PICL_PROP_PICL_VERSION "PICLVersion"
3472 #define PICL_VERSION 1.1
3474 err
= ptree_init_propinfo(&pinfo
, PTREE_PROPINFO_VERSION_1
,
3475 PICL_PTYPE_FLOAT
, PICL_READ
, sizeof (picl_vers
),
3476 PICL_PROP_PICL_VERSION
, NULL
, NULL
);
3477 if (err
!= PICL_SUCCESS
)
3480 picl_vers
= PICL_VERSION
;
3481 err
= ptree_create_and_add_prop(rooth
, &pinfo
, &picl_vers
, &proph
);
3486 construct_picltree(void)
3489 picld_plugin_reg_list_t
*iter
;
3490 picl_nodehdl_t rhdl
;
3495 if ((err
= ptree_create_node(PICL_NODE_ROOT
, PICL_CLASS_PICL
,
3496 &rhdl
)) != PICL_SUCCESS
) {
3500 if (picltree_set_root(rhdl
) != PICL_SUCCESS
) {
3501 return (PICL_FAILURE
);
3504 err
= add_root_props(rhdl
);
3505 if (err
!= PICL_SUCCESS
)
3509 * Initialize the registered plug-in modules
3511 iter
= plugin_reg_list
;
3512 while (iter
!= NULL
) {
3513 if (iter
->reg
.plugin_init
)
3514 (iter
->reg
.plugin_init
)();
3517 return (PICL_SUCCESS
);
3521 xptree_destroy(void)
3523 dbg_print(1, "xptree_destroy: picl_root_obj = %s\n",
3524 (picl_root_obj
== NULL
? "NULL" : "not-NULL"));
3526 if (picl_root_obj
== NULL
)
3529 dbg_print(1, "xptree_destroy: call plugin_fini\n");
3530 plugin_fini(plugin_reg_list
);
3531 dbg_print(1, "xptree_destroy: plugin_fini DONE\n");
3533 (void) ptree_delete_node(picl_root_obj
->ptree_hdl
);
3534 (void) ptree_destroy_node(picl_root_obj
->ptree_hdl
);
3536 (void) rw_wrlock(&ptree_rwlock
);
3537 picl_root_obj
= NULL
;
3538 (void) rw_unlock(&ptree_rwlock
);
3543 xptree_initialize(int flg
)
3546 pthread_attr_t attr
;
3549 picld_pid
= getpid();
3550 picld_cred
.dc_euid
= geteuid();
3551 picld_cred
.dc_egid
= getegid();
3552 picld_cred
.dc_ruid
= getuid();
3553 picld_cred
.dc_rgid
= getgid();
3554 picld_cred
.dc_pid
= getpid();
3558 ptree_generation
= 1;
3561 if (pthread_mutex_init(&ptree_refresh_mutex
, NULL
) != 0)
3562 return (PICL_FAILURE
);
3564 if (picltree_init() != PICL_SUCCESS
)
3565 return (PICL_FAILURE
);
3567 init_plugin_reg_list();
3571 err
= construct_picltree();
3572 if (err
!= PICL_SUCCESS
)
3576 * Dispatch events after all plug-ins have initialized
3578 if (pthread_attr_init(&attr
) != 0)
3579 return (PICL_FAILURE
);
3581 (void) pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
);
3582 if (pthread_create(&tid
, &attr
, ptree_event_thread
, NULL
))
3583 return (PICL_FAILURE
);
3585 return (PICL_SUCCESS
);
3589 xptree_reinitialize(void)
3594 * Wait for eventq to become empty
3596 dbg_print(1, "xptree_reinitialize: wait for evtq empty\n");
3597 (void) pthread_mutex_lock(&evtq_lock
);
3599 while (eventqp
!= NULL
)
3600 (void) pthread_cond_wait(&evtq_empty
, &evtq_lock
);
3602 (void) pthread_mutex_unlock(&evtq_lock
);
3603 dbg_print(1, "xptree_reinitialize: evtq empty is EMPTY\n");
3605 (void) rw_wrlock(&ptree_rwlock
);
3606 picl_root_obj
= NULL
;
3607 ptree_root_hdl
= PICL_INVALID_PICLHDL
;
3608 (void) rw_unlock(&ptree_rwlock
);
3609 (void) pthread_mutex_lock(&ptree_refresh_mutex
);
3611 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
3613 err
= construct_picltree();
3614 (void) pthread_mutex_lock(&ptree_refresh_mutex
);
3615 (void) pthread_cond_broadcast(&ptree_refresh_cond
);
3616 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
3618 (void) pthread_mutex_lock(&evtq_lock
);
3619 (void) pthread_cond_broadcast(&evtq_cv
);
3620 (void) pthread_mutex_unlock(&evtq_lock
);
3626 * This function is called by the PICL daemon on behalf of clients to
3627 * wait for a tree refresh
3630 xptree_refresh_notify(uint32_t secs
)
3637 if (pthread_mutex_lock(&ptree_refresh_mutex
) != 0)
3638 return (PICL_FAILURE
);
3640 curgen
= ptree_generation
;
3642 while (curgen
== ptree_generation
) {
3643 if (secs
== UINT32_MAX
) /* wait forever */
3644 (void) pthread_cond_wait(&ptree_refresh_cond
,
3645 &ptree_refresh_mutex
);
3649 ret
= pthread_cond_reltimedwait_np(
3650 &ptree_refresh_cond
,
3651 &ptree_refresh_mutex
, &to
);
3652 if (ret
== ETIMEDOUT
)
3657 (void) pthread_mutex_unlock(&ptree_refresh_mutex
);
3660 return (PICL_SUCCESS
);
3665 dbg_print(int level
, const char *fmt
, ...)
3667 if (verbose_level
>= level
) {
3671 (void) vprintf(fmt
, ap
);
3678 dbg_exec(int level
, void (*fn
)(void *args
), void *args
)
3680 if (verbose_level
> level
)