sml.c revision 5c51f1241dbbdf2656d0e10011981411ed0c9673
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
* or http://www.opensolaris.org/os/licensing.
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Module: sml.c
* Synopsis: simplified markup language (SML) support
* Taxonomy: project private
* Debug flag: sml
* Description:
*
* This module implements methods that support the processing of a
* simplified markup language (SML). Objects that contain SML data
* can be created and manipulated, and SML can be imported into
* internal SML objects or exported from internal SML objects.
*
* Public Methods:
*
* smlAddTag - Add new tag object into existing tag object
* smlConvertStringToTag - Convert string into tag object
* smlConvertTagToString - Convert a tag object into a string
* representation of the XML
* smlDbgPrintTag - Print a representation of an XML tag if debugging
* smlDelParam - Delete a parameter from a tag object
* smlDelTag - Delete element from tag object
* smlDup - Duplicate a tag object
* smlFindAndDelTag - Delete a tag if found in tag object
* smlFreeTag - Free a tag object and all its contents when no
* longer needed
* smlFstatCompareEq - Compare file status information
* smlGetElementName - Return a tag's element name
* smlGetNumParams - Get number of parameters set in tag
* smlGetParam - Get a parameter from a tag
* smlGetParamF - Get a formatted parameter from a tag
* smlGetParamByTag - Get a parameter by tag and index
* smlGetParamByTagParam Get parameter given tag name, index,
* parameter name, and value
* smlGetParamName - Get the name of a tag parameter given its index
* smlGetParam_r - Get a parameter from a tag into fixed buffer
* smlGetTag - Get an element from a tag
* smlGetTagByName - Get an element given a name and an index
* smlGetTagByTagParam - Get element given tag name, index, parameter name,
* and value
* smlGetVerbose - get current verbose mode setting
* smlLoadTagFromFile - Load a file into a tag object
* smlNewTag - Create a new (empty) tag object
* smlParamEq - Determine if parameter is equal to a specified value
* smlParamEqF - Determine if parameter is equal to a specified value
* smlPrintTag - Print a simple XML representation of a tag to stderr
* smlReadOneTag - read one complete tag from a datastream
* smlReadTagFromDs - read tag object from datastream
* smlSetFileStatInfo - encode file status information into tag
* smlSetVerbose - set/clear verbose mode for debugging output
* smlSetParam - Set parameter value in tag object
* smlSetParamF - Set parameter value in tag object
* smlWriteTagToDs - Write an XML representation of a tag to a datastream
* smlWriteTagToFd - Write an XML representation of a tag to an open file
* descriptor
* smlWriteTagToFile - Write an XML representation of a tag to a file
*/
/*
* Unix includes
*/
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <libintl.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/statvfs.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <strings.h>
/*
* liblu Includes
*/
#include "libinst.h"
#include "messages.h"
/* Should be defined by cc -D */
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
/*
* Private Method Forward Declarations
*/
/*PRINTFLIKE2*/
static void _smlLogMsg(LogMsgType a_type, const char *a_format, ...);
static int _smlReadTag(SML_TAG **r_tag, char **a_str, char *parent);
static int _smlWriteSimpleTag(char **a_str,
SML_TAG *tag);
static int _smlWriteParamValue(char **a_str, char *value);
static void _smlFreeTag(SML_TAG *tag);
static char *_sml_fileStatInfoTag = "File-Stat-Info";
static boolean_t verbose = B_FALSE;
/*
*
* This definition controls the maximum size of any individual sml
* component, such as a tag name, tag *value*, etc. The code should
* someday be revised to dynamically allocate whatever memory is needed
* to hold such components while parsing, but that exercise is left for
* another day. Any component that exceeds this length is silently
* truncated...
*/
#define MAX_SML_COMPONENT_LENGTH 16384
/*
* Public Methods
*/
/*
* Name: smlAddTag
* Description: Add new tag object into existing tag object
* Arguments: r_tag - [RO, *RW] - (SML_TAG **)
* Pointer to handle to the tag object to update
* The handle may be updated if the tag object is
* moved in memory
* a_index - [RO] - (int)
* Add the tag after the "n"th tag in the tag object
* -1 == add the tag to the end of the tag object
* 0 == add the tag to the beginning of the tag object
* a_subTag - [RO, *RW] - (SML_TAG *)
* The tag to add to 'tag'
* Returns: SML_TAG *
* The location within "r_tag" where "a_subTag"
* has been added - this is the handle into the r_tag
* object to the tag that was just added
* Errors: If the tag object cannot be updated, the process exits
*/
SML_TAG *
smlAddTag(SML_TAG **r_tag, int a_index, SML_TAG *a_subTag)
{
SML_TAG *tag;
/* entry assertions */
assert(SML_TAG__ISVALID(a_subTag));
assert(SML_TAG__R_ISVALID(r_tag));
/* if no tag to update specified, ignore request */
tag = *r_tag;
if (tag == SML_TAG__NULL) {
return (tag);
}
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_ADD_TAG,
a_subTag->name, tag->name);
/* if index is out of range or -1, append to tag object */
if ((a_index > tag->tags_num) || (a_index == -1)) {
a_index = tag->tags_num;
}
/* bump number of tags in tag object */
tag->tags_num++;
/* expand tag object to hold new subtag */
tag->tags = (SML_TAG *)realloc(tag->tags,
sizeof (SML_TAG) * tag->tags_num);
/* if not appending, adjust tag object to hold new subtag */
if (a_index < (tag->tags_num - 1)) {
(void) memmove(&(tag->tags[a_index + 1]), &(tag->tags[a_index]),
sizeof (SML_TAG) * (tag->tags_num - a_index - 1));
}
/* copy new subtag into correct location in tag object */
(void) memcpy(&(tag->tags[a_index]), a_subTag,
sizeof (SML_TAG));
return (&(tag->tags[a_index]));
}
/*
* Name: smlDelTag
* Description: Delete element from tag object
* Arguments: tag - [RO, *RW] - (SML_TAG *)
* The tag object to update
* sub_tag - [RO, *RW] - (SML_TAG *)
* Element to be removed from the tag object
* Returns: void
* The sub_tag is removed from the tag object
* NOTE: The sub-tag and all elements contained within it are deallocated
* the sub-tag is no longer valid when this method returns
*/
void
smlDelTag(SML_TAG *tag, SML_TAG *sub_tag)
{
int index;
/* entry assertions */
assert(SML_TAG__ISVALID(sub_tag));
/* if no tag to update specified, ignore request */
if (tag == SML_TAG__NULL) {
return;
}
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_DEL_TAG,
sub_tag->name, tag->name);
/* if tag object is empty, ignore request */
if (tag->tags_num == 0) {
return;
}
/* determine index into tag object of element to remove */
for (index = 0; index < tag->tags_num; index++) {
if (sub_tag == &tag->tags[index]) {
break;
}
}
/* if element not found in tag, ignore request */
if (index >= tag->tags_num) {
return;
}
/* free up the subtag to be deleted */
_smlFreeTag(sub_tag);
/*
* if not removing last element, collapse tag object removing
* target element
*/
if (index < (tag->tags_num - 1)) {
(void) memmove(&(tag->tags[index]), &(tag->tags[index + 1]),
sizeof (SML_TAG) *(tag->tags_num - index - 1));
}
/* one less tag object in tag */
tag->tags_num --;
/*
* If only one tag left, then delete entire tag structure
* otherwise reallocate removing unneeded entry
*/
if (tag->tags_num > 0) {
/* realloc removing last element in tag object */
tag->tags = (SML_TAG *)realloc(tag->tags,
sizeof (SML_TAG) *tag->tags_num);
} else {
tag->tags = SML_TAG__NULL;
}
}
/*
* Name: smlFreeTag
* Description: Free a tag object and all its contents when no longer needed
* Arguments: tag - [RO, *RW] - (SML_TAG *)
* The tag object to be deleted
* Returns: void
* The tag object and all its contents are deallocated
*/
void
smlFreeTag(SML_TAG *tag)
{
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
/* entry debugging info */
if (tag->name != (char *)NULL) {
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_FREE_TAG,
(unsigned long)tag, tag->name);
}
/* free the tag object contents */
_smlFreeTag(tag);
/* free the tag object handle */
bzero(tag, sizeof (SML_TAG));
free(tag);
}
/*
* Name: smlGetNumParams
* Synopsis: Get number of parameters set in tag
* Description: Return the number of parameters set in a tag
* Arguments: a_tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the # params from
* Returns: int
* Number of parameters set in tag
* 0 = no parameters are set
*/
int
smlGetNumParams(SML_TAG *a_tag)
{
return (a_tag ? a_tag->params_num : 0);
}
/*
* Name: smlGetParam_r
* Description: Get a parameter from a tag into a buffer of fixed size
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the parameter from
* name - [RO, *RO] - (char *)
* Name of the parameter to retrieve
* buf - [RO, *RW] - (char *)
* Location of buffer to contain results
* bufLen - [RO, *RO] - (int)
* Maximum bytes available in buffer to contain results
* Returns: void
*/
void
smlGetParam_r(SML_TAG *tag, char *name, char *buf, int bufLen)
{
int k;
/* entry assertions */
assert(name != (char *)NULL);
assert(*name != '\0');
assert(buf != (char *)NULL);
assert(bufLen > 0);
/* terminate the buffer */
buf[0] = '\0';
buf[bufLen-1] = '\0';
bzero(buf, bufLen);
/* if no tag specified, return NULL */
if (tag == SML_TAG__NULL) {
return;
}
/* if no parameters in tag, return NULL */
if (tag->params == NULL) {
return;
}
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM,
name, tag->name);
/* scan tag object looking for specified parameter */
for (k = 0; k < tag->params_num; k++) {
assert(tag->params[k].name != (char *)NULL);
assert(tag->params[k].value != (char *)NULL);
if (streq(tag->params[k].name, name)) {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_GOT_PARAM,
tag->name, name, tag->params[k].value);
(void) strncpy(buf, tag->params[k].value, bufLen-1);
return;
}
}
/* parameter not found - return */
}
/*
* Name: smlGetParam
* Description: Get a parameter from a tag
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the parameter from
* name - [RO, *RO] - (char *)
* Name of the parameter to retrieve
* Returns: char *
* Value of the specified parameter
* == (char *)NULL if the parameter does not exist
* NOTE: Any parameter returned is placed in new storage for the
* calling method. The caller must use 'free' to dispose
* of the storage once the parameter is no longer needed.
*/
char *
smlGetParam(SML_TAG *tag, char *name)
{
int k;
/* entry assertions */
assert(name != (char *)NULL);
assert(*name != '\0');
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, "get param param <%s>", name);
/* if no tag specified, return NULL */
if (tag == SML_TAG__NULL) {
return ((char *)NULL);
}
/* if no parameters in tag, return NULL */
if (tag->params == NULL) {
return ((char *)NULL);
}
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM,
name, tag->name);
/* scan tag object looking for specified parameter */
for (k = 0; k < tag->params_num; k++) {
assert(tag->params[k].name != (char *)NULL);
assert(tag->params[k].value != (char *)NULL);
if (streq(tag->params[k].name, name)) {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_GOT_PARAM,
tag->name, name, tag->params[k].value);
return (strdup(tag->params[k].value));
}
}
/* parameter not found - return NULL */
return ((char *)NULL);
}
/*
* Name: smlGetParamName
* Description: Get the name of a tag parameter given its index
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the parameter name from
* index - [RO] - (int)
* Index of parameter name to return
* Returns: char *
* Name of 'index'th parameter
* == (char *)NULL if no such parameter exists in tag
* NOTE: Any parameter name returned is placed in new storage for the
* calling method. The caller must use 'free' to dispose
* of the storage once the parameter name is no longer needed.
*/
char *
smlGetParamName(SML_TAG *tag, int index)
{
/* if no tag specified, return NULL */
if (tag == NULL) {
return ((char *)NULL);
}
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM_NAME,
tag->name, index);
/* if no parameters in tag, return NULL */
if (tag->params == NULL) {
return ((char *)NULL);
}
/* if index not within range, return NULL */
if (index >= tag->params_num) {
return ((char *)NULL);
}
/* index within range - return parameter name */
assert(tag->params[index].name != (char *)NULL);
assert(tag->params[index].value != (char *)NULL);
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GOT_PARAM_NAME,
tag->name, index, tag->params[index].name);
return (strdup(tag->params[index].name));
}
/*
* Name: smlGetParamByTag
* Synopsis: Get a parameter value from a tag by name and index
* Description: Call to look for a parameter value from a tag with
* a given name with a parameter of a given name
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the parameter
* index - [RO] - (int)
* Index of nth tag by name to look for
* tagName - [RO, *RO] - (char *)
* Name of tag to look for
* paramName - [RO, *RO] - (char *)
* Name of parameter to return value of
* Returns: char *
* == (char *)NULL - no parameter value set
* != (char *)NULL - value of parameter set
*/
char *
smlGetParamByTag(SML_TAG *tag, int index,
char *tagName, char *paramName)
{
SML_TAG *rtag;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(tagName != (char *)NULL);
assert(*tagName != '\0');
assert(paramName != (char *)NULL);
assert(*paramName != '\0');
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM_BY_TAG,
tagName, index, paramName);
/* find the requested tag by name and index */
rtag = smlGetTagByName(tag, index, tagName);
if (rtag == SML_TAG__NULL) {
return ((char *)NULL);
}
return (smlGetParam(rtag, paramName));
}
/*
* Name: smlGetTagByTagParam
* Synopsis: Get element given tag name, index, parameter name, and value
* Description: Call to look for a tag with a given nae, that has a parameter
* of a given name with a specified value
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the element from
* index - [RO] - (int)
* Index of nth name to return
* tagName - [RO, *RO] - (char *)
* Tag name to look up
* paramName - [RO, *RO] - (char *)
* Parameter name to look up
* paramValue - [RO, *RO] - (char *)
* Parameter value to match
* Returns: SML_TAG *
* The 'index'th occurance of element 'name' with
* a parameter 'name' with value specified
* == SML_TAG__NULL if no such element exists
*/
SML_TAG *
smlGetTagByTagParam(SML_TAG *tag, int index,
char *tagName, char *paramName, char *paramValue)
{
int ti; /* tag structure index */
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(tagName != (char *)NULL);
assert(*tagName != '\0');
assert(paramName != (char *)NULL);
assert(*paramName != '\0');
assert(paramValue != (char *)NULL);
assert(*paramValue != '\0');
/* if tag has no elements, return NULL */
if (tag->tags == NULL) {
return (SML_TAG__NULL);
}
/*
* Search algorithm:
* -> search tag structure; for each tag with element == "tagName":
* -> search tag parameters; if parameter name == "paramName"
* -> if parameter value != "paramValue"; to next tag
* -> if parameter value == "paramValue":
* -> if not the "index"th paramValue found; to next tag
* -> return tag found
*/
for (ti = 0; ti < tag->tags_num; ti++) {
int pi; /* parameter structure index */
/* if tag element does not match, go on to next tag */
if (strcmp(tag->tags[ti].name, tagName)) {
continue;
}
/* element matches: search for specified parameter name/value */
for (pi = 0; pi < tag->tags[ti].params_num; pi++) {
assert(tag->tags[ti].params[pi].name != (char *)NULL);
assert(tag->tags[ti].params[pi].value != (char *)NULL);
/* if parameter name doesnt match to next parameter */
if (strcmp(tag->tags[ti].params[pi].name, paramName)) {
continue;
}
/* if parameter value doesnt match to next tag */
if (strcmp(tag->tags[ti].params[pi].value,
paramValue)) {
break;
}
/*
* found element/paramname/paramvalue:
* -> if this is not the 'index'th one, go to next tag
*/
if (index-- != 0) {
break;
}
/*
* found specified element/paramname/paramvalue:
* -> return the tag found
*/
return (&tag->tags[ti]);
}
}
/* no such element found - return NULL */
return (SML_TAG__NULL);
}
/*
* Name: smlGetParamByTagParam
* Synopsis: Get parameter given tag name, index, parameter name, and value
* Description: Call to return the value of a parameter from a tag of a
* given name, with a parameter of a given name with a
* specified value
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the element from
* index - [RO] - (int)
* Index of nth name to return
* tagName - [RO, *RO] - (char *)
* Tag name to look up
* paramName - [RO, *RO] - (char *)
* Parameter name to look up
* paramValue - [RO, *RO] - (char *)
* Parameter value to match
* paramReturn - [RO, *RO] - (char *)
* Parameter name to return the value of
* Returns: char *
* The value of parameter 'paramReturn' from the
* The 'index'th occurance of element 'name' with
* a parameter 'name' with value specified
* == (char *)NULL if no such parameter exists
*/
char *
smlGetParamByTagParam(SML_TAG *tag, int index,
char *tagName, char *paramName, char *paramValue, char *paramReturn)
{
int ti; /* tag structure index */
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(tagName != (char *)NULL);
assert(*tagName != '\0');
assert(paramName != (char *)NULL);
assert(*paramName != '\0');
assert(paramValue != (char *)NULL);
assert(*paramValue != '\0');
assert(paramReturn != (char *)NULL);
assert(*paramReturn != '\0');
/* if tag has no elements, return NULL */
if (tag->tags == NULL) {
return ((char *)NULL);
}
/*
* Search algorithm:
* -> search tag structure; for each tag with element == "tagName":
* -> search tag parameters; if parameter name == "paramName"
* -> if parameter value != "paramValue"; to next tag
* -> if parameter value == "paramValue":
* -> if not the "index"th paramValue found; to next tag
* -> return value of "paramReturn"
*/
for (ti = 0; ti < tag->tags_num; ti++) {
int pi; /* parameter structure index */
/* if tag element does not match, go on to next tag */
if (strcmp(tag->tags[ti].name, tagName)) {
continue;
}
/* element matches: search for specified parameter name/value */
for (pi = 0; pi < tag->tags[ti].params_num; pi++) {
assert(tag->tags[ti].params[pi].name != (char *)NULL);
assert(tag->tags[ti].params[pi].value != (char *)NULL);
/* if parameter name doesnt match to next parameter */
if (strcmp(tag->tags[ti].params[pi].name, paramName)) {
continue;
}
/* if parameter value doesnt match to next tag */
if (strcmp(tag->tags[ti].params[pi].value,
paramValue)) {
break;
}
/*
* found element/paramname/paramvalue:
* -> if this is not the 'index'th one, go to next tag
*/
if (index-- != 0) {
break;
}
/*
* found specified element/paramname/paramvalue:
* -> return parameter requested
*/
return (smlGetParam(&tag->tags[ti], paramReturn));
}
}
/* no such element found - return NULL */
return ((char *)NULL);
}
/*
* Name: smlGetElementName
* Description: Return the name of a given tag
* Arguments: a_tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the element name from
* Returns: char *
* Value of name of specified tag
* NOTE: Any name string returned is placed in new storage for the
* calling method. The caller must use 'free' to dispose
* of the storage once the name string is no longer needed.
*/
char *
smlGetElementName(SML_TAG *a_tag)
{
/* entry assertions */
assert(SML_TAG__ISVALID(a_tag));
assert(a_tag->name != (char *)NULL);
assert(*a_tag->name != '\0');
/* return the tag name */
return (strdup(a_tag->name));
}
/*
* Name: smlGetTag
* Description: Get an element from a tag
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the element from
* index - [RO] - (int)
* Index of element to return
* Returns: SML_TAG *
* The 'index'th element from the specified tag
* == SML_TAG__NULL if no such tag or element
*/
SML_TAG *
smlGetTag(SML_TAG *tag, int index)
{
/* if no tag specified, return NULL */
if (tag == NULL) {
return (SML_TAG__NULL);
}
/* if tag has no elements, return NULL */
if (tag->tags == NULL) {
return (SML_TAG__NULL);
}
/* if index not within range, return NULL */
if (tag->tags_num <= index) {
return (SML_TAG__NULL);
}
/* index within range, return element specified */
assert(SML_TAG__ISVALID(&tag->tags[index]));
return (&tag->tags[index]);
}
/*
* Name: smlGetTagByName
* Description: Get an element given a name and an index
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the element from
* index - [RO] - (int)
* Index of nth name to return
* name - [RO, *RO] - (char *)
* Tag name to look up
* Returns: SML_TAG *
* The 'index'th occurance of element 'name'
* == SML_TAG__NULL if no such element exists
*/
SML_TAG *
smlGetTagByName(SML_TAG *tag, int index, char *name)
{
int k;
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_TAG_BY_NAME, name, index);
/* if no tag specified, return NULL */
if (tag == NULL) {
return (SML_TAG__NULL);
}
/* if this tag is the one mentioned, return it */
if (streq(tag->name, name) && (index == 0)) {
return (tag);
}
/* if tag has no elements, return NULL */
if (tag->tags == NULL) {
return (SML_TAG__NULL);
}
/* if index out of range, return NULL */
if (tag->tags_num <= index) {
return (SML_TAG__NULL);
}
/* index within range - search for specified element */
for (k = 0; k < tag->tags_num; k++) {
if (streq(tag->tags[k].name, name)) {
if (index == 0) {
assert(SML_TAG__ISVALID(&tag->tags[k]));
return (&tag->tags[k]);
} else {
index--;
}
}
}
/* no such element found - return NULL */
return (SML_TAG__NULL);
}
/*
* Name: smlConvertStringToTag
* Description: Convert string into tag object
* Arguments: err - [RO, *RW] (LU_ERR)
* Error object - used to contain any errors encountered
* and return those errors to this methods caller
* r_tag - [RW, *RW] - (SML_TAG **)
* Pointer to handle to place new tag object
* str - [RO, *RO] - (char *)
* String object to convert to tag object
* Returns: int
* RESULT_OK - string converted to tag object
* RESULT_ERR - problem converting string to tag object
* NOTE: Any tag object returned is placed in new storage for the
* calling method. The caller must use 'smlFreeTag' to dispose
* of the storage once the tag object name is no longer needed.
*/
int
smlConvertStringToTag(SML_TAG **r_tag, char *str)
{
int r;
SML_TAG *tag = SML_TAG__NULL;
SML_TAG *tmp_tag;
/* entry assertions */
assert(SML_TAG__R_ISVALID(r_tag));
assert(str != (char *)NULL);
assert(*str != '\0');
tag = smlNewTag("tagfile");
for (;;) {
r = _smlReadTag(&tmp_tag, &str, NULL);
if (r != RESULT_OK) {
smlFreeTag(tag);
return (r);
}
if (tmp_tag == SML_TAG__NULL) {
if (*str != '\0') {
continue;
}
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_LOADED_TAGS_FROM_STR,
(unsigned long)tag, tag->name);
*r_tag = tag;
return (RESULT_OK);
}
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_IN_TOP_TAG,
tmp_tag->name);
tag->tags_num++;
tag->tags = (SML_TAG *)realloc(tag->tags,
sizeof (SML_TAG) *tag->tags_num);
(void) memcpy(&(tag->tags[tag->tags_num - 1]), tmp_tag,
sizeof (SML_TAG));
}
}
/*
* Name: smlReadOneTag
* Description: read one complete tag from a datastream
* Arguments: err - [RO, *RW] (LU_ERR)
* Error object - used to contain any errors encountered
* and return those errors to this methods caller
* r_tag - [RW, *RW] - (SML_TAG **)
* Pointer to handle to place new tag object
* == SML_TAG__NULL if empty tag found (not an error)
* ds - [RO, *RO] - (LU_DS)
* Handle to datastream to read tag from
* Returns: int
* RESULT_OK - tag successfully read
* RESULT_ERR - problem reading tag
* NOTE: Any tag object returned is placed in new storage for the
* calling method. The caller must use 'smlFreeTag' to dispose
* of the storage once the tag object name is no longer needed.
*/
int
smlReadOneTag(SML_TAG **r_tag, char *a_str)
{
int r;
/* entry assertions */
assert(SML_TAG__R_ISVALID(r_tag));
assert(a_str != (char *)NULL);
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_ONE_TAG, a_str);
/* reset return tag */
*r_tag = SML_TAG__NULL;
/* read tag from datastream, no parent tag to attach it to */
r = _smlReadTag(r_tag, &a_str, NULL);
if (r != RESULT_OK) {
_smlLogMsg(LOG_MSG_ERR, ERR_SML_CANNOT_READ_TAG);
return (r);
}
if (*r_tag != SML_TAG__NULL) {
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_ONE_TAG_READ,
(unsigned long)*r_tag,
(*r_tag)->name ? (*r_tag)->name : "<no name>");
} else {
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_ONE_TAG_NOTAG);
}
/* exit debugging info */
return (RESULT_OK);
}
/*
* Name: smlNewTag
* Description: Create a new (empty) tag object
* Arguments: name - [RO, *RO] - (char *)
* Name of tag; NULL to give the tag no name
* Returns: SML_TAG *
* Tag object created
* NOTE: Any tag object returned is placed in new storage for the
* calling method. The caller must use 'smlFreeTag' to dispose
* of the storage once the tag object name is no longer needed.
* Errors: If the tag object cannot be created, the process exits
*/
SML_TAG *
smlNewTag(char *name)
{
SML_TAG *tag;
/* entry assertions */
assert((name == (char *)NULL) || (*name != '\0'));
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_CREATE_NEW_TAG_OBJECT,
name ? name : "<no name>");
/* allocate zeroed storage for the tag object */
tag = (SML_TAG *)calloc(1, sizeof (SML_TAG));
assert(tag != SML_TAG__NULL);
/* if name is provided, duplicate and assign it */
if (name != (char *)NULL) {
tag->name = strdup(name);
}
/* exit assertions */
assert(SML_TAG__ISVALID(tag));
/* exit debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_CREATED_NEW_TAG_OBJECT,
(unsigned long)tag, name ? name : "<no name>");
return (tag);
}
/*
* Name: smlConvertTagToString
* Description: Convert a tag object into a string representation of the XML
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to convert to a string
* Returns: char *
* String representation (in XML) of tag object
* == (char *)NULL if conversion is not possible
* NOTE: Any string returned is placed in new storage for the
* calling method. The caller must use 'free' to dispose
* of the storage once the string is no longer needed.
*/
char *
smlConvertTagToString(SML_TAG *tag)
{
char *str = (char *)NULL;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
/* convert the tag object into the datastream */
(void) _smlWriteSimpleTag(&str, tag);
assert(str != (char *)NULL);
assert(*str != '\0');
/* return the results */
return (str);
}
/*
* Name: smlDbgPrintTag
* Synopsis: Print a representation of an XML tag if debugging
* Arguments: a_tag - [RO, *RO] - (SML_TAG *)
* Pointer to tag structure to dump
* a_format - [RO, RO*] (char *)
* printf-style format for debugging message to be output
* VARG_LIST - [RO] (?)
* arguments as appropriate to 'format' specified
* Returns: void
* If one of the debugging flags is set, the hexdump
* is output.
*/
/*PRINTFLIKE2*/
void
smlDbgPrintTag(SML_TAG *a_tag, char *a_format, ...)
{
va_list ap;
size_t vres = 0;
char bfr[1];
char *rstr = (char *)NULL;
/* entry assertions */
assert(a_format != (char *)NULL);
assert(*a_format != '\0');
assert(SML_TAG__ISVALID(a_tag));
/*
* output the message header
*/
/* determine size of the message in bytes */
va_start(ap, a_format);
vres = vsnprintf(bfr, 1, a_format, ap);
va_end(ap);
assert(vres > 0);
/* allocate storage to hold the message */
rstr = (char *)calloc(1, vres+2);
assert(rstr != (char *)NULL);
/* generate the results of the printf conversion */
va_start(ap, a_format);
vres = vsnprintf(rstr, vres+1, a_format, ap);
va_end(ap);
assert(vres > 0);
assert(*rstr != '\0');
_smlLogMsg(LOG_MSG_DEBUG, "%s", rstr);
free(rstr);
/* convert the tag into a string to be printed */
rstr = smlConvertTagToString(a_tag);
if (rstr != (char *)NULL) {
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_PRINTTAG, a_tag->name,
strlen(rstr), rstr);
}
free(rstr);
}
/*
* Name: smlDelParam
* Description: Delete a parameter from a tag object
* Arguments: tag - [RO, *RW] - (SML_TAG *)
* The tag object to delete the parameter from
* name - [RO, *RO] - (char *)
* The parameter to delete from the tag object
* Returns: void
* If the parameter exists, it is deleted from the tag
*/
void
smlDelParam(SML_TAG *tag, char *name)
{
int k;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(tag->name != (char *)NULL);
assert(name != NULL);
assert(*name != '\0');
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_DELETE_PARAM,
tag->name, name);
/* if tag has no parameters, nothing to delete */
if (tag->params == NULL) {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_DELETE_PARAM_NO_PARAMS);
return;
}
assert(tag->params_num > 0);
/* search the tag for the parameter */
for (k = 0; k < tag->params_num; k++) {
if (streq(tag->params[k].name, name)) {
break;
}
}
/* if the parameter was not found, nothing to delete */
if (k >= tag->params_num) {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_DELETE_PARAM_NOT_FOUND,
name);
return;
}
/* parameter found - indicate deleted */
assert(tag->params[k].name != (char *)NULL);
assert(tag->params[k].value != (char *)NULL);
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_DELETE_PARAM_FOUND,
name, tag->params[k].value);
/* free up storage fro parameter */
free(tag->params[k].name);
free(tag->params[k].value);
/* if not at end, compact parameter storage */
if (k < (tag->params_num -1)) {
(void) memmove(&(tag->params[k]), &(tag->params[k + 1]),
sizeof (SML_PARAM) *(tag->params_num - k - 1));
}
/* one less parameter object in tag */
tag->params_num --;
/*
* If only one parameter left, then delete entire parameter storage,
* otherwise reallocate removing unneeded entry
*/
if (tag->params_num > 0) {
/* realloc removing last element in tag object */
tag->params = (SML_PARAM *)
realloc(tag->params,
sizeof (SML_PARAM) *tag->params_num);
} else {
tag->params = (SML_PARAM *)NULL;
}
}
/*
* Name: smlSetParamF
* Description: Set formatted parameter value in tag object
* Arguments: tag - [RO, *RW] - (SML_TAG *)
* The tag object to set the parameter in
* name - [RO, *RO] - (char *)
* The parameter to add to the tag object
* format - [RO, RO*] (char *)
* printf-style format to create parameter value from
* ... - [RO] (?)
* arguments as appropriate to 'format' specified
* Returns: void
* The parameter value is set in the tag object
* according to the results of the format string
* and arguments
*/
/*PRINTFLIKE3*/
void
smlSetParamF(SML_TAG *tag, char *name, char *format, ...)
{
va_list ap;
size_t vres = 0;
char *bfr = NULL;
char fbfr[1];
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(name != (char *)NULL);
assert(*name != '\0');
assert(format != NULL);
assert(*format != '\0');
/* determine size of the parameter name in bytes */
va_start(ap, format);
vres = vsnprintf(fbfr, 1, format, ap);
va_end(ap);
assert(vres > 0);
/* allocate storage to hold the message */
bfr = (char *)calloc(1, vres+2);
assert(bfr != (char *)NULL);
/* generate the parameter name and store it in the allocated storage */
va_start(ap, format);
vres = vsnprintf(bfr, vres+1, format, ap);
va_end(ap);
assert(vres > 0);
assert(*bfr != '\0');
/* add the parameter to the tag */
smlSetParam(tag, name, bfr);
/* free up temporary storage and return */
free(bfr);
}
/*
* Name: smlGetParam
* Description: Get a format-generated parameter from a tag
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to obtain the parameter from
* format - [RO, RO*] (char *)
* printf-style format for parameter name to be
* looked up to be formatted
* ... - [RO] (?)
* arguments as appropriate to 'format' specified
* Returns: char *
* Value of the specified parameter
* == (char *)NULL if the parameter does not exist
* NOTE: Any parameter returned is placed in new storage for the
* calling method. The caller must use 'free' to dispose
* of the storage once the parameter is no longer needed.
*/
/*PRINTFLIKE2*/
char *
smlGetParamF(SML_TAG *tag, char *format, ...)
{
va_list ap;
size_t vres = 0;
char *bfr = NULL;
char fbfr[1];
char *p;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(format != NULL);
assert(*format != '\0');
/* determine size of the parameter name in bytes */
va_start(ap, format);
vres = vsnprintf(fbfr, 1, format, ap);
va_end(ap);
assert(vres > 0);
/* allocate storage to hold the message */
bfr = (char *)calloc(1, vres+2);
assert(bfr != (char *)NULL);
/* generate the parameter name and store it in the allocated storage */
va_start(ap, format);
vres = vsnprintf(bfr, vres+1, format, ap);
va_end(ap);
assert(vres > 0);
assert(*bfr != '\0');
/* add the parameter to the tag */
p = smlGetParam(tag, bfr);
/* free up temporary storage and return */
free(bfr);
return (p);
}
/*
* Name: smlSetParam
* Description: Set parameter value in tag object
* Arguments: tag - [RO, *RW] - (SML_TAG *)
* The tag object to set the parameter in
* name - [RO, *RO] - (char *)
* The parameter to add to the tag object
* value - [RO, *RO] - (char *)
* The value of the parameter to set in the tag object
* Returns: void
* The parameter value is set in the tag object
*/
void
smlSetParam(SML_TAG *tag, char *name, char *value)
{
SML_PARAM *parameter;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(name != (char *)NULL);
assert(*name != '\0');
assert(value != (char *)NULL);
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_SET_PARAM,
tag->name, name, value);
/* if parameters exist, see if modifying existing parameter */
if (tag->params != NULL) {
int k;
for (k = 0; k < tag->params_num; k++) {
assert(tag->params[k].name != (char *)NULL);
assert(tag->params[k].value != (char *)NULL);
/* if name does not match, skip */
if (!streq(tag->params[k].name, name)) {
continue;
}
/* found parameter - if value is same, leave alone */
if (streq(tag->params[k].value, value)) {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_SET_PARAM_LEAVE_ALONE,
tag->params[k].value);
return;
}
/* exists and has different value - change */
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_SET_PARAM_MODIFY,
tag->params[k].value);
free(tag->params[k].value);
tag->params[k].value = strdup(value);
return;
}
}
/* not modifying existing - add new parameter */
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_SET_PARAM_CREATE_NEW);
parameter = (SML_PARAM *)calloc(1, sizeof (SML_PARAM));
bzero(parameter, sizeof (SML_PARAM));
parameter->name = strdup(name);
parameter->value = strdup(value);
tag->params_num++;
tag->params = (SML_PARAM *)realloc(tag->params,
sizeof (SML_PARAM) *tag->params_num);
(void) memcpy(&(tag->params[tag->params_num - 1]), parameter,
sizeof (SML_PARAM));
free(parameter);
}
/*
* Name: smlParamEqF
* Description: Determine if parameter is equal to a specified formatted value
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to look for the parameter to compare
* findTag - [RO, *RO] - (char *)
* Tag within tag object to look for the parameter in
* findParam - [RO, *RO] - (char *)
* Parameter within tag to look for
* format - [RO, RO*] (char *)
* printf-style format for value to be compared against
* parameter value
* ... - [RO] (?)
* arguments as appropriate to 'format' specified to
* generate the value to compare parameter with
* Returns: boolean_t
* B_TRUE - the parameter exists and matches given value
* B_FALSE - parameter does not exist or does not match
*/
/*PRINTFLIKE4*/
boolean_t
smlParamEqF(SML_TAG *tag, char *findTag, char *findParam, char *format, ...)
{
va_list ap;
size_t vres = 0;
char *bfr = NULL;
char fbfr[1];
boolean_t b;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(format != NULL);
assert(*format != '\0');
/* determine size of the parameter value in bytes */
va_start(ap, format);
vres = vsnprintf(fbfr, 1, format, ap);
va_end(ap);
assert(vres > 0);
/* allocate storage to hold the message */
bfr = (char *)calloc(1, vres+2);
assert(bfr != (char *)NULL);
/* generate the parameter value and store it in the allocated storage */
va_start(ap, format);
vres = vsnprintf(bfr, vres+1, format, ap);
va_end(ap);
assert(vres > 0);
assert(*bfr != '\0');
/* add the parameter to the tag */
b = smlParamEq(tag, findTag, findParam, bfr);
/* free up temporary storage and return */
free(bfr);
return (b);
}
/*
* Name: smlParamEq
* Description: Determine if parameter is equal to a specified value
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to look for the parameter to compare
* findTag - [RO, *RO] - (char *)
* Tag within tag object to look for the parameter in
* findParam - [RO, *RO] - (char *)
* Parameter within tag to look for
* str - [RO, *RO] - (char *)
* Value to compare parameter with
* Returns: boolean_t
* B_TRUE - the parameter exists and matches given value
* B_FALSE - parameter does not exist or does not match
*/
boolean_t
smlParamEq(SML_TAG *tag, char *findTag, char *findParam, char *str)
{
SML_TAG *rtag;
char *rparm;
boolean_t answer;
/* entry assertions */
assert(str != (char *)NULL);
assert(findParam != (char *)NULL);
assert(findTag != (char *)NULL);
assert(SML_TAG__ISVALID(tag));
/* look for the specified tag - if not found, return false */
rtag = smlGetTagByName(tag, 0, findTag);
if (rtag == SML_TAG__NULL) {
return (B_FALSE);
}
/* look for the specified parameter - if not found, return false */
rparm = smlGetParam(rtag, findParam);
if (rparm == (char *)NULL) {
return (B_FALSE);
}
/* parameter found - compare against given value */
answer = strcasecmp(str, rparm);
/* free up parameter storage */
free(rparm);
/* return results of comparison */
return (answer == 0 ? B_TRUE : B_FALSE);
}
/*
* Name: smlFindAndDelTag
* Description: Delete a tag if found in tag object
* Arguments: tag - [RO, *RW] - (SML_TAG *)
* The tag object to delete the tag from
* findTag - [RO, *RO] - (char *)
* Tag within tag object to delete
* Returns: boolean_t
* B_TRUE - tag found and deleted
* B_FALSE - tag not found
*/
boolean_t
smlFindAndDelTag(SML_TAG *tag, char *findTag)
{
SML_TAG *rtag = SML_TAG__NULL;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
assert(findTag != (char *)NULL);
assert(*findTag != '\0');
/* find the specified tag - if not found, return false */
rtag = smlGetTagByName(tag, 0, findTag);
if (rtag == SML_TAG__NULL) {
return (B_FALSE);
}
/* tag found - delete it and return true */
smlDelTag(tag, rtag);
return (B_TRUE);
}
/*
* Name: smlDup
* Description: Duplicate a tag object
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to duplicate
* Returns: SML_TAG *
* A handle to a complete duplicate of the tag provided
* NOTE: Any tag object returned is placed in new storage for the
* calling method. The caller must use 'smlFreeTag' to dispose
* of the storage once the tag object name is no longer needed.
* Errors: If the tag object cannot be duplicated, the process exits
*/
SML_TAG *
smlDup(SML_TAG *tag)
{
SML_TAG *rtag = SML_TAG__NULL;
int i;
/* entry assertions */
assert(SML_TAG__ISVALID(tag));
/* allocate zeroed storage for the tag object */
rtag = (SML_TAG *)calloc(1, sizeof (SML_TAG));
assert(rtag != SML_TAG__NULL);
/* duplicate all parameters of the tag */
rtag->name = (tag->name ? strdup(tag->name) : (char *)NULL);
rtag->params_num = tag->params_num;
if (tag->params != (SML_PARAM *)NULL) {
rtag->params = (SML_PARAM *)
calloc(1, sizeof (SML_PARAM)*rtag->params_num);
bzero(rtag->params, sizeof (SML_PARAM)*rtag->params_num);
for (i = 0; i < rtag->params_num; i++) {
rtag->params[i].name = tag->params[i].name ?
strdup(tag->params[i].name) :
(char *)NULL;
rtag->params[i].value = tag->params[i].value ?
strdup(tag->params[i].value) :
(char *)NULL;
}
}
/* duplicate all elements of the tag */
rtag->tags_num = tag->tags_num;
if (tag->tags != SML_TAG__NULL) {
rtag->tags = (SML_TAG *)
calloc(1, sizeof (SML_TAG)*rtag->tags_num);
bzero(rtag->tags, sizeof (SML_TAG)*rtag->tags_num);
for (i = 0; i < rtag->tags_num; i++) {
SML_TAG *stag;
stag = smlDup(&tag->tags[i]);
(void) memcpy(&rtag->tags[i], stag,
sizeof (SML_TAG));
free(stag);
}
}
/* exit assertions */
assert(SML_TAG__ISVALID(rtag));
/* return */
return (rtag);
}
/*
* Name: smlSetFileStatInfo
* Description; Given a file status structure and path name, encode the
* structure and place it and the name into the specified tag
* in a "_sml_fileStatInfoTag" (private) element
* Arguments: tag - [RO, *RO] - (SML_TAG *)
* The tag object to deposit the information into
* statbuf - [RO, *RO] - (struct stat *)
* Pointer to file status structure to encode
* path - [RO, *RO] - (char *)
* Pointer to path name of file to encode
* Returns: void
* The information is placed into the specified tag object
*/
void
smlSetFileStatInfo(SML_TAG **tag, struct stat *statbuf, char *path)
{
SML_TAG *rtag;
/* entry assertions */
assert(SML_TAG__R_ISVALID(tag));
assert(SML_TAG__ISVALID(*tag));
assert(statbuf != (struct stat *)NULL);
/* if stat info exists, delete it */
(void) smlFindAndDelTag(*tag, _sml_fileStatInfoTag);
/* create the file stat info inside of the top level tag */
assert(smlGetTagByName(*tag, 0, _sml_fileStatInfoTag)
== SML_TAG__NULL);
rtag = smlNewTag(_sml_fileStatInfoTag);
assert(SML_TAG__ISVALID(rtag));
(void) smlAddTag(tag, 0, rtag);
free(rtag);
/* obtain handle on newly created file stat info tag */
rtag = smlGetTagByName(*tag, 0, _sml_fileStatInfoTag);
assert(SML_TAG__ISVALID(rtag));
/* add file info as parameters to the tag */
if (path != (char *)NULL) {
smlSetParam(rtag, "st_path", path);
}
smlSetParamF(rtag, "st_ino", "0x%llx",
(unsigned long long)statbuf->st_ino);
smlSetParamF(rtag, "st_mode", "0x%llx",
(unsigned long long)statbuf->st_mode);
smlSetParamF(rtag, "st_mtime", "0x%llx",
(unsigned long long)statbuf->st_mtime);
smlSetParamF(rtag, "st_ctime", "0x%llx",
(unsigned long long)statbuf->st_ctime);
smlSetParamF(rtag, "st_size", "0x%llx",
(unsigned long long)statbuf->st_size);
}
/*
* Name: smlFstatCompareEQ
* Description: Given a file status structure and path name, look for the
* information placed into a tag object via smlSetFileStatInfo
* and if present compare the encoded information with the
* arguments provided
* Arguments: statbuf - [RO, *RO] - (struct stat *)
* Pointer to file status structure to compare
* tag - [RO, *RO] - (SML_TAG *)
* The tag object to compare against
* path - [RO, *RO] - (char *)
* Pointer to path name of file to compare
* Returns: boolean_t
* B_TRUE - both status structures are identical
* B_FALSE - the status structures are not equal
*/
boolean_t
smlFstatCompareEq(struct stat *statbuf, SML_TAG *tag, char *path)
{
if (tag == SML_TAG__NULL) {
return (B_FALSE);
}
assert(SML_TAG__ISVALID(tag));
if (statbuf == (struct stat *)NULL) {
return (B_FALSE);
}
if (path != (char *)NULL) {
if (smlParamEq(tag,
_sml_fileStatInfoTag, "st_path", path) != B_TRUE) {
return (B_FALSE);
}
}
if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_ino",
"0x%llx", (unsigned long long)statbuf->st_ino) != B_TRUE) {
return (B_FALSE);
}
if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_mode",
"0x%llx", (unsigned long long)statbuf->st_mode) != B_TRUE) {
return (B_FALSE);
}
if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_mtime",
"0x%llx", (unsigned long long)statbuf->st_mtime) != B_TRUE) {
return (B_FALSE);
}
if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_ctime",
"0x%llx", (unsigned long long)statbuf->st_ctime) != B_TRUE) {
return (B_FALSE);
}
if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_size",
"0x%llx", (unsigned long long)statbuf->st_size) != B_TRUE) {
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Name: set_verbose
* Description: Turns on verbose output
* Scope: public
* Arguments: verbose = B_TRUE indicates verbose mode
* Returns: none
*/
void
smlSetVerbose(boolean_t setting)
{
verbose = setting;
}
/*
* Name: get_verbose
* Description: Returns whether or not to output verbose messages
* Scope: public
* Arguments: none
* Returns: B_TRUE - verbose messages should be output
*/
boolean_t
smlGetVerbose()
{
return (verbose);
}
/*
* Name: sml_strPrintf
* Synopsis: Create string from printf style format and arguments
* Description: Call to convert a printf style format and arguments into a
* string of characters placed in allocated storage
* Arguments: format - [RO, RO*] (char *)
* printf-style format for string to be formatted
* ... - [RO] (?)
* arguments as appropriate to 'format' specified
* Returns: char *
* A string representing the printf conversion results
* NOTE: Any string returned is placed in new storage for the
* calling method. The caller must use 'free' to dispose
* of the storage once the string is no longer needed.
* Errors: If the string cannot be created, the process exits
*/
/*PRINTFLIKE1*/
char *
sml_strPrintf(char *a_format, ...)
{
va_list ap;
size_t vres = 0;
char bfr[1];
char *rstr = (char *)NULL;
/* entry assertions */
assert(a_format != (char *)NULL);
assert(*a_format != '\0');
/* determine size of the message in bytes */
va_start(ap, a_format);
vres = vsnprintf(bfr, 1, a_format, ap);
va_end(ap);
assert(vres > 0);
/* allocate storage to hold the message */
rstr = (char *)calloc(1, vres+2);
assert(rstr != (char *)NULL);
/* generate the results of the printf conversion */
va_start(ap, a_format);
vres = vsnprintf(rstr, vres+1, a_format, ap);
va_end(ap);
assert(vres > 0);
assert(*rstr != '\0');
/* return the results */
return (rstr);
}
/*
* Name: sml_strPrintf_r
* Synopsis: Create string from printf style format and arguments
* Description: Call to convert a printf style format and arguments into a
* string of characters placed in allocated storage
* Arguments: a_buf - [RO, *RW] - (char *)
* - Pointer to buffer used as storage space for the
* returned string created
* a_bufLen - [RO, *RO] - (int)
* - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
* bytes will be placed in 'a_buf' - the returned
* string is always null terminated
* a_format - [RO, RO*] (char *)
* printf-style format for string to be formatted
* VARG_LIST - [RO] (?)
* arguments as appropriate to 'format' specified
* Returns: void
*/
/*PRINTFLIKE3*/
void
sml_strPrintf_r(char *a_buf, int a_bufLen, char *a_format, ...)
{
va_list ap;
size_t vres = 0;
/* entry assertions */
assert(a_format != (char *)NULL);
assert(*a_format != '\0');
assert(a_buf != (char *)NULL);
assert(a_bufLen > 1);
/* generate the results of the printf conversion */
va_start(ap, a_format);
vres = vsnprintf(a_buf, a_bufLen-1, a_format, ap);
va_end(ap);
assert(vres > 0);
assert(vres < a_bufLen);
a_buf[a_bufLen-1] = '\0';
}
/*
* Name: sml_XmlEncodeString
* Description: Given a plain text string, convert that string into one that
* encoded using the XML character reference encoding format.
* Arguments: a_plain_text_string - [RO, *RO] (char *)
* The plain text string to convert (encode)
* Returns: char *
* The encoded form of the plain text string provided
* NOTE: Any string returned is placed in new storage for the
* calling method. The caller must use 'lu_memFree' to dispose
* of the storage once the string is no longer needed.
*/
char *
sml_XmlEncodeString(char *a_plainTextString)
{
char *stringHead; /* -> start of string containing encoded data */
long stringTail; /* byte pos of first free byte in stringHead */
long stringLength; /* total bytes allocd starting at stringHead */
char *p; /* temp -> to retrieve bytes from src string */
long textLength = 0; /* length of the string to convert */
/* entry assertions */
assert(a_plainTextString != (char *)NULL);
textLength = strlen(a_plainTextString);
/* Allocate initial string buffer to hold results */
stringLength = textLength*2;
stringTail = 0;
stringHead = (char *)calloc(1, (size_t)stringLength+2);
assert(stringHead != (char *)NULL);
/* Add in the encoded message text */
for (p = a_plainTextString; textLength > 0; p++, textLength--) {
/*
* Must have at least 12 bytes: this must be at least the
* maximum number of bytes that can be added for a single
* byte as the last byte of the stream. Assuming the byte
* needs to be encoded, it could be:
* &#xxxxxxxx;\0
* If not that many bytes left, grow the buffer.
*/
if ((stringLength-stringTail) < 12) {
stringLength += (textLength*2)+12;
stringHead =
realloc(stringHead,
(size_t)stringLength+2);
assert(stringHead != (char *)NULL);
}
/*
* See if this byte is a 'printable 7-bit ascii value'.
* If so just add it to the new string; otherwise, must
* output an XML character value encoding for the byte.
*/
switch (*p) {
case '!':
case '#':
case '%':
case '\'':
case '(':
case ')':
case '*':
case '+':
case ',':
case '-':
case '.':
case '/':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case ':':
case ';':
case '<':
case '=':
case '>':
case '?':
case '@':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '[':
case ']':
case '^':
case '_':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case '{':
case '|':
case '}':
case '~':
case ' ':
/*
* It is a printable 7-bit ascii character:
* just add it to the end of the new string.
*/
stringHead[stringTail++] = *p;
break;
default:
/*
* It is not a printable 7-bit ascii character:
* add it as an xml character value encoding.
*/
stringTail += sprintf(&stringHead[stringTail], "&#%x;",
(*p)&0xFF);
break;
}
}
/* Terminate the new string */
stringHead[stringTail] = '\0';
/* realloc the string so it is only as big as it needs to be */
stringHead = realloc(stringHead, stringTail+1);
assert(stringHead != (char *)NULL);
return (stringHead);
}
/*
* Name: sml_XmlDecodeString
* Description: Given a string encoded using the XML character reference format,
* convert that string into a plain text (unencoded) string.
* Arguments: a_xml_encoded_string - [RO, *RO] (char *)
* The XML encoded string to convert to plain text
* Returns: char *
* The unencoded (plain text) form of the encoded string
* NOTE: Any string returned is placed in new storage for the
* calling method. The caller must use 'lu_memFree' to dispose
* of the storage once the string is no longer needed.
*/
char *
sml_XmlDecodeString(char *a_xmlEncodedString)
{
char *s = NULL; /* -> index into encoded bytes string */
char *d = NULL; /* -> index into decoded bytes string */
char *rs = NULL; /* -> string holding ref bytes allocated */
char *ri = NULL; /* -> index into string holding reference */
long textLength = 0; /* length of encoded string to decode */
unsigned long rv = 0; /* temp to hold scanf results of byte conv */
char *i = NULL; /* temp to hold strchr results */
char *stringHead = NULL; /* -> plain test buffer */
ptrdiff_t tmpdiff;
/*
* A finite state machine is used to convert the xml encoded string
* into plain text. The states of the machine are defined below.
*/
int fsmsState = -1; /* Finite state machine state */
#define fsms_text 0 /* Decoding plain text */
#define fsms_seenAmp 1 /* Found & */
#define fsms_seenPound 2 /* Found # following & */
#define fsms_collect 3 /* Collecting character reference bytes */
/* entry assertions */
assert(a_xmlEncodedString != (char *)NULL);
textLength = strlen(a_xmlEncodedString);
/*
* Allocate string that can contain the decoded string.
* Since decoding always results in a shorter string (bytes encoded
* using the XML character reference are larger in the encoded form)
* we can allocate a string the same size as the encoded string.
*/
stringHead = (char *)calloc(1, textLength+1);
assert(stringHead != (char *)NULL);
/*
* Convert all bytes.
*/
/* Decoding plain text */
fsmsState = fsms_text;
for (s = a_xmlEncodedString, d = stringHead; textLength > 0;
s++, textLength--) {
switch (fsmsState) {
case fsms_text: /* Decoding plain text */
if (rs != NULL) {
free(rs);
rs = NULL;
ri = NULL;
}
if (*s == '&') {
/* Found & */
fsmsState = fsms_seenAmp;
continue;
}
*d++ = *s;
continue;
case fsms_seenAmp: /* Found & */
if (*s == '#') {
/* Found # following & */
fsmsState = fsms_seenPound;
continue;
}
fsmsState = fsms_text; /* Decoding plain text */
*d++ = '&';
*d++ = *s;
continue;
case fsms_seenPound: /* Found # following & */
i = strchr(s, ';');
if (i == NULL) {
/* Decoding plain text */
fsmsState = fsms_text;
*d++ = '&';
*d++ = '#';
*d++ = *s;
continue;
}
tmpdiff = (ptrdiff_t)i - (ptrdiff_t)s;
rs = (char *)calloc(1, tmpdiff + 1);
assert(rs != (char *)NULL);
ri = rs;
/* Collecting character reference bytes */
fsmsState = fsms_collect;
/*FALLTHRU*/
/* Collecting character reference bytes */
case fsms_collect:
if (*s != ';') {
switch (*s) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
*ri++ = *s;
break;
default:
*ri = '\0';
*d++ = '&';
*d++ = '#';
tmpdiff = (ptrdiff_t)ri - (ptrdiff_t)rs;
(void) strncpy(d, rs, tmpdiff-1);
*d++ = *s;
/* Decoding plain text */
fsmsState = fsms_text;
break;
}
continue;
}
*ri = '\0';
if (sscanf(rs, "%lx", &rv) != 1) {
*d++ = '?';
} else {
*d++ = (rv & 0xFF);
}
/* Decoding plain text */
fsmsState = fsms_text;
}
}
/* Done converting bytes - deallocate reference byte storage */
free(rs);
/* terminate the converted (plain text) string */
*d = '\0';
/* exit assertions */
assert(stringHead != (char *)NULL);
return (stringHead);
}
/*
* Private Methods
*/
/*
* Name: _smlReadTag
* Description: read complete tag from a datastream
* Arguments: err - [RO, *RW] (LU_ERR)
* Error object - used to contain any errors encountered
* and return those errors to this methods caller
* r_tag - [RW, *RW] - (SML_TAG **)
* Pointer to handle to place new tag object
* == SML_TAG__NULL if empty tag found (not an error)
* ds - [RO, *RO] - (LU_DS)
* Handle to datastream to read tag from
* parent - [RO, *RO] - (char *)
* Name for parent of tag (NONE if top of tag)
* Returns: int
* RESULT_OK - tag successfully read
* RESULT_ERR - problem reading tag
* NOTE: Any tag object returned is placed in new storage for the
* calling method. The caller must use 'smlFreeTag' to dispose
* of the storage once the tag object name is no longer needed.
* Errors: If the tag object cannot be duplicated, the process exits
*/
static int
_smlReadTag(SML_TAG **r_tag, char **a_str, char *parent)
{
int r;
SML_TAG *tag;
SML_TAG *tmp_tag;
char name[MAX_SML_COMPONENT_LENGTH];
int pos = 0;
int c;
char *p = *a_str;
/* entry assertions */
assert(SML_TAG__R_ISVALID(r_tag));
assert(a_str != (char **)NULL);
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_TAG,
parent ? parent : "<<TOP TAG>>");
/* reset return tag */
*r_tag = SML_TAG__NULL;
/* allocate zeroed storage for the tag object */
tag = (SML_TAG *)calloc(1, sizeof (SML_TAG));
assert(tag != SML_TAG__NULL);
/* reset name accumulator storage */
bzero(name, sizeof (name));
/* ignore delimters before tag */
for (;;) {
/* read tag character - handle failure/EOF */
if ((*p == '\0') || ((c = (*p++)) == '\0')) {
if (parent == NULL) {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_READTAG_EXPECTED_EOF,
p ? p : "?");
smlFreeTag(tag);
*a_str = p;
return (RESULT_OK);
}
/* EOF in middle of processing tag */
_smlLogMsg(LOG_MSG_ERR,
DBG_SML_READTAG_UNEXPECTED_EOF,
p ? p : "?");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* if beginning of tag, break out */
if (c == '<') {
break;
}
/* not tag beginning: ignore delimiters if not inside tag yet */
if (parent == (char *)NULL) {
/* ignore delimters */
if (strchr(" \t", c) != (char *)NULL) {
continue;
}
/* on blank lines, return no tag object */
if (c == '\n') {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_READTAG_BLANKLINE,
p ? p : "?");
smlFreeTag(tag);
*a_str = p;
return (RESULT_OK);
}
/* invalid character before tag start */
_smlLogMsg(LOG_MSG_ERR, ERR_SML_READTAG_BAD_START_CHAR,
c, (unsigned int)c);
*a_str = p;
return (RESULT_ERR);
}
}
/*
* all delimiters have been ignored and opening tag character seen;
* process tag
*/
assert(c == '<');
c = *p;
if (*p != '\0') {
p++;
}
/* handle EOF after tag opening character found */
if (c == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_EOF_BEFORE_TAG_NAME,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* is this a tag closure? */
if (c == '/') {
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_START_CLOSE_TAG,
parent ? parent : "<<NONE>>");
for (;;) {
/* get next character of tag name */
c = *p;
if (*p != '\0') {
p++;
}
/* EOF inside tag name? */
if (c == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_CLOSE_TAG_EOF,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* tag close: break out of collection loop */
if (c == '>') {
break;
}
/* see if illegal character in tag name */
/* CSTYLED */
if (strchr("/ \t\n\":<?$'\\`!@#%^&*()+=|[]{};,", c)
!= NULL) {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_CLOSE_TAG_ILLCHAR,
c, (unsigned int)c, name);
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* valid character - add to name if room left */
if (pos < sizeof (name)-1) {
name[pos] = (c&0xFF);
pos++;
}
assert(pos < sizeof (name));
}
/* close of tag found */
assert(c == '>');
/* is the tag empty? If so that's an error */
if (*name == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_CLOSE_EMPTY_TAG);
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* if no parent, a close tag outside of any open tag */
if (parent == (char *)NULL) {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_CLOSE_NO_PARENT,
name);
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* if not close to current parent, error */
if (!streq(parent, name)) {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_CLOSE_WRONG_TAG,
name, parent);
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* close of current tag found - success */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READTAG_CLOSE_TAG,
name);
smlFreeTag(tag);
*a_str = p;
return (RESULT_OK);
}
/* not starting a close tag */
assert(c != '/');
assert(c != '<');
/* at start of tag - input tag name */
bzero(name, sizeof (name));
pos = 0;
for (;;) {
/* EOF inside of tag name? */
if (c == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_TAG_EOF,
name, parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* if separator or end of line then tag name collected */
if (strchr(" >\t\n", c) != NULL) {
break;
}
/* see if illegal character in tag name */
/*CSTYLED*/
if (strchr("\":<>?$'\\`!@#%^&*()+=|[]{};,", c) != NULL) {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_TAG_ILLCHAR,
c, (unsigned int)c, name);
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* close current tag? */
if (c == '/') {
/* get next character of tag name */
c = *p;
if (*p != '\0') {
p++;
}
/* tag close not found? */
if (c != '>') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_BADTAG_CLOSE,
name, parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* is the tag empty? If so that's an error */
if (*name == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_EMPTY_TAG,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* tag closed */
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_READTAG_CLOSED_TAG,
name, parent ? parent : "<<NONE>>");
tag->name = strdup(name);
*r_tag = tag;
*a_str = p;
return (RESULT_OK);
}
/* valid character - add to name if room left */
if (pos < sizeof (name)-1) {
name[pos] = (c&0xFF);
pos++;
}
assert(pos < sizeof (name));
/* get next character to parse */
c = *p;
if (*p != '\0') {
p++;
}
}
/* have a valid tag name: <tagname */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_HAVE_TAG_NAME,
name, parent ? parent : "<<NONE>>");
assert(*name != '\0');
/* place tag name inside of tag object */
tag->name = strdup(name);
/* clear out name accumulator to get parameters */
bzero(name, sizeof (name));
pos = 0;
/* input parameters */
if (c != '>')
for (;;) {
char *pname;
char *pvalue;
SML_PARAM *parameter;
/* pass spaces before parameter name */
for (;;) {
/* get next character of parameter name */
c = *p;
if (*p != '\0') {
p++;
}
/* EOF inside parameter name? */
if (c == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_PARM_EOF,
tag->name,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* if separator/end of line tag parameter collected */
if (strchr(" \t\n", c) != NULL) {
continue;
}
/* see if illegal character in parameter name */
/*CSTYLED*/
if (strchr("\":<?$'\\`!@#%^&*()+=|[]{};,.", c) !=
(char *)NULL) {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_PARMNAME_ILLCHAR,
c, (unsigned int)c, name, tag->name,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* tag close found? */
if (c == '>') {
break;
}
/* close tag found ? */
if (c == '/') {
c = *p;
if (*p != '\0') {
p++;
}
if (c == '>') {
_smlLogMsg(LOG_MSG_DEBUG,
DBG_SML_TAG_ONLY,
tag->name);
*r_tag = tag;
*a_str = p;
return (RESULT_OK);
}
/* / not followed by > */
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_BADPARMNAME_CLOSE,
name, tag->name,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* valid character - add to name if room left */
if (pos < sizeof (name)-1) {
name[pos] = (c&0xFF);
pos++;
}
assert(pos < sizeof (name));
break;
}
if (c == '>') {
break;
}
/* input parameter name */
for (;;) {
c = *p;
if (*p != '\0') {
p++;
}
/* EOF inside of parameter name? */
if (c == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_PARM_EOF,
tag->name,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/*CSTYLED*/
if (strchr("\t \n\":<>?$'\\`!@%^*()+|[]{},./", c) != NULL) {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_PARMNAME_ILLCHAR,
c, (unsigned int)c, name, tag->name,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* name - value separator found ? */
if (c == '=') {
break;
}
/* valid character - add to name if room left */
if (pos < sizeof (name)-1) {
name[pos] = (c&0xFF);
pos++;
}
assert(pos < sizeof (name));
}
/* is the parameter name empty? If so that's an error */
if (*name == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_EMPTY_PARMNAME,
tag->name, parent ? parent : "<<NONE>>");
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* have a parameter name */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_HAVE_PARM_NAME,
name, tag->name);
/* duplicate (save) parameter name */
pname = strdup(name);
/* clear out name accumulator to get parameters */
bzero(name, sizeof (name));
pos = 0;
c = *p;
if (*p != '\0') {
p++;
}
if (c != '"') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_PARM_SEP_BAD,
c, (unsigned int)c);
free(pname);
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* input parameter value */
for (;;) {
c = *p;
if (*p != '\0') {
p++;
}
/* EOF inside of parameter value? */
if (c == '\0') {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_PARMVAL_EOF,
pname, tag->name,
parent ? parent : "<<NONE>>");
smlFreeTag(tag);
free(pname);
*a_str = p;
return (RESULT_ERR);
}
/* close of parameter value? */
if (c == '"') {
break;
}
if (strchr("\n", c) != NULL) {
_smlLogMsg(LOG_MSG_ERR,
ERR_SML_READTAG_PARMVAL_NL,
pname, tag->name,
parent ? parent : "<<NONE>>");
free(pname);
smlFreeTag(tag);
*a_str = p;
return (RESULT_ERR);
}
/* valid character - add to value if room left */
if (pos < sizeof (name)-1) {
name[pos] = (c&0xFF);
pos++;
}
assert(pos < sizeof (name));
}
/* got the value */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_HAVE_PARM_VALUE,
pname, name, tag->name);
pvalue = sml_XmlDecodeString(name);
bzero(name, sizeof (name));
pos = 0;
parameter = (SML_PARAM *)calloc(1, sizeof (SML_PARAM));
bzero(parameter, sizeof (SML_PARAM));
parameter->name = pname;
parameter->value = pvalue;
tag->params_num++;
tag->params = (SML_PARAM *)
realloc(tag->params,
sizeof (SML_PARAM) *tag->params_num);
(void) memcpy(&(tag->params[tag->params_num - 1]), parameter,
sizeof (SML_PARAM));
free(parameter);
if (c == '>') {
break;
}
}
/* finished processing this tag element entry */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_TAG_HEAD_DONE,
tag->name, parent ? parent : "<<NULL>>");
tag->tags = NULL;
while (((r = _smlReadTag(&tmp_tag, &p, tag->name))
== RESULT_OK) && (tmp_tag != NULL)) {
tag->tags_num++;
tag->tags = (SML_TAG *)realloc(tag->tags,
sizeof (SML_TAG) *tag->tags_num);
(void) memcpy(&(tag->tags[tag->tags_num - 1]), tmp_tag,
sizeof (SML_TAG));
free(tmp_tag);
}
c = *p;
if (*p != '\0') {
p++;
}
*r_tag = tag;
*a_str = p;
return (r);
}
/*
* Name: _smlWriteParamValue
* Description: XML Encode a plain text parameter value and write to datastream
* Arguments: ds - [RO, *RO] - (LU_DS)
* Handle to datastream to write parameter value to
* value - [RO, *RO] - (char *)
* Parameter value to be encoded and written
* Returns: int
* RESULT_OK - tag successfully read
* RESULT_ERR - problem reading tag
*/
static int
_smlWriteParamValue(char **a_str, char *value)
{
char *ns;
char *p;
/* entry assertions */
assert(a_str != (char **)NULL);
assert(value != (char *)NULL);
/* xml encode the plain text string */
p = sml_XmlEncodeString(value);
assert(p != (char *)NULL);
/* write the xml encoded parameter value to the datastream */
ns = sml_strPrintf("%s\"%s\"", *a_str ? *a_str : "", p);
/* free up xml encoded value storage */
free(p);
if (ns == NULL) {
return (RESULT_ERR);
}
if (*a_str != NULL) {
free(*a_str);
}
*a_str = ns;
/* return results */
return (RESULT_OK);
}
static int
_smlWriteSimpleTag(char **a_str, SML_TAG *tag)
{
int r;
int k;
char *ns;
char *np0;
char *np1;
if (tag == NULL) {
return (RESULT_OK);
}
if (*a_str == NULL) {
*a_str = strdup("");
}
if (tag->params_num == 0) {
if (tag->tags_num == 0) {
ns = sml_strPrintf("%s<%s/>\n", *a_str, tag->name);
free(*a_str);
*a_str = ns;
return (RESULT_OK);
} else {
ns = sml_strPrintf("%s<%s>\n", *a_str, tag->name);
if (ns == NULL) {
return (RESULT_ERR);
}
free(*a_str);
*a_str = ns;
}
} else {
ns = sml_strPrintf("%s<%s %s=", *a_str ? *a_str : "", tag->name,
tag->params[0].name);
if (ns == NULL) {
return (RESULT_ERR);
}
free(*a_str);
*a_str = ns;
np0 = NULL;
r = _smlWriteParamValue(&np0, tag->params[0].value);
if ((np0 == NULL) || (r != RESULT_OK)) {
return (RESULT_ERR);
}
ns = sml_strPrintf("%s%s", *a_str, np0);
if (ns == NULL) {
return (RESULT_ERR);
}
free(np0);
free(*a_str);
*a_str = ns;
for (k = 1; k < tag->params_num; k++) {
np0 = sml_strPrintf(" %s=", tag->params[k].name);
if (np0 == NULL) {
return (RESULT_ERR);
}
np1 = NULL;
r = _smlWriteParamValue(&np1, tag->params[k].value);
if ((np1 == NULL) || (r != RESULT_OK)) {
return (RESULT_ERR);
}
ns = sml_strPrintf("%s%s%s", *a_str, np0, np1);
if (ns == NULL) {
return (RESULT_ERR);
}
free(np0);
free(np1);
free(*a_str);
*a_str = ns;
}
if (tag->tags_num == 0) {
np0 = sml_strPrintf("/>\n");
if (np0 == NULL) {
return (RESULT_ERR);
}
ns = sml_strPrintf("%s%s", *a_str, np0);
if (ns == NULL) {
return (RESULT_ERR);
}
free(np0);
free(*a_str);
*a_str = ns;
} else {
np0 = sml_strPrintf(">\n");
if (np0 == NULL) {
return (RESULT_ERR);
}
ns = sml_strPrintf("%s%s", *a_str, np0);
if (ns == NULL) {
return (RESULT_ERR);
}
free(np0);
free(*a_str);
*a_str = ns;
}
}
for (k = 0; k < tag->tags_num; k++) {
r = _smlWriteSimpleTag(a_str, &(tag->tags[k]));
if (r != RESULT_OK) {
return (r);
}
}
if (tag->tags_num > 0) {
np0 = sml_strPrintf("</%s>\n", tag->name);
if (np0 == NULL) {
return (RESULT_ERR);
}
ns = sml_strPrintf("%s%s", *a_str ? *a_str : "", np0);
if (ns == NULL) {
return (RESULT_ERR);
}
free(np0);
free(*a_str);
*a_str = ns;
}
return (RESULT_OK);
}
static void
_smlFreeTag(SML_TAG *tag)
{
int k;
/* entry assertions */
assert(tag != SML_TAG__NULL);
/* entry debugging info */
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_TAG,
(unsigned long)tag,
tag->name ? tag->name : "<<NONE>>",
tag->params_num, tag->tags_num);
for (k = 0; k < tag->params_num; k++) {
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_PARAM_NAME,
(unsigned long)(&tag->params[k]),
(unsigned long)(tag->params[k].name),
tag->params[k].name);
free(tag->params[k].name);
tag->params[k].name = (char *)NULL;
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_PARAM_VALUE,
(unsigned long)(&tag->params[k]),
(unsigned long)(tag->params[k].value),
tag->params[k].value);
free(tag->params[k].value);
tag->params[k].value = (char *)NULL;
}
for (k = 0; k < tag->tags_num; k++) {
_smlFreeTag(&tag->tags[k]);
}
if (tag->name != NULL) {
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_TAG_NAME,
(unsigned long)tag->name, tag->name);
free(tag->name);
tag->name = NULL;
}
if (tag->params != NULL) {
assert(tag->params_num > 0);
bzero(tag->params, sizeof (SML_PARAM)*tag->params_num);
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_PARAMS,
(unsigned long)tag->params);
free(tag->params);
tag->params = NULL;
tag->params_num = 0;
}
if (tag->tags != NULL) {
assert(tag->tags_num > 0);
bzero(tag->tags, sizeof (SML_TAG)*tag->tags_num);
_smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_TAGS,
(unsigned long)tag->tags);
free(tag->tags);
tag->tags = NULL;
tag->tags_num = 0;
}
}
/*
* Name: log_msg
* Description: Outputs messages to logging facility.
* Scope: public
* Arguments: type - the severity of the message
* out - where to output the message.
* fmt - the printf format, plus its arguments
* Returns: none
*/
/*PRINTFLIKE2*/
static void
_smlLogMsg(LogMsgType a_type, const char *a_format, ...)
{
va_list ap;
size_t vres = 0;
char bfr[1];
char *rstr = (char *)NULL;
FILE *out;
char *prefix;
switch (a_type) {
case LOG_MSG_ERR:
default:
out = stderr;
prefix = MSG_LOG_ERROR;
break;
case LOG_MSG_WRN:
out = stderr;
prefix = MSG_LOG_WARNING;
break;
case LOG_MSG_INFO:
out = stdout;
prefix = NULL;
break;
case LOG_MSG_DEBUG:
if (!smlGetVerbose()) {
/* no debug messages if not verbose mode */
return;
}
out = stderr;
prefix = MSG_LOG_DEBUG;
break;
}
if (prefix != NULL) {
(void) fprintf(out, "%s: ", prefix);
}
/* determine size of the message in bytes */
va_start(ap, a_format);
vres = vsnprintf(bfr, 1, a_format, ap);
va_end(ap);
/* allocate storage to hold the message */
rstr = (char *)malloc(vres+2);
/* generate the results of the printf conversion */
va_start(ap, a_format);
vres = vsnprintf(rstr, vres+1, a_format, ap);
va_end(ap);
if (fprintf(out, "%s\n", rstr) < 0) {
/*
* nothing output, try stderr as a
* last resort
*/
(void) fprintf(stderr, ERR_LOG_FAIL, a_format);
}
free(rstr);
}