/*
* 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"
#include "xml_convert.h"
#include <errno.h>
#include <string.h>
#include <libintl.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <locale.h>
#include <unistd.h>
#include "volume_error.h"
#include "volume_output.h"
#include "volume_string.h"
/*
* IDs for localized messages in the generated command script
*/
/* CSTYLED */
/* CSTYLED */
/* CSTYLED */
/*
* ******************************************************************
*
* Data types
*
* ******************************************************************
*/
/*
* Encapsulates the parsing of an XML attribute
*/
typedef struct {
/* The name of the attribute */
char *name;
/*
* A function to validate and set the XML attribute value in
* the given devconfig_t structure.
*
* @param name
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 if the given value was valid and set
* successfully, non-zero otherwise.
*/
/*
* A function to get the XML attribute value in the given
* devconfig_t structure.
*
* @param name
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 if the given value was retrieved
* successfully, non-zero otherwise.
*/
} attr_t;
/*
* Encapsulates the parsing of an XML element
*/
typedef struct {
/* The name of the element */
char *name;
/* The type of element to set in the devconfig_t */
/*
* When converting from XML to a devconfig_t hierarchy,
* indicates whether to create a new devconfig_t structure in
* the hierarchy when this XML element is encountered.
*/
/*
* If is_hierarchical is B_TRUE, whether to use an existing
* devconfig_t structure of this type when this element is
* encountered
*/
/* The valid XML attributes for this element */
} element_t;
typedef struct {
char *msgid;
char *message;
/*
* ******************************************************************
*
* Function prototypes
*
* ******************************************************************
*/
static int devconfig_to_xml(
static int xml_to_devconfig(
static xmlNodePtr xml_find_node(
static xmlDocPtr create_localized_message_doc();
static int create_localized_message_file(char **tmpfile);
static int validate_set_size(
static int validate_set_size_in_blocks(
static int validate_set_diskset_name(
static int validate_add_available_name(
static int validate_add_unavailable_name(
static int validate_set_hsp_name(
static int validate_set_disk_name(
static int validate_set_slice_name(
static int validate_set_slice_start_block(
static int validate_set_volume_name(
static int validate_set_stripe_interlace(
static int validate_set_stripe_mincomp(
static int validate_set_stripe_maxcomp(
static int validate_set_volume_usehsp(
static int validate_set_mirror_nsubmirrors(
static int validate_set_mirror_read(
static int validate_set_mirror_write(
static int validate_set_mirror_passnum(
static int validate_set_volume_redundancy(
static int validate_set_volume_datapaths(
static int get_as_string_name(
static int get_as_string_mirror_passnum(
static int get_as_string_mirror_read(
static int get_as_string_mirror_write(
static int get_as_string_size_in_blocks(
static int get_as_string_slice_start_block(
static int get_as_string_stripe_interlace(
/*
* ******************************************************************
*
* Data
*
* ******************************************************************
*/
/* Valid units for the size attribute */
{NULL, 0}
};
/* Valid units for the interlace attribute */
{NULL, 0}
};
/* <diskset> attributes */
};
/* <available> attributes */
};
/* <unavailable> attributes */
};
/* <hsp> attributes */
};
/* <disk> attributes */
};
/* <slice> attributes */
};
/* <stripe> attributes */
};
/* <concat> attributes */
};
/* <mirror> attributes */
};
/* <volume> attributes */
};
/* volume-request elements */
};
/* volume-defaults elements */
};
/* volume-config elements */
};
/*
* ******************************************************************
*
* External functions
*
* ******************************************************************
*/
/*
* Initialize the XML parser, setting defaults across all XML
* routines.
*/
void
init_xml()
{
/* COMPAT: Do not generate nodes for formatting spaces */
/* Turn on line numbers for debugging */
/* Substitute entities as files are parsed */
/* Don't load external entity subsets */
/* Don't validate against DTD by default */
/* Set up output handlers for XML parsing */
}
/*
* Clean up any remaining structures before exiting.
*/
void
{
}
/*
* Converts a volume-request XML document into a request_t.
*
* @param doc
* an existing volume-request XML document
*
* @param request
* RETURN: a new request_t which must be freed via
* free_request
*
* @return 0 on success, non-zero otherwise.
*/
int
{
int error = 0;
/* Validate doc against known DTD */
if ((error = validate_doc(
/* Create a request */
/* Convert the XML doc into a request_t */
}
}
return (error);
}
/*
* Converts a volume-defaults XML document into a defaults_t.
*
* @param doc
* an existing volume-defaults XML document
*
* @param defaults
* RETURN: a new defaults_t which must be freed via
* free_defaults
*
* @return 0 on success, non-zero otherwise.
*/
int
{
int error = 0;
/* Validate doc against known DTD */
VOLUME_DEFAULTS_DTD_LOC)) == 0) {
/* Create request defaults */
/* Get defaults for all disk sets */
if ((error = defaults_get_diskset_by_name(
/* Populate the global devconfig_t from the XML doc */
default_elements, global)) == 0) {
/* Get the components of the global devconfig_t */
/*
* Move all named disk set settings out from
* under global settings
*/
/* CONSTANTCONDITION */
while (1) {
/* Remove named disk set from under global */
/* No named disk set found */
break;
}
/* Append named disk set to disk set list */
}
}
}
}
}
return (error);
}
/*
* Converts a volume-config XML document into a devconfig_t.
*
* @param doc
* an existing volume-config XML document
*
* @param config
* RETURN: a new devconfig_t which must be freed via
* free_devconfig
*
* @return 0 on success, non-zero otherwise.
*/
int
{
int error = 0;
/* Validate doc against known DTD */
if ((error = validate_doc(
/* Create a devconfig_t */
/* Populate the devconfig_t from the XML doc */
}
}
return (error);
}
/*
* Converts a devconfig_t into a volume-config XML document.
*
* @param config
* an existing devconfig_t representing a volume
* configuration.
*
* @param doc
* RETURN: a new volume-config XML document which must be
* freed via xmlFreeDoc
*
* @return 0 on success, non-zero otherwise.
*/
int
{
int error = 0;
/* Create the XML document */
/* Create the root node */
/* Create sub-nodes from the config devconfig_t */
/* Add DTD node and validate */
}
if (error) {
xmlFreeDoc(*doc);
}
return (error);
}
/*
* Converts a volume-config XML document into a Bourne shell script.
*
* @param doc
* an existing volume-config XML document
*
* @param commands
* RETURN: a new char* which must be freed
*
* @return 0 on success, non-zero otherwise.
*/
int
char **commands)
{
int error = 0;
/* Read in XSL stylesheet as a normal XML document */
/*
* Find the "msgfile" variable node. This is where
* we'll set the location of the file we'll create
* containing the localized messages.
*/
/*
* Find the "lang" node. This is where we'll set the
* current locale.
*/
/*
* Ignore if the nodes are not found -- the script
* will default to the C locale.
*/
/* Write localized messages to a temporary file */
char *newsel;
/* Clear current value of select attribute, if any */
}
/*
* The select attribute calls the XSLT function
* document() to load an external XML file
*/
error = -1;
} else {
/* Set the new value of the select attribute */
}
}
}
if (error == 0) {
}
}
gettext("could not load stylesheet from %s"),
error = -1;
} else {
gettext("could not apply stylesheet to volume-config"));
error = -1;
} else {
int length;
}
}
}
/* Ignore failure */
}
return (error);
}
/*
* ******************************************************************
*
* Static functions
*
* ******************************************************************
*/
/*
* Sets the external DTD node in the given XML document and then
* validates it.
*
* @param doc
* an existing XML document
*
* @param name
* the expected root element name of the XML document
*
* @param systemID
* the location of the DTD
*
* @return 0 on success, non-zero otherwise.
*/
static int
const char *name,
const char *systemID)
{
return (-1);
}
/*
* Assume that we can't trust any DTD but our own.
*/
/* Was a DTD (external or internal) included in the document? */
/* Remove the DTD node */
}
/* Create the (external) DTD node */
return (-1);
}
/* Validate against DTD */
return (-1);
}
return (0);
}
/*
* Converts a devconfig_t into an XML node subject to the rules in
* the given element_t array.
*
* @param parent
* the XML node to which to add new XML nodes resulting
* from conversion of the given devconfig_t
*
* @param elements
* the element_ts that describe the structure of the XML
* document and govern the conversion of the given
* devconfig_t
*
* @param device
* the devconfig_t to convert
*
* @return 0 on success, non-zero otherwise.
*/
static int
{
int i;
int error = 0;
/* Get device type */
return (error);
}
/* Search for this element definition */
int j;
char **array;
/* Create the XML node */
node = xmlNewChild(
/* For each attribute defined for this element... */
char *value;
/* Is there a valid accessor for this attribute? */
/* Get the attribute value from the device */
/* Attribute is set in this device */
case 0:
/* Set the value in the XML node */
/* FALLTHROUGH */
/* Attribute is not set in this device */
case ERR_ATTR_UNSET:
error = 0;
break;
/* Error */
default:
return (error);
}
}
}
/* Is this node hierarchical? */
}
/* Create <available> nodes */
}
}
/* Create <unavailable> nodes */
}
}
/*
* Recursively convert subcomponents of this device to
* XML, taking care to encode them in the order
* specified in the element_t list (which should
* mirror what's expected by the DTD).
*/
/* For each element type... */
/* For each component of this device... */
/* Are the types the same? */
return (error);
} else {
/* Encode child */
}
}
}
}
/* Element found */
break;
}
}
/* Was this device successfully converted? */
gettext("can't convert device of type \"%s\" to XML element"),
error = -1;
}
return (error);
}
/*
* Converts an XML node into a devconfig_t subject to the rules in
* the given element_t array.
*
* @param cure
* the existing XML node to convert
*
* @param elements
* the element_ts that describe the structure of the XML
* document and govern the conversion of the given XML
* node
*
* @param device
* the devconfig_t node to which to add new devconfig_ts
* resulting from conversion of the given XML node
*
* @return 0 on success, non-zero otherwise.
*/
static int
{
int error = 0;
/* For each child node... */
int i;
/* Search for this element definition */
int j;
/* Flag that this element has been parsed */
/* Should a new device be created for this element? */
/* Should we use an existing device of this type? */
}
gettext("Creating new device\n"));
/* Create device of this type */
if ((error = new_devconfig(
return (error);
}
/* Add component to the toplevel device */
}
} else {
}
/* For each attribute defined for this element... */
/* Get the value of this attribute */
char *value = (char *)
/* Was this attribute specified? */
gettext("line %d:\tAttribute %s=%s\n"),
/* Set this value in the device */
return (error);
}
}
}
/* Get recursive sub-elements */
if ((error = xml_to_devconfig(
return (error);
}
/* Element found */
break;
}
}
if (parsed_elem == B_FALSE &&
}
}
return (0);
}
/*
* Returns 0 if obj2 (devconfig_t *) is a disk set, 1 otherwise.
*/
static int
void *obj1,
void *obj2)
{
return (devconfig_isA(
}
/*
* Recursively searches the given xmlNodePtr for an element of the
* specified type and name.
*
* @param node
* the root node to search
*
* @param element
* the name of the element type
*
* @param name
* the value of the name attribute
*
* @return a valid xmlNodePtr if an element of the specified
* type and name was found, NULL otherwise.
*/
static xmlNodePtr
{
/* Is the element the right type? */
/* Does this element's name attribute match? */
return (node);
}
/* Check child nodes */
return (found);
}
}
return (NULL);
}
/*
* Creates an XML document containing all of the localized message
* strings for the generated command script.
*
* @return a xmlDocPtr which must be freed via xmlFreeDoc
*/
static xmlDocPtr
{
int i;
char *locale;
/* Create the XML document */
/* Create the root node */
/* Add localized <message> elements to stylesheet */
/* Lang attribute */
/* Message ID attribute */
}
if (get_max_verbosity() >= OUTPUT_DEBUG) {
/* Get the text dump */
}
return (doc);
}
/*
* Creates a temporary XML file containing all of the localized
* message strings for the generated command script.
*
* @param tmpfile
* RETURN: the name of the temporary XML file
*
* @return 0 on success, non-zero otherwise.
*/
static int
char **tmpfile)
{
int error = 0;
/*
* Create temporary file name -- "XXXXXX" is replaced with
* unique char sequence by mkstemp()
*/
error = -1;
} else {
int fildes;
/* Open temp file */
}
"could not open file for writing: %s"), *tmpfile);
error = -1;
} else {
"could not create localized message file: %s"),
*tmpfile);
error = -1;
}
}
}
return (error);
}
/*
* Converts the given string into a boolean. The string must be
* either VALID_ATTR_TRUE or VALID_ATTR_FALSE.
*
* @param str
* the string to convert
*
* @param bool
* the addr of the boolean_t
*
* @return 0 if the given string could be converted to a boolean
* non-zero otherwise.
*/
static int
char *str,
{
int error = 0;
} else
} else
error = -1;
return (error);
}
/*
* Wrapper for oprintf with a OUTPUT_TERSE level of verbosity.
* Provides an fprintf-like syntax to enable use as substitute output
* handler for man of the XML commands.
*
* @param unused
* unused, in favor of the FILE* passed to
* set_max_verbosity().
*
* @param fmt
* a printf-style format string
*
* @return the number of characters output
*/
static int
void *unused,
char *fmt,
...)
{
int ret;
return (ret);
}
/*
* Wrapper for oprintf with a OUTPUT_VERBOSE level of verbosity.
* Provides an fprintf-like syntax to enable use as substitute output
* handler for man of the XML commands.
*
* @param unused
* unused, in favor of the FILE* passed to
* set_max_verbosity().
*
* @param fmt
* a printf-style format string
*
* @return the number of characters output
*/
static int
void *unused,
char *fmt,
...)
{
int ret;
return (ret);
}
/*
* ******************************************************************
*
* XML attribute validators/mutators
*
* These functions convert the given XML attribute string to the
* appropriate data type, and then pass it on to the appropriate
* devconfig_t mutator. A non-zero status is returned if the given
* string could not be converted or was invalid.
*
* ******************************************************************
*/
/*
* Validate and set the size attribute in the given volume
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the size
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
int error;
/* Convert size string to bytes */
return (error);
}
/* Set size in volume */
}
/*
* Validate and set the size_in_blocks attribute in the given slice
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the size_in_blocks
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
long long size;
/* Convert string to long long */
return (-1);
}
/* Set the number of submirrors in the slice */
}
/*
* Validate and set the name attribute in the given diskset
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the name
*
* @param attr
* the name of the XML attribute
*
* @param name
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *name)
{
}
/*
* Validate and add the given name to the list of available devices in
* the given volume devconfig_t.
*
* @param device
* the devconfig_t whose available device list to modify
*
* @param attr
* the name of the XML attribute
*
* @param name
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *name)
{
char **available;
/* Get available devices for this device */
/* Try to add name to array via realloc */
return (ENOMEM);
}
/* Set available devices in the device */
return (0);
}
/*
* Validate and add the given name to the list of unavailable devices
* in the given volume devconfig_t.
*
* @param device
* the devconfig_t whose unavailable device list to modify
*
* @param attr
* the name of the XML attribute
*
* @param name
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *name)
{
char **unavailable;
/* Get unavailable devices for this device */
/* Try to add name to array via realloc */
return (ENOMEM);
}
/* Set unavailable devices in the device */
return (0);
}
/*
* Validate and set the name attribute in the given hsp devconfig_t.
*
* @param volume
* the devconfig_t in which to set the name
*
* @param attr
* the name of the XML attribute
*
* @param name
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *name)
{
}
/*
* Validate and set the name attribute in the given disk devconfig_t.
*
* @param volume
* the devconfig_t in which to set the name
*
* @param attr
* the name of the XML attribute
*
* @param name
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *name)
{
}
/*
* Validate and set the name attribute in the given slice devconfig_t.
*
* @param volume
* the devconfig_t in which to set the name
*
* @param attr
* the name of the XML attribute
*
* @param name
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *name)
{
}
/*
* Validate and set the start_block attribute in the given slice
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the start_block
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
long long startsector;
/* Convert string to long long */
return (-1);
}
/* Set the number of submirrors in the slice */
}
/*
* Validate and set the name attribute in the given volume
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the name
*
* @param attr
* the name of the XML attribute
*
* @param name
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *name)
{
}
/*
* Validate and set the interlace attribute in the given stripe
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the interlace
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
int error;
/* Convert interlace string to bytes */
if ((error = sizestr_to_bytes(
return (error);
}
/* Set interlace in stripe */
}
/*
* Validate and set the mincomp attribute in the given stripe
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the mincomp
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
/* Convert string to a uint16_t */
gettext("invalid minimum stripe components (%s): %s"),
return (-1);
}
/* Set in stripe */
}
/*
* Validate and set the maxcomp attribute in the given stripe
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the maxcomp
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
/* Convert string to a uint16_t */
gettext("invalid maximum stripe components (%s): %s"),
return (-1);
}
/* Set in stripe */
}
/*
* Validate and set the usehsp attribute in the given volume
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the usehsp
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
/* Get boolean value */
gettext("%s: invalid boolean value for \"%s\" attribute"),
return (-1);
}
/* Set in volume */
}
/*
* Validate and set the nsubmirrors attribute in the given mirror
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the nsubmirrors
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
/* Convert string to a uint16_t */
gettext("invalid number of submirrors (%s): %s"),
return (-1);
}
/* Set in stripe */
}
/*
* Validate and set the read attribute in the given mirror
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the read
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
} else
} else
} else
{
return (-1);
}
}
/*
* Validate and set the write attribute in the given mirror
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the write
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
} else
} else
{
return (-1);
}
}
/*
* Validate and set the passnum attribute in the given mirror
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the passnum
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
/* Convert string to a uint16_t */
gettext("invalid mirror pass number (%s): %s"),
return (-1);
}
/* Set in stripe */
}
/*
* Validate and set the redundancy attribute in the given volume
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the redundancy
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
/* Convert string to a uint16_t */
gettext("invalid redundancy level (%s): %s"),
return (-1);
}
/* Set in stripe */
}
/*
* Validate and set the datapaths attribute in the given volume
* devconfig_t.
*
* @param volume
* the devconfig_t in which to set the datapaths
*
* @param attr
* the name of the XML attribute
*
* @param value
* the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char *value)
{
/* Convert string to a uint16_t */
gettext("invalid number of data paths (%s): %s"),
return (-1);
}
/* Set in stripe */
}
/*
* ******************************************************************
*
* XML attribute accessors/converters
*
* These functions get a value from the appropriate devconfig_t
* accessor, and then convert it to a string.
*
* ******************************************************************
*/
/*
* Get, as a string, the value of the name attribute of the given
* devconfig_t. This data must be freed.
*
* @param device
* the devconfig_t from which to retrieve the name
*
* @param attr
* the name of the XML attribute
*
* @param value
* RETURN: the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char **value)
{
int error;
char *name;
/* Get name */
}
}
return (error);
}
/*
* Get, as a string, the value of the passnum attribute of the given
* mirror devconfig_t. This data must be freed.
*
* @param device
* the devconfig_t from which to retrieve the passnum
*
* @param attr
* the name of the XML attribute
*
* @param value
* RETURN: the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char **value)
{
int error;
/* Get mirror pass number */
}
return (error);
}
/*
* Get, as a string, the value of the read attribute of the given
* mirror devconfig_t. This data must be freed.
*
* @param device
* the devconfig_t from which to retrieve the read
*
* @param attr
* the name of the XML attribute
*
* @param value
* RETURN: the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char **value)
{
int error;
/* Get mirror read strategy */
}
}
return (error);
}
/*
* Get, as a string, the value of the write attribute of the given
* mirror devconfig_t. This data must be freed.
*
* @param device
* the devconfig_t from which to retrieve the write
*
* @param attr
* the name of the XML attribute
*
* @param value
* RETURN: the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char **value)
{
int error;
/* Get mirror write strategy */
}
}
return (error);
}
/*
* Get, as a string, the value of the in_blocks attribute of the given
* device devconfig_t. This data must be freed.
*
* @param device
* the devconfig_t from which to retrieve the in_blocks
*
* @param attr
* the name of the XML attribute
*
* @param value
* RETURN: the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char **value)
{
int error;
/* Get size in blocks */
}
return (error);
}
/*
* Get, as a string, the value of the start_block attribute of the
* given slice devconfig_t. This data must be freed.
*
* @param device
* the devconfig_t from which to retrieve the start_block
*
* @param attr
* the name of the XML attribute
*
* @param value
* RETURN: the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char **value)
{
int error;
/* Get slice start block */
}
return (error);
}
/*
* Get, as a string, the value of the interlace attribute of the given
* stripe devconfig_t. This data must be freed.
*
* @param device
* the devconfig_t from which to retrieve the interlace
*
* @param attr
* the name of the XML attribute
*
* @param value
* RETURN: the value of the XML attribute
*
* @return 0 on success, non-zero otherwise.
*/
static int
char *attr,
char **value)
{
int error;
/* Get interlace */
if ((error = devconfig_get_stripe_interlace(
}
return (error);
}