picltree.c revision cec46d775eb90ec3bcda95b59e0c3e8aa9206b22
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This module implements the PTree interface and the PICL to PTree calls
*/
/*
* Note:
* PICL Node and Property Handles Table:
* A node or property in PICL tree has two handles: a ptree handle, which is
* used by plug-ins and the libpicltree interface, and a picl handle
* which is used by clients and the libpicl interface.
* The mapping of ptree handles to the internal PICL object (picl_obj_t) is
* kept in a ptree hash table (ptreetbl), and the mapping of a picl handle
* to its ptree handle is kept in the picl hash table (picltbl).
* or modifying picl hash table (picltbl).
*
* The mutex, ptreehdl_lock, is used to control allocation of ptree handles.
* The mutex, piclhdl_lock, is used to control allocation of picl handles.
*
* The mutex, ptree_refresh_mutex, and the condition, ptree_refresh_cond,
* change in PICL tree structure.
*
* The counter, picl_hdl_hi, is the hi water mark for allocated picl handles.
* The counter, ptree_hdl_hi, is the hi water mark for allocated ptree handles.
* A stale handle error is returned for handle values below the hi water
* mark, and invalid handles are returned for handle values above the hi water
* mark or when the process id field of the handle does not match.
*
* Locking Scheme:
* The structure of the PICL tree is controlled by the ptree_rwlock. The
* properties of a node are controlled by individual node locks. The
* piclize-ing or unpiclize-ing of a node is controlled by picltbl_rwlock.
*
* Two-Phase Locking scheme: lock acquire phase and lock release phase.
*
* Lock Ordering:
* The ptree_rwlock and node locks are always acquired in the following order:
* lock ptree_rwlock
* lock node
*
* Lock Strategy:
* There are three locks:
* ptree_rwlock: a reader lock is obtained to do ptree hash table
* lookups and traverse tree. A writer lock is obtained
* when creating or destroying nodes from the ptree,
* or when modifying node linkages: parent, peer, child.
* picltbl_rwlock: a reader lock is obtained for picl hash table lookups.
* A writer lock is obtained when piclize-ing or
* unpiclize-ing nodes or properties.
* A reader lock is obtained before reading property
* values. A writer lock is obtained when adding or
* removing properties and when modifying a property value.
*
* Never hold more than one node lock at a time.
*
* Event Locking:
* There are two locks:
* evtq_lock: this lock protects the event queue. It is obtained
* to queue events that are posted and to unqueue
* events to be dispatched.
* evtq_cv: condition variable is protected by evtq_lock. It is
* used by the ptree event thread to wait for events
* until eventqp is not NULL.
* evtq_empty: condition variable protected by evtq_lock. It is
* used to signal when the eventq becomes empty. The
* reinitialization process waits on this condition.
* evthandler_lock: this protects the event handler list. It is obtained
* to add event handlers on registration and to remove
* event handlers on unregistration.
* (handler)->cv: condition variable per handler protected by
* evthandler_lock. It is used to wait until the
* event handler completes execution (execflg == 0)
* before unregistering the handler.
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdarg.h>
#include <alloca.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <libintl.h>
#include <syslog.h>
#include <pthread.h>
#include <synch.h>
#include <setjmp.h>
#include <signal.h>
#include <dlfcn.h>
#include <dirent.h>
#include <door.h>
#include <time.h>
#include <inttypes.h>
#include <sys/systeminfo.h>
#include <picl.h>
#include <picltree.h>
#include "picldefs.h"
#include "ptree_impl.h"
#define SO_VERS ".so.1"
static pthread_mutex_t ptreehdl_lock;
static pthread_mutex_t piclhdl_lock;
static pthread_mutex_t ptree_refresh_mutex;
static int ptree_generation = 0;
static door_cred_t picld_cred;
static int qempty_wait; /* evtq_empty condition waiter flag */
static picld_plugin_desc_t *plugin_desc;
/*
* PICL daemon verbose level
*/
int verbose_level;
/*
* Event handler free functions
*/
static void
{
}
/*
* queue_event to events queue
*/
static void
{
else {
}
}
/*
* unqueue_event from the specified eventq
*/
static eventq_t *
{
return (evtp);
}
/*
* register an event handler by adding it to the list
*/
int
ptree_register_handler(const char *ename,
{
return (PICL_INVALIDARG);
/*
* Initialize event handler entry
*/
return (PICL_FAILURE);
return (PICL_FAILURE);
}
/*
* add handler to the handler list
*/
(void) pthread_mutex_lock(&evthandler_lock);
if (evt_handlers == NULL) {
evt_handlers = ent;
(void) pthread_mutex_unlock(&evthandler_lock);
return (PICL_SUCCESS);
}
iter = evt_handlers;
(void) pthread_mutex_unlock(&evthandler_lock);
return (PICL_SUCCESS);
}
/*
* unregister handler
*/
void
ptree_unregister_handler(const char *ename,
{
return;
/*
* unlink handler from handler list
*/
(void) pthread_mutex_lock(&evthandler_lock);
continue;
/*
* If the handler is in execution, release the lock
* and wait for it to complete and retry.
*/
goto retry;
}
/*
* Unlink this handler from the linked list
*/
break;
}
(void) pthread_mutex_unlock(&evthandler_lock);
}
/*
* Call all registered handlers for the event
*/
static void
{
(void) pthread_mutex_lock(&evthandler_lock);
iter = evt_handlers;
(void) pthread_mutex_unlock(&evthandler_lock);
if (evhandler) {
}
(void) pthread_mutex_lock(&evthandler_lock);
}
}
}
(void) pthread_mutex_unlock(&evthandler_lock);
dbg_print(2,
"ptree_evthr: Invoking completion hdlr:%p ename:%s\n",
}
(void) pthread_mutex_lock(&ptree_refresh_mutex);
(void) pthread_cond_broadcast(&ptree_refresh_cond);
(void) pthread_mutex_unlock(&ptree_refresh_mutex);
}
/*
* This function is called by a plug-in to post an event
*/
int
{
return (PICL_INVALIDARG);
return (PICL_FAILURE);
(void) pthread_mutex_lock(&evtq_lock);
(void) pthread_cond_broadcast(&evtq_cv);
(void) pthread_mutex_unlock(&evtq_lock);
return (PICL_SUCCESS);
}
/*
* PICLTREE event thread
*/
/*ARGSUSED*/
static void *
ptree_event_thread(void *argp)
{
for (;;) {
(void) pthread_mutex_lock(&evtq_lock);
/*
* Signal empty queue
*/
if (qempty_wait)
(void) pthread_cond_broadcast(&evtq_empty);
}
(void) pthread_mutex_unlock(&evtq_lock);
} else
(void) pthread_mutex_unlock(&evtq_lock);
}
/*NOTREACHED*/
return (NULL);
}
/*
* Create a new element
*/
static hash_elem_t *
{
hash_elem_t *n;
n = malloc(sizeof (*n));
if (n == NULL)
return (NULL);
return (n);
}
static hash_elem_t *
{
hash_elem_t *n;
n = malloc(sizeof (*n));
if (n == NULL)
return (NULL);
return (n);
}
/*
* Initialize a hash table by setting all entries to NULL
*/
static int
{
int i;
return (-1);
return (0);
}
/*
* Lock free function to add an entry in the hash table
*/
static int
{
int indx;
hash_elem_t *n;
if (n == NULL)
return (-1);
return (0);
}
static int
{
int indx;
hash_elem_t *n;
if (n == NULL)
return (-1);
return (0);
}
/*
* Lock free function to remove the handle from the hash table
* Returns -1 if element not found, 0 if successful
*/
static int
{
int i;
return (-1);
return (0);
}
return (0);
}
}
return (-1);
}
/*
* Lock free function to lookup the hash table for a given handle
* Returns NULL if not found
*/
static void *
{
int i;
}
return (NULL);
}
static picl_hdl_t
{
int i;
}
return (PICL_INVALID_PICLHDL);
}
/*
* Is the PICL handle stale or invalid handle?
*/
static int
{
int err;
(void) pthread_mutex_lock(&piclhdl_lock);
(void) pthread_mutex_unlock(&piclhdl_lock);
return (err);
}
/*
* Is the Ptree handle stale or invalid handle?
*/
static int
{
int err;
(void) pthread_mutex_lock(&ptreehdl_lock);
(void) pthread_mutex_unlock(&ptreehdl_lock);
return (err);
}
/*
* For a PICL handle, return the PTree handle and the PICL object
* Locks and releases the PICL table.
*/
int
{
int err;
if (tmph == PICL_INVALID_PICLHDL) {
return (err);
}
return (PICL_SUCCESS);
}
/*
* Allocate a ptree handle
*/
static picl_hdl_t
alloc_ptreehdl(void)
{
++ptree_hdl_hi;
return (hdl);
}
/*
* Allocate a picl handle
* A PICL handle is ptree_hdl value with 1 in MSB of handle value.
* If a ptree handle already has 1 in MSB, then it cannot be piclized
* and the daemon must be restarted.
*/
static picl_hdl_t
alloc_piclhdl(void)
{
++picl_hdl_hi;
return (hdl);
}
/*
* Allocate and add handle to PTree hash table
*/
static void
{
(void) rw_wrlock(&ptree_rwlock);
(void) rw_unlock(&ptree_rwlock);
}
/*
* Lock a picl node object
*/
static int
{
if (rw == RDLOCK_NODE)
else if (rw == WRLOCK_NODE)
else
return (-1);
return (0);
}
/*
* Release the picl node object.
* This function may be called with a NULL object pointer.
*/
static void
{
return;
}
/*
* This function locks the node of a property and returns the node object
* and the property object.
*/
static int
picl_obj_t **propp)
{
return (ptree_hdl_error(proph));
/*
* Get the property's or table entry's node object
*/
else {
return (PICL_NOTPROP);
}
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* This function locks the node of a table and returns the node object
* and the table object.
*/
static int
picl_obj_t **tblobj)
{
return (ptree_hdl_error(tblh));
/*
* Get the property's or table entry's node object
*/
return (PICL_NOTTABLE);
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* This locks the node of a table or a table entry and returns the
* node object and the table or table entry object
*/
static int
{
return (ptree_hdl_error(tblproph));
/*
* Get the property's or table entry's node object
*/
return (PICL_NOTTABLE);
else
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* Lock the node corresponding to the given handle and return its object
*/
static int
{
return (ptree_hdl_error(nodeh));
return (PICL_NOTNODE);
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* Is the property name a restricted property name?
*/
static int
picl_restricted(const char *name)
{
return (0); /* not restricted */
return (1);
return (0);
}
/*
* Check the value size with the property size
* Return PICL_INVALIDARG if the size does not match exactly for strongly
* typed properties.
* For charstring reads allow sizes that match the value size
* For bytearray return PICL_VALUETOOBIG
* if the size is greater than the buffer size.
*/
static int
{
return (PICL_INVALIDARG);
else
return (PICL_SUCCESS);
}
/*
* check size for non-volatile properties
*/
case PICL_PTYPE_CHARSTRING:
return (PICL_VALUETOOBIG);
return (PICL_VALUETOOBIG);
break;
case PICL_PTYPE_BYTEARRAY:
if (op == PROP_WRITE) {
return (PICL_VALUETOOBIG);
return (PICL_SUCCESS); /* allow small writes */
}
/* fall through for reads */
default:
return (PICL_INVALIDARG);
break;
}
return (PICL_SUCCESS);
}
void
{
(void) rw_rdlock(&ptree_rwlock);
else
(void) rw_unlock(&ptree_rwlock);
}
/*
* The caller of the piclize() set of functions is assumed to hold
* the ptree_rwlock().
*/
static void
{
(void) rw_wrlock(&picltbl_rwlock);
(void) rw_unlock(&picltbl_rwlock);
}
static void
{
}
static void
{
return;
}
}
/*
* Function to create PICL handles for a subtree and add them to
* the table
*/
static void
{
}
/* go through the children */
}
/*
* Function to remove PICL handles
*/
static void
{
(void) rw_wrlock(&picltbl_rwlock);
(void) rw_unlock(&picltbl_rwlock);
}
static void
{
}
static void
{
if (!IS_PICLIZED(propp))
return;
}
}
/*
* Function to remove PICL handles for a subtree and its
* properties
*/
static void
{
if (!IS_PICLIZED(nodep))
return;
}
/* go through the children */
}
/*
* The caller holds the lock on the ptree_lock when calling this.
* If ret is not NULL then this function returns the referenced object.
*/
static int
{
return (ptree_hdl_error(refh));
return (PICL_INVREFERENCE);
if (ret)
return (PICL_SUCCESS);
}
/*
* The caller holds the lock on ptree_lock when calling this.
* If ret is not NULL, then this function returns the table object
*/
static int
{
return (ptree_hdl_error(tblh));
return (PICL_NOTTABLE);
if (ret)
return (PICL_SUCCESS);
}
static int
{
return (ptree_hdl_error(proph));
return (PICL_NOTPROP);
if (ret)
return (PICL_SUCCESS);
}
static int
{
return (ptree_hdl_error(nodeh));
return (PICL_NOTNODE);
if (ret)
return (PICL_SUCCESS);
}
static int
{
return (PICL_PROPNOTFOUND);
else
return (PICL_SUCCESS);
}
return (PICL_PROPNOTFOUND);
else
return (PICL_SUCCESS);
}
return (PICL_PROPNOTFOUND);
else
return (PICL_SUCCESS);
}
if (ret)
return (PICL_SUCCESS);
}
}
return (PICL_PROPNOTFOUND);
}
/*
* This function locks the ptree, verifies that the handle is a reference
* to a node of specified class name, releases the lock
*/
static int
{
int err;
(void) rw_unlock(&ptree_rwlock);
return (PICL_INVREFERENCE);
}
return (err);
}
static int
{
int err;
(void) rw_rdlock(&ptree_rwlock);
err = PICL_SUCCESS;
err = PICL_NOTTABLE;
(void) rw_unlock(&ptree_rwlock);
return (err);
}
/*
* PICLTree Interface routines for plug-in modules
*/
int
{
*rooth = ptree_root_hdl;
return (PICL_SUCCESS);
}
/*
* Lock free create a property object
*/
static int
picl_obj_t **pobjp)
{
return (PICL_NOTSUPPORTED);
return (PICL_INVALIDARG);
return (PICL_FAILURE);
return (PICL_FAILURE);
}
else
}
return (PICL_SUCCESS);
}
/*
* Check for valid arguments, create a property object,
* Lock ptree_rwlock, add the new property handle, release the lock
* For reference properties and table properties, the handles are verified
* before creating the property.
*/
int
{
int err;
char *ptr;
int refflag;
char classname[PICL_PROPNAMELEN_MAX];
return (PICL_INVALIDARG);
return (PICL_NOTSUPPORTED);
return (PICL_VALUETOOBIG);
return (PICL_RESERVEDNAME);
refflag = 0;
refflag = 1;
if (refflag == 0)
return (PICL_INVREFERENCE);
/*
* check valid reference handle for non-volatiles
*/
return (PICL_INVREFERENCE);
return (PICL_INVREFERENCE);
*ptr = '\0';
if (err != PICL_SUCCESS)
return (err);
}
} else if (refflag == 1)
return (PICL_INVREFERENCE);
return (PICL_INVALIDARG);
if (err != PICL_SUCCESS)
return (err);
return (PICL_RESERVEDNAME);
return (PICL_RESERVEDNAME);
/*
* No locks held when you get here
*/
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
/*
* Lock free routine to destroy table entries
* This function removes the destroyed handles from the hash table
* Uses lock free routines: hash_lookup() and hash_remove()
*/
static void
{
return;
/* Delete all entries */
}
}
}
/*
* Lock free function that frees up a property object and removes the
* handles from Ptree table
*/
static void
{
}
/*
* This function destroys a previously deleted property.
* A deleted property does not have an associated node.
* All memory allocated for this property are freed
*/
int
{
return (ptree_hdl_error(proph));
}
/* Is the prop still attached to a node? */
return (PICL_CANTDESTROY);
}
return (PICL_SUCCESS);
}
/*
* This function adds a property to the property list of a node and adds
* it to the PICL table if the node has a PICL handle.
* This function locks the picl_rwlock and ptree_rwlock.
*/
int
{
int err;
/*
* Verify property handle
*/
if (err != PICL_SUCCESS) {
return (err);
}
(void) rw_unlock(&ptree_rwlock);
return (PICL_INVALIDARG);
}
/*
* Exclusive Lock the node's properties
*/
if (err != PICL_SUCCESS) {
return (err);
}
/*
* check if prop already exists
*/
if (err == PICL_SUCCESS) {
return (PICL_PROPEXISTS);
}
/*
* Verify property's value
*/
case PICL_PTYPE_TABLE:
break;
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
break;
case PICL_PTYPE_REFERENCE:
break;
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
(void) rw_unlock(&ptree_rwlock);
return (err);
}
break;
default:
break;
}
if (IS_PICLIZED(nodep))
/*
* Add prop to beginning of list
*/
return (PICL_SUCCESS);
}
/*
* Lock free function that unlinks a property from its node
*/
static int
{
return (PICL_SUCCESS);
}
return (PICL_PROPNOTFOUND);
return (PICL_SUCCESS);
}
/*
* This function deletes the specified property from the property list
* of its node and removes the handle from PICL table, if the node
* was piclized.
*/
int
{
int err;
/*
* Lookup the property's node and lock it if there is one
* return the objects for the property and the node
*/
if (err != PICL_SUCCESS) {
return (err);
/* Nothing to do - already deleted! */
return (PICL_SUCCESS);
}
return (PICL_NOTPROP);
}
if (err != PICL_SUCCESS) {
return (err);
}
return (PICL_SUCCESS);
}
/*
* Create a table object and return its handle
*/
int
{
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
/*
* Add the properties in <props> array as a row in the table
* Add PICL handles if the table has a valid PICL handle
*/
int
const picl_prophdl_t *props)
{
picl_obj_t **newrow;
int i;
int err;
int picl_it;
if (nprops < 1)
return (PICL_INVALIDARG);
return (PICL_FAILURE);
if (err != PICL_SUCCESS) {
return (err);
}
/*
* make sure all are either props or table handles
*/
for (i = 0; i < nprops; ++i) {
break;
}
err = PICL_NOTPROP;
break;
}
break;
}
}
if (err != PICL_SUCCESS) {
return (err);
}
/*
* Mark all props as table entries, set up row linkages
*/
picl_it = 0;
if (IS_PICLIZED(tbl_obj))
picl_it = 1;
for (i = 0; i < nprops; ++i) {
if (picl_it)
piclize_obj(newrow[i]);
if (i != nprops - 1)
}
} else {
i = 0;
++i;
}
}
return (PICL_SUCCESS);
}
/*
* This function returns the handle of the next property in the row
*/
int
{
int err;
/*
* proph could be a table handle or a table entry handle
* Look it up as a table entry handle first, check error code
* to see if it is a table handle
*/
&propp);
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
else
return (err);
}
int
{
int err;
/*
* proph could be a table handle or a table entry handle
* Look it up as a table entry handle first, check error code
* to see if it is a table handle
*/
&propp);
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
else
return (err);
}
/*
* This function creates node object and adds its handle to the Ptree
*/
int
{
int err;
return (PICL_INVALIDARG);
return (PICL_VALUETOOBIG);
/*
* Create the picl object for node
*/
return (PICL_FAILURE);
return (PICL_FAILURE);
}
/*
* create name property
*/
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
(void) ptree_destroy_prop(phdl);
return (err);
}
/*
* create picl classname property
*/
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
(void) ptree_destroy_prop(cphdl);
return (err);
}
return (PICL_SUCCESS);
}
/*
* Removed destroyed objects' handles from PTree table
*/
static void
{
return;
}
/*
* Lock the node
*/
/*
* destroy all properties associated with this node
*/
}
}
/*
* are freed and removed from the PTree table.
* Only one destroy is in progress at any time.
*/
int
{
picl_obj_t *np;
int err;
if (err != PICL_SUCCESS) {
return (err);
}
/*
*/
if (IS_PICLIZED(nodep)) {
return (PICL_CANTDESTROY);
}
/*
* update parent's child list to repair the tree when
* parent is not null
*/
return (PICL_SUCCESS);
}
} else {
}
return (PICL_SUCCESS);
}
/*
* from PICL table
*/
int
{
picl_obj_t *np;
int err;
if (err != PICL_SUCCESS) {
return (err);
}
/*
* unparent it
*/
else {
}
}
return (PICL_SUCCESS);
}
/*
* This function adds a node as a child of another node
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
return (err);
}
/* is chdh already a child? */
return (PICL_CANTPARENT);
}
/*
* append child to children list
*/
else {
continue;
}
/* piclize */
if (IS_PICLIZED(pnodep))
return (PICL_SUCCESS);
}
static void
{
}
static void
{
}
/*
* This function returns the property information to a plug-in
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
else
err = PICL_FAILURE;
return (err);
}
/*
* This function returns the property information to a plug-in
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
if (picl_restricted(pname))
else
err = PICL_FAILURE;
return (err);
}
/*
* This function must be called only after a lookup_prop_by_name() returns
* success and only if picl_restricted() returns true.
*/
static int
{
void *srcp;
if (size != sizeof (picl_nodehdl_t))
return (PICL_VALUETOOBIG);
else
return (PICL_FAILURE);
(void) rw_unlock(&ptree_rwlock);
return (PICL_SUCCESS);
}
/*
* Returns the property value in the buffer and releases the node and
* ptree locks.
* For volatile properties, this function releases the locks on ptree
* table and the node before calling the plug-in provided access function
*/
static int
{
int err;
err = PICL_SUCCESS;
if (nodep)
else
err = PICL_FAILURE;
else
return (err);
else
(void) rw_unlock(&ptree_rwlock);
return (err);
}
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
return (err);
}
}
/*
* This function gets the credentials and calls get_propval_with_cred.
*/
int
{
}
/*
* This function retrieves a property's value by by its name
* For volatile properties, the locks on ptree and node are released
* before calling the plug-in provided access function
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
if (picl_restricted(pname))
size));
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
}
/*
* This function is used by plugins to get a value of a property
* looking it up by its name.
*/
int
{
picld_cred));
}
/*
* This function updates a property's value.
* For volatile properties, the locks on the node and the ptree table
* are released before calling the plug-in provided access function.
*/
static int
{
int err;
err = PICL_SUCCESS;
if (nodep)
else
err = PICL_FAILURE;
else
return (err);
} else
return (err);
}
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
return (err);
}
}
/*
* Ptree function used by plug-ins to update a property's value
* calls update_propval_with_cred(), which releases locks for volatile props
*/
int
{
}
/*
* by its name.
* For volatile properties this function releases the locks on the
* node and the ptree table.
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (picl_restricted(pname)) {
(void) rw_unlock(&ptree_rwlock);
return (PICL_RESERVEDNAME);
}
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (err);
}
}
/*
* This function updates the value of a property specified by its name
*/
int
{
size, picld_cred));
}
/*
* This function retrieves the handle of a property by its name
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (picl_restricted(pname)) {
return (err);
}
if (err == PICL_SUCCESS)
return (err);
}
/*
* This function returns the handle of the first property
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
if (pobj->first_prop)
else
return (err);
}
/*
* This function returns the handle of next property in the list
*/
int
{
int err;
if (err != PICL_SUCCESS) {
return (err);
}
} else
return (err);
}
/*
* These functions are called by ptree_get_node_by_path()
* Append a prop expression entry to the list
*/
static prop_list_t *
{
return (list);
return (list);
}
/*
* Add it to the end of list
*/
return (list);
}
/*
* Free the property expression list
*/
static void
{
}
}
static int
{
char *propptr;
char *ptr;
char *pname;
char *pval;
return (PICL_FAILURE);
return (PICL_FAILURE);
/*
* get property expression
*/
*ptr = '\0';
} else
/*
* get bus value
*/
*ptr = '\0';
return (PICL_FAILURE);
}
/*
* create the prop list
*/
*ptr = '\0';
} else
return (PICL_FAILURE);
*ptr = '\0';
/*
* <prop>= is treated as void property
*/
}
}
return (PICL_SUCCESS);
}
static int
{
float fval;
double dval;
case PICL_PTYPE_CHARSTRING:
return (1);
}
return (1);
else
return (0);
case PICL_PTYPE_INT:
case sizeof (int8_t):
case sizeof (int16_t):
case sizeof (int32_t):
case sizeof (int64_t):
default:
return (0);
}
case PICL_PTYPE_UNSIGNED_INT:
case sizeof (uint8_t):
case sizeof (uint16_t):
case sizeof (uint32_t):
case sizeof (uint64_t):
default:
return (0);
}
case PICL_PTYPE_FLOAT:
case sizeof (float):
case sizeof (double):
default:
return (0);
}
case PICL_PTYPE_VOID:
case PICL_PTYPE_TIMESTAMP:
case PICL_PTYPE_TABLE:
case PICL_PTYPE_REFERENCE:
case PICL_PTYPE_BYTEARRAY:
case PICL_PTYPE_UNKNOWN:
default:
return (0);
}
}
static int
{
int err;
void *vbuf;
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_SUCCESS)
return (err);
return (PICL_FAILURE);
} else {
return (PICL_FAILURE);
if (err != PICL_SUCCESS)
return (err);
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
static int
{
int err;
char *nameval;
char *nodename;
char *path;
char *baddr;
char *busval;
return (PICL_FAILURE);
return (PICL_FAILURE);
if (err != PICL_SUCCESS) {
return (err);
}
return (PICL_FAILURE);
return (PICL_FAILURE);
}
return (PICL_FAILURE);
}
}
sizeof (picl_nodehdl_t))) {
if (err != PICL_SUCCESS) {
return (PICL_FAILURE);
}
/*
* compare name
*/
if (err != PICL_SUCCESS)
continue;
continue;
}
/*
* compare device address with bus-addr prop first
* then with UnitAddress property
*/
continue;
continue; /* not match */
}
return (PICL_SUCCESS);
}
/*
* compare the property expression list
*/
if (err != PICL_SUCCESS)
break;
}
return (PICL_SUCCESS);
}
}
return (PICL_NOTNODE);
}
/*
* This functions returns the handle of node specified by its path
*/
int
{
char *path;
char *ptr;
char *defprop;
char *tokindex;
int err;
int len;
int npflg; /* namepath flag */
return (PICL_FAILURE);
if (path[0] == '/') {
*tokindex = '\0';
++tokindex;
if (*tokindex == '/')
else
return (PICL_NOTNODE);
npflg = 0;
} else
return (PICL_NOTNODE);
if (err != PICL_SUCCESS)
return (err);
*tokindex = '\0';
if (npflg)
else
defprop);
if (err != PICL_SUCCESS)
return (err);
}
/*
* check if last token is empty or not
* eg. /a/b/c/ or /a/b/c
*/
if (*ptr == '\0') {
return (PICL_SUCCESS);
}
if (len == 0) {
return (PICL_SUCCESS);
}
if (npflg)
else
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
/*
* Initialize propinfo
*/
int
int (*writefn)(ptree_warg_t *, const void *))
{
if (version != PTREE_PROPINFO_VERSION_1)
return (PICL_NOTSUPPORTED);
return (PICL_INVALIDARG);
return (PICL_SUCCESS);
}
/*
* Creates a property, adds it to the node, and returns the property
* handle to the caller if successful and proph is not NULL
*/
int
{
int err;
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_SUCCESS) {
(void) ptree_destroy_prop(tmph);
return (err);
}
if (proph)
return (PICL_SUCCESS);
}
/*
* Creates a node, adds it to its parent node, and returns the node
* handle to the caller if successful
*/
int
{
int err;
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_SUCCESS) {
(void) ptree_destroy_node(tmph);
return (err);
}
return (PICL_SUCCESS);
}
/*
* recursively visit all nodes
*/
static int
{
int err;
char classval[PICL_CLASSNAMELEN_MAX];
sizeof (chdh));
while (err == PICL_SUCCESS) {
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_WALK_CONTINUE)
return (err);
}
return (err);
sizeof (chdh));
}
return (PICL_WALK_CONTINUE);
return (err);
}
/*
* This function visits all the nodes in the subtree rooted at <rooth>.
* For each node that matches the class name specified, the callback
* function is invoked.
*/
int
{
int err;
if (callback_fn == NULL)
return (PICL_INVALIDARG);
return (PICL_SUCCESS);
return (err);
}
static int
{
int err;
void *vbuf;
if (err != PICL_SUCCESS)
return (0);
if (err != PICL_SUCCESS)
return (0);
return (0);
return (1);
return (0);
return (0);
return (0);
if (err != PICL_SUCCESS)
return (0);
return (1);
return (0);
}
/*
* This function traverses the subtree and finds a node that has a property
* of the specified name and type with the specified value.
* The matched node in the tree is returned in retnodeh. If there is
* no node with that property, then PICL_NODENOTFOUND is returned.
*/
int
{
int err;
return (PICL_INVALIDARG);
sizeof (chdh));
while (err == PICL_SUCCESS) {
if (retnodeh)
return (PICL_SUCCESS);
}
retnodeh);
if (err != PICL_NODENOTFOUND)
return (err);
sizeof (chdh));
}
if (err == PICL_PROPNOTFOUND)
return (PICL_NODENOTFOUND);
return (err);
}
/*
* This function gets the frutree parent for a given node.
* Traverse up the tree and look for the following properties:
* Frutree parent reference properties:
* _fru_parent
* _location_parent
* _port_parent
* If the frutree reference property is found, return its value.
*/
int
{
int err;
err = PICL_SUCCESS;
while (err == PICL_SUCCESS) {
if (err == PICL_SUCCESS) {
return (PICL_SUCCESS);
}
if (err == PICL_SUCCESS) {
return (PICL_SUCCESS);
}
if (err == PICL_SUCCESS) {
return (PICL_SUCCESS);
}
sizeof (nparh));
}
if (err == PICL_SUCCESS) {
return (PICL_SUCCESS);
}
}
return (err);
}
/*
* This function is called by plug-ins to register with the daemon
*/
int
{
return (PICL_FAILURE);
return (PICL_NOTSUPPORTED);
return (PICL_FAILURE);
return (PICL_FAILURE);
if (plugin_reg_list == NULL) {
} else { /* add to end */
}
return (PICL_SUCCESS);
}
/*
* Call fini routines of the registered plugins
*/
static void
{
if (p == NULL)
return;
plugin_fini(p->next);
if (p->reg.plugin_fini)
(p->reg.plugin_fini)();
}
/*
* Create PICL Tree
*/
static void
init_plugin_reg_list(void)
{
}
static int
{
int err;
if (err != PICL_SUCCESS) {
(void) rw_unlock(&ptree_rwlock);
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
static int
picltree_init(void)
{
return (PICL_FAILURE);
return (PICL_FAILURE);
return (PICL_FAILURE);
return (PICL_FAILURE);
return (PICL_FAILURE);
return (PICL_FAILURE);
return (PICL_FAILURE);
evt_handlers = NULL;
return (PICL_SUCCESS);
}
static void
{
char *buf;
pl = plugin_desc;
return;
else
}
return;
return;
return;
return;
if (plugin_desc == NULL)
plugin_desc = pl;
else {
tmp = plugin_desc;
}
}
static void
get_plugins_from_dir(char *dirname)
{
int len;
return;
continue;
continue;
}
}
static void
init_plugin_list(void)
{
plugin_desc = NULL;
}
}
}
static void
load_plugins(void)
{
pl = plugin_desc;
return;
}
}
}
static int
{
int err;
float picl_vers;
#define PICL_PROP_PICL_VERSION "PICLVersion"
#define PICL_VERSION 1.1
if (err != PICL_SUCCESS)
return (err);
return (err);
}
static int
construct_picltree(void)
{
int err;
/*
* Create "/" node
*/
&rhdl)) != PICL_SUCCESS) {
return (err);
}
return (PICL_FAILURE);
}
if (err != PICL_SUCCESS)
return (err);
/*
* Initialize the registered plug-in modules
*/
}
return (PICL_SUCCESS);
}
void
xptree_destroy(void)
{
if (picl_root_obj == NULL)
return;
(void) rw_wrlock(&ptree_rwlock);
(void) rw_unlock(&ptree_rwlock);
}
/*ARGSUSED*/
int
xptree_initialize(int flg)
{
int err;
picl_hdl_hi = 1;
ptree_hdl_hi = 1;
ptree_generation = 1;
qempty_wait = 0;
return (PICL_FAILURE);
if (picltree_init() != PICL_SUCCESS)
return (PICL_FAILURE);
load_plugins();
err = construct_picltree();
if (err != PICL_SUCCESS)
return (err);
/*
* Dispatch events after all plug-ins have initialized
*/
if (pthread_attr_init(&attr) != 0)
return (PICL_FAILURE);
return (PICL_FAILURE);
return (PICL_SUCCESS);
}
int
xptree_reinitialize(void)
{
int err;
/*
* Wait for eventq to become empty
*/
(void) pthread_mutex_lock(&evtq_lock);
qempty_wait = 1;
qempty_wait = 0;
(void) pthread_mutex_unlock(&evtq_lock);
(void) rw_wrlock(&ptree_rwlock);
(void) rw_unlock(&ptree_rwlock);
(void) pthread_mutex_lock(&ptree_refresh_mutex);
(void) pthread_mutex_unlock(&ptree_refresh_mutex);
err = construct_picltree();
(void) pthread_mutex_lock(&ptree_refresh_mutex);
(void) pthread_cond_broadcast(&ptree_refresh_cond);
(void) pthread_mutex_unlock(&ptree_refresh_mutex);
(void) pthread_mutex_lock(&evtq_lock);
(void) pthread_cond_broadcast(&evtq_cv);
(void) pthread_mutex_unlock(&evtq_lock);
return (err);
}
/*
* This function is called by the PICL daemon on behalf of clients to
* wait for a tree refresh
*/
int
{
int curgen;
int ret;
if (secs != 0) {
if (pthread_mutex_lock(&ptree_refresh_mutex) != 0)
return (PICL_FAILURE);
while (curgen == ptree_generation) {
(void) pthread_cond_wait(&ptree_refresh_cond,
else {
&ptree_refresh_mutex, &to);
break;
}
}
(void) pthread_mutex_unlock(&ptree_refresh_mutex);
}
return (PICL_SUCCESS);
}
/*VARARGS2*/
void
{
if (verbose_level >= level) {
}
}
/*ARGSUSED*/
void
{
if (verbose_level > level)
}